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 }