Annotation of researchv10no/cmd/sml/src/runtime/callgc.c, revision 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.