The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/port/segment.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include        "u.h"
    2 #include        "../port/lib.h"
    3 #include        "mem.h"
    4 #include        "dat.h"
    5 #include        "fns.h"
    6 #include        "../port/error.h"
    7 
    8 static void     imagereclaim(void);
    9 static void     imagechanreclaim(void);
   10 
   11 #include "io.h"
   12 
   13 /*
   14  * Attachable segment types
   15  */
   16 static Physseg physseg[10] = {
   17         { SG_SHARED,    "shared",       0,      SEGMAXSIZE,     0,      0 },
   18         { SG_BSS,       "memory",       0,      SEGMAXSIZE,     0,      0 },
   19         { 0,            0,              0,      0,              0,      0 },
   20 };
   21 
   22 static Lock physseglock;
   23 
   24 #define NFREECHAN       64
   25 #define IHASHSIZE       64
   26 #define ihash(s)        imagealloc.hash[s%IHASHSIZE]
   27 static struct Imagealloc
   28 {
   29         Lock;
   30         Image   *free;
   31         Image   *hash[IHASHSIZE];
   32         QLock   ireclaim;       /* mutex on reclaiming free images */
   33 
   34         Chan    **freechan;     /* free image channels */
   35         int     nfreechan;      /* number of free channels */
   36         int     szfreechan;     /* size of freechan array */
   37         QLock   fcreclaim;      /* mutex on reclaiming free channels */
   38 }imagealloc;
   39 
   40 Segment* (*_globalsegattach)(Proc*, char*);
   41 
   42 void
   43 initseg(void)
   44 {
   45         Image *i, *ie;
   46 
   47         imagealloc.free = xalloc(conf.nimage*sizeof(Image));
   48         if (imagealloc.free == nil)
   49                 panic("initseg: no memory");
   50         ie = &imagealloc.free[conf.nimage-1];
   51         for(i = imagealloc.free; i < ie; i++)
   52                 i->next = i+1;
   53         i->next = 0;
   54         imagealloc.freechan = malloc(NFREECHAN * sizeof(Chan*));
   55         imagealloc.szfreechan = NFREECHAN;
   56 }
   57 
   58 Segment *
   59 newseg(int type, ulong base, ulong size)
   60 {
   61         Segment *s;
   62         int mapsize;
   63 
   64         if(size > (SEGMAPSIZE*PTEPERTAB))
   65                 error(Enovmem);
   66 
   67         if(swapfull())
   68                 error(Enoswap);
   69         s = smalloc(sizeof(Segment));
   70         s->ref = 1;
   71         s->type = type;
   72         s->base = base;
   73         s->top = base+(size*BY2PG);
   74         s->size = size;
   75         s->sema.prev = &s->sema;
   76         s->sema.next = &s->sema;
   77 
   78         mapsize = ROUND(size, PTEPERTAB)/PTEPERTAB;
   79         if(mapsize > nelem(s->ssegmap)){
   80                 mapsize *= 2;
   81                 if(mapsize > (SEGMAPSIZE*PTEPERTAB))
   82                         mapsize = (SEGMAPSIZE*PTEPERTAB);
   83                 s->map = smalloc(mapsize*sizeof(Pte*));
   84                 s->mapsize = mapsize;
   85         }
   86         else{
   87                 s->map = s->ssegmap;
   88                 s->mapsize = nelem(s->ssegmap);
   89         }
   90 
   91         return s;
   92 }
   93 
   94 void
   95 putseg(Segment *s)
   96 {
   97         Pte **pp, **emap;
   98         Image *i;
   99 
  100         if(s == 0)
  101                 return;
  102 
  103         i = s->image;
  104         if(i != 0) {
  105                 lock(i);
  106                 lock(s);
  107                 if(i->s == s && s->ref == 1)
  108                         i->s = 0;
  109                 unlock(i);
  110         }
  111         else
  112                 lock(s);
  113 
  114         s->ref--;
  115         if(s->ref != 0) {
  116                 unlock(s);
  117                 return;
  118         }
  119         unlock(s);
  120 
  121         qlock(&s->lk);
  122         if(i)
  123                 putimage(i);
  124 
  125         emap = &s->map[s->mapsize];
  126         for(pp = s->map; pp < emap; pp++)
  127                 if(*pp)
  128                         freepte(s, *pp);
  129 
  130         qunlock(&s->lk);
  131         if(s->map != s->ssegmap)
  132                 free(s->map);
  133         if(s->profile != 0)
  134                 free(s->profile);
  135         free(s);
  136 }
  137 
  138 void
  139 relocateseg(Segment *s, ulong offset)
  140 {
  141         Page **pg, *x;
  142         Pte *pte, **p, **endpte;
  143 
  144         endpte = &s->map[s->mapsize];
  145         for(p = s->map; p < endpte; p++) {
  146                 if(*p == 0)
  147                         continue;
  148                 pte = *p;
  149                 for(pg = pte->first; pg <= pte->last; pg++) {
  150                         if(x = *pg)
  151                                 x->va += offset;
  152                 }
  153         }
  154 }
  155 
  156 Segment*
  157 dupseg(Segment **seg, int segno, int share)
  158 {
  159         int i, size;
  160         Pte *pte;
  161         Segment *n, *s;
  162 
  163         SET(n);
  164         s = seg[segno];
  165 
  166         qlock(&s->lk);
  167         if(waserror()){
  168                 qunlock(&s->lk);
  169                 nexterror();
  170         }
  171         switch(s->type&SG_TYPE) {
  172         case SG_TEXT:           /* New segment shares pte set */
  173         case SG_SHARED:
  174         case SG_PHYSICAL:
  175                 goto sameseg;
  176 
  177         case SG_STACK:
  178                 n = newseg(s->type, s->base, s->size);
  179                 break;
  180 
  181         case SG_BSS:            /* Just copy on write */
  182                 if(share)
  183                         goto sameseg;
  184                 n = newseg(s->type, s->base, s->size);
  185                 break;
  186 
  187         case SG_DATA:           /* Copy on write plus demand load info */
  188                 if(segno == TSEG){
  189                         poperror();
  190                         qunlock(&s->lk);
  191                         return data2txt(s);
  192                 }
  193 
  194                 if(share)
  195                         goto sameseg;
  196                 n = newseg(s->type, s->base, s->size);
  197 
  198                 incref(s->image);
  199                 n->image = s->image;
  200                 n->fstart = s->fstart;
  201                 n->flen = s->flen;
  202                 break;
  203         }
  204         size = s->mapsize;
  205         for(i = 0; i < size; i++)
  206                 if(pte = s->map[i])
  207                         n->map[i] = ptecpy(pte);
  208 
  209         n->flushme = s->flushme;
  210         if(s->ref > 1)
  211                 procflushseg(s);
  212         poperror();
  213         qunlock(&s->lk);
  214         return n;
  215 
  216 sameseg:
  217         incref(s);
  218         poperror();
  219         qunlock(&s->lk);
  220         return s;
  221 }
  222 
  223 void
  224 segpage(Segment *s, Page *p)
  225 {
  226         Pte **pte;
  227         ulong off;
  228         Page **pg;
  229 
  230         if(p->va < s->base || p->va >= s->top)
  231                 panic("segpage");
  232 
  233         off = p->va - s->base;
  234         pte = &s->map[off/PTEMAPMEM];
  235         if(*pte == 0)
  236                 *pte = ptealloc();
  237 
  238         pg = &(*pte)->pages[(off&(PTEMAPMEM-1))/BY2PG];
  239         *pg = p;
  240         if(pg < (*pte)->first)
  241                 (*pte)->first = pg;
  242         if(pg > (*pte)->last)
  243                 (*pte)->last = pg;
  244 }
  245 
  246 Image*
  247 attachimage(int type, Chan *c, ulong base, ulong len)
  248 {
  249         Image *i, **l;
  250 
  251         /* reclaim any free channels from reclaimed segments */
  252         if(imagealloc.nfreechan)
  253                 imagechanreclaim();
  254 
  255         lock(&imagealloc);
  256 
  257         /*
  258          * Search the image cache for remains of the text from a previous
  259          * or currently running incarnation
  260          */
  261         for(i = ihash(c->qid.path); i; i = i->hash) {
  262                 if(c->qid.path == i->qid.path) {
  263                         lock(i);
  264                         if(eqqid(c->qid, i->qid) &&
  265                            eqqid(c->mqid, i->mqid) &&
  266                            c->mchan == i->mchan &&
  267                            c->type == i->type) {
  268                                 goto found;
  269                         }
  270                         unlock(i);
  271                 }
  272         }
  273 
  274         /*
  275          * imagereclaim dumps pages from the free list which are cached by image
  276          * structures. This should free some image structures.
  277          */
  278         while(!(i = imagealloc.free)) {
  279                 unlock(&imagealloc);
  280                 imagereclaim();
  281                 sched();
  282                 lock(&imagealloc);
  283         }
  284 
  285         imagealloc.free = i->next;
  286 
  287         lock(i);
  288         incref(c);
  289         i->c = c;
  290         i->type = c->type;
  291         i->qid = c->qid;
  292         i->mqid = c->mqid;
  293         i->mchan = c->mchan;
  294         l = &ihash(c->qid.path);
  295         i->hash = *l;
  296         *l = i;
  297 found:
  298         unlock(&imagealloc);
  299 
  300         if(i->s == 0) {
  301                 /* Disaster after commit in exec */
  302                 if(waserror()) {
  303                         unlock(i);
  304                         pexit(Enovmem, 1);
  305                 }
  306                 i->s = newseg(type, base, len);
  307                 i->s->image = i;
  308                 i->ref++;
  309                 poperror();
  310         }
  311         else
  312                 incref(i->s);
  313 
  314         return i;
  315 }
  316 
  317 static struct {
  318         int     calls;                  /* times imagereclaim was called */
  319         int     loops;                  /* times the main loop was run */
  320         uvlong  ticks;                  /* total time in the main loop */
  321         uvlong  maxt;                   /* longest time in main loop */
  322 } irstats;
  323 
  324 static void
  325 imagereclaim(void)
  326 {
  327         int n;
  328         Page *p;
  329         uvlong ticks;
  330 
  331         irstats.calls++;
  332         /* Somebody is already cleaning the page cache */
  333         if(!canqlock(&imagealloc.ireclaim))
  334                 return;
  335 
  336         lock(&palloc);
  337         ticks = fastticks(nil);
  338         n = 0;
  339         /*
  340          * All the pages with images backing them are at the
  341          * end of the list (see putpage) so start there and work
  342          * backward.
  343          */
  344         for(p = palloc.tail; p && p->image && n<1000; p = p->prev) {
  345                 if(p->ref == 0 && canlock(p)) {
  346                         if(p->ref == 0) {
  347                                 n++;
  348                                 uncachepage(p);
  349                         }
  350                         unlock(p);
  351                 }
  352         }
  353         ticks = fastticks(nil) - ticks;
  354         unlock(&palloc);
  355         irstats.loops++;
  356         irstats.ticks += ticks;
  357         if(ticks > irstats.maxt)
  358                 irstats.maxt = ticks;
  359         //print("T%llud+", ticks);
  360         qunlock(&imagealloc.ireclaim);
  361 }
  362 
  363 /*
  364  *  since close can block, this has to be called outside of
  365  *  spin locks.
  366  */
  367 static void
  368 imagechanreclaim(void)
  369 {
  370         Chan *c;
  371 
  372         /* Somebody is already cleaning the image chans */
  373         if(!canqlock(&imagealloc.fcreclaim))
  374                 return;
  375 
  376         /*
  377          * We don't have to recheck that nfreechan > 0 after we
  378          * acquire the lock, because we're the only ones who decrement 
  379          * it (the other lock contender increments it), and there's only
  380          * one of us thanks to the qlock above.
  381          */
  382         while(imagealloc.nfreechan > 0){
  383                 lock(&imagealloc);
  384                 imagealloc.nfreechan--;
  385                 c = imagealloc.freechan[imagealloc.nfreechan];
  386                 unlock(&imagealloc);
  387                 cclose(c);
  388         }
  389 
  390         qunlock(&imagealloc.fcreclaim);
  391 }
  392 
  393 void
  394 putimage(Image *i)
  395 {
  396         Chan *c, **cp;
  397         Image *f, **l;
  398 
  399         if(i->notext)
  400                 return;
  401 
  402         lock(i);
  403         if(--i->ref == 0) {
  404                 l = &ihash(i->qid.path);
  405                 mkqid(&i->qid, ~0, ~0, QTFILE);
  406                 unlock(i);
  407                 c = i->c;
  408 
  409                 lock(&imagealloc);
  410                 for(f = *l; f; f = f->hash) {
  411                         if(f == i) {
  412                                 *l = i->hash;
  413                                 break;
  414                         }
  415                         l = &f->hash;
  416                 }
  417 
  418                 i->next = imagealloc.free;
  419                 imagealloc.free = i;
  420 
  421                 /* defer freeing channel till we're out of spin lock's */
  422                 if(imagealloc.nfreechan == imagealloc.szfreechan){
  423                         imagealloc.szfreechan += NFREECHAN;
  424                         cp = malloc(imagealloc.szfreechan*sizeof(Chan*));
  425                         if(cp == nil)
  426                                 panic("putimage");
  427                         memmove(cp, imagealloc.freechan, imagealloc.nfreechan*sizeof(Chan*));
  428                         free(imagealloc.freechan);
  429                         imagealloc.freechan = cp;
  430                 }
  431                 imagealloc.freechan[imagealloc.nfreechan++] = c;
  432                 unlock(&imagealloc);
  433 
  434                 return;
  435         }
  436         unlock(i);
  437 }
  438 
  439 long
  440 ibrk(ulong addr, int seg)
  441 {
  442         Segment *s, *ns;
  443         ulong newtop, newsize;
  444         int i, mapsize;
  445         Pte **map;
  446 
  447         s = up->seg[seg];
  448         if(s == 0)
  449                 error(Ebadarg);
  450 
  451         if(addr == 0)
  452                 return s->base;
  453 
  454         qlock(&s->lk);
  455 
  456         /* We may start with the bss overlapping the data */
  457         if(addr < s->base) {
  458                 if(seg != BSEG || up->seg[DSEG] == 0 || addr < up->seg[DSEG]->base) {
  459                         qunlock(&s->lk);
  460                         error(Enovmem);
  461                 }
  462                 addr = s->base;
  463         }
  464 
  465         newtop = PGROUND(addr);
  466         newsize = (newtop-s->base)/BY2PG;
  467         if(newtop < s->top) {
  468                 mfreeseg(s, newtop, (s->top-newtop)/BY2PG);
  469                 s->top = newtop;
  470                 s->size = newsize;
  471                 qunlock(&s->lk);
  472                 flushmmu();
  473                 return 0;
  474         }
  475 
  476         if(swapfull()){
  477                 qunlock(&s->lk);
  478                 error(Enoswap);
  479         }
  480 
  481         for(i = 0; i < NSEG; i++) {
  482                 ns = up->seg[i];
  483                 if(ns == 0 || ns == s)
  484                         continue;
  485                 if(newtop >= ns->base && newtop < ns->top) {
  486                         qunlock(&s->lk);
  487                         error(Esoverlap);
  488                 }
  489         }
  490 
  491         if(newsize > (SEGMAPSIZE*PTEPERTAB)) {
  492                 qunlock(&s->lk);
  493                 error(Enovmem);
  494         }
  495         mapsize = ROUND(newsize, PTEPERTAB)/PTEPERTAB;
  496         if(mapsize > s->mapsize){
  497                 map = smalloc(mapsize*sizeof(Pte*));
  498                 memmove(map, s->map, s->mapsize*sizeof(Pte*));
  499                 if(s->map != s->ssegmap)
  500                         free(s->map);
  501                 s->map = map;
  502                 s->mapsize = mapsize;
  503         }
  504 
  505         s->top = newtop;
  506         s->size = newsize;
  507         qunlock(&s->lk);
  508         return 0;
  509 }
  510 
  511 /*
  512  *  called with s->lk locked
  513  */
  514 void
  515 mfreeseg(Segment *s, ulong start, int pages)
  516 {
  517         int i, j, size;
  518         ulong soff;
  519         Page *pg;
  520         Page *list;
  521 
  522         soff = start-s->base;
  523         j = (soff&(PTEMAPMEM-1))/BY2PG;
  524 
  525         size = s->mapsize;
  526         list = nil;
  527         for(i = soff/PTEMAPMEM; i < size; i++) {
  528                 if(pages <= 0)
  529                         break;
  530                 if(s->map[i] == 0) {
  531                         pages -= PTEPERTAB-j;
  532                         j = 0;
  533                         continue;
  534                 }
  535                 while(j < PTEPERTAB) {
  536                         pg = s->map[i]->pages[j];
  537                         /*
  538                          * We want to zero s->map[i]->page[j] and putpage(pg),
  539                          * but we have to make sure other processors flush the
  540                          * entry from their TLBs before the page is freed.
  541                          * We construct a list of the pages to be freed, zero
  542                          * the entries, then (below) call procflushseg, and call
  543                          * putpage on the whole list.
  544                          *
  545                          * Swapped-out pages don't appear in TLBs, so it's okay
  546                          * to putswap those pages before procflushseg.
  547                          */
  548                         if(pg){
  549                                 if(onswap(pg))
  550                                         putswap(pg);
  551                                 else{
  552                                         pg->next = list;
  553                                         list = pg;
  554                                 }
  555                                 s->map[i]->pages[j] = 0;
  556                         }
  557                         if(--pages == 0)
  558                                 goto out;
  559                         j++;
  560                 }
  561                 j = 0;
  562         }
  563 out:
  564         /* flush this seg in all other processes */
  565         if(s->ref > 1)
  566                 procflushseg(s);
  567 
  568         /* free the pages */
  569         for(pg = list; pg != nil; pg = list){
  570                 list = list->next;
  571                 putpage(pg);
  572         }
  573 }
  574 
  575 Segment*
  576 isoverlap(Proc *p, ulong va, int len)
  577 {
  578         int i;
  579         Segment *ns;
  580         ulong newtop;
  581 
  582         newtop = va+len;
  583         for(i = 0; i < NSEG; i++) {
  584                 ns = p->seg[i];
  585                 if(ns == 0)
  586                         continue;
  587                 if((newtop > ns->base && newtop <= ns->top) ||
  588                    (va >= ns->base && va < ns->top))
  589                         return ns;
  590         }
  591         return nil;
  592 }
  593 
  594 int
  595 addphysseg(Physseg* new)
  596 {
  597         Physseg *ps;
  598 
  599         /*
  600          * Check not already entered and there is room
  601          * for a new entry and the terminating null entry.
  602          */
  603         lock(&physseglock);
  604         for(ps = physseg; ps->name; ps++){
  605                 if(strcmp(ps->name, new->name) == 0){
  606                         unlock(&physseglock);
  607                         return -1;
  608                 }
  609         }
  610         if(ps-physseg >= nelem(physseg)-2){
  611                 unlock(&physseglock);
  612                 return -1;
  613         }
  614 
  615         *ps = *new;
  616         unlock(&physseglock);
  617 
  618         return 0;
  619 }
  620 
  621 int
  622 isphysseg(char *name)
  623 {
  624         Physseg *ps;
  625         int rv = 0;
  626 
  627         lock(&physseglock);
  628         for(ps = physseg; ps->name; ps++){
  629                 if(strcmp(ps->name, name) == 0){
  630                         rv = 1;
  631                         break;
  632                 }
  633         }
  634         unlock(&physseglock);
  635         return rv;
  636 }
  637 
  638 ulong
  639 segattach(Proc *p, ulong attr, char *name, ulong va, ulong len)
  640 {
  641         int sno;
  642         Segment *s, *os;
  643         Physseg *ps;
  644 
  645         if(va != 0 && va >= USTKTOP)
  646                 error(Ebadarg);
  647 
  648         validaddr((ulong)name, 1, 0);
  649         vmemchr(name, 0, ~0);
  650 
  651         for(sno = 0; sno < NSEG; sno++)
  652                 if(p->seg[sno] == nil && sno != ESEG)
  653                         break;
  654 
  655         if(sno == NSEG)
  656                 error(Enovmem);
  657 
  658         /*
  659          *  first look for a global segment with the
  660          *  same name
  661          */
  662         if(_globalsegattach != nil){
  663                 s = (*_globalsegattach)(p, name);
  664                 if(s != nil){
  665                         p->seg[sno] = s;
  666                         return s->base;
  667                 }
  668         }
  669 
  670         len = PGROUND(len);
  671         if(len == 0)
  672                 error(Ebadarg);
  673 
  674         /*
  675          * Find a hole in the address space.
  676          * Starting at the lowest possible stack address - len,
  677          * check for an overlapping segment, and repeat at the
  678          * base of that segment - len until either a hole is found
  679          * or the address space is exhausted.
  680          */
  681         if(va == 0) {
  682                 va = p->seg[SSEG]->base - len;
  683                 for(;;) {
  684                         os = isoverlap(p, va, len);
  685                         if(os == nil)
  686                                 break;
  687                         va = os->base;
  688                         if(len > va)
  689                                 error(Enovmem);
  690                         va -= len;
  691                 }
  692         }
  693 
  694         va = va&~(BY2PG-1);
  695         if(isoverlap(p, va, len) != nil)
  696                 error(Esoverlap);
  697 
  698         for(ps = physseg; ps->name; ps++)
  699                 if(strcmp(name, ps->name) == 0)
  700                         goto found;
  701 
  702         error(Ebadarg);
  703 found:
  704         if(len > ps->size)
  705                 error(Enovmem);
  706 
  707         attr &= ~SG_TYPE;               /* Turn off what is not allowed */
  708         attr |= ps->attr;               /* Copy in defaults */
  709 
  710         s = newseg(attr, va, len/BY2PG);
  711         s->pseg = ps;
  712         p->seg[sno] = s;
  713 
  714         return va;
  715 }
  716 
  717 void
  718 pteflush(Pte *pte, int s, int e)
  719 {
  720         int i;
  721         Page *p;
  722 
  723         for(i = s; i < e; i++) {
  724                 p = pte->pages[i];
  725                 if(pagedout(p) == 0)
  726                         memset(p->cachectl, PG_TXTFLUSH, sizeof(p->cachectl));
  727         }
  728 }
  729 
  730 long
  731 syssegflush(ulong *arg)
  732 {
  733         Segment *s;
  734         ulong addr, l;
  735         Pte *pte;
  736         int chunk, ps, pe, len;
  737 
  738         addr = arg[0];
  739         len = arg[1];
  740 
  741         while(len > 0) {
  742                 s = seg(up, addr, 1);
  743                 if(s == 0)
  744                         error(Ebadarg);
  745 
  746                 s->flushme = 1;
  747         more:
  748                 l = len;
  749                 if(addr+l > s->top)
  750                         l = s->top - addr;
  751 
  752                 ps = addr-s->base;
  753                 pte = s->map[ps/PTEMAPMEM];
  754                 ps &= PTEMAPMEM-1;
  755                 pe = PTEMAPMEM;
  756                 if(pe-ps > l){
  757                         pe = ps + l;
  758                         pe = (pe+BY2PG-1)&~(BY2PG-1);
  759                 }
  760                 if(pe == ps) {
  761                         qunlock(&s->lk);
  762                         error(Ebadarg);
  763                 }
  764 
  765                 if(pte)
  766                         pteflush(pte, ps/BY2PG, pe/BY2PG);
  767 
  768                 chunk = pe-ps;
  769                 len -= chunk;
  770                 addr += chunk;
  771 
  772                 if(len > 0 && addr < s->top)
  773                         goto more;
  774 
  775                 qunlock(&s->lk);
  776         }
  777         flushmmu();
  778         return 0;
  779 }
  780 
  781 void
  782 segclock(ulong pc)
  783 {
  784         Segment *s;
  785 
  786         s = up->seg[TSEG];
  787         if(s == 0 || s->profile == 0)
  788                 return;
  789 
  790         s->profile[0] += TK2MS(1);
  791         if(pc >= s->base && pc < s->top) {
  792                 pc -= s->base;
  793                 s->profile[pc>>LRESPROF] += TK2MS(1);
  794         }
  795 }
  796 

Cache object: 86c8730ce0bd3b34ff5bc5fef6a89b41


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.