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
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 #ifndef lint
00075 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/pmalloc.c,v 14.12 2006/09/16 02:04:25 lbutler Exp $ (BRL)";
00076 #endif
00077
00078 #include "common.h"
00079
00080 #include <stdio.h>
00081 #include <string.h>
00082 #include <math.h>
00083 #include "machine.h"
00084 #include "bu.h"
00085 #include "vmath.h"
00086 #include "bn.h"
00087 #include "raytrace.h"
00088
00089
00090
00091
00092
00093
00094
00095 #define NALIGN sizeof(double)
00096
00097
00098 typedef long Size;
00099
00100
00101
00102
00103
00104
00105
00106
00107 #ifndef CURBRK
00108 #define CURBRK sbrk(0)
00109 #else
00110 # if CURBRK == curbrk
00111 extern Size curbrk;
00112 # endif
00113 #endif
00114
00115
00116
00117
00118
00119
00120
00121
00122 #ifndef BRK
00123 #define BRK(x) brk(x)
00124 #endif
00125
00126
00127
00128 #define MAGIC_FREE 0x548a934c
00129 #define MAGIC_BUSY 0xc139569a
00130
00131 #if 0
00132 #define RT_PM_NBUCKETS 18
00133
00134 struct rt_qelem {
00135 struct rt_qelem *q_forw;
00136 struct rt_qelem *q_back;
00137 };
00138
00139 #endif
00140 struct overhead {
00141 struct rt_qelem ov_adj;
00142 struct rt_qelem ov_buk;
00143 long ov_magic;
00144 Size ov_length;
00145 };
00146
00147
00148
00149
00150 #define TOADJ(p) ((struct rt_qelem *)(p))
00151 #define FROMADJ(p) ((struct overhead *)(p))
00152 #define FROMBUK(p) ((struct overhead *)( (char *)p - sizeof(struct rt_qelem)))
00153 #define TOBUK(p) ((struct rt_qelem *)( (char *)p + sizeof(struct rt_qelem)))
00154
00155 extern char endfree;
00156
00157 static Size mlindx();
00158 static void rt_pm_insque(), rt_pm_remque();
00159 static void mllcerr();
00160 static void mlfree_end();
00161
00162 extern void (*mlabort)();
00163
00164 #define debug 1
00165 #ifdef debug
00166 # define ASSERT(p,q) if (!(p)) { \
00167 bu_semaphore_acquire( BU_SEM_SYSCALL ); \
00168 mllcerr(q); \
00169 bu_semaphore_release( BU_SEM_SYSCALL ); \
00170 }
00171 #else
00172 # define ASSERT(p,q)
00173 #endif
00174
00175 #ifndef NULL
00176 #define NULL 0
00177 #endif
00178
00179
00180
00181
00182
00183 char endfree = 0;
00184
00185
00186 static Size mlsizes[RT_PM_NBUCKETS] = {
00187 0, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768,
00188 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304
00189 };
00190
00191 #if 0
00192
00193 static struct rt_qelem adjhead = { &adjhead, &adjhead };
00194
00195
00196 static struct rt_qelem buck[RT_PM_NBUCKETS] = {
00197 &buck[0], &buck[0], &buck[1], &buck[1],
00198 &buck[2], &buck[2], &buck[3], &buck[3],
00199 &buck[4], &buck[4], &buck[5], &buck[5],
00200 &buck[6], &buck[6], &buck[7], &buck[7],
00201 &buck[8], &buck[8], &buck[9], &buck[9],
00202 &buck[10], &buck[10], &buck[11], &buck[11],
00203 &buck[12], &buck[12], &buck[13], &buck[13],
00204 &buck[14], &buck[14], &buck[15], &buck[15],
00205 &buck[16], &buck[16], &buck[17], &buck[17]
00206 };
00207 #endif
00208
00209 void (*mlabort)() = {0};
00210
00211 char *
00212 rt_pmalloc(nbytes, pmem)
00213 long nbytes;
00214 struct rt_pm_res *pmem;
00215 {
00216 register struct overhead *p, *q;
00217 register struct rt_qelem *bucket;
00218 register Size surplus;
00219
00220 nbytes = ((nbytes + (NALIGN-1)) & ~(NALIGN-1))
00221 + sizeof(struct overhead);
00222
00223 for (
00224 bucket = &pmem->buckets[mlindx(nbytes)];
00225 bucket < &pmem->buckets[RT_PM_NBUCKETS];
00226 bucket++
00227 ) {
00228 register struct rt_qelem *b;
00229 for(b = bucket->q_forw; b != bucket; b = b->q_forw) {
00230 p = FROMBUK(b);
00231 ASSERT(p->ov_magic == MAGIC_FREE,
00232 "\nrt_pmalloc: Entry not marked FREE found on Free List!\n")
00233 if (p->ov_length >= nbytes) {
00234 rt_pm_remque(b);
00235 surplus = p->ov_length - nbytes;
00236 goto foundit;
00237 }
00238 }
00239 }
00240
00241
00242 {
00243 register Size i;
00244 long ret;
00245
00246 bu_semaphore_acquire( BU_SEM_SYSCALL );
00247 p = (struct overhead *)CURBRK;
00248 i = ((Size)p)&(NALIGN-1);
00249 if (i != 0)
00250 p = (struct overhead *)((char *)p + NALIGN - i);
00251 ret = (long)BRK(((char *)p) + nbytes);
00252 bu_semaphore_release( BU_SEM_SYSCALL );
00253
00254 if( ret )
00255 bu_bomb( "rt_pmalloc: brk() failure. Insufficient memory available!\n" );
00256
00257 p->ov_length = nbytes;
00258 surplus = 0;
00259
00260
00261 #if 0
00262 ASSERT((FROMADJ(pmem->adjhead.q_back)) < p,
00263 "\nrt_pmalloc: Entry in adjacency chain found with address lower than Chain head!\n"
00264 )
00265 #endif
00266 rt_pm_insque(TOADJ(p),pmem->adjhead.q_back);
00267 }
00268
00269 foundit:
00270
00271 if (surplus > sizeof(struct overhead)) {
00272
00273 q = (struct overhead *)((char *)p + nbytes);
00274
00275 q->ov_length = surplus;
00276 p->ov_length = nbytes;
00277 q->ov_magic = MAGIC_FREE;
00278
00279
00280 rt_pm_insque(TOADJ(q),TOADJ(p));
00281
00282
00283 rt_pm_insque(TOBUK(q),&pmem->buckets[mlindx(surplus)]);
00284 }
00285
00286 p->ov_magic = MAGIC_BUSY;
00287 return((char*)p + sizeof(struct overhead));
00288 }
00289
00290
00291
00292
00293 #if 0
00294 static Size
00295 mlindx(n)
00296 register Size n;
00297 {
00298 register Size *p, *q, *r;
00299 p = &mlsizes[0];
00300 r = &mlsizes[RT_PM_NBUCKETS];
00301
00302 while ((q = (p + (r-p)/2)) > p) {
00303 if (n < *q)
00304 r = q;
00305 else
00306 p = q;
00307 }
00308 return(q - &mlsizes[0]);
00309 }
00310 #else
00311
00312
00313
00314 static Size
00315 mlindx( n )
00316 register Size n;
00317 {
00318 register Size index=0, shifter;
00319
00320 if( n >= mlsizes[RT_PM_NBUCKETS-1] )
00321 index = RT_PM_NBUCKETS-1;
00322 else if( n < mlsizes[1] )
00323 index = 0;
00324 else
00325 {
00326 shifter = n >> 6;
00327 while( shifter )
00328 {
00329 index++;
00330 shifter = shifter >> 1;
00331 }
00332 }
00333
00334 return( index );
00335 }
00336 #endif
00337
00338 static void
00339 mllcerr(p)
00340 char *p;
00341 {
00342 register char *q;
00343 q = p;
00344 while (*q++);
00345 (void)write(2,p,q-p-1);
00346 if (mlabort)
00347 (*mlabort)();
00348 else
00349 abort();
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 static void
00361 rt_pm_insque(item,queu)
00362 register struct rt_qelem *item, *queu;
00363
00364 {
00365 register struct rt_qelem *pueu;
00366 pueu = queu->q_forw;
00367 item->q_forw = pueu;
00368 item->q_back = queu;
00369 queu->q_forw = item;
00370 pueu->q_back = item;
00371 }
00372
00373 static void
00374 rt_pm_remque(item)
00375 register struct rt_qelem *item;
00376
00377 {
00378 register struct rt_qelem *queu, *pueu;
00379 pueu = item->q_forw;
00380 queu = item->q_back;
00381 queu->q_forw = pueu;
00382 pueu->q_back = queu;
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392 void
00393 rt_pfree(mem, pmem)
00394 register char *mem;
00395 register struct rt_pm_res *pmem;
00396 {
00397 register struct overhead *p, *q;
00398
00399 if (mem == NULL)
00400 return;
00401
00402 p = (struct overhead *)(mem - sizeof(struct overhead));
00403
00404
00405 if (p->ov_magic == MAGIC_FREE)
00406 return;
00407
00408 if (p->ov_magic != MAGIC_BUSY)
00409 mllcerr("rt_pfree: attempt to free memory not allocated with rt_pmalloc!\n");
00410
00411
00412 q = FROMADJ((TOADJ(p))->q_back);
00413
00414 if (q != FROMADJ(&pmem->adjhead)) {
00415 ASSERT(q < p,
00416 "\nrt_pfree: While trying to merge a free area with a lower adjacent free area,\n\
00417 addresses were found out of order!\n")
00418
00419 if ( q->ov_magic == MAGIC_FREE
00420 && (char *)q + q->ov_length == (char *)p
00421 ) {
00422
00423 rt_pm_remque(TOBUK(q));
00424
00425
00426 rt_pm_remque(TOADJ(p));
00427
00428 q->ov_length += p->ov_length;
00429 p->ov_magic = 0;
00430 p = q;
00431 }
00432 }
00433
00434
00435 q = FROMADJ((TOADJ(p))->q_forw);
00436
00437 if (q != FROMADJ(&pmem->adjhead)) {
00438
00439 ASSERT(q > p,
00440 "\nrt_pfree: While trying to merge a free area with a higher adjacent free area,\n\
00441 addresses were found out of order!\n")
00442 if ( q->ov_magic == MAGIC_FREE
00443 && (char *)p + p->ov_length == (char *)q
00444 ) {
00445
00446 rt_pm_remque(TOBUK(q));
00447
00448
00449 rt_pm_remque(TOADJ(q));
00450
00451 p->ov_length += q->ov_length;
00452 q->ov_magic = 0;
00453 }
00454 }
00455
00456 p->ov_magic = MAGIC_FREE;
00457
00458
00459 rt_pm_insque(TOBUK(p),&pmem->buckets[mlindx(p->ov_length)]);
00460
00461 if (endfree)
00462 mlfree_end( pmem );
00463
00464 return;
00465 }
00466
00467 static void
00468 mlfree_end( pmem )
00469 register struct rt_pm_res *pmem;
00470 {
00471 register struct overhead *p;
00472
00473 p = FROMADJ(pmem->adjhead.q_back);
00474 if( p->ov_magic != MAGIC_FREE )
00475 return;
00476
00477 bu_semaphore_acquire( BU_SEM_SYSCALL );
00478 if ( (char*)p + p->ov_length == (char *)CURBRK)
00479 {
00480
00481
00482 p->ov_magic = 0;
00483
00484
00485 rt_pm_remque(TOADJ(p));
00486
00487
00488 rt_pm_remque(TOBUK(p));
00489
00490
00491 (void)BRK((char *)p);
00492 }
00493 bu_semaphore_release( BU_SEM_SYSCALL );
00494
00495 return;
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 char *
00508 rt_prealloc(mem,nbytes, pmem)
00509 register char *mem; unsigned nbytes;
00510 register struct rt_pm_res *pmem;
00511 {
00512 register char *newmem;
00513 register struct overhead *p, *q;
00514 Size surplus, length;
00515 char oendfree;
00516
00517 if (mem == NULL)
00518 return(rt_pmalloc((long)nbytes, pmem));
00519
00520
00521 if(mem > (char*)FROMADJ(pmem->adjhead.q_back) + sizeof(struct overhead))
00522 return(NULL);
00523
00524 p = (struct overhead *)(mem - sizeof(struct overhead));
00525
00526 if (p->ov_magic != MAGIC_BUSY && p->ov_magic != MAGIC_FREE)
00527 return(NULL);
00528
00529 length = p->ov_length;
00530
00531 nbytes = (nbytes + (NALIGN-1)) & (~(NALIGN-1));
00532
00533 if (p->ov_magic == MAGIC_BUSY) {
00534 oendfree = endfree; endfree = 0;
00535 rt_pfree(mem, pmem);
00536 endfree = oendfree;
00537 }
00538
00539 if( p->ov_magic == MAGIC_FREE
00540 && (surplus = length - nbytes - sizeof(struct overhead)) >= 0
00541 ) {
00542
00543 if (surplus > sizeof(struct overhead)) {
00544 q = (struct overhead *)( (char *)p + nbytes
00545 + sizeof(struct overhead));
00546 q->ov_length = surplus;
00547 q->ov_magic = MAGIC_FREE;
00548 rt_pm_insque(TOADJ(q),TOADJ(p));
00549 rt_pm_insque(TOBUK(q),&pmem->buckets[mlindx(surplus)]);
00550 p->ov_length -= surplus;
00551 }
00552
00553 rt_pm_remque(TOBUK(p));
00554 p->ov_magic = MAGIC_BUSY;
00555
00556 if (endfree)
00557 mlfree_end( pmem );
00558 return(mem);
00559 }
00560
00561
00562
00563 bu_semaphore_acquire( BU_SEM_SYSCALL );
00564 if (p->ov_magic == MAGIC_FREE && ((char *)p + p->ov_length) == (char *)CURBRK) {
00565 nbytes += sizeof(struct overhead);
00566
00567 BRK((char *)p + nbytes);
00568 bu_semaphore_release( BU_SEM_SYSCALL );
00569
00570 p->ov_length = nbytes;
00571
00572 rt_pm_remque(TOBUK(p));
00573 p->ov_magic = MAGIC_BUSY;
00574 return(mem);
00575 }
00576 else
00577 bu_semaphore_release( BU_SEM_SYSCALL );
00578
00579 newmem = rt_pmalloc((long)nbytes, pmem);
00580
00581 if (newmem != mem && newmem != NULL) {
00582 register Size n;
00583 n = length - sizeof(struct overhead);
00584 nbytes = (nbytes < n) ? nbytes: n;
00585 (void)bcopy(mem,newmem,nbytes);
00586
00587
00588
00589
00590 }
00591
00592 if (endfree)
00593 mlfree_end( pmem );
00594
00595 return(newmem);
00596 }
00597
00598 #if 0
00599
00600
00601
00602
00603
00604
00605
00606
00607 void
00608 rt_forget(bpnt, pmem)
00609 char *bpnt;
00610 struct rt_pm_res *pmem;
00611 {
00612 register struct overhead *p, *q, *r, *b;
00613 register Size l;
00614 struct overhead *crbrk;
00615 char pinvalid, oendfree;
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 pinvalid = 0;
00626 oendfree = endfree; endfree = 0;
00627 b = (struct overhead *)bpnt;
00628 p = FROMADJ(pmem->adjhead.q_back);
00629 q = (struct overhead *)0;
00630 bu_semaphore_acquire( BU_SEM_SYSCALL );
00631 r = crbrk = (struct overhead *)CURBRK;
00632 bu_semaphore_release( BU_SEM_SYSCALL );
00633
00634 for (;pinvalid == 0 && b < r; p = FROMADJ(TOADJ(r = p)->q_back)) {
00635 if ( p == FROMADJ(&pmem->adjhead)
00636 || (q = (struct overhead *)((char *)p + p->ov_length)) < b
00637 ) {
00638 pinvalid = 1;
00639 q = b;
00640 }
00641
00642 if (q == r)
00643 continue;
00644
00645 ASSERT(q < r,
00646 "\nrt_forget: addresses in adjacency chain are out of order!\n")
00647
00648
00649 if (oendfree && r == crbrk) {
00650
00651 bu_semaphore_acquire( BU_SEM_SYSCALL );
00652 (void)BRK((char *)q);
00653 bu_semaphore_release( BU_SEM_SYSCALL );
00654
00655 crbrk = r = q;
00656 continue;
00657 }
00658
00659 if (pinvalid)
00660 q = (struct overhead *)
00661 (((long)q + (NALIGN-1)) & (~(NALIGN-1)));
00662
00663 l = (char *)r - (char *)q;
00664
00665
00666
00667
00668
00669 if (l >= sizeof(struct overhead)) {
00670
00671 q->ov_magic = MAGIC_BUSY;
00672 q->ov_length = l;
00673 rt_pm_insque(TOADJ(q),TOADJ(p));
00674 rt_pfree((char *)q + sizeof(struct overhead));
00675 } else if (pinvalid == 0) {
00676
00677 p->ov_length += l;
00678 if (p->ov_magic == MAGIC_FREE) {
00679 rt_pm_remque(TOBUK(p));
00680 rt_pm_insque(TOBUK(p),&pmem->buckets[mlindx(p->ov_length)]);
00681 }
00682 }
00683 }
00684 endfree = oendfree;
00685 if (endfree)
00686 mlfree_end( pmem );
00687 return;
00688 }
00689 #endif
00690
00691
00692
00693
00694
00695 char *
00696 rt_pcalloc(num, size, pmem)
00697 register unsigned num, size;
00698 register struct rt_pm_res *pmem;
00699 {
00700 register char *p;
00701
00702 size *= num;
00703 if ( (p = rt_pmalloc((long)size, pmem)) ) {
00704 memset( p, 0, size );
00705 }
00706 return (p);
00707 }
00708
00709 void
00710 rt_cfree(p, num, size, pmem)
00711 char *p;
00712 unsigned num;
00713 unsigned size;
00714 struct rt_pm_res *pmem;
00715 {
00716 rt_pfree(p, pmem);
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727