00001
00002
00003
00004
00005
00006
00007
00008 #ifndef _NLIBC_BSDMALLOC_H_
00009 #define _NLIBC_BSDMALLOC_H_
00010
00011 #include <nlibc.h>
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
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #include <unistd.h>
00060
00061 #if !defined(__cflow_processed) || defined(_uses_getpagesize_bsdmalloc_h)
00062 inline int getpagesize() {
00063 return 0x200;
00064 }
00065 #endif // _uses_getpagesize_bsdmalloc_h
00066
00067 static void morecore();
00068 static int findbucket();
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #define overhead __malloc_overhead
00083 #define pagebucket __malloc_pagebucket
00084 #define pagesz __malloc_pagesz
00085 #define nmalloc __malloc_nmalloc
00086 #define realloc_srchlen __malloc_realloc_srchlen
00087
00088 union overhead {
00089 union overhead *ov_next;
00090 struct {
00091 unsigned ovu_magic;
00092 unsigned ovu_index;
00093 #ifdef RCHECK
00094 unsigned ovu_rmagic;
00095 unsigned ovu_size;
00096 #endif // RCHECK
00097 } ovu;
00098 #define ov_magic ovu.ovu_magic
00099 #define ov_index ovu.ovu_index
00100 #define ov_rmagic ovu.ovu_rmagic
00101 #define ov_size ovu.ovu_size
00102 };
00103
00104 #define MAGIC 0xef
00105 #define RMAGIC 0x5555
00106
00107 #ifdef RCHECK
00108 #define RSLOP sizeof (unsigned)
00109 #else
00110 #define RSLOP 0
00111 #endif // RCHECK
00112
00113
00114
00115
00116
00117
00118
00119 #define NBUCKETS 30
00120 static union overhead *nextf[NBUCKETS];
00121
00122 static int pagebucket = 0;
00123 static int pagesz = 0;
00124
00125 #ifdef MSTATS
00126
00127
00128
00129
00130 static unsigned nmalloc[NBUCKETS];
00131 #include <stdio.h>
00132 #endif // MSTATS
00133
00134 #if defined(DEBUG) || defined(RCHECK)
00135 #define MALLOC_ASSERT(p) if (!(p)) botch("p")
00136 #include <stdio.h>
00137
00138 #ifndef __HAS_MAIN
00139
00140 #else
00141 #if !defined(__cflow_processed) || defined(_uses_botch_bsdmalloc_h)
00142 static void botch(char *s)
00143 {
00144 fprintf(stderr, "\r\nassertion botched: %s\r\n", s);
00145 abort();
00146 }
00147 #endif // _uses_botch_bsdmalloc_h
00148 #endif // Has Main
00149
00150 #else
00151 #define MALLOC_ASSERT(p)
00152 #endif // DEBUG && RCHECK
00153
00154 #define w_sizeof(OBJ) (sizeof_aligned(OBJ)>>4)
00155
00156 #define malloc(BYTES) wmalloc(((BYTES)+15)>>4)
00157
00158 #ifndef __HAS_MAIN
00159 extern void * wmalloc(size_t nwords);
00160 #else
00161 #if !defined(__cflow_processed) || defined(_uses_wmalloc_bsdmalloc_h)
00162 void * wmalloc(size_t nwords)
00163 {
00164 register union overhead *op;
00165 register int bucket, n;
00166 register unsigned amt;
00167
00168
00169
00170
00171
00172
00173 if (pagesz == 0) {
00174 pagesz = n = getpagesize();
00175 op = (union overhead *)w_sbrk(w_sizeof(union overhead));
00176 n = n - w_sizeof(*op) - ((int)op & (n - 1));
00177 if (n < 0)
00178 n += pagesz;
00179 if (n) {
00180 if (w_sbrk(n) == (char *)-1)
00181 return (NULL);
00182 }
00183 bucket = 0;
00184 amt = 8;
00185 while (pagesz > amt) {
00186 amt <<= 1;
00187 bucket++;
00188 }
00189 pagebucket = bucket;
00190 memset(nextf, 0, NBUCKETS * sizeof_aligned(union overhead *));
00191 #ifdef MSTATS
00192 memset(nmalloc, 0, NBUCKETS * sizeof_aligned(unsigned));
00193 #endif // MSTATS
00194 }
00195
00196
00197
00198
00199
00200 if (nwords <= (n = pagesz - w_sizeof(*op) - RSLOP)) {
00201 #ifndef RCHECK
00202 amt = 8;
00203 bucket = 0;
00204 #else
00205 amt = 16;
00206 bucket = 1;
00207 #endif // RCHECK
00208 n = -(int)(w_sizeof(*op) + RSLOP);
00209 } else {
00210 amt = pagesz;
00211 bucket = pagebucket;
00212 }
00213 while (nwords > amt + n) {
00214 amt <<= 1;
00215 if (amt == 0)
00216 return (NULL);
00217 bucket++;
00218 }
00219
00220
00221
00222
00223 if ((op = nextf[bucket]) == NULL) {
00224 morecore(bucket);
00225 if ((op = nextf[bucket]) == NULL)
00226 return (NULL);
00227 }
00228
00229 nextf[bucket] = op->ov_next;
00230 op->ov_magic = MAGIC;
00231 op->ov_index = bucket;
00232 #ifdef MSTATS
00233 nmalloc[bucket]++;
00234 #endif // MSTATS
00235 #ifdef RCHECK
00236
00237
00238
00239
00240 op->ov_size = (nwords + RSLOP - 1) & ~(RSLOP - 1);
00241 op->ov_rmagic = RMAGIC;
00242 *(unsigned *)((unsigned)(op + 1) + op->ov_size) = RMAGIC;
00243 #endif // RCHECK
00244 return ((char *)(op + 1));
00245 }
00246 #endif // _uses_wmalloc_bsdmalloc_h
00247 #endif // Has Main
00248
00249
00250
00251
00252 #ifndef __HAS_MAIN
00253 #else
00254 #if !defined(__cflow_processed) || defined(_uses_morecore_bsdmalloc_h)
00255 static void morecore(int bucket)
00256 {
00257 register union overhead *op;
00258 register int sz;
00259 int amt;
00260 int nblks;
00261
00262 sz = 1 << (bucket + 3);
00263 #ifdef DEBUG
00264 MALLOC_ASSERT(sz > 0);
00265 #else
00266 if (sz <= 0)
00267 return;
00268 #endif // DEBUG
00269 if (sz < pagesz) {
00270 amt = pagesz;
00271 nblks = amt / sz;
00272 } else {
00273 amt = sz + pagesz;
00274 nblks = 1;
00275 }
00276 op = (union overhead *)w_sbrk(amt);
00277
00278 if ((int)op == -1)
00279 return;
00280
00281
00282
00283
00284 nextf[bucket] = op;
00285 while (--nblks > 0) {
00286 op->ov_next = (union overhead *)((unsigned)op + sz);
00287 op = (union overhead *)((unsigned)op + sz);
00288 }
00289 op->ov_next = NULL;
00290 }
00291 #endif // _uses_morecore_bsdmalloc_h
00292 #endif // Has Main
00293
00294
00295 #ifndef __HAS_MAIN
00296 extern void free(void *cp);
00297 #else
00298 #if !defined(__cflow_processed) || defined(_uses_free_bsdmalloc_h)
00299 void free(void *cp)
00300 {
00301 register int size;
00302 register union overhead *op;
00303
00304 if (cp == NULL)
00305 return;
00306 op = (union overhead *)((unsigned)cp - w_sizeof (union overhead));
00307 #ifdef DEBUG
00308 MALLOC_ASSERT(op->ov_magic == MAGIC);
00309 #else
00310 if (op->ov_magic != MAGIC)
00311 return;
00312 #endif // DEBUG
00313 #ifdef RCHECK
00314 MALLOC_ASSERT(op->ov_rmagic == RMAGIC);
00315 MALLOC_ASSERT(*(unsigned *)((unsigned)(op + 1) + op->ov_size) == RMAGIC);
00316 #endif // RCHECK
00317 size = op->ov_index;
00318 MALLOC_ASSERT(size < NBUCKETS);
00319 op->ov_next = nextf[size];
00320 nextf[size] = op;
00321 #ifdef MSTATS
00322 nmalloc[size]--;
00323 #endif // MSTATS
00324 }
00325 #endif // _uses_free_bsdmalloc_h
00326 #endif // Has Main
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 int realloc_srchlen = 4;
00340
00341 #define realloc(PTR, NBYTES) wrealloc(PTR,((NBYTES)+15)>>4)
00342
00343 #ifndef __HAS_MAIN
00344 extern void *wrealloc(void *cp, size_t nwords);
00345 #else
00346 #if !defined(__cflow_processed) || defined(_uses_wrealloc_bsdmalloc_h)
00347 void *wrealloc(void *cp, size_t nwords)
00348 {
00349 register unsigned onb;
00350 register int i;
00351 union overhead *op;
00352 char *res;
00353 int was_alloced = 0;
00354
00355 if (cp == NULL)
00356 return (wmalloc(nwords));
00357 op = (union overhead *)((unsigned)cp - w_sizeof (union overhead));
00358 if (op->ov_magic == MAGIC) {
00359 was_alloced++;
00360 i = op->ov_index;
00361 } else {
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 if ((i = findbucket(op, 1)) < 0 &&
00377 (i = findbucket(op, realloc_srchlen)) < 0)
00378 i = NBUCKETS;
00379 }
00380 onb = 1 << (i + 3);
00381 if (onb < pagesz)
00382 onb -= w_sizeof (*op) + RSLOP;
00383 else
00384 onb += pagesz - w_sizeof (*op) - RSLOP;
00385
00386 if (was_alloced) {
00387 if (i) {
00388 i = 1 << (i + 2);
00389 if (i < pagesz)
00390 i -= w_sizeof (*op) + RSLOP;
00391 else
00392 i += pagesz - w_sizeof (*op) - RSLOP;
00393 }
00394 if (nwords <= onb && nwords > i) {
00395 #ifdef RCHECK
00396 op->ov_size = (nwords + RSLOP - 1) & ~(RSLOP - 1);
00397 *(unsigned *)((unsigned)(op + 1) + op->ov_size) = RMAGIC;
00398 #endif // RCHECK
00399 return(cp);
00400 } else
00401 free(cp);
00402 }
00403 if ((res = wmalloc(nwords)) == NULL)
00404 return (NULL);
00405 if (cp != res)
00406 wmemcpy(res, cp, (nwords < onb) ? nwords : onb);
00407 return (res);
00408 }
00409 #endif // _uses_realloc_bsdmalloc_h
00410 #endif // Has Main
00411
00419 #define calloc(N,BYTESIZE) wcalloc((N),((BYTESIZE+15)>>4))
00420
00428 #if !defined(__cflow_processed) || defined(_uses_wcalloc_bsdmalloc_h)
00429 inline void *wcalloc(size_t nmemb, size_t words)
00430 {
00431 void *p = wmalloc( nmemb * words );
00432 if( p ) {
00433 wmemset(p,0,nmemb * words);
00434 }
00435 return p;
00436 }
00437 #endif // _uses_wcalloc_bsdmalloc_h
00438
00439
00440
00441
00442
00443
00444
00445 #ifndef __HAS_MAIN
00446 #else
00447 #if !defined(__cflow_processed) || defined(_uses_findbucket_bsdmalloc_h)
00448 static int findbucket( union overhead *freep, int srchlen)
00449 {
00450 register union overhead *p;
00451 register int i, j;
00452
00453 for (i = 0; i < NBUCKETS; i++) {
00454 j = 0;
00455 for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
00456 if (p == freep)
00457 return (i);
00458 j++;
00459 }
00460 }
00461 return (-1);
00462 }
00463 #endif // _uses_findbucket_bsdmalloc_h
00464 #endif // Has Main
00465
00466 #ifdef MSTATS
00467
00468
00469
00470
00471
00472
00473
00474
00475 #ifndef __HAS_MAIN
00476 extern int mstats(char *s);
00477 #else
00478 #if !defined(__cflow_processed) || defined(_uses_mstats_bsdmalloc_h)
00479 int mstats(char *s)
00480 {
00481 register int i, j;
00482 register union overhead *p;
00483 int totfree = 0,
00484 totused = 0;
00485
00486 fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s);
00487 for (i = 0; i < NBUCKETS; i++) {
00488 for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
00489 ;
00490 fprintf(stderr, " %d", j);
00491 totfree += j * (1 << (i + 3));
00492 }
00493 fprintf(stderr, "\nused:\t");
00494 for (i = 0; i < NBUCKETS; i++) {
00495 fprintf(stderr, " %d", nmalloc[i]);
00496 totused += nmalloc[i] * (1 << (i + 3));
00497 }
00498 fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n",
00499 totused, totfree);
00500 }
00501 #endif // _uses_mstats_bsdmalloc_h
00502 #endif // Has Main
00503
00504 #endif // MSTATS
00505
00506 #undef overhead
00507 #undef pagebucket
00508 #undef pagesz
00509 #undef nmalloc
00510 #undef realloc_srchlen
00511
00512 #endif // _BSDMALLOC_H_
00513