Mercurial > emacs
comparison src/alloc.c @ 32692:0343fe9ef3ac
(toplevel) [SYSTEM_MALLOC || DOUG_LEA_MALLOC]: Undef
GC_MALLOC_CHECK.
(toplevel) [GC_MARK_STACK || GC_MALLOC_CHECK]: Move mem_node
structure definition and related variabled to the top of the file.
Include this code when GC_MALLOC_CHECK is defined.
(lisp_malloc, lisp_free) [GC_MALLOC_CHECK]: Don't
register/unregister allocated region.
(emacs_blocked_free) [GC_MALLOC_CHECK]: Check if freeing something
which isn't allocated.
(emacs_blocked_malloc) [GC_MALLOC_CHECK]: Check if returning
something which is already in use.
(emacs_blocked_realloc) [GC_MALLOC_CHECK]: Likewise.
(mem_insert) [GC_MALLOC_CHECK]: Use _malloc_internal.
(mem_delete) [GC_MALLOC_CHECK]: Use _free_internal.
(init_alloc_once) [GC_MALLOC_CHECK]: Call mem_init.
| author | Gerd Moellmann <gerd@gnu.org> |
|---|---|
| date | Fri, 20 Oct 2000 15:55:14 +0000 |
| parents | 350e0378e6f9 |
| children | 52f570fdddce |
comparison
equal
deleted
inserted
replaced
| 32691:14c36c7829ff | 32692:0343fe9ef3ac |
|---|---|
| 25 /* Note that this declares bzero on OSF/1. How dumb. */ | 25 /* Note that this declares bzero on OSF/1. How dumb. */ |
| 26 | 26 |
| 27 #include <signal.h> | 27 #include <signal.h> |
| 28 | 28 |
| 29 /* Define this temporarily to hunt a bug. If defined, the size of | 29 /* Define this temporarily to hunt a bug. If defined, the size of |
| 30 strings is always recorded in sdata structures so that it can be | 30 strings is redundantly recorded in sdata structures so that it can |
| 31 compared to the sizes recorded in Lisp strings. */ | 31 be compared to the sizes recorded in Lisp strings. */ |
| 32 | 32 |
| 33 #define GC_CHECK_STRING_BYTES 1 | 33 #define GC_CHECK_STRING_BYTES 1 |
| 34 | |
| 35 /* GC_MALLOC_CHECK defined means perform validity checks of malloc'd | |
| 36 memory. Can do this only if using gmalloc.c. */ | |
| 37 | |
| 38 #if defined SYSTEM_MALLOC || defined DOUG_LEA_MALLOC | |
| 39 #undef GC_MALLOC_CHECK | |
| 40 #endif | |
| 34 | 41 |
| 35 /* This file is part of the core Lisp implementation, and thus must | 42 /* This file is part of the core Lisp implementation, and thus must |
| 36 deal with the real data structures. If the Lisp implementation is | 43 deal with the real data structures. If the Lisp implementation is |
| 37 replaced, this file likely will not be used. */ | 44 replaced, this file likely will not be used. */ |
| 38 | 45 |
| 276 MEM_TYPE_SYMBOL, | 283 MEM_TYPE_SYMBOL, |
| 277 MEM_TYPE_FLOAT, | 284 MEM_TYPE_FLOAT, |
| 278 MEM_TYPE_VECTOR | 285 MEM_TYPE_VECTOR |
| 279 }; | 286 }; |
| 280 | 287 |
| 281 #if GC_MARK_STACK | 288 #if GC_MARK_STACK || defined GC_MALLOC_CHECK |
| 282 | 289 |
| 283 #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | 290 #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
| 284 #include <stdio.h> /* For fprintf. */ | 291 #include <stdio.h> /* For fprintf. */ |
| 285 #endif | 292 #endif |
| 286 | 293 |
| 287 /* A unique object in pure space used to make some Lisp objects | 294 /* A unique object in pure space used to make some Lisp objects |
| 288 on free lists recognizable in O(1). */ | 295 on free lists recognizable in O(1). */ |
| 289 | 296 |
| 290 Lisp_Object Vdead; | 297 Lisp_Object Vdead; |
| 291 | 298 |
| 292 struct mem_node; | 299 #ifdef GC_MALLOC_CHECK |
| 300 | |
| 301 enum mem_type allocated_mem_type; | |
| 302 int dont_register_blocks; | |
| 303 | |
| 304 #endif /* GC_MALLOC_CHECK */ | |
| 305 | |
| 306 /* A node in the red-black tree describing allocated memory containing | |
| 307 Lisp data. Each such block is recorded with its start and end | |
| 308 address when it is allocated, and removed from the tree when it | |
| 309 is freed. | |
| 310 | |
| 311 A red-black tree is a balanced binary tree with the following | |
| 312 properties: | |
| 313 | |
| 314 1. Every node is either red or black. | |
| 315 2. Every leaf is black. | |
| 316 3. If a node is red, then both of its children are black. | |
| 317 4. Every simple path from a node to a descendant leaf contains | |
| 318 the same number of black nodes. | |
| 319 5. The root is always black. | |
| 320 | |
| 321 When nodes are inserted into the tree, or deleted from the tree, | |
| 322 the tree is "fixed" so that these properties are always true. | |
| 323 | |
| 324 A red-black tree with N internal nodes has height at most 2 | |
| 325 log(N+1). Searches, insertions and deletions are done in O(log N). | |
| 326 Please see a text book about data structures for a detailed | |
| 327 description of red-black trees. Any book worth its salt should | |
| 328 describe them. */ | |
| 329 | |
| 330 struct mem_node | |
| 331 { | |
| 332 struct mem_node *left, *right, *parent; | |
| 333 | |
| 334 /* Start and end of allocated region. */ | |
| 335 void *start, *end; | |
| 336 | |
| 337 /* Node color. */ | |
| 338 enum {MEM_BLACK, MEM_RED} color; | |
| 339 | |
| 340 /* Memory type. */ | |
| 341 enum mem_type type; | |
| 342 }; | |
| 343 | |
| 344 /* Base address of stack. Set in main. */ | |
| 345 | |
| 346 Lisp_Object *stack_base; | |
| 347 | |
| 348 /* Root of the tree describing allocated Lisp memory. */ | |
| 349 | |
| 350 static struct mem_node *mem_root; | |
| 351 | |
| 352 /* Sentinel node of the tree. */ | |
| 353 | |
| 354 static struct mem_node mem_z; | |
| 355 #define MEM_NIL &mem_z | |
| 356 | |
| 293 static POINTER_TYPE *lisp_malloc P_ ((size_t, enum mem_type)); | 357 static POINTER_TYPE *lisp_malloc P_ ((size_t, enum mem_type)); |
| 294 static void lisp_free P_ ((POINTER_TYPE *)); | 358 static void lisp_free P_ ((POINTER_TYPE *)); |
| 295 static void mark_stack P_ ((void)); | 359 static void mark_stack P_ ((void)); |
| 296 static void init_stack P_ ((Lisp_Object *)); | 360 static void init_stack P_ ((Lisp_Object *)); |
| 297 static int live_vector_p P_ ((struct mem_node *, void *)); | 361 static int live_vector_p P_ ((struct mem_node *, void *)); |
| 314 | 378 |
| 315 #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS | 379 #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS |
| 316 static void check_gcpros P_ ((void)); | 380 static void check_gcpros P_ ((void)); |
| 317 #endif | 381 #endif |
| 318 | 382 |
| 319 #endif /* GC_MARK_STACK != 0 */ | 383 #endif /* GC_MARK_STACK || GC_MALLOC_CHECK */ |
| 320 | 384 |
| 321 /* Recording what needs to be marked for gc. */ | 385 /* Recording what needs to be marked for gc. */ |
| 322 | 386 |
| 323 struct gcpro *gcprolist; | 387 struct gcpro *gcprolist; |
| 324 | 388 |
| 513 enum mem_type type; | 577 enum mem_type type; |
| 514 { | 578 { |
| 515 register void *val; | 579 register void *val; |
| 516 | 580 |
| 517 BLOCK_INPUT; | 581 BLOCK_INPUT; |
| 582 | |
| 583 #ifdef GC_MALLOC_CHECK | |
| 584 allocated_mem_type = type; | |
| 585 #endif | |
| 586 | |
| 518 val = (void *) malloc (nbytes); | 587 val = (void *) malloc (nbytes); |
| 519 | 588 |
| 520 #if GC_MARK_STACK | 589 #if GC_MARK_STACK && !defined GC_MALLOC_CHECK |
| 521 if (val && type != MEM_TYPE_NON_LISP) | 590 if (val && type != MEM_TYPE_NON_LISP) |
| 522 mem_insert (val, (char *) val + nbytes, type); | 591 mem_insert (val, (char *) val + nbytes, type); |
| 523 #endif | 592 #endif |
| 524 | 593 |
| 525 UNBLOCK_INPUT; | 594 UNBLOCK_INPUT; |
| 526 if (!val && nbytes) | 595 if (!val && nbytes) |
| 527 memory_full (); | 596 memory_full (); |
| 528 return val; | 597 return val; |
| 529 } | 598 } |
| 547 lisp_free (block) | 616 lisp_free (block) |
| 548 POINTER_TYPE *block; | 617 POINTER_TYPE *block; |
| 549 { | 618 { |
| 550 BLOCK_INPUT; | 619 BLOCK_INPUT; |
| 551 free (block); | 620 free (block); |
| 552 #if GC_MARK_STACK | 621 #if GC_MARK_STACK && !defined GC_MALLOC_CHECK |
| 553 mem_delete (mem_find (block)); | 622 mem_delete (mem_find (block)); |
| 554 #endif | 623 #endif |
| 555 UNBLOCK_INPUT; | 624 UNBLOCK_INPUT; |
| 556 } | 625 } |
| 557 | 626 |
| 582 static void | 651 static void |
| 583 emacs_blocked_free (ptr) | 652 emacs_blocked_free (ptr) |
| 584 void *ptr; | 653 void *ptr; |
| 585 { | 654 { |
| 586 BLOCK_INPUT; | 655 BLOCK_INPUT; |
| 656 | |
| 657 #ifdef GC_MALLOC_CHECK | |
| 658 { | |
| 659 struct mem_node *m; | |
| 660 | |
| 661 m = mem_find (ptr); | |
| 662 if (m == MEM_NIL || m->start != ptr) | |
| 663 { | |
| 664 fprintf (stderr, | |
| 665 "Freeing `%p' which wasn't allocated with malloc\n", ptr); | |
| 666 abort (); | |
| 667 } | |
| 668 else | |
| 669 { | |
| 670 /* fprintf (stderr, "free %p...%p (%p)\n", m->start, m->end, ptr); */ | |
| 671 mem_delete (m); | |
| 672 } | |
| 673 } | |
| 674 #endif /* GC_MALLOC_CHECK */ | |
| 675 | |
| 587 __free_hook = old_free_hook; | 676 __free_hook = old_free_hook; |
| 588 free (ptr); | 677 free (ptr); |
| 678 | |
| 589 /* If we released our reserve (due to running out of memory), | 679 /* If we released our reserve (due to running out of memory), |
| 590 and we have a fair amount free once again, | 680 and we have a fair amount free once again, |
| 591 try to set aside another reserve in case we run out once more. */ | 681 try to set aside another reserve in case we run out once more. */ |
| 592 if (spare_memory == 0 | 682 if (spare_memory == 0 |
| 593 /* Verify there is enough space that even with the malloc | 683 /* Verify there is enough space that even with the malloc |
| 630 #ifdef DOUG_LEA_MALLOC | 720 #ifdef DOUG_LEA_MALLOC |
| 631 mallopt (M_TOP_PAD, malloc_hysteresis * 4096); | 721 mallopt (M_TOP_PAD, malloc_hysteresis * 4096); |
| 632 #else | 722 #else |
| 633 __malloc_extra_blocks = malloc_hysteresis; | 723 __malloc_extra_blocks = malloc_hysteresis; |
| 634 #endif | 724 #endif |
| 725 | |
| 635 value = (void *) malloc (size); | 726 value = (void *) malloc (size); |
| 727 | |
| 728 #ifdef GC_MALLOC_CHECK | |
| 729 { | |
| 730 struct mem_node *m = mem_find (value); | |
| 731 if (m != MEM_NIL) | |
| 732 { | |
| 733 fprintf (stderr, "Malloc returned %p which is already in use\n", | |
| 734 value); | |
| 735 fprintf (stderr, "Region in use is %p...%p, %u bytes, type %d\n", | |
| 736 m->start, m->end, (char *) m->end - (char *) m->start, | |
| 737 m->type); | |
| 738 abort (); | |
| 739 } | |
| 740 | |
| 741 if (!dont_register_blocks) | |
| 742 { | |
| 743 mem_insert (value, (char *) value + max (1, size), allocated_mem_type); | |
| 744 allocated_mem_type = MEM_TYPE_NON_LISP; | |
| 745 } | |
| 746 } | |
| 747 #endif /* GC_MALLOC_CHECK */ | |
| 748 | |
| 636 __malloc_hook = emacs_blocked_malloc; | 749 __malloc_hook = emacs_blocked_malloc; |
| 637 UNBLOCK_INPUT; | 750 UNBLOCK_INPUT; |
| 638 | 751 |
| 752 /* fprintf (stderr, "%p malloc\n", value); */ | |
| 639 return value; | 753 return value; |
| 640 } | 754 } |
| 641 | 755 |
| 642 | 756 |
| 643 /* This function is the realloc hook that Emacs uses. */ | 757 /* This function is the realloc hook that Emacs uses. */ |
| 649 { | 763 { |
| 650 void *value; | 764 void *value; |
| 651 | 765 |
| 652 BLOCK_INPUT; | 766 BLOCK_INPUT; |
| 653 __realloc_hook = old_realloc_hook; | 767 __realloc_hook = old_realloc_hook; |
| 768 | |
| 769 #ifdef GC_MALLOC_CHECK | |
| 770 if (ptr) | |
| 771 { | |
| 772 struct mem_node *m = mem_find (ptr); | |
| 773 if (m == MEM_NIL || m->start != ptr) | |
| 774 { | |
| 775 fprintf (stderr, | |
| 776 "Realloc of %p which wasn't allocated with malloc\n", | |
| 777 ptr); | |
| 778 abort (); | |
| 779 } | |
| 780 | |
| 781 mem_delete (m); | |
| 782 } | |
| 783 | |
| 784 /* fprintf (stderr, "%p -> realloc\n", ptr); */ | |
| 785 | |
| 786 /* Prevent malloc from registering blocks. */ | |
| 787 dont_register_blocks = 1; | |
| 788 #endif /* GC_MALLOC_CHECK */ | |
| 789 | |
| 654 value = (void *) realloc (ptr, size); | 790 value = (void *) realloc (ptr, size); |
| 791 | |
| 792 #ifdef GC_MALLOC_CHECK | |
| 793 dont_register_blocks = 0; | |
| 794 | |
| 795 { | |
| 796 struct mem_node *m = mem_find (value); | |
| 797 if (m != MEM_NIL) | |
| 798 { | |
| 799 fprintf (stderr, "Realloc returns memory that is already in use\n"); | |
| 800 abort (); | |
| 801 } | |
| 802 | |
| 803 /* Can't handle zero size regions in the red-black tree. */ | |
| 804 mem_insert (value, (char *) value + max (size, 1), MEM_TYPE_NON_LISP); | |
| 805 } | |
| 806 | |
| 807 /* fprintf (stderr, "%p <- realloc\n", value); */ | |
| 808 #endif /* GC_MALLOC_CHECK */ | |
| 809 | |
| 655 __realloc_hook = emacs_blocked_realloc; | 810 __realloc_hook = emacs_blocked_realloc; |
| 656 UNBLOCK_INPUT; | 811 UNBLOCK_INPUT; |
| 657 | 812 |
| 658 return value; | 813 return value; |
| 659 } | 814 } |
| 2373 | 2528 |
| 2374 /************************************************************************ | 2529 /************************************************************************ |
| 2375 C Stack Marking | 2530 C Stack Marking |
| 2376 ************************************************************************/ | 2531 ************************************************************************/ |
| 2377 | 2532 |
| 2378 #if GC_MARK_STACK | |
| 2379 | |
| 2380 | |
| 2381 /* Base address of stack. Set in main. */ | |
| 2382 | |
| 2383 Lisp_Object *stack_base; | |
| 2384 | |
| 2385 /* A node in the red-black tree describing allocated memory containing | |
| 2386 Lisp data. Each such block is recorded with its start and end | |
| 2387 address when it is allocated, and removed from the tree when it | |
| 2388 is freed. | |
| 2389 | |
| 2390 A red-black tree is a balanced binary tree with the following | |
| 2391 properties: | |
| 2392 | |
| 2393 1. Every node is either red or black. | |
| 2394 2. Every leaf is black. | |
| 2395 3. If a node is red, then both of its children are black. | |
| 2396 4. Every simple path from a node to a descendant leaf contains | |
| 2397 the same number of black nodes. | |
| 2398 5. The root is always black. | |
| 2399 | |
| 2400 When nodes are inserted into the tree, or deleted from the tree, | |
| 2401 the tree is "fixed" so that these properties are always true. | |
| 2402 | |
| 2403 A red-black tree with N internal nodes has height at most 2 | |
| 2404 log(N+1). Searches, insertions and deletions are done in O(log N). | |
| 2405 Please see a text book about data structures for a detailed | |
| 2406 description of red-black trees. Any book worth its salt should | |
| 2407 describe them. */ | |
| 2408 | |
| 2409 struct mem_node | |
| 2410 { | |
| 2411 struct mem_node *left, *right, *parent; | |
| 2412 | |
| 2413 /* Start and end of allocated region. */ | |
| 2414 void *start, *end; | |
| 2415 | |
| 2416 /* Node color. */ | |
| 2417 enum {MEM_BLACK, MEM_RED} color; | |
| 2418 | |
| 2419 /* Memory type. */ | |
| 2420 enum mem_type type; | |
| 2421 }; | |
| 2422 | |
| 2423 /* Root of the tree describing allocated Lisp memory. */ | |
| 2424 | |
| 2425 static struct mem_node *mem_root; | |
| 2426 | |
| 2427 /* Sentinel node of the tree. */ | |
| 2428 | |
| 2429 static struct mem_node mem_z; | |
| 2430 #define MEM_NIL &mem_z | |
| 2431 | |
| 2432 | |
| 2433 /* Initialize this part of alloc.c. */ | 2533 /* Initialize this part of alloc.c. */ |
| 2434 | 2534 |
| 2435 static void | 2535 static void |
| 2436 mem_init () | 2536 mem_init () |
| 2437 { | 2537 { |
| 2499 } | 2599 } |
| 2500 | 2600 |
| 2501 #endif /* GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS */ | 2601 #endif /* GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS */ |
| 2502 | 2602 |
| 2503 /* Create a new node. */ | 2603 /* Create a new node. */ |
| 2604 #ifdef GC_MALLOC_CHECK | |
| 2605 x = (struct mem_node *) _malloc_internal (sizeof *x); | |
| 2606 if (x == NULL) | |
| 2607 abort (); | |
| 2608 #else | |
| 2504 x = (struct mem_node *) xmalloc (sizeof *x); | 2609 x = (struct mem_node *) xmalloc (sizeof *x); |
| 2610 #endif | |
| 2505 x->start = start; | 2611 x->start = start; |
| 2506 x->end = end; | 2612 x->end = end; |
| 2507 x->type = type; | 2613 x->type = type; |
| 2508 x->parent = parent; | 2614 x->parent = parent; |
| 2509 x->left = x->right = MEM_NIL; | 2615 x->left = x->right = MEM_NIL; |
| 2520 else | 2626 else |
| 2521 mem_root = x; | 2627 mem_root = x; |
| 2522 | 2628 |
| 2523 /* Re-establish red-black tree properties. */ | 2629 /* Re-establish red-black tree properties. */ |
| 2524 mem_insert_fixup (x); | 2630 mem_insert_fixup (x); |
| 2631 | |
| 2525 return x; | 2632 return x; |
| 2526 } | 2633 } |
| 2527 | 2634 |
| 2528 | 2635 |
| 2529 /* Re-establish the red-black properties of the tree, and thereby | 2636 /* Re-establish the red-black properties of the tree, and thereby |
| 2719 z->type = y->type; | 2826 z->type = y->type; |
| 2720 } | 2827 } |
| 2721 | 2828 |
| 2722 if (y->color == MEM_BLACK) | 2829 if (y->color == MEM_BLACK) |
| 2723 mem_delete_fixup (x); | 2830 mem_delete_fixup (x); |
| 2831 | |
| 2832 #ifdef GC_MALLOC_CHECK | |
| 2833 _free_internal (y); | |
| 2834 #else | |
| 2724 xfree (y); | 2835 xfree (y); |
| 2836 #endif | |
| 2725 } | 2837 } |
| 2726 | 2838 |
| 2727 | 2839 |
| 2728 /* Re-establish the red-black properties of the tree, after a | 2840 /* Re-establish the red-black properties of the tree, after a |
| 2729 deletion. */ | 2841 deletion. */ |
| 2959 return (m->type == MEM_TYPE_BUFFER | 3071 return (m->type == MEM_TYPE_BUFFER |
| 2960 && p == m->start | 3072 && p == m->start |
| 2961 && !NILP (((struct buffer *) p)->name)); | 3073 && !NILP (((struct buffer *) p)->name)); |
| 2962 } | 3074 } |
| 2963 | 3075 |
| 3076 #if GC_MARK_STACK | |
| 2964 | 3077 |
| 2965 #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | 3078 #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
| 2966 | 3079 |
| 2967 /* Array of objects that are kept alive because the C stack contains | 3080 /* Array of objects that are kept alive because the C stack contains |
| 2968 a pattern that looks like a reference to them . */ | 3081 a pattern that looks like a reference to them . */ |
| 4905 void | 5018 void |
| 4906 init_alloc_once () | 5019 init_alloc_once () |
| 4907 { | 5020 { |
| 4908 /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */ | 5021 /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */ |
| 4909 pure_bytes_used = 0; | 5022 pure_bytes_used = 0; |
| 4910 #if GC_MARK_STACK | 5023 #if GC_MARK_STACK || defined GC_MALLOC_CHECK |
| 4911 mem_init (); | 5024 mem_init (); |
| 4912 Vdead = make_pure_string ("DEAD", 4, 4, 0); | 5025 Vdead = make_pure_string ("DEAD", 4, 4, 0); |
| 4913 #endif | 5026 #endif |
| 4914 #ifdef HAVE_SHM | 5027 #ifdef HAVE_SHM |
| 4915 pure_size = PURESIZE; | 5028 pure_size = PURESIZE; |
