Mercurial > emacs
comparison src/ralloc.c @ 9666:d50850d0c8f8
(struct heap): New fields first_bloc, last_bloc.
(struct bp): New field heap.
(get_bloc, free_bloc, obtain, r_alloc_sbrk): Update new fields.
(reorder_bloc): New function.
(update_heap_bloc_correspondence):
Renamed from update_heap_free_pointers. Update new fields.
(relinquish): Add error check for new fields.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Sun, 23 Oct 1994 06:16:43 +0000 |
parents | 134f7085c56b |
children | 15d01ad97928 |
comparison
equal
deleted
inserted
replaced
9665:36bdda3a1dc9 | 9666:d50850d0c8f8 |
---|---|
141 POINTER end; | 141 POINTER end; |
142 /* Start of relocatable data in this heap. */ | 142 /* Start of relocatable data in this heap. */ |
143 POINTER bloc_start; | 143 POINTER bloc_start; |
144 /* Start of unused space in this heap. */ | 144 /* Start of unused space in this heap. */ |
145 POINTER free; | 145 POINTER free; |
146 /* First bloc in this heap. */ | |
147 struct bp *first_bloc; | |
148 /* Last bloc in this heap. */ | |
149 struct bp *last_bloc; | |
146 } *heap_ptr; | 150 } *heap_ptr; |
147 | 151 |
148 #define NIL_HEAP ((heap_ptr) 0) | 152 #define NIL_HEAP ((heap_ptr) 0) |
149 #define HEAP_PTR_SIZE (sizeof (struct heap)) | 153 #define HEAP_PTR_SIZE (sizeof (struct heap)) |
150 | 154 |
166 struct bp *prev; | 170 struct bp *prev; |
167 POINTER *variable; | 171 POINTER *variable; |
168 POINTER data; | 172 POINTER data; |
169 SIZE size; | 173 SIZE size; |
170 POINTER new_data; /* tmporarily used for relocation */ | 174 POINTER new_data; /* tmporarily used for relocation */ |
175 /* Heap this bloc is in. */ | |
176 struct heap *heap; | |
171 } *bloc_ptr; | 177 } *bloc_ptr; |
172 | 178 |
173 #define NIL_BLOC ((bloc_ptr) 0) | 179 #define NIL_BLOC ((bloc_ptr) 0) |
174 #define BLOC_PTR_SIZE (sizeof (struct bp)) | 180 #define BLOC_PTR_SIZE (sizeof (struct bp)) |
175 | 181 |
265 new_heap->end = bloc_start; | 271 new_heap->end = bloc_start; |
266 new_heap->bloc_start = bloc_start; | 272 new_heap->bloc_start = bloc_start; |
267 new_heap->free = bloc_start; | 273 new_heap->free = bloc_start; |
268 new_heap->next = NIL_HEAP; | 274 new_heap->next = NIL_HEAP; |
269 new_heap->prev = last_heap; | 275 new_heap->prev = last_heap; |
276 new_heap->first_bloc = NIL_BLOC; | |
277 new_heap->last_bloc = NIL_BLOC; | |
270 last_heap->next = new_heap; | 278 last_heap->next = new_heap; |
271 last_heap = new_heap; | 279 last_heap = new_heap; |
272 | 280 |
273 address = bloc_start; | 281 address = bloc_start; |
274 already_available = 0; | 282 already_available = 0; |
316 And don't free anything unless we can free at least extra_bytes. */ | 324 And don't free anything unless we can free at least extra_bytes. */ |
317 excess -= extra_bytes; | 325 excess -= extra_bytes; |
318 | 326 |
319 if ((char *)last_heap->end - (char *)last_heap->bloc_start <= excess) | 327 if ((char *)last_heap->end - (char *)last_heap->bloc_start <= excess) |
320 { | 328 { |
329 /* This heap should have no blocs in it. */ | |
330 if (last_heap->first_bloc != NIL_BLOC | |
331 || last_heap->last_bloc != NIL_BLOC) | |
332 abort (); | |
333 | |
321 /* Return the last heap, with its header, to the system. */ | 334 /* Return the last heap, with its header, to the system. */ |
322 excess = (char *)last_heap->end - (char *)last_heap->start; | 335 excess = (char *)last_heap->end - (char *)last_heap->start; |
323 last_heap = last_heap->prev; | 336 last_heap = last_heap->prev; |
324 last_heap->next = NIL_HEAP; | 337 last_heap->next = NIL_HEAP; |
325 } | 338 } |
386 | 399 |
387 /* Record in the heap that this space is in use. */ | 400 /* Record in the heap that this space is in use. */ |
388 heap = find_heap (new_bloc->data); | 401 heap = find_heap (new_bloc->data); |
389 heap->free = break_value; | 402 heap->free = break_value; |
390 | 403 |
404 /* Maintain the correspondence between heaps and blocs. */ | |
405 new_bloc->heap = heap; | |
406 heap->last_bloc = new_bloc; | |
407 if (heap->first_bloc == NIL_BLOC) | |
408 heap->first_bloc = new_bloc; | |
409 | |
391 /* Put this bloc on the doubly-linked list of blocs. */ | 410 /* Put this bloc on the doubly-linked list of blocs. */ |
392 if (first_bloc) | 411 if (first_bloc) |
393 { | 412 { |
394 new_bloc->prev = last_bloc; | 413 new_bloc->prev = last_bloc; |
395 last_bloc->next = new_bloc; | 414 last_bloc->next = new_bloc; |
401 new_bloc->prev = NIL_BLOC; | 420 new_bloc->prev = NIL_BLOC; |
402 } | 421 } |
403 | 422 |
404 return new_bloc; | 423 return new_bloc; |
405 } | 424 } |
406 | 425 |
407 /* Calculate new locations of blocs in the list beginning with BLOC, | 426 /* Calculate new locations of blocs in the list beginning with BLOC, |
408 relocating it to start at ADDRESS, in heap HEAP. If enough space is | 427 relocating it to start at ADDRESS, in heap HEAP. If enough space is |
409 not presently available in our reserve, call obtain for | 428 not presently available in our reserve, call obtain for |
410 more space. | 429 more space. |
411 | 430 |
462 } | 481 } |
463 | 482 |
464 return 1; | 483 return 1; |
465 } | 484 } |
466 | 485 |
467 /* Update the free pointers of all heaps starting with HEAP | 486 /* Reorder the bloc BLOC to go before bloc BEFORE in the doubly linked list. |
468 based on the blocs starting with BLOC. BLOC should be in | 487 This is necessary if we put the memory of space of BLOC |
469 heap HEAP. */ | 488 before that of BEFORE. */ |
470 | 489 |
471 static | 490 static void |
472 update_heap_free_pointers (bloc, heap) | 491 reorder_bloc (bloc, before) |
492 bloc_ptr bloc, before; | |
493 { | |
494 bloc_ptr prev, next; | |
495 | |
496 /* Splice BLOC out from where it is. */ | |
497 prev = bloc->prev; | |
498 next = bloc->next; | |
499 | |
500 if (prev) | |
501 prev->next = next; | |
502 if (next) | |
503 next->prev = prev; | |
504 | |
505 /* Splice it in before BEFORE. */ | |
506 prev = before->prev; | |
507 | |
508 if (prev) | |
509 prev->next = bloc; | |
510 bloc->prev = prev; | |
511 | |
512 before->prev = bloc; | |
513 bloc->next = before; | |
514 } | |
515 | |
516 /* Update the records of which heaps contain which blocs, starting | |
517 with heap HEAP and bloc BLOC. */ | |
518 | |
519 static void | |
520 update_heap_bloc_correspondence (bloc, heap) | |
473 bloc_ptr bloc; | 521 bloc_ptr bloc; |
474 heap_ptr heap; | 522 heap_ptr heap; |
475 { | 523 { |
476 register bloc_ptr b; | 524 register bloc_ptr b; |
477 | 525 |
526 /* Initialize HEAP's status to reflect blocs before BLOC. */ | |
527 if (bloc != NIL_BLOC && bloc->prev != NIL_BLOC && bloc->prev->heap == heap) | |
528 { | |
529 /* The previous bloc is in HEAP. */ | |
530 heap->last_bloc = bloc->prev; | |
531 heap->free = bloc->prev->data + bloc->prev->size; | |
532 } | |
533 else | |
534 { | |
535 /* HEAP contains no blocs before BLOC. */ | |
536 heap->first_bloc = NIL_BLOC; | |
537 heap->last_bloc = NIL_BLOC; | |
538 heap->free = heap->bloc_start; | |
539 } | |
540 | |
478 /* Advance through blocs one by one. */ | 541 /* Advance through blocs one by one. */ |
479 for (b = bloc; b != NIL_BLOC; b = b->next) | 542 for (b = bloc; b != NIL_BLOC; b = b->next) |
480 { | 543 { |
481 /* Advance through heaps in sync with the blocs that are in them. */ | 544 /* Advance through heaps, marking them empty, |
545 till we get to the one that B is in. */ | |
482 while (heap) | 546 while (heap) |
483 { | 547 { |
484 if (heap->bloc_start <= b->data && b->data <= heap->end) | 548 if (heap->bloc_start <= b->data && b->data <= heap->end) |
485 break; | 549 break; |
486 heap = heap->next; | 550 heap = heap->next; |
551 /* We know HEAP is not null now, | |
552 because there has to be space for bloc B. */ | |
553 heap->first_bloc = NIL_BLOC; | |
554 heap->last_bloc = NIL_BLOC; | |
487 heap->free = heap->bloc_start; | 555 heap->free = heap->bloc_start; |
488 } | 556 } |
489 /* In each heap, record the end of the last bloc in it. */ | 557 |
558 /* Update HEAP's status for bloc B. */ | |
490 heap->free = b->data + b->size; | 559 heap->free = b->data + b->size; |
560 heap->last_bloc = b; | |
561 if (heap->first_bloc == NIL_BLOC) | |
562 heap->first_bloc = b; | |
563 | |
564 /* Record that B is in HEAP. */ | |
565 b->heap = heap; | |
491 } | 566 } |
492 | 567 |
493 /* If there are any remaining heaps and no blocs left, | 568 /* If there are any remaining heaps and no blocs left, |
494 update the `free' slot assuming they contain no blocs. */ | 569 mark those heaps as empty. */ |
495 heap = heap->next; | 570 heap = heap->next; |
496 while (heap) | 571 while (heap) |
497 { | 572 { |
573 heap->first_bloc = NIL_BLOC; | |
574 heap->last_bloc = NIL_BLOC; | |
498 heap->free = heap->bloc_start; | 575 heap->free = heap->bloc_start; |
499 heap = heap->next; | 576 heap = heap->next; |
500 } | 577 } |
501 } | 578 } |
502 | 579 |
503 /* Resize BLOC to SIZE bytes. This relocates the blocs | 580 /* Resize BLOC to SIZE bytes. This relocates the blocs |
504 that come after BLOC in memory. */ | 581 that come after BLOC in memory. */ |
505 | 582 |
506 static int | 583 static int |
507 resize_bloc (bloc, size) | 584 resize_bloc (bloc, size) |
562 safe_bcopy (b->data, b->new_data, b->size); | 639 safe_bcopy (b->data, b->new_data, b->size); |
563 *b->variable = b->data = b->new_data; | 640 *b->variable = b->data = b->new_data; |
564 } | 641 } |
565 } | 642 } |
566 | 643 |
567 update_heap_free_pointers (bloc, heap); | 644 update_heap_bloc_correspondence (bloc, heap); |
568 | 645 |
569 break_value = (last_bloc ? last_bloc->data + last_bloc->size | 646 break_value = (last_bloc ? last_bloc->data + last_bloc->size |
570 : first_heap->bloc_start); | 647 : first_heap->bloc_start); |
571 return 1; | 648 return 1; |
572 } | 649 } |
573 | 650 |
574 /* Free BLOC from the chain of blocs, relocating any blocs above it. | 651 /* Free BLOC from the chain of blocs, relocating any blocs above it. |
575 This may return space to the system. */ | 652 This may return space to the system. */ |
576 | 653 |
577 static void | 654 static void |
578 free_bloc (bloc) | 655 free_bloc (bloc) |
579 bloc_ptr bloc; | 656 bloc_ptr bloc; |
580 { | 657 { |
658 heap_ptr heap = bloc->heap; | |
659 | |
581 resize_bloc (bloc, 0); | 660 resize_bloc (bloc, 0); |
582 | 661 |
583 if (bloc == first_bloc && bloc == last_bloc) | 662 if (bloc == first_bloc && bloc == last_bloc) |
584 { | 663 { |
585 first_bloc = last_bloc = NIL_BLOC; | 664 first_bloc = last_bloc = NIL_BLOC; |
596 } | 675 } |
597 else | 676 else |
598 { | 677 { |
599 bloc->next->prev = bloc->prev; | 678 bloc->next->prev = bloc->prev; |
600 bloc->prev->next = bloc->next; | 679 bloc->prev->next = bloc->next; |
680 } | |
681 | |
682 /* Update the records of which blocs are in HEAP. */ | |
683 if (heap->first_bloc == bloc) | |
684 { | |
685 if (bloc->next->heap == heap) | |
686 heap->first_bloc = bloc->next; | |
687 else | |
688 heap->first_bloc = heap->last_bloc = NIL_BLOC; | |
689 } | |
690 if (heap->last_bloc == bloc) | |
691 { | |
692 if (bloc->prev->heap == heap) | |
693 heap->last_bloc = bloc->prev; | |
694 else | |
695 heap->first_bloc = heap->last_bloc = NIL_BLOC; | |
601 } | 696 } |
602 | 697 |
603 relinquish (); | 698 relinquish (); |
604 free (bloc); | 699 free (bloc); |
605 } | 700 } |
686 *b->variable = b->data = b->new_data; | 781 *b->variable = b->data = b->new_data; |
687 } | 782 } |
688 | 783 |
689 h->bloc_start = new_bloc_start; | 784 h->bloc_start = new_bloc_start; |
690 | 785 |
691 update_heap_free_pointers (first_bloc, h); | 786 update_heap_bloc_correspondence (first_bloc, h); |
692 } | 787 } |
693 | 788 |
694 if (h != first_heap) | 789 if (h != first_heap) |
695 { | 790 { |
696 /* Give up managing heaps below the one the new | 791 /* Give up managing heaps below the one the new |
698 first_heap->prev = NIL_HEAP; | 793 first_heap->prev = NIL_HEAP; |
699 first_heap->next = h->next; | 794 first_heap->next = h->next; |
700 first_heap->start = h->start; | 795 first_heap->start = h->start; |
701 first_heap->end = h->end; | 796 first_heap->end = h->end; |
702 first_heap->free = h->free; | 797 first_heap->free = h->free; |
798 first_heap->first_bloc = h->first_bloc; | |
799 first_heap->last_bloc = h->last_bloc; | |
703 first_heap->bloc_start = h->bloc_start; | 800 first_heap->bloc_start = h->bloc_start; |
704 | 801 |
705 if (first_heap->next) | 802 if (first_heap->next) |
706 first_heap->next->prev = first_heap; | 803 first_heap->next->prev = first_heap; |
707 else | 804 else |
719 | 816 |
720 if (r_alloc_freeze_level == 0 && excess > 2 * extra_bytes) | 817 if (r_alloc_freeze_level == 0 && excess > 2 * extra_bytes) |
721 { | 818 { |
722 excess -= extra_bytes; | 819 excess -= extra_bytes; |
723 first_heap->bloc_start | 820 first_heap->bloc_start |
724 = (POINTER) MEM_ROUNDUP ((char *)first_heap->bloc_start - excess); | 821 = (POINTER) MEM_ROUNDUP ((char *)first_heap->bloc_start - excess); |
725 | 822 |
726 relocate_blocs (first_bloc, first_heap, first_heap->bloc_start); | 823 relocate_blocs (first_bloc, first_heap, first_heap->bloc_start); |
727 | 824 |
728 for (b = first_bloc; b != NIL_BLOC; b = b->next) | 825 for (b = first_bloc; b != NIL_BLOC; b = b->next) |
729 { | 826 { |
738 first_heap->start = (POINTER) ((char *)virtual_break_value + size); | 835 first_heap->start = (POINTER) ((char *)virtual_break_value + size); |
739 } | 836 } |
740 } | 837 } |
741 | 838 |
742 virtual_break_value = (POINTER) ((char *)address + size); | 839 virtual_break_value = (POINTER) ((char *)address + size); |
743 break_value = last_bloc ? last_bloc->data + last_bloc->size | 840 break_value = (last_bloc |
744 : first_heap->bloc_start; | 841 ? last_bloc->data + last_bloc->size |
842 : first_heap->bloc_start); | |
745 if (size < 0) | 843 if (size < 0) |
746 relinquish (); | 844 relinquish (); |
747 | 845 |
748 return address; | 846 return address; |
749 } | 847 } |