00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #if _EM_WSIZE == _EM_PSIZE
00044 typedef unsigned int size_type;
00045 #elif _EM_LSIZE == _EM_PSIZE
00046 typedef unsigned long size_type;
00047 #else
00048 #error funny pointer size
00049 #endif
00050 #include <stdlib.h>
00051 #include <stdio.h>
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 # undef NON_STANDARD
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 # define ASSERT
00078
00079
00080
00081
00082
00083
00084 # define CHECK
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 # undef EXTERN
00098
00099
00100
00101
00102 # define STORE
00103
00104
00105
00106
00107 # undef SYSTEM
00108
00109
00110
00111 #define ALIGNMENT 8
00112
00113 #define LOG_MIN_SIZE 3
00114 #define LOG_MAX_SIZE 24
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 #define MIN_SIZE (1<<LOG_MIN_SIZE)
00133 #define MAX_FLIST (LOG_MAX_SIZE - LOG_MIN_SIZE)
00134 #if ALIGNMENT != 4 && ALIGNMENT != 8 && ALIGNMENT != 16
00135 #error ALIGNMENT must be 4, 8 or 16
00136 #elif ALIGNMENT % _EM_LSIZE
00137
00138 #error ALIGNMENT must be a multiple of the long size
00139 #endif
00140 #define align(n) (((n) + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1))
00141
00142 union _inf {
00143 union _inf *ptr;
00144 size_type ui;
00145 };
00146
00147 typedef union _inf mallink;
00148 #define MAL_NULL ((mallink *)0)
00149
00150
00151
00152
00153 #ifndef NON_STANDARD
00154 #define OFF_SET 0
00155 #else
00156 #define OFF_SET 2
00157 #endif
00158
00159 #define _log_prev_of(ml) ((ml)[-1+OFF_SET]).ptr
00160 #define _log_next_of(ml) ((ml)[-2+OFF_SET]).ptr
00161 #define _phys_prev_of(ml) ((ml)[-3+OFF_SET]).ptr
00162 #define _this_size_of(ml) ((ml)[-4+OFF_SET]).ui
00163 #ifndef CHECK
00164 #define N_WORDS 4
00165 #else
00166 #define _checksum_of(ml) ((ml)[-5+OFF_SET]).ui
00167 #define _print_of(ml) ((ml)[-6+OFF_SET]).ui
00168 #define _mark_of(ml) ((ml)[-7+OFF_SET]).ui
00169 #define N_WORDS 7
00170 #endif
00171
00172 #define mallink_size() (size_t) \
00173 align((N_WORDS - OFF_SET) * sizeof (mallink))
00174
00175 #ifdef CHECK
00176 #define set_mark(ml,e) (_mark_of(ml) = (e))
00177 #define mark_of(ml) (_mark_of(ml))
00178
00179 #define set_checksum(ml,e) (_checksum_of(ml) = (e))
00180 #define checksum_of(ml) (_checksum_of(ml))
00181 #endif
00182
00183 #define new_mallink(ml) ( _log_prev_of(ml) = 0, \
00184 _log_next_of(ml) = 0, \
00185 _phys_prev_of(ml) = 0, \
00186 _this_size_of(ml) = 0 )
00187
00188 #define block_of_mallink(ml) ((void *)ml)
00189 #define mallink_of_block(addr) ((mallink *)addr)
00190
00191 #define public extern
00192 #define publicdata extern
00193 #ifndef EXTERN
00194 #define private static
00195 #define privatedata static
00196 #else
00197 #define private extern
00198 #define privatedata
00199 #endif
00200
00201 #ifdef ASSERT
00202 private m_assert(const char *fn, int ln);
00203 #define assert(b) (!(b) ? m_assert(__FILE__, __LINE__) : 0)
00204 #else
00205 #define assert(b) 0
00206 #endif
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 #ifdef CHECK
00221
00222 private check_mallinks(const char *s), calc_checksum(mallink *ml);
00223 private check_work_empty(const char *s);
00224 private started_working_on(mallink *ml), stopped_working_on(mallink *ml);
00225
00226 #else
00227
00228 #define maldump(n) abort()
00229 #define check_mallinks(s) 0
00230 #define calc_checksum(ml) 0
00231 #define started_working_on(ml) 0
00232 #define stopped_working_on(ml) 0
00233 #define check_work_empty(s) 0
00234
00235 #endif
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 private link_free_chunk(mallink *ml), unlink_free_chunk(mallink *ml);
00254 private mallink *first_present(int class);
00255 private mallink *search_free_list(int class, size_t n);
00256
00257 #ifdef STORE
00258 #define in_store(ml) ((size_type)_phys_prev_of(ml) & STORE_BIT)
00259 #define set_store(ml, e) \
00260 (_phys_prev_of(ml) = (mallink *) \
00261 ((e) ? (size_type) _phys_prev_of(ml) | STORE_BIT : \
00262 (size_type) _phys_prev_of(ml) & ~STORE_BIT))
00263 #endif
00264 #define set_log_prev(ml,e) (_log_prev_of(ml) = (e))
00265 #define log_prev_of(ml) (mallink *) (_log_prev_of(ml))
00266
00267 #define set_log_next(ml,e) (_log_next_of(ml) = (e))
00268 #define log_next_of(ml) (mallink *) (_log_next_of(ml))
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 privatedata mallink *ml_last;
00287
00288 #define FREE_BIT 01
00289 #ifdef STORE
00290 #define STORE_BIT 02
00291 #define BITS (FREE_BIT|STORE_BIT)
00292 #else
00293 #define BITS (FREE_BIT)
00294 #endif
00295
00296 #define __bits(ml) ((int)((size_type)_phys_prev_of(ml) & BITS))
00297 #define __free_of(ml) ((int)((size_type)_phys_prev_of(ml) & FREE_BIT))
00298 #define __phys_prev_of(ml) ((mallink *)((size_type)_phys_prev_of(ml) & ~BITS))
00299 #define prev_size_of(ml) ((char *)(ml) - \
00300 (char *)__phys_prev_of(ml) - \
00301 mallink_size() \
00302 )
00303 #define set_phys_prev(ml,e) \
00304 (_phys_prev_of(ml) = (mallink *) ((char *)e + __bits(ml)))
00305
00306 #ifdef CHECK
00307 private Error(const char *fmt, const char *s, mallink *ml);
00308 #define phys_prev_of(ml) (mallink *) \
00309 (first_mallink(ml) ? \
00310 (char *)Error("phys_prev_of first_mallink %p", "somewhere", ml) : \
00311 (char *)__phys_prev_of(ml) \
00312 )
00313 #else
00314 #define phys_prev_of(ml) __phys_prev_of(ml)
00315 #endif
00316
00317 #define first_mallink(ml) (int) (__phys_prev_of(ml) == 0)
00318 #define last_mallink(ml) (int) ((ml) == ml_last)
00319
00320
00321
00322
00323
00324
00325
00326
00327 #define size_of(ml) (_this_size_of(ml) - mallink_size())
00328 #define set_phys_next(ml,e) \
00329 (_this_size_of(ml) = (size_type)((char *)(e) - (char *)(ml)))
00330 #define phys_next_of(ml) (mallink *) ((char *)(ml) + _this_size_of(ml))
00331
00332 #define set_free(ml,e) \
00333 (_phys_prev_of(ml) = (mallink *) \
00334 ((e) ? (size_type) _phys_prev_of(ml) | FREE_BIT : \
00335 (size_type) _phys_prev_of(ml) & ~FREE_BIT))
00336 #define free_of(ml) (__free_of(ml))
00337
00338 #define coalesce_forw(ml,nxt) ( unlink_free_chunk(nxt), \
00339 combine_chunks((ml), (nxt)))
00340
00341 #define coalesce_backw(ml,prv) ( unlink_free_chunk(prv), \
00342 stopped_working_on(ml), \
00343 combine_chunks((prv), (ml)), \
00344 started_working_on(prv))
00345
00346 #ifdef CHECK
00347 #define set_print(ml,e) (_print_of(ml) = (e))
00348 #define print_of(ml) (_print_of(ml))
00349 #endif
00350
00351 private truncate(mallink *ml, size_t size);
00352 private combine_chunks(register mallink *ml1, register mallink *ml2);
00353 private mallink *create_chunk(void *p, size_t n);
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 #include <limits.h>
00368 #include <stdlib.h>
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 #ifdef SYSTEM
00380 #include <system.h>
00381 #define SBRK sys_break
00382 #else
00383 #define SBRK _sbrk
00384 #define ILL_BREAK (void *)(-1)
00385 #endif
00386 extern void *SBRK(int incr);
00387 #ifdef STORE
00388 #define MAX_STORE 32
00389 private do_free(mallink *ml), sell_out(void);
00390 privatedata mallink *store[MAX_STORE];
00391 #endif
00392
00393 void *privious_free= (void *)-1;
00394 void *
00395 malloc(register size_t n)
00396 {check_mallinks("malloc entry");{
00397 register mallink *ml;
00398 register int min_class;
00399 void *tmp;
00400
00401 { static int reent= 0; if (!reent) { reent++; printf("malloc\n"); reent--; } }
00402 privious_free= (void *)-1;
00403 if (n == 0) {
00404 return NULL;
00405 }
00406 if (n < MIN_SIZE) n = align(MIN_SIZE); else n = align(n);
00407 #ifdef STORE
00408 if (n <= MAX_STORE*MIN_SIZE) {
00409
00410 register mallink **stp = &store[(n >> LOG_MIN_SIZE) - 1];
00411
00412 if (ml = *stp) {
00413 *stp = log_next_of(ml);
00414 set_store(ml, 0);
00415 check_mallinks("malloc fast exit");
00416 assert(! in_store(ml));
00417 tmp= block_of_mallink(ml);
00418 { static int reent= 0; if (!reent) { reent++; printf("= 0x%x\n", tmp);reent--; } }
00419 return tmp;
00420 }
00421 }
00422 #endif
00423
00424 check_work_empty("malloc, entry");
00425
00426
00427
00428
00429 {
00430
00431
00432 register size_t n1 = n;
00433
00434 assert(n1 < (1L << LOG_MAX_SIZE));
00435 min_class = 0;
00436
00437 do {
00438 n1 >>= 1;
00439 min_class++;
00440 } while (n1 >= MIN_SIZE);
00441 }
00442
00443 if (min_class >= MAX_FLIST)
00444 return NULL;
00445 ml = first_present(min_class);
00446 if (ml == MAL_NULL) {
00447
00448 register void *p;
00449 #define GRABSIZE 4096
00450 register size_t req =
00451 ((MIN_SIZE<<min_class)+ mallink_size() + GRABSIZE - 1) &
00452 ~(GRABSIZE-1);
00453
00454 if (!ml_last) {
00455
00456
00457 p = SBRK(0);
00458 SBRK((int) (align((size_type) p) - (size_type) p));
00459 }
00460
00461
00462 if ((int) req < 0) {
00463 p = ILL_BREAK;
00464 } else {
00465 p = SBRK((int)req);
00466 }
00467 if (p == ILL_BREAK) {
00468 req = n + mallink_size();
00469 if ((int) req >= 0) p = SBRK((int)req);
00470 }
00471 if (p == ILL_BREAK) {
00472
00473
00474
00475
00476 #ifdef STORE
00477 sell_out();
00478 ml = first_present(min_class);
00479 if (ml == MAL_NULL) {
00480 #endif
00481
00482
00483
00484
00485 ml = search_free_list(min_class - 1, n);
00486 if (!ml)
00487 return NULL;
00488 started_working_on(ml);
00489 unlink_free_chunk(ml);
00490 check_mallinks("suitable_chunk, forced");
00491 #ifdef STORE
00492 }
00493 else started_working_on(ml);
00494 #endif
00495 }
00496 else {
00497 assert((size_type)p == align((size_type)p));
00498 ml = create_chunk(p, req);
00499 }
00500 check_mallinks("suitable_chunk, extended");
00501 }
00502 else started_working_on(ml);
00503
00504
00505 set_free(ml, 0);
00506 calc_checksum(ml);
00507 check_mallinks("suitable_chunk, removed");
00508 n += mallink_size();
00509 if (n + MIN_SIZE <= size_of(ml)) {
00510 truncate(ml, n);
00511 }
00512 stopped_working_on(ml);
00513 check_mallinks("malloc exit");
00514 check_work_empty("malloc exit");
00515 #ifdef STORE
00516 assert(! in_store(ml));
00517 #endif
00518 tmp= block_of_mallink(ml);
00519 { static int reent= 0; if (!reent) { reent++; printf("= 0x%x\n", tmp);reent--; } }
00520 return tmp;
00521 }}
00522
00523 void
00524 free(void *addr)
00525 {check_mallinks("free entry");{
00526 register mallink *ml;
00527
00528 printf("free 0x%x\n", addr);
00529 if (privious_free == addr) { fflush(stdout); fflush(stderr); abort(); }
00530 privious_free= addr;
00531 if (addr == NULL) {
00532 check_mallinks("free(0) very fast exit");
00533 return;
00534 }
00535
00536 ml = mallink_of_block(addr);
00537 #ifdef STORE
00538
00539 if (free_of(ml) || in_store(ml))
00540 return;
00541 if (size_of(ml) <= MAX_STORE*MIN_SIZE) {
00542
00543 mallink **stp = &store[(size_of(ml) >> LOG_MIN_SIZE) - 1];
00544
00545 set_log_next(ml, *stp);
00546 *stp = ml;
00547 set_store(ml, 1);
00548 calc_checksum(ml);
00549 check_mallinks("free fast exit");
00550 }
00551 else {
00552 do_free(ml);
00553 check_mallinks("free exit");
00554 }
00555 }}
00556
00557 private
00558 do_free(register mallink *ml)
00559 {{
00560 #endif
00561
00562 #ifndef STORE
00563 if (free_of(ml)) return;
00564 #endif
00565 started_working_on(ml);
00566 set_free(ml, 1);
00567 calc_checksum(ml);
00568 if (! last_mallink(ml)) {
00569 register mallink *next = phys_next_of(ml);
00570
00571 if (free_of(next)) coalesce_forw(ml, next);
00572 }
00573
00574 if (! first_mallink(ml)) {
00575 register mallink *prev = phys_prev_of(ml);
00576
00577 if (free_of(prev)) {
00578 coalesce_backw(ml, prev);
00579 ml = prev;
00580 }
00581 }
00582 link_free_chunk(ml);
00583 stopped_working_on(ml);
00584 check_work_empty("free");
00585
00586
00587 switch (0) {
00588 case MIN_SIZE < OFF_SET * sizeof(mallink): break;
00589 case 1: break;
00590
00591
00592
00593
00594
00595 }
00596 switch(0) {
00597 case sizeof(void *) != sizeof(size_type): break;
00598 case 1: break;
00599
00600
00601
00602
00603 }
00604 }}
00605
00606 void *
00607 realloc(void *addr, register size_t n)
00608 {check_mallinks("realloc entry");{
00609 register mallink *ml, *ph_next;
00610 register size_type size;
00611
00612 printf("realloc 0x%x, %d\n", addr, n);
00613 if (addr == NULL) {
00614
00615
00616
00617 return malloc(n);
00618 }
00619 if (n == 0) {
00620 free(addr);
00621 return NULL;
00622 }
00623 ml = mallink_of_block(addr);
00624 if (n < MIN_SIZE) n = align(MIN_SIZE); else n = align(n);
00625 #ifdef STORE
00626 if (in_store(ml)) {
00627 register mallink *stp = store[(size_of(ml) >> LOG_MIN_SIZE) - 1];
00628 mallink *stp1 = NULL;
00629 while (ml != stp) {
00630 stp1 = stp;
00631 stp = log_next_of(stp);
00632 }
00633 stp = log_next_of(stp);
00634 if (! stp1) store[(size_of(ml) >> LOG_MIN_SIZE) - 1] = stp;
00635 else set_log_next(stp1, stp);
00636 set_store(ml, 0);
00637 calc_checksum(ml);
00638 }
00639 #endif
00640 if (free_of(ml)) {
00641 unlink_free_chunk(ml);
00642 set_free(ml, 0);
00643 }
00644 started_working_on(ml);
00645 size = size_of(ml);
00646 if (
00647 n > size &&
00648 !last_mallink(ml) &&
00649 (ph_next = phys_next_of(ml), free_of(ph_next)) &&
00650 n <= size + mallink_size() + size_of(ph_next)
00651 ) {
00652
00653 unlink_free_chunk(ph_next);
00654 combine_chunks(ml, ph_next);
00655 size = size_of(ml);
00656 check_mallinks("realloc, combining");
00657 }
00658 if (n > size) {
00659 void *new;
00660 register char *l1, *l2 = addr;
00661
00662 stopped_working_on(ml);
00663 if (!(new = l1 = malloc(n))) return NULL;
00664 while (size--) *l1++ = *l2++;
00665 free(addr);
00666 check_work_empty("mv_realloc");
00667 #ifdef STORE
00668 assert(! in_store(mallink_of_block(new)));
00669 #endif
00670 return new;
00671 }
00672
00673 n += mallink_size();
00674 if (n + MIN_SIZE <= size_of(ml)) {
00675 truncate(ml, n);
00676 }
00677 stopped_working_on(ml);
00678 check_mallinks("realloc exit");
00679 check_work_empty("realloc");
00680 #ifdef STORE
00681 assert(! in_store(ml));
00682 #endif
00683 return addr;
00684 }}
00685
00686 void *
00687 calloc(size_t nmemb, size_t size)
00688 {check_mallinks("calloc entry");{
00689 long *l1, *l2;
00690 size_t n;
00691
00692 printf("calloc\n");
00693 if (size == 0) return NULL;
00694 if (nmemb == 0) return NULL;
00695
00696
00697
00698
00699 if (sizeof(size_t) == sizeof(int)) {
00700 if (UINT_MAX / size < nmemb) return NULL;
00701 } else if (sizeof(size_t) == sizeof(long)) {
00702 if (ULONG_MAX / size < nmemb) return NULL;
00703 } else return NULL;
00704
00705 n = size * nmemb;
00706 if (n < MIN_SIZE) n = align(MIN_SIZE); else n = align(n);
00707 if (n >= (1L << LOG_MAX_SIZE)) return NULL;
00708 l1 = (long *) malloc(n);
00709 l2 = l1 + (n / sizeof(long));
00710 while ( l2 != l1 ) *--l2 = 0;
00711 check_mallinks("calloc exit");
00712 check_work_empty("calloc exit");
00713 return (void *)l1;
00714 }}
00715
00716
00717 #ifdef STORE
00718 private
00719 sell_out(void) {
00720
00721
00722 register mallink **stp;
00723
00724 for (stp = &store[0]; stp < &store[MAX_STORE]; stp++) {
00725 register mallink *ml = *stp;
00726
00727 while (ml) {
00728 *stp = log_next_of(ml);
00729 set_store(ml, 0);
00730 do_free(ml);
00731 ml = *stp;
00732 }
00733 }
00734
00735 }
00736 #endif
00737
00738 #ifdef ASSERT
00739 private
00740 m_assert(const char *fn, int ln)
00741 {
00742 char ch;
00743
00744 while (*fn)
00745 write(2, fn++, 1);
00746 write(2, ": malloc assert failed in line ", 31);
00747 ch = (ln / 100) + '0'; write(2, &ch, 1); ln %= 100;
00748 ch = (ln / 10) + '0'; write(2, &ch, 1); ln %= 10;
00749 ch = (ln / 1) + '0'; write(2, &ch, 1);
00750 write(2, "\n", 1);
00751 maldump(1);
00752 }
00753 #endif
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772 privatedata mallink *free_list[MAX_FLIST];
00773
00774 private
00775 link_free_chunk(register mallink *ml)
00776 {
00777
00778
00779
00780 register mallink **mlp = &free_list[-1];
00781 register size_type n = size_of(ml);
00782 register mallink *ml1;
00783
00784 assert(n < (1L << LOG_MAX_SIZE));
00785
00786 do {
00787 n >>= 1;
00788 mlp++;
00789 }
00790 while (n >= MIN_SIZE);
00791
00792 ml1 = *mlp;
00793 set_log_prev(ml, MAL_NULL);
00794 set_log_next(ml, ml1);
00795 calc_checksum(ml);
00796 if (ml1) {
00797
00798
00799 set_log_prev(ml1, ml);
00800 calc_checksum(ml1);
00801 }
00802 *mlp = ml;
00803 }
00804
00805 private
00806 unlink_free_chunk(register mallink *ml)
00807 {
00808
00809
00810
00811 register mallink *next = log_next_of(ml);
00812 register mallink *prev = log_prev_of(ml);
00813
00814 if (!prev) {
00815
00816 register mallink **mlp = &free_list[-1];
00817 register size_type n = size_of(ml);
00818
00819 assert(n < (1L << LOG_MAX_SIZE));
00820 do {
00821 n >>= 1;
00822 mlp++;
00823 }
00824 while (n >= MIN_SIZE);
00825 *mlp = next;
00826 }
00827 else {
00828 set_log_next(prev, next);
00829 calc_checksum(prev);
00830 }
00831 if (next) {
00832 set_log_prev(next, prev);
00833 calc_checksum(next);
00834 }
00835 }
00836
00837 private mallink *
00838 search_free_list(int class, size_t n)
00839 {
00840
00841
00842
00843
00844 register mallink *ml;
00845
00846 for (ml = free_list[class]; ml; ml = log_next_of(ml))
00847 if (size_of(ml) >= n)
00848 return ml;
00849 return MAL_NULL;
00850 }
00851
00852 private mallink *
00853 first_present(int class)
00854 {
00855
00856
00857
00858
00859
00860
00861 register mallink **mlp, *ml;
00862
00863 for (mlp = &free_list[class]; mlp < &free_list[MAX_FLIST]; mlp++) {
00864 if ((ml = *mlp) != MAL_NULL) {
00865
00866 *mlp = log_next_of(ml);
00867 if (*mlp) {
00868
00869
00870 set_log_prev(*mlp, MAL_NULL);
00871 calc_checksum(*mlp);
00872 }
00873 return ml;
00874 }
00875 }
00876 return MAL_NULL;
00877 }
00878
00879 #ifdef CHECK
00880 private mallink *
00881 free_list_entry(int i) {
00882
00883
00884 return free_list[i];
00885 }
00886 #endif
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900 #include <stdlib.h>
00901
00902
00903
00904
00905
00906 private mallink *
00907 create_chunk(void *p, size_t n)
00908 {
00909
00910
00911
00912
00913
00914 register mallink *ml;
00915
00916
00917
00918
00919
00920 register mallink *last = ml_last;
00921
00922 assert(!last || p == (char *)phys_next_of(last) - mallink_size());
00923 ml = (mallink *)((char *)p + mallink_size());
00924 new_mallink(ml);
00925 started_working_on(ml);
00926 set_free(ml, 1);
00927 set_phys_prev(ml, last);
00928 ml_last = ml;
00929
00930 set_phys_next(ml, (mallink *)((char *)ml + n));
00931 calc_checksum(ml);
00932 assert(size_of(ml) + mallink_size() == n);
00933 if (last && free_of(last)) {
00934 coalesce_backw(ml, last);
00935 ml = last;
00936 }
00937 check_mallinks("create_chunk, phys. linked");
00938 return ml;
00939 }
00940
00941 private
00942 truncate(register mallink *ml, size_t size)
00943 {
00944
00945
00946
00947
00948 register mallink *new = (mallink *)((char *)ml + size);
00949 register mallink *ph_next = phys_next_of(ml);
00950
00951 new_mallink(new);
00952 set_free(new, 1);
00953 set_phys_prev(new, ml);
00954 set_phys_next(new, ph_next);
00955 calc_checksum(new);
00956 if (! last_mallink(ml)) {
00957 set_phys_prev(ph_next, new);
00958 calc_checksum(ph_next);
00959 if (free_of(ph_next)) coalesce_forw(new, ph_next);
00960 }
00961 else ml_last = new;
00962 set_phys_next(ml, new);
00963 calc_checksum(ml);
00964
00965 started_working_on(new);
00966 link_free_chunk(new);
00967 stopped_working_on(new);
00968 check_mallinks("truncate");
00969 }
00970
00971 private
00972 combine_chunks(register mallink *ml1, register mallink *ml2)
00973 {
00974
00975
00976 register mallink *ml3 = phys_next_of(ml2);
00977
00978 set_phys_next(ml1, ml3);
00979 calc_checksum(ml1);
00980 if (!last_mallink(ml2)) {
00981 set_phys_prev(ml3, ml1);
00982 calc_checksum(ml3);
00983 }
00984 if (ml_last == ml2)
00985 ml_last = ml1;
00986 }
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000 #include <stdio.h>
01001
01002 #ifdef CHECK
01003
01004
01005 private acquire_malout(void), check_ml_last(const char *s);
01006 private dump_all_mallinks(void), dump_free_list(int i);
01007 private dump_mallink(const char *s, mallink *ml), print_loop(mallink *ml);
01008 private working_on(mallink *ml);
01009 private size_type checksum(mallink *ml);
01010 static FILE *malout;
01011
01012 private mallink *free_list_entry(int i);
01013
01014 #define for_free_list(i,p) \
01015 for (p = free_list_entry(i); p; p = log_next_of(p))
01016
01017 #define for_all_mallinks(ml) \
01018 for (ml = ml_last; ml; \
01019 ml = first_mallink(ml) ? MAL_NULL : phys_prev_of(ml))
01020
01021
01022
01023 static int pr_cnt = 0;
01024
01025 maldump(int n) {
01026
01027
01028
01029 static int dumping = 0;
01030 int i;
01031
01032 if (dumping)
01033 return;
01034 dumping++;
01035 acquire_malout();
01036 fprintf(malout,
01037 ">>>>>>>>>>>>>>>> DUMP OF ALL MALLINKS <<<<<<<<<<<<<<<<");
01038 fprintf(malout, " ml_last = %p\n", ml_last);
01039 if (++pr_cnt == 100) pr_cnt = 0;
01040 dump_all_mallinks();
01041 fprintf(malout,
01042 ">>>>>>>>>>>>>>>> DUMP OF FREE_LISTS <<<<<<<<<<<<<<<<\n");
01043 if (++pr_cnt == 100) pr_cnt = 0;
01044 for (i = 0; i < MAX_FLIST; i++)
01045 dump_free_list(i);
01046 fprintf(malout,
01047 ">>>>>>>>>>>>>>>> END OF DUMP <<<<<<<<<<<<<<<<\n");
01048 fclose(malout);
01049 dumping--;
01050 if (n)
01051 abort();
01052 }
01053
01054 private
01055 acquire_malout(void) {
01056 static char buf[BUFSIZ];
01057
01058 if (!malout) {
01059 malout = freopen("mal.out", "w", stderr);
01060 setbuf(malout, buf);
01061 }
01062 }
01063
01064 private
01065 dump_all_mallinks(void) {
01066 mallink *ml;
01067
01068 for_all_mallinks (ml) {
01069 if (print_loop(ml))
01070 return;
01071 dump_mallink((char *)0, ml);
01072 }
01073 }
01074
01075 private
01076 dump_free_list(int i) {
01077 mallink *ml = free_list_entry(i);
01078
01079 if (!ml)
01080 return;
01081 fprintf(malout, "%2d: ", i);
01082 for_free_list(i, ml) {
01083 if (print_loop(ml))
01084 return;
01085 fprintf(malout, "%p ", ml);
01086 }
01087 fprintf(malout, "<\n");
01088 }
01089
01090 private int
01091 print_loop(mallink *ml) {
01092 if (print_of(ml) == pr_cnt) {
01093 fprintf(malout, "... PRINT LOOP\n");
01094 return 1;
01095 }
01096 set_print(ml, pr_cnt);
01097 return 0;
01098 }
01099
01100 private
01101 dump_mallink(const char *s, mallink *ml) {
01102 acquire_malout();
01103 if (s)
01104 fprintf(malout, "%s: ", s);
01105 fprintf(malout, "@: %p;", ml);
01106 if (ml && checksum_of(ml) != checksum(ml))
01107 fprintf(malout, ">>>> CORRUPTED <<<<");
01108 if (!ml) {
01109 fprintf(malout, "\n");
01110 return;
01111 }
01112 if (free_of(ml)) {
01113 fprintf(malout, " l_p: %p;", _log_prev_of(ml));
01114 fprintf(malout, " l_n: %p;", _log_next_of(ml));
01115 }
01116 fprintf(malout, " p_s: %p;", prev_size_of(ml));
01117 fprintf(malout, " t_s: %p;", _this_size_of(ml));
01118 fprintf(malout, " sz: %lu;", (unsigned long) size_of(ml));
01119 fprintf(malout, " fr: %d;", free_of(ml));
01120 fprintf(malout, "\n");
01121 }
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132 #define IN_ML_LAST 93
01133 #define IN_FREE_LIST 57
01134 #define CLEAR 21
01135
01136 #define VRIJ 1
01137 #define BEZET 2
01138
01139 private
01140 check_mallinks(const char *s) {
01141 mallink *ml;
01142 size_type size;
01143 int i;
01144 char stat;
01145
01146 check_ml_last(s);
01147 stat = BEZET;
01148 for_all_mallinks(ml) {
01149 if (checksum_of(ml) != checksum(ml))
01150 Error("mallink info at %p corrupted", s, ml);
01151 if (working_on(ml)) {
01152 stat = BEZET;
01153 continue;
01154 }
01155 if ( !last_mallink(ml) &&
01156 phys_prev_of(phys_next_of(ml)) != ml
01157 )
01158 Error("upward chain bad at %p", s, ml);
01159 if ( !first_mallink(ml) &&
01160 phys_next_of(phys_prev_of(ml)) != ml
01161 )
01162 Error("downward chain bad at %p", s, ml);
01163 if (free_of(ml)) {
01164 if (stat == VRIJ)
01165 Error("free mallink at %p follows free mallink",
01166 s, ml);
01167 stat = VRIJ;
01168 }
01169 else
01170 stat = BEZET;
01171 set_mark(ml, IN_ML_LAST);
01172 }
01173
01174 for (i = 0, size = MIN_SIZE; i < MAX_FLIST; i++, size *= 2) {
01175 for_free_list(i, ml) {
01176 if (working_on(ml))
01177 continue;
01178 if (!free_of(ml))
01179 Error("occupied mallink %p occurs in free_list", s, ml);
01180 switch (mark_of(ml)) {
01181 case IN_ML_LAST:
01182 set_mark(ml, IN_FREE_LIST);
01183 break;
01184 case IN_FREE_LIST:
01185 Error("mallink %p occurs in 2 free_lists",
01186 s, ml);
01187 default:
01188 Error("unknown mallink %p in free_list",
01189 s, ml);
01190 }
01191 if (size_of(ml) < size)
01192 Error("size of mallink %p too small", s, ml);
01193 if (size_of(ml) >= 2*size)
01194 Error("size of mallink %p too large", s, ml);
01195 }
01196 }
01197 for_all_mallinks (ml) {
01198 if (working_on(ml))
01199 continue;
01200 if (free_of(ml) && mark_of(ml) != IN_FREE_LIST)
01201 Error("free mallink %p is in no free_list", s, ml);
01202 set_mark(ml, CLEAR);
01203 }
01204 }
01205
01206 private
01207 check_ml_last(const char *s) {
01208 if (ml_last && _this_size_of(ml_last) == 0)
01209 Error("size of ml_last == 0, at %p", s, ml_last);
01210 }
01211
01212 private size_type
01213 checksum(mallink *ml) {
01214 size_type sum = 0;
01215
01216 if (free_of(ml)) {
01217 sum += (size_type)_log_prev_of(ml);
01218 sum += (size_type)_log_next_of(ml);
01219 }
01220 sum += (size_type)prev_size_of(ml);
01221 sum += (size_type)_this_size_of(ml);
01222 return sum;
01223 }
01224
01225 private
01226 calc_checksum(mallink *ml) {
01227 set_checksum(ml, checksum(ml));
01228 }
01229
01230 #define N_COLOUR 10
01231 static mallink *off_colour[N_COLOUR];
01232
01233 private
01234 started_working_on(mallink *ml) {
01235 int i;
01236
01237 for (i = 0; i < N_COLOUR; i++)
01238 if (off_colour[i] == MAL_NULL) {
01239 off_colour[i] = ml;
01240 return;
01241 }
01242 Error("out of off_colour array at %p", "started_working_on", ml);
01243 }
01244
01245 private
01246 stopped_working_on(mallink *ml) {
01247 int i;
01248
01249 for (i = 0; i < N_COLOUR; i++)
01250 if (off_colour[i] == ml) {
01251 off_colour[i] = MAL_NULL;
01252 return;
01253 }
01254 Error("stopped working on mallink %p", "stopped_working_on", ml);
01255 }
01256
01257 private int
01258 working_on(mallink *ml) {
01259 int i;
01260
01261 for (i = 0; i < N_COLOUR; i++)
01262 if (off_colour[i] == ml)
01263 return 1;
01264 return 0;
01265 }
01266
01267 private
01268 check_work_empty(const char *s) {
01269 int i;
01270 int cnt = 0;
01271
01272 for (i = 0; i < N_COLOUR; i++)
01273 if (off_colour[i] != MAL_NULL)
01274 cnt++;
01275 if (cnt != 0)
01276 Error("off_colour not empty", s, MAL_NULL);
01277 }
01278
01279 private int
01280 Error(const char *fmt, const char *s, mallink *ml) {
01281 static int already_called = 0;
01282
01283 if (already_called++) return 0;
01284 setbuf(stdout, (char *) 0);
01285 printf("%s: ", s);
01286 printf(fmt, (long)ml);
01287 printf("\n");
01288 acquire_malout();
01289 fprintf(malout, "%s: ", s);
01290 fprintf(malout, fmt, (long)ml);
01291 fprintf(malout, "\n");
01292 fflush(stdout);
01293 maldump(1);
01294 return 0;
01295 }
01296
01297 #endif
01298