Annotation of researchv10no/cmd/sml/src/runtime/callgc.c, revision 1.1.1.1

1.1       root        1: /* Copyright 1989 by AT&T Bell Laboratories */
                      2: #include <signal.h>
                      3: #include <sys/types.h>
                      4: #ifdef BSD
                      5: #include <sys/time.h>
                      6: #include <sys/resource.h>
                      7: #endif
                      8: 
                      9: #ifdef MIPS
                     10: #include <sys/syscall.h>
                     11: #include <mips/cachectl.h>
                     12: #include <errno.h>
                     13: #endif
                     14: 
                     15: #include "tags.h"
                     16: #include "descriptor.h"
                     17: 
                     18: #define refcell(z) int z[2] = {mak_desc(1,tag_array), ML_INT(0)};
                     19: 
                     20: #ifdef NeXT
                     21: 
                     22: #include <c.h>                 /* TRUE and FALSE */
                     23: #include <sys/kern_return.h>   /* KERN_whatever */
                     24: #include <mach.h>              /* type definitions */
                     25: 
                     26: #endif NeXT
                     27: 
                     28: refcell(collected0)
                     29: refcell(collectedfrom0)
                     30: refcell(current0)
                     31: refcell(gcmessages0)
                     32: refcell(majorcollections0)
                     33: refcell(minorcollections0)
                     34: refcell(pstruct0)
                     35: refcell(ratio0)
                     36: refcell(softmax0)
                     37: 
                     38: #define collected (collected0[1])
                     39: #define collectedfrom (collectedfrom0[1])
                     40: #define current (current0[1])
                     41: #define gcmessages (gcmessages0[1])
                     42: #define majorcollections (majorcollections0[1])
                     43: #define minorcollections (minorcollections0[1])
                     44: #define pstruct (pstruct0[1])
                     45: #define ratio (ratio0[1])
                     46: #define softmax (softmax0[1])
                     47: 
                     48: int arenabase;               /* bottom of the heap */
                     49: int arenasize = 0;           /* heap starts empty */
                     50: int new_size = 1024 * 1024;  /* default heap size of 1 megabyte */
                     51: int arstart;                 /* beginning of main arena */
                     52: int arend;                   /* end of main arena, and the heap */
                     53: int old_high;                /* marks end of persistent heap */
                     54: int new_high;
                     55: int new_new_high;
                     56: int lastbreak;
                     57: 
                     58: int cause, fault_code;
                     59: int bottom;                 /* saved stack-pointer */
                     60: int fpsave;                /* saved frame pointer */
                     61: int saved_pc_relative;
                     62: int saved_pc, saved_dataptr, saved_exnptr, saved_storeptr=1, saved_limit;
                     63: #ifdef SPARC
                     64: extern int saved_ptrs[], saved_nonptrs[]; /* allocated in SPARC.prim.s */
                     65: #else
                     66: int saved_ptrs[32], saved_nonptrs[32];
                     67: #endif
                     68: 
                     69: int store_preserve=1, preserving=0;
                     70: 
                     71: extern int handle_c[], return_c[];
                     72: 
                     73: apply(func,arg) int func, arg;
                     74: {int i;
                     75:     saved_exnptr = (int) handle_c;
                     76:     saved_ptrs[0] = arg;
                     77:     saved_ptrs[1] = (int) return_c;
                     78:     saved_ptrs[2] = func;
                     79:     saved_pc = *(int*)func;
                     80:     for(i=3;i<32;i++) saved_ptrs[i]=0;
                     81:     runML();
                     82:     return saved_ptrs[0];
                     83: }
                     84: 
                     85: int exportFilid;
                     86: 
                     87: runML()
                     88: {int i;
                     89:  for(;;)
                     90:       {cause=0;
                     91: #ifdef MIPS
                     92:        cacheflush((char *) arenabase, arenasize, ICACHE);
                     93: #endif
                     94:        restoreregs();
                     95:        switch(cause)
                     96:        {case CAUSE_EXN: return uncaught(saved_ptrs[0]);
                     97:         case CAUSE_GC:  callgc0(); break;
                     98:         case CAUSE_RET: return;
                     99:         case CAUSE_EXPORT: saved_pc=0;
                    100:                            for(i=2;i<32;i++) saved_ptrs[i]=0;
                    101:                            callgc0(); callgc0();
                    102:                            saved_pc = *(int*)saved_ptrs[1];
                    103:                            export(exportFilid);
                    104:                            saved_ptrs[0]=1;
                    105:                            break;
                    106:         case CAUSE_BLAST: saved_pc=0;
                    107:                           callgc0();
                    108:                           saved_pc = *(int*)saved_ptrs[1];
                    109:                           break;
                    110:         case CAUSE_STOR:  saved_pc=0;
                    111:                           callgc0();
                    112:                           preserving = (saved_ptrs[0]!=1);
                    113:                           saved_ptrs[0]= uniq(store_preserve);
                    114:                           store_preserve=1;
                    115:                           saved_pc = *(int*)saved_ptrs[1];
                    116:                           break;
                    117:         case CAUSE_FAULT:   
                    118:                           for(i=0;i<32;i++) saved_ptrs[i]=0;
                    119:                           saved_ptrs[0]=fault_code;
                    120:                           saved_ptrs[1]=saved_exnptr;
                    121:                           saved_pc = *(int*)saved_ptrs[1];
                    122:                           break;
                    123:        }
                    124:       }
                    125: }
                    126: 
                    127: 
                    128: #define pagesize 8192
                    129: 
                    130: #ifdef NeXT
                    131: 
                    132: /**
                    133:  ** This implements sbrk/brk using vm_allocate/vm_deallocate.
                    134:  ** Arguments are assumed to be page multiples, and the argument
                    135:  ** to brk is assumed to be just after the desired breakpoint.
                    136:  **
                    137:  ** No relationship between the mapped region and the rest of the
                    138:  ** process image is guaranteed, but it is expected that the region
                    139:  ** will follow the end of data/bss.
                    140:  **
                    141:  ** Works with NeXT Mach (software release 0.9).  5/15/89
                    142:  **
                    143:  ** James William O'Toole Jr.
                    144:  **
                    145:  **/
                    146: 
                    147: extern vm_task_t task_self_;
                    148: 
                    149: int mach_sbrk_needsinit = TRUE;
                    150: int mach_maplimit = 0;
                    151: int mach_brkpt = 0;
                    152: int mach_quant = 0x800000;
                    153: int big_heap = 0x2000000;
                    154: 
                    155: static int sbrk(incr)
                    156: int incr;
                    157: {
                    158:         if (incr) die("sbrk called with nonzero value");
                    159:        if (mach_sbrk_needsinit != FALSE) {
                    160:                if (vm_allocate(task_self_, &mach_brkpt, big_heap,TRUE)
                    161:                    != KERN_SUCCESS)
                    162:                        die("vm_allocate failed");
                    163:                mach_maplimit = mach_brkpt + big_heap;
                    164:                mach_sbrk_needsinit = FALSE;
                    165:                }
                    166:        return(mach_brkpt);
                    167: }
                    168: 
                    169: static int brk(pos)
                    170: int pos;
                    171: {
                    172:  if (pos>mach_maplimit) return KERN_FAILURE;
                    173:  return KERN_SUCCESS;
                    174: }
                    175: 
                    176: #endif NeXT
                    177: 
                    178: init_gc()
                    179: {
                    180:  arenabase=sbrk(0);
                    181:  lastbreak=arenabase;
                    182:  increase_heapsize();
                    183:  old_high = arenabase;
                    184:  arstart = arenabase+arenasize/2;
                    185:  saved_dataptr = (int)arstart;
                    186:  saved_limit = arenabase+arenasize-4096;
                    187: }
                    188: 
                    189: #ifdef ADVICE
                    190: struct timeval zero, ogtime, ostime, otime;
                    191: int getting_advice;
                    192: int old_size;
                    193: int old_minorcount;
                    194: #endif
                    195: 
                    196: restarter()
                    197: {extern int edata;
                    198:  resettimers();
                    199:  lastbreak = (int)&edata;
                    200:  getmore_restart();
                    201: #ifdef ADVICE
                    202:  ostime=zero; otime=zero; ogtime=zero;
                    203:  getting_advice=1;
                    204:  initadvice();
                    205: #endif
                    206:  saved_dataptr = (int)arstart;
                    207:  saved_limit = lastbreak-4096;
                    208:  setupsignals();
                    209:  saved_ptrs[0]=3;
                    210:  runML();
                    211: #ifdef ADVICE
                    212:  call_endadvice();
                    213: #endif
                    214:  _exit(0);
                    215: }
                    216: 
                    217: callgc0()
                    218: {int i; int *roots[40]; int **rootsptr = roots;
                    219: #ifdef V9
                    220:  int (*inthandle)();
                    221:  inthandle = signal(SIGINT,SIG_IGN);
                    222: #endif
                    223:  suspendtimers();
                    224:  *rootsptr++ = &pstruct;
                    225:  *rootsptr++ = &saved_exnptr;
                    226:  for(i=0;i<32;i++) *rootsptr++ = saved_ptrs+i;
                    227:   {extern int gcprof[];
                    228:    int *currentsave = (int *) current;
                    229:    current = (int) (gcprof+1);
                    230:    *rootsptr++ = (int *) &currentsave;
                    231:    *rootsptr++ = (int *) &store_preserve;
                    232:    *rootsptr++ = (int *) &saved_pc;
                    233:    *rootsptr=0;
                    234:    i=0;
                    235:    callgc(roots,&saved_dataptr,saved_storeptr);
                    236:    saved_storeptr=1;
                    237:    current = (int) currentsave;
                    238:   }
                    239:  restarttimers();
                    240: #ifdef V9
                    241:  signal(SIGINT,inthandle);
                    242: #endif
                    243: }
                    244: 
                    245: int getmore_die(){die("bug: insufficient to_space\n");}
                    246: 
                    247: int amount_desired;
                    248: 
                    249: int decrease_heapsize()
                    250: {int p = arenabase+new_size;
                    251:  p = (p + pagesize-1 ) & ~(pagesize-1);
                    252:  if (p<lastbreak)
                    253:     {brk(p);
                    254:      arenasize = p-arenabase;
                    255:      if (gcmessages >= ML_INT(2))
                    256:         chatting("\n[Decreasing heap to %dk]\n",arenasize/1024);
                    257:      lastbreak=p;}
                    258:  return lastbreak;}
                    259: 
                    260: int increase_heapsize() /* new_size > arenasize */
                    261: {int p = arenabase+new_size;
                    262:  RESTART:
                    263:  p = (p + pagesize-1 ) & ~(pagesize-1);
                    264:  if (p==lastbreak)
                    265:     {if (gcmessages >= ML_INT(2)) chatting("\nWarning: can't increase heap\n");
                    266:      return p;}
                    267:  else if (brk(p))
                    268:          {if (gcmessages >= ML_INT(3))
                    269:             chatting("\nWarning: must reduce heap request\n");
                    270:           p=(lastbreak+(p-pagesize))/2; goto RESTART;}
                    271:       else {lastbreak=p;
                    272:             arenasize = p-arenabase;
                    273:            if (gcmessages >= ML_INT(2))
                    274:                chatting("\n[Increasing heap to %dk]\n",arenasize/1024);
                    275:             return p;}
                    276:  }
                    277: 
                    278: int compute_new_size(live_size) 
                    279:    int live_size;
                    280: {int new_size,  gamma = (ratio<7?7:ratio)>>1,  max = softmax>>1;
                    281:   if (2000000000 / gamma < live_size)
                    282:           new_size = 2000000000;
                    283:           else new_size=live_size*gamma;
                    284:  if (max < new_size)
                    285:     {int new = 3*live_size;
                    286:      new_size = (new>max?new:max);}
                    287:  return new_size;
                    288: }
                    289: 
                    290: int getmore_must()
                    291: {int oldsize=arenasize;
                    292:  int live_size = amount_desired+arenasize+arenabase-old_high;
                    293:  new_size=compute_new_size(live_size);
                    294:  {int r=increase_heapsize();
                    295: #ifdef ADVICE
                    296:   while (oldsize==arenasize) 
                    297:     {chatting("\nCan't get more memory; waiting\n");
                    298:      sleep(10);
                    299:      chatting("Trying again\n");
                    300:      r=increase_heapsize();
                    301:     }
                    302: #else
                    303:   if (oldsize==arenasize) die("\nRan out of memory");
                    304: #endif
                    305:   return r;
                    306:  }
                    307: }
                    308: 
                    309: getmore_restart()
                    310: {int live_size = old_high - arenabase;
                    311:  int a = 0;
                    312:  int x = gcmessages;
                    313:  gcmessages=ML_INT(0);
                    314:  new_size=compute_new_size(live_size);
                    315:  do {increase_heapsize();
                    316:      if (arenasize==a) die("Can't get enough memory to start ML\n");
                    317:      a=arenasize;
                    318:    } while (arenasize < 3*live_size);
                    319:  gcmessages=x;
                    320: }
                    321: 
                    322: callgc(misc_roots,  /* vector of ptrs to extra root words */
                    323:        arptr,      /* place to put new freespace pointer */
                    324:        store_list   /* list of refs stored into */
                    325:       )
                    326:     int ***misc_roots; int *arptr; int **store_list;
                    327: {int amount_desired;
                    328:  arend = arenabase+arenasize;
                    329:  if (cause==CAUSE_EXPORT || cause==CAUSE_STOR) amount_desired = 0;
                    330:            else amount_desired = 4+arend-(*arptr);
                    331:  if (arstart== *arptr) new_high = old_high; /* no minor needed */
                    332:  else 
                    333:  {if (gcmessages >= ML_INT(3)) chatting("\n[Minor collection...");
                    334:   starttime();
                    335:   gc(arstart,arend,
                    336:     old_high,arstart,
                    337:     old_high,
                    338:     &new_high,
                    339:     misc_roots,store_list,
                    340:     getmore_die, 0);
                    341:     {int a = new_high-old_high, b =(*arptr)-arstart, msec=endtime();
                    342:      if (gcmessages >= ML_INT(3))
                    343:        chatting(" %d%% used (%d/%d), %d msec]\n", (100*a)/b, a, b, msec);
                    344:      collected += 2*((a+512)/1024); /* round to nearest k */
                    345:      collectedfrom += 2*((b+512)/1024);
                    346:      minorcollections+=2;
                    347:     }
                    348: #ifdef GCDEBUG
                    349:  checkup(arstart,new_high);
                    350:  clear(new_high,arenabase+arenasize);
                    351: #endif
                    352:    }
                    353: {int need_major = 0; int was_preserving; int gamma = (ratio<7?7:ratio)>>1;
                    354:   if (cause==CAUSE_EXPORT || cause==CAUSE_BLAST) need_major = 1;
                    355:  else {int cut = arenasize-arenasize/gamma;
                    356:        int max = softmax>>1;
                    357:        int halfmax = max/2;
                    358:        int halfsize = arenasize/2;
                    359:        cut = (cut<halfmax?cut:halfmax);
                    360:        cut = (cut>halfsize?cut:halfsize);
                    361:        if (new_high+amount_desired > arenabase+cut) need_major = 1;
                    362:        else {int live_size = amount_desired+new_high-old_high;
                    363: #ifdef ADVICE
                    364:           if ((arenabase+arenasize-new_high)/2 <= amount_desired*3+100) need_major=1;
                    365:           if (minorcollections > old_minorcount+200) need_major=1;
                    366: #else
                    367:              new_size=compute_new_size(live_size);
                    368:             if (new_size > arenasize
                    369:                         && (increase_heapsize()-new_high)/2 <= amount_desired)
                    370:                 need_major = 1;
                    371: #endif ADVICE
                    372:           }}
                    373:  if (cause==CAUSE_BLAST) old_high=new_high;
                    374:  if (need_major)
                    375:     {if (gcmessages >= ML_INT(1)) chatting("\n[Major collection...");
                    376:      starttime();
                    377:      was_preserving=preserving; preserving=0;
                    378:      if (gc(arenabase,old_high,
                    379:        old_high,arenabase+arenasize,
                    380:        new_high,
                    381:        &new_new_high,
                    382:         misc_roots,1,
                    383:         getmore_must, cause==CAUSE_BLAST? &saved_ptrs[0]: 0))
                    384:        {moveback(old_high,new_new_high,
                    385:              arenabase,
                    386:              misc_roots);
                    387:         {int a = new_new_high-new_high, 
                    388:              b = new_high-arenabase, msec=endtime();
                    389:          if (gcmessages >= ML_INT(1))
                    390:                chatting(" %d%% used (%d/%d), %d msec]\n",(100*a)/b, a, b, msec);
                    391:          collected += 2*((a+512)/1024);
                    392:          collectedfrom += 2*((b+512)/1024);
                    393:          majorcollections+=2;}
                    394:        {int live_size = amount_desired+new_new_high-old_high;
                    395:          old_high=arenabase+new_new_high-old_high;
                    396: #ifdef ADVICE
                    397:         new_size = ask_new_size(live_size);
                    398: #else
                    399:         new_size = compute_new_size(live_size);
                    400: #endif
                    401:         if (new_size > arenasize)
                    402:            {int end = increase_heapsize();
                    403:             if ((end-old_high)/2 <= amount_desired)
                    404:                die("\nRan out of memory\n");}
                    405: #ifdef ADVICE
                    406:          else if (new_size < arenasize) decrease_heapsize();
                    407:         old_size = arenasize;
                    408:         old_minorcount = minorcollections;
                    409: #else
                    410:          else if (new_size < (arenasize/4)*3) decrease_heapsize();
                    411: #endif
                    412:        }}
                    413:        else {endtime(); if (gcmessages >= ML_INT(1)) chatting("abandoned]\n");}
                    414:     preserving=was_preserving;
                    415:    }
                    416:  else old_high=new_high;
                    417:  }
                    418:  arend = arenabase+arenasize;
                    419:  arstart = (((arend+old_high)/2)+3)&(~3);
                    420:  (*arptr) = arstart;
                    421:  saved_limit = arend-4096;
                    422: #ifdef V9
                    423:  { extern int ghandle();
                    424:    signal(SIGFPE, ghandle);
                    425:  }
                    426: #endif /* V9 */
                    427: }
                    428: 
                    429: #ifdef GCDEBUG
                    430: clear(low,high) int *low, *high;
                    431: {int *i;
                    432:  chatting("clearing new space...  ");
                    433:  for(i=low; i<high; i++) *i=0;
                    434:  chatting("done\n");
                    435: }
                    436: 
                    437: int *descriptor;
                    438: checkup(low,high)
                    439: int *low,*high;
                    440: {int *i,*j;
                    441:  chatting("checking to_space...  ");
                    442:  i = low;
                    443:  while (i < high) {
                    444:    descriptor = i;
                    445:    switch(get_tag(i)) {
                    446:         case tag_backptr:
                    447:                chatting("Uncool backpointer at %x in to_space\n",i);
                    448:                exit(0);
                    449:                break;
                    450:        case tag_embedded:
                    451:                chatting("Uncool embedded tag at %x in to_space\n",i);
                    452:                exit(0);
                    453:                break;
                    454:        case tag_string:
                    455:        case tag_bytearray:
                    456:                i += (get_len(i)+7)>>2;
                    457:                break;
                    458:        case tag_record:
                    459:        case tag_array:
                    460:                j = i + get_len(i) + 1;
                    461:                while(++i < j) {
                    462:                 if (*i & 1) continue;
                    463:                 else if ((int*)*i > high) {
                    464:                         chatting("Uncool pointer %x at %x\n", *i,i);
                    465:                         chatting("Descriptor is at %x\n",descriptor);
                    466:                      }
                    467:                 else if ((int*)*i < low) {
                    468:                         chatting("Uncool pointer %#x at %#x\n", *i,i);
                    469:                         chatting("Descriptor is at %#x\n",descriptor);
                    470:                      }
                    471:                }
                    472:                break;
                    473:        case tag_forwarded:
                    474:                chatting("Uncool forwarding tag at %x in to_space\n",i);
                    475:                exit(0);
                    476:                break;
                    477:        default: /* function pointers */
                    478:                chatting("Unexpected even tag %d at %x in to_space\n",
                    479:                         get_tag(i),i);
                    480:                exit(0);
                    481:                break;
                    482:              }
                    483:  }
                    484:  chatting("done\n");
                    485: }
                    486: #endif /* GCDEBUG */
                    487: 
                    488: int g_sec,g_usec,t_sec,t_usec;
                    489: #ifdef BSD
                    490: struct rusage r1, r2;
                    491: 
                    492: starttime()
                    493: {getrusage(0,&r1);}
                    494: 
                    495: endtime()
                    496: {
                    497:  int sec,usec;
                    498:  getrusage(0,&r2);
                    499:  sec = r2.ru_utime.tv_sec-r1.ru_utime.tv_sec;
                    500:  usec = r2.ru_utime.tv_usec-r1.ru_utime.tv_usec;
                    501:  if (usec < 0) {sec--; usec += 1000000;}
                    502:  return (usec/1000 + sec*1000);
                    503: }
                    504: 
                    505: struct rusage garbagetime,timestamp,s1,s2;
                    506: 
                    507: suspendtimers()
                    508: {
                    509:  getrusage(0,&s1);
                    510: }
                    511: 
                    512: restarttimers()
                    513: {
                    514:  int sec,usec;
                    515:  getrusage(0,&s2);
                    516:  sec = s2.ru_utime.tv_sec-s1.ru_utime.tv_sec+garbagetime.ru_utime.tv_sec;
                    517:  usec = s2.ru_utime.tv_usec-s1.ru_utime.tv_usec+garbagetime.ru_utime.tv_usec;
                    518:  if (usec < 0) {sec--; usec += 1000000;}
                    519:  else if (usec > 1000000) {sec++; usec -= 1000000;}
                    520:  garbagetime.ru_utime.tv_sec = sec;
                    521:  garbagetime.ru_utime.tv_usec = usec;
                    522: }
                    523: 
                    524: resettimers()
                    525: {
                    526:  garbagetime.ru_utime.tv_sec = 0;
                    527:  garbagetime.ru_utime.tv_usec = 0;
                    528:  s2.ru_utime.tv_sec = s1.ru_utime.tv_sec = 0;
                    529:  s2.ru_utime.tv_usec = s1.ru_utime.tv_usec = 0;
                    530:  r2.ru_utime.tv_sec = r1.ru_utime.tv_sec = 0;
                    531:  r2.ru_utime.tv_usec = r1.ru_utime.tv_usec = 0;
                    532:  collected = collectedfrom = minorcollections = majorcollections = ML_INT(0);
                    533: }
                    534: 
                    535: timer()
                    536: {
                    537:  getrusage(0,&timestamp);
                    538:  g_usec = garbagetime.ru_utime.tv_usec * 2 + 1;
                    539:  g_sec = garbagetime.ru_utime.tv_sec * 2 + 1;
                    540:  t_usec = timestamp.ru_utime.tv_usec * 2 + 1;
                    541:  t_sec = timestamp.ru_utime.tv_sec * 2 + 1;
                    542: }
                    543: 
                    544: #ifdef ADVICE
                    545: struct timeval subt(a,b) struct timeval a,b;
                    546: {struct timeval x;
                    547:  x.tv_sec = a.tv_sec - b.tv_sec;
                    548:  x.tv_usec = a.tv_usec - b.tv_usec;
                    549:  if (x.tv_usec<0) {x.tv_sec--; x.tv_usec+=1000000;}
                    550:  else if (x.tv_usec > 1000000) {x.tv_sec--; x.tv_usec+=1000000;}
                    551:  return x;
                    552: }
                    553: 
                    554: struct timezone zone;
                    555: 
                    556: int milli(t) struct timeval t;
                    557: {
                    558:     return t.tv_sec*1000 + t.tv_usec/1000;
                    559: }
                    560: 
                    561: int ask_new_size(live_size) int live_size;
                    562: {int answer;
                    563:  int s0 = arenabase+2*live_size;
                    564:  int sf = /* (old_size?old_size:arenasize) */ arenasize - 2*live_size;
                    565:  int delta; struct rusage adv; struct timeval newgtime, newttime, systime;
                    566:  getrusage(0,&adv);
                    567:  newgtime = subt(subt(adv.ru_utime,s1.ru_utime),
                    568:                 subt(ogtime,garbagetime.ru_utime));
                    569:  newttime = subt(subt(adv.ru_utime,otime),newgtime);
                    570:  systime = subt(adv.ru_stime,ostime);
                    571:  ostime=adv.ru_stime;
                    572:  otime=adv.ru_utime;
                    573:  ogtime = subt(garbagetime.ru_utime,subt(s1.ru_utime,adv.ru_utime));
                    574:  if ((!getting_advice) || 
                    575:      memadvice(s0,sf,milli(newttime),milli(newgtime),0,
                    576:               live_size,milli(systime),&answer))
                    577:     return compute_new_size(live_size);
                    578:  else if (answer < live_size/2) return 5*live_size/2;
                    579:      else return answer+2*live_size;
                    580: }
                    581: 
                    582: call_endadvice()
                    583: {
                    584:  int delta; struct rusage adv; struct timeval newgtime, newttime, systime;
                    585:  getrusage(0,&adv);
                    586:  newgtime = subt(garbagetime.ru_utime,ogtime);
                    587:  newttime = subt(subt(adv.ru_utime,otime),newgtime);
                    588:  systime = subt(adv.ru_stime,ostime);
                    589:  if (getting_advice)
                    590:     endadvice(milli(newttime),milli(newgtime),milli(systime));
                    591: }
                    592: 
                    593: 
                    594: 
                    595: #endif
                    596: #endif /* BSD */
                    597: 
                    598: #ifdef V9
                    599: #include <sys/times.h>
                    600: struct tms t1,t2;
                    601: 
                    602: starttime()
                    603: {times(&t1);}
                    604: 
                    605: endtime()
                    606: {
                    607:  int hzsec;
                    608:  times(&t2);
                    609:  hzsec = t2.tms_utime-t1.tms_utime;
                    610:  return(hzsec*1000/60);
                    611: }
                    612: 
                    613: struct tms timestamp,s1,s2;
                    614: int garbagetime;
                    615: 
                    616: suspendtimers()
                    617: {
                    618:  times(&s1);
                    619: }
                    620: 
                    621: restarttimers()
                    622: {
                    623:  times(&s2);
                    624:  garbagetime += s2.tms_utime-s1.tms_utime;
                    625: }
                    626: 
                    627: resettimers()
                    628: {
                    629:  garbagetime = 0;
                    630:  s2.tms_utime = s1.tms_utime = 0;
                    631:  t2.tms_utime = t1.tms_utime = 0;
                    632:  collected = collectedfrom = minorcollections = majorcollections = ML_INT(0);
                    633: }
                    634: 
                    635: 
                    636: timer()
                    637: {
                    638:  times(&timestamp);
                    639:  g_usec = garbagetime % 60 * 1000000 / 60 * 2 + 1;
                    640:  g_sec = garbagetime / 60 * 2 + 1;
                    641:  t_usec = timestamp.tms_utime % 60 * 1000000 / 60 * 2 + 1;
                    642:  t_sec = timestamp.tms_utime / 60 * 2 + 1;
                    643: }
                    644: 
                    645: #endif /* V9 */
                    646: 
                    647: int uniq(arg) int arg;
                    648: {int q, *p;
                    649: #define BASE(ptr) (((int**)(ptr))[0])
                    650: #define INDEX(ptr) ((((int*)(ptr))[1]-1)>>1)
                    651: #define NEXTP(ptr) (((int*)(ptr))[2])
                    652:  for(q=arg;q!=1;q=NEXTP(q))
                    653:     if ( INDEX(q) == -1)
                    654:       {((int*)q)[-1]= BASE(q)[-1];
                    655:        ((int**)q)[0][-1] = 0;
                    656:       }
                    657:  for(q=arg;q!=1;q=NEXTP(q))
                    658:     if ( BASE(q)[-1] && INDEX(q)>=0 && BASE(q)[INDEX(q)])
                    659:       {((int*)q)[-1]= BASE(q)[INDEX(q)];
                    660:        BASE(q)[INDEX(q)] = 0;
                    661:       }
                    662:  p= &arg;
                    663:  while (*p!=1)
                    664:     if (((int**)*p)[0][(((int*)*p)[1]-1)/2])
                    665:           *p = NEXTP(*p);
                    666:     else  {BASE(*p)[INDEX(*p)] = ((int*)*p)[-1];
                    667:            ((int*)*p)[-1] = 3*16+1;
                    668:            p = &NEXTP(*p);
                    669:           }
                    670: 
                    671:  return arg;
                    672: }
                    673: 
                    674: #ifdef ADVICE
                    675: 
                    676: static char mallocbuf[0x10000], *mallocptr=mallocbuf;
                    677: 
                    678: char *malloc(n) int n;
                    679: {char *p;
                    680:  n = (n+3) & ~3;
                    681:  if (mallocptr+n > mallocbuf+0x10000) die ("Too much malloc.");
                    682:  p=mallocptr;
                    683:  mallocptr+=n;
                    684:  return p;
                    685: }
                    686: 
                    687: char *free(){}
                    688: 
                    689: char *realloc(){
                    690:     die ("Didn't expect realloc.");
                    691: }
                    692: 
                    693: char *calloc(n,m) int n,m; 
                    694: {char *p = malloc(n*m); int i;
                    695:  for(i=0;i<n;i++) p[i]=0;
                    696:  return p;    
                    697: }
                    698: 
                    699: char *cfree() {}
                    700: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.