13e12c5d1SDavid du Colombier #include "u.h"
23e12c5d1SDavid du Colombier #include "../port/lib.h"
33e12c5d1SDavid du Colombier #include "mem.h"
43e12c5d1SDavid du Colombier #include "dat.h"
53e12c5d1SDavid du Colombier #include "fns.h"
63e12c5d1SDavid du Colombier #include "../port/error.h"
73e12c5d1SDavid du Colombier
87dd7cddfSDavid du Colombier static void imagereclaim(void);
97dd7cddfSDavid du Colombier static void imagechanreclaim(void);
103e12c5d1SDavid du Colombier
11219b2ee8SDavid du Colombier #include "io.h"
129a747e4fSDavid du Colombier
139a747e4fSDavid du Colombier /*
149a747e4fSDavid du Colombier * Attachable segment types
159a747e4fSDavid du Colombier */
169a747e4fSDavid du Colombier static Physseg physseg[10] = {
179a747e4fSDavid du Colombier { SG_SHARED, "shared", 0, SEGMAXSIZE, 0, 0 },
189a747e4fSDavid du Colombier { SG_BSS, "memory", 0, SEGMAXSIZE, 0, 0 },
199a747e4fSDavid du Colombier { 0, 0, 0, 0, 0, 0 },
209a747e4fSDavid du Colombier };
213e12c5d1SDavid du Colombier
227dd7cddfSDavid du Colombier static Lock physseglock;
237dd7cddfSDavid du Colombier
247dd7cddfSDavid du Colombier #define NFREECHAN 64
253e12c5d1SDavid du Colombier #define IHASHSIZE 64
263e12c5d1SDavid du Colombier #define ihash(s) imagealloc.hash[s%IHASHSIZE]
2759cc4ca5SDavid du Colombier static struct Imagealloc
283e12c5d1SDavid du Colombier {
293e12c5d1SDavid du Colombier Lock;
303e12c5d1SDavid du Colombier Image *free;
313e12c5d1SDavid du Colombier Image *hash[IHASHSIZE];
327dd7cddfSDavid du Colombier QLock ireclaim; /* mutex on reclaiming free images */
337dd7cddfSDavid du Colombier
347dd7cddfSDavid du Colombier Chan **freechan; /* free image channels */
357dd7cddfSDavid du Colombier int nfreechan; /* number of free channels */
367dd7cddfSDavid du Colombier int szfreechan; /* size of freechan array */
377dd7cddfSDavid du Colombier QLock fcreclaim; /* mutex on reclaiming free channels */
383e12c5d1SDavid du Colombier }imagealloc;
393e12c5d1SDavid du Colombier
409a747e4fSDavid du Colombier Segment* (*_globalsegattach)(Proc*, char*);
419a747e4fSDavid du Colombier
423e12c5d1SDavid du Colombier void
initseg(void)433e12c5d1SDavid du Colombier initseg(void)
443e12c5d1SDavid du Colombier {
453e12c5d1SDavid du Colombier Image *i, *ie;
463e12c5d1SDavid du Colombier
473e12c5d1SDavid du Colombier imagealloc.free = xalloc(conf.nimage*sizeof(Image));
489c63691cSDavid du Colombier if (imagealloc.free == nil)
499c63691cSDavid du Colombier panic("initseg: no memory");
503e12c5d1SDavid du Colombier ie = &imagealloc.free[conf.nimage-1];
513e12c5d1SDavid du Colombier for(i = imagealloc.free; i < ie; i++)
523e12c5d1SDavid du Colombier i->next = i+1;
533e12c5d1SDavid du Colombier i->next = 0;
547dd7cddfSDavid du Colombier imagealloc.freechan = malloc(NFREECHAN * sizeof(Chan*));
557dd7cddfSDavid du Colombier imagealloc.szfreechan = NFREECHAN;
563e12c5d1SDavid du Colombier }
573e12c5d1SDavid du Colombier
583e12c5d1SDavid du Colombier Segment *
newseg(int type,ulong base,ulong size)593e12c5d1SDavid du Colombier newseg(int type, ulong base, ulong size)
603e12c5d1SDavid du Colombier {
613e12c5d1SDavid du Colombier Segment *s;
627dd7cddfSDavid du Colombier int mapsize;
633e12c5d1SDavid du Colombier
643e12c5d1SDavid du Colombier if(size > (SEGMAPSIZE*PTEPERTAB))
653e12c5d1SDavid du Colombier error(Enovmem);
663e12c5d1SDavid du Colombier
673e12c5d1SDavid du Colombier s = smalloc(sizeof(Segment));
683e12c5d1SDavid du Colombier s->ref = 1;
693e12c5d1SDavid du Colombier s->type = type;
703e12c5d1SDavid du Colombier s->base = base;
713e12c5d1SDavid du Colombier s->top = base+(size*BY2PG);
723e12c5d1SDavid du Colombier s->size = size;
733c2ddefeSDavid du Colombier s->sema.prev = &s->sema;
743c2ddefeSDavid du Colombier s->sema.next = &s->sema;
757dd7cddfSDavid du Colombier
767dd7cddfSDavid du Colombier mapsize = ROUND(size, PTEPERTAB)/PTEPERTAB;
777dd7cddfSDavid du Colombier if(mapsize > nelem(s->ssegmap)){
787dd7cddfSDavid du Colombier mapsize *= 2;
797dd7cddfSDavid du Colombier if(mapsize > (SEGMAPSIZE*PTEPERTAB))
807dd7cddfSDavid du Colombier mapsize = (SEGMAPSIZE*PTEPERTAB);
817dd7cddfSDavid du Colombier s->map = smalloc(mapsize*sizeof(Pte*));
827dd7cddfSDavid du Colombier s->mapsize = mapsize;
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier else{
857dd7cddfSDavid du Colombier s->map = s->ssegmap;
867dd7cddfSDavid du Colombier s->mapsize = nelem(s->ssegmap);
877dd7cddfSDavid du Colombier }
887dd7cddfSDavid du Colombier
893e12c5d1SDavid du Colombier return s;
903e12c5d1SDavid du Colombier }
913e12c5d1SDavid du Colombier
923e12c5d1SDavid du Colombier void
putseg(Segment * s)933e12c5d1SDavid du Colombier putseg(Segment *s)
943e12c5d1SDavid du Colombier {
953e12c5d1SDavid du Colombier Pte **pp, **emap;
963e12c5d1SDavid du Colombier Image *i;
973e12c5d1SDavid du Colombier
983e12c5d1SDavid du Colombier if(s == 0)
993e12c5d1SDavid du Colombier return;
1003e12c5d1SDavid du Colombier
1013e12c5d1SDavid du Colombier i = s->image;
102219b2ee8SDavid du Colombier if(i != 0) {
1033e12c5d1SDavid du Colombier lock(i);
104219b2ee8SDavid du Colombier lock(s);
105219b2ee8SDavid du Colombier if(i->s == s && s->ref == 1)
1063e12c5d1SDavid du Colombier i->s = 0;
1073e12c5d1SDavid du Colombier unlock(i);
1083e12c5d1SDavid du Colombier }
109219b2ee8SDavid du Colombier else
110219b2ee8SDavid du Colombier lock(s);
1113e12c5d1SDavid du Colombier
112219b2ee8SDavid du Colombier s->ref--;
113219b2ee8SDavid du Colombier if(s->ref != 0) {
114219b2ee8SDavid du Colombier unlock(s);
115219b2ee8SDavid du Colombier return;
116219b2ee8SDavid du Colombier }
1179a747e4fSDavid du Colombier unlock(s);
118219b2ee8SDavid du Colombier
1193e12c5d1SDavid du Colombier qlock(&s->lk);
1203e12c5d1SDavid du Colombier if(i)
1213e12c5d1SDavid du Colombier putimage(i);
1223e12c5d1SDavid du Colombier
1237dd7cddfSDavid du Colombier emap = &s->map[s->mapsize];
1243e12c5d1SDavid du Colombier for(pp = s->map; pp < emap; pp++)
1253e12c5d1SDavid du Colombier if(*pp)
1263e12c5d1SDavid du Colombier freepte(s, *pp);
1273e12c5d1SDavid du Colombier
1283e12c5d1SDavid du Colombier qunlock(&s->lk);
1297dd7cddfSDavid du Colombier if(s->map != s->ssegmap)
1307dd7cddfSDavid du Colombier free(s->map);
1317dd7cddfSDavid du Colombier if(s->profile != 0)
1327dd7cddfSDavid du Colombier free(s->profile);
1333e12c5d1SDavid du Colombier free(s);
1343e12c5d1SDavid du Colombier }
1353e12c5d1SDavid du Colombier
1363e12c5d1SDavid du Colombier void
relocateseg(Segment * s,ulong offset)1373e12c5d1SDavid du Colombier relocateseg(Segment *s, ulong offset)
1383e12c5d1SDavid du Colombier {
1397dd7cddfSDavid du Colombier Page **pg, *x;
1407dd7cddfSDavid du Colombier Pte *pte, **p, **endpte;
1413e12c5d1SDavid du Colombier
1427dd7cddfSDavid du Colombier endpte = &s->map[s->mapsize];
1433e12c5d1SDavid du Colombier for(p = s->map; p < endpte; p++) {
1447dd7cddfSDavid du Colombier if(*p == 0)
1457dd7cddfSDavid du Colombier continue;
1467dd7cddfSDavid du Colombier pte = *p;
1477dd7cddfSDavid du Colombier for(pg = pte->first; pg <= pte->last; pg++) {
1487dd7cddfSDavid du Colombier if(x = *pg)
1497dd7cddfSDavid du Colombier x->va += offset;
1503e12c5d1SDavid du Colombier }
1513e12c5d1SDavid du Colombier }
1523e12c5d1SDavid du Colombier }
1533e12c5d1SDavid du Colombier
1543e12c5d1SDavid du Colombier Segment*
dupseg(Segment ** seg,int segno,int share)155bd389b36SDavid du Colombier dupseg(Segment **seg, int segno, int share)
1563e12c5d1SDavid du Colombier {
1577dd7cddfSDavid du Colombier int i, size;
1583e12c5d1SDavid du Colombier Pte *pte;
159bd389b36SDavid du Colombier Segment *n, *s;
1603e12c5d1SDavid du Colombier
1613e12c5d1SDavid du Colombier SET(n);
162bd389b36SDavid du Colombier s = seg[segno];
163bd389b36SDavid du Colombier
16480ee5cbfSDavid du Colombier qlock(&s->lk);
16580ee5cbfSDavid du Colombier if(waserror()){
16680ee5cbfSDavid du Colombier qunlock(&s->lk);
16780ee5cbfSDavid du Colombier nexterror();
16880ee5cbfSDavid du Colombier }
1693e12c5d1SDavid du Colombier switch(s->type&SG_TYPE) {
1703e12c5d1SDavid du Colombier case SG_TEXT: /* New segment shares pte set */
1713e12c5d1SDavid du Colombier case SG_SHARED:
1723e12c5d1SDavid du Colombier case SG_PHYSICAL:
17380ee5cbfSDavid du Colombier goto sameseg;
1743e12c5d1SDavid du Colombier
1753e12c5d1SDavid du Colombier case SG_STACK:
1763e12c5d1SDavid du Colombier n = newseg(s->type, s->base, s->size);
1773e12c5d1SDavid du Colombier break;
1783e12c5d1SDavid du Colombier
1793e12c5d1SDavid du Colombier case SG_BSS: /* Just copy on write */
1809a747e4fSDavid du Colombier if(share)
18180ee5cbfSDavid du Colombier goto sameseg;
1823e12c5d1SDavid du Colombier n = newseg(s->type, s->base, s->size);
1833e12c5d1SDavid du Colombier break;
1843e12c5d1SDavid du Colombier
1853e12c5d1SDavid du Colombier case SG_DATA: /* Copy on write plus demand load info */
18680ee5cbfSDavid du Colombier if(segno == TSEG){
18780ee5cbfSDavid du Colombier poperror();
18880ee5cbfSDavid du Colombier qunlock(&s->lk);
189bd389b36SDavid du Colombier return data2txt(s);
1903e12c5d1SDavid du Colombier }
19180ee5cbfSDavid du Colombier
1929a747e4fSDavid du Colombier if(share)
19380ee5cbfSDavid du Colombier goto sameseg;
1943e12c5d1SDavid du Colombier n = newseg(s->type, s->base, s->size);
1953e12c5d1SDavid du Colombier
1963e12c5d1SDavid du Colombier incref(s->image);
1973e12c5d1SDavid du Colombier n->image = s->image;
1983e12c5d1SDavid du Colombier n->fstart = s->fstart;
1993e12c5d1SDavid du Colombier n->flen = s->flen;
2003e12c5d1SDavid du Colombier break;
2013e12c5d1SDavid du Colombier }
2027dd7cddfSDavid du Colombier size = s->mapsize;
2037dd7cddfSDavid du Colombier for(i = 0; i < size; i++)
2043e12c5d1SDavid du Colombier if(pte = s->map[i])
2053e12c5d1SDavid du Colombier n->map[i] = ptecpy(pte);
2063e12c5d1SDavid du Colombier
2073e12c5d1SDavid du Colombier n->flushme = s->flushme;
2089a747e4fSDavid du Colombier if(s->ref > 1)
2099a747e4fSDavid du Colombier procflushseg(s);
21080ee5cbfSDavid du Colombier poperror();
2113e12c5d1SDavid du Colombier qunlock(&s->lk);
2123e12c5d1SDavid du Colombier return n;
21380ee5cbfSDavid du Colombier
21480ee5cbfSDavid du Colombier sameseg:
21580ee5cbfSDavid du Colombier incref(s);
21680ee5cbfSDavid du Colombier poperror();
21780ee5cbfSDavid du Colombier qunlock(&s->lk);
21880ee5cbfSDavid du Colombier return s;
2193e12c5d1SDavid du Colombier }
2203e12c5d1SDavid du Colombier
2213e12c5d1SDavid du Colombier void
segpage(Segment * s,Page * p)2223e12c5d1SDavid du Colombier segpage(Segment *s, Page *p)
2233e12c5d1SDavid du Colombier {
2243e12c5d1SDavid du Colombier Pte **pte;
2253e12c5d1SDavid du Colombier ulong off;
2263e12c5d1SDavid du Colombier Page **pg;
2273e12c5d1SDavid du Colombier
2283e12c5d1SDavid du Colombier if(p->va < s->base || p->va >= s->top)
2293e12c5d1SDavid du Colombier panic("segpage");
2303e12c5d1SDavid du Colombier
2313e12c5d1SDavid du Colombier off = p->va - s->base;
2323e12c5d1SDavid du Colombier pte = &s->map[off/PTEMAPMEM];
2333e12c5d1SDavid du Colombier if(*pte == 0)
2343e12c5d1SDavid du Colombier *pte = ptealloc();
2353e12c5d1SDavid du Colombier
2363e12c5d1SDavid du Colombier pg = &(*pte)->pages[(off&(PTEMAPMEM-1))/BY2PG];
2373e12c5d1SDavid du Colombier *pg = p;
2383e12c5d1SDavid du Colombier if(pg < (*pte)->first)
2393e12c5d1SDavid du Colombier (*pte)->first = pg;
2403e12c5d1SDavid du Colombier if(pg > (*pte)->last)
2413e12c5d1SDavid du Colombier (*pte)->last = pg;
2423e12c5d1SDavid du Colombier }
2433e12c5d1SDavid du Colombier
2443e12c5d1SDavid du Colombier Image*
attachimage(int type,Chan * c,ulong base,ulong len)2453e12c5d1SDavid du Colombier attachimage(int type, Chan *c, ulong base, ulong len)
2463e12c5d1SDavid du Colombier {
2473e12c5d1SDavid du Colombier Image *i, **l;
2483e12c5d1SDavid du Colombier
2497dd7cddfSDavid du Colombier /* reclaim any free channels from reclaimed segments */
2507dd7cddfSDavid du Colombier if(imagealloc.nfreechan)
2517dd7cddfSDavid du Colombier imagechanreclaim();
2527dd7cddfSDavid du Colombier
2533e12c5d1SDavid du Colombier lock(&imagealloc);
2543e12c5d1SDavid du Colombier
2553e12c5d1SDavid du Colombier /*
2563e12c5d1SDavid du Colombier * Search the image cache for remains of the text from a previous
2573e12c5d1SDavid du Colombier * or currently running incarnation
2583e12c5d1SDavid du Colombier */
2593e12c5d1SDavid du Colombier for(i = ihash(c->qid.path); i; i = i->hash) {
2603e12c5d1SDavid du Colombier if(c->qid.path == i->qid.path) {
2613e12c5d1SDavid du Colombier lock(i);
2623e12c5d1SDavid du Colombier if(eqqid(c->qid, i->qid) &&
2633e12c5d1SDavid du Colombier eqqid(c->mqid, i->mqid) &&
2643e12c5d1SDavid du Colombier c->mchan == i->mchan &&
2653e12c5d1SDavid du Colombier c->type == i->type) {
2663e12c5d1SDavid du Colombier goto found;
2673e12c5d1SDavid du Colombier }
2683e12c5d1SDavid du Colombier unlock(i);
2693e12c5d1SDavid du Colombier }
2703e12c5d1SDavid du Colombier }
2713e12c5d1SDavid du Colombier
2723e12c5d1SDavid du Colombier /*
2733e12c5d1SDavid du Colombier * imagereclaim dumps pages from the free list which are cached by image
2743e12c5d1SDavid du Colombier * structures. This should free some image structures.
2753e12c5d1SDavid du Colombier */
2763e12c5d1SDavid du Colombier while(!(i = imagealloc.free)) {
2773e12c5d1SDavid du Colombier unlock(&imagealloc);
2783e12c5d1SDavid du Colombier imagereclaim();
2797dd7cddfSDavid du Colombier sched();
2803e12c5d1SDavid du Colombier lock(&imagealloc);
2813e12c5d1SDavid du Colombier }
2823e12c5d1SDavid du Colombier
2833e12c5d1SDavid du Colombier imagealloc.free = i->next;
2843e12c5d1SDavid du Colombier
2853e12c5d1SDavid du Colombier lock(i);
2863e12c5d1SDavid du Colombier incref(c);
2873e12c5d1SDavid du Colombier i->c = c;
2883e12c5d1SDavid du Colombier i->type = c->type;
2893e12c5d1SDavid du Colombier i->qid = c->qid;
2903e12c5d1SDavid du Colombier i->mqid = c->mqid;
2913e12c5d1SDavid du Colombier i->mchan = c->mchan;
2923e12c5d1SDavid du Colombier l = &ihash(c->qid.path);
2933e12c5d1SDavid du Colombier i->hash = *l;
2943e12c5d1SDavid du Colombier *l = i;
2953e12c5d1SDavid du Colombier found:
2963e12c5d1SDavid du Colombier unlock(&imagealloc);
2973e12c5d1SDavid du Colombier
2983e12c5d1SDavid du Colombier if(i->s == 0) {
299219b2ee8SDavid du Colombier /* Disaster after commit in exec */
300219b2ee8SDavid du Colombier if(waserror()) {
301219b2ee8SDavid du Colombier unlock(i);
302219b2ee8SDavid du Colombier pexit(Enovmem, 1);
303219b2ee8SDavid du Colombier }
3043e12c5d1SDavid du Colombier i->s = newseg(type, base, len);
3053e12c5d1SDavid du Colombier i->s->image = i;
3062839d78eSDavid du Colombier i->ref++;
307219b2ee8SDavid du Colombier poperror();
3083e12c5d1SDavid du Colombier }
3093e12c5d1SDavid du Colombier else
3103e12c5d1SDavid du Colombier incref(i->s);
3113e12c5d1SDavid du Colombier
3123e12c5d1SDavid du Colombier return i;
3133e12c5d1SDavid du Colombier }
3143e12c5d1SDavid du Colombier
3157dd7cddfSDavid du Colombier static struct {
3167dd7cddfSDavid du Colombier int calls; /* times imagereclaim was called */
3177dd7cddfSDavid du Colombier int loops; /* times the main loop was run */
3187dd7cddfSDavid du Colombier uvlong ticks; /* total time in the main loop */
3197dd7cddfSDavid du Colombier uvlong maxt; /* longest time in main loop */
3207dd7cddfSDavid du Colombier } irstats;
3217dd7cddfSDavid du Colombier
3227dd7cddfSDavid du Colombier static void
imagereclaim(void)3233e12c5d1SDavid du Colombier imagereclaim(void)
3243e12c5d1SDavid du Colombier {
3255437ee90SDavid du Colombier int n;
3263e12c5d1SDavid du Colombier Page *p;
3277dd7cddfSDavid du Colombier uvlong ticks;
3283e12c5d1SDavid du Colombier
3297dd7cddfSDavid du Colombier irstats.calls++;
3303e12c5d1SDavid du Colombier /* Somebody is already cleaning the page cache */
3313e12c5d1SDavid du Colombier if(!canqlock(&imagealloc.ireclaim))
3323e12c5d1SDavid du Colombier return;
3333e12c5d1SDavid du Colombier
3343e12c5d1SDavid du Colombier lock(&palloc);
3357dd7cddfSDavid du Colombier ticks = fastticks(nil);
3365437ee90SDavid du Colombier n = 0;
3375437ee90SDavid du Colombier /*
3385437ee90SDavid du Colombier * All the pages with images backing them are at the
3395437ee90SDavid du Colombier * end of the list (see putpage) so start there and work
3405437ee90SDavid du Colombier * backward.
3415437ee90SDavid du Colombier */
3425437ee90SDavid du Colombier for(p = palloc.tail; p && p->image && n<1000; p = p->prev) {
3435437ee90SDavid du Colombier if(p->ref == 0 && canlock(p)) {
3445437ee90SDavid du Colombier if(p->ref == 0) {
3455437ee90SDavid du Colombier n++;
3463e12c5d1SDavid du Colombier uncachepage(p);
3475437ee90SDavid du Colombier }
3483e12c5d1SDavid du Colombier unlock(p);
3493e12c5d1SDavid du Colombier }
3503e12c5d1SDavid du Colombier }
3517dd7cddfSDavid du Colombier ticks = fastticks(nil) - ticks;
3523e12c5d1SDavid du Colombier unlock(&palloc);
3537dd7cddfSDavid du Colombier irstats.loops++;
3547dd7cddfSDavid du Colombier irstats.ticks += ticks;
3557dd7cddfSDavid du Colombier if(ticks > irstats.maxt)
3567dd7cddfSDavid du Colombier irstats.maxt = ticks;
3577dd7cddfSDavid du Colombier //print("T%llud+", ticks);
3583e12c5d1SDavid du Colombier qunlock(&imagealloc.ireclaim);
3593e12c5d1SDavid du Colombier }
3603e12c5d1SDavid du Colombier
3617dd7cddfSDavid du Colombier /*
3627dd7cddfSDavid du Colombier * since close can block, this has to be called outside of
3637dd7cddfSDavid du Colombier * spin locks.
3647dd7cddfSDavid du Colombier */
3657dd7cddfSDavid du Colombier static void
imagechanreclaim(void)3667dd7cddfSDavid du Colombier imagechanreclaim(void)
3677dd7cddfSDavid du Colombier {
3687dd7cddfSDavid du Colombier Chan *c;
3697dd7cddfSDavid du Colombier
3707dd7cddfSDavid du Colombier /* Somebody is already cleaning the image chans */
3717dd7cddfSDavid du Colombier if(!canqlock(&imagealloc.fcreclaim))
3727dd7cddfSDavid du Colombier return;
3737dd7cddfSDavid du Colombier
3747dd7cddfSDavid du Colombier /*
3757dd7cddfSDavid du Colombier * We don't have to recheck that nfreechan > 0 after we
3767dd7cddfSDavid du Colombier * acquire the lock, because we're the only ones who decrement
3777dd7cddfSDavid du Colombier * it (the other lock contender increments it), and there's only
3787dd7cddfSDavid du Colombier * one of us thanks to the qlock above.
3797dd7cddfSDavid du Colombier */
3807dd7cddfSDavid du Colombier while(imagealloc.nfreechan > 0){
3817dd7cddfSDavid du Colombier lock(&imagealloc);
3827dd7cddfSDavid du Colombier imagealloc.nfreechan--;
3837dd7cddfSDavid du Colombier c = imagealloc.freechan[imagealloc.nfreechan];
3847dd7cddfSDavid du Colombier unlock(&imagealloc);
3857dd7cddfSDavid du Colombier cclose(c);
3867dd7cddfSDavid du Colombier }
3877dd7cddfSDavid du Colombier
3887dd7cddfSDavid du Colombier qunlock(&imagealloc.fcreclaim);
3897dd7cddfSDavid du Colombier }
3907dd7cddfSDavid du Colombier
3913e12c5d1SDavid du Colombier void
putimage(Image * i)3923e12c5d1SDavid du Colombier putimage(Image *i)
3933e12c5d1SDavid du Colombier {
3947dd7cddfSDavid du Colombier Chan *c, **cp;
3953e12c5d1SDavid du Colombier Image *f, **l;
3963e12c5d1SDavid du Colombier
3977dd7cddfSDavid du Colombier if(i->notext)
3983e12c5d1SDavid du Colombier return;
3993e12c5d1SDavid du Colombier
4003e12c5d1SDavid du Colombier lock(i);
4013e12c5d1SDavid du Colombier if(--i->ref == 0) {
4023e12c5d1SDavid du Colombier l = &ihash(i->qid.path);
4039a747e4fSDavid du Colombier mkqid(&i->qid, ~0, ~0, QTFILE);
4043e12c5d1SDavid du Colombier unlock(i);
4053e12c5d1SDavid du Colombier c = i->c;
4063e12c5d1SDavid du Colombier
4073e12c5d1SDavid du Colombier lock(&imagealloc);
4083e12c5d1SDavid du Colombier for(f = *l; f; f = f->hash) {
4093e12c5d1SDavid du Colombier if(f == i) {
4103e12c5d1SDavid du Colombier *l = i->hash;
4113e12c5d1SDavid du Colombier break;
4123e12c5d1SDavid du Colombier }
4133e12c5d1SDavid du Colombier l = &f->hash;
4143e12c5d1SDavid du Colombier }
4153e12c5d1SDavid du Colombier
4163e12c5d1SDavid du Colombier i->next = imagealloc.free;
4173e12c5d1SDavid du Colombier imagealloc.free = i;
4187dd7cddfSDavid du Colombier
4197dd7cddfSDavid du Colombier /* defer freeing channel till we're out of spin lock's */
4207dd7cddfSDavid du Colombier if(imagealloc.nfreechan == imagealloc.szfreechan){
4217dd7cddfSDavid du Colombier imagealloc.szfreechan += NFREECHAN;
4227dd7cddfSDavid du Colombier cp = malloc(imagealloc.szfreechan*sizeof(Chan*));
4237dd7cddfSDavid du Colombier if(cp == nil)
4247dd7cddfSDavid du Colombier panic("putimage");
4257dd7cddfSDavid du Colombier memmove(cp, imagealloc.freechan, imagealloc.nfreechan*sizeof(Chan*));
4267dd7cddfSDavid du Colombier free(imagealloc.freechan);
4277dd7cddfSDavid du Colombier imagealloc.freechan = cp;
4287dd7cddfSDavid du Colombier }
4297dd7cddfSDavid du Colombier imagealloc.freechan[imagealloc.nfreechan++] = c;
4303e12c5d1SDavid du Colombier unlock(&imagealloc);
4313e12c5d1SDavid du Colombier
4323e12c5d1SDavid du Colombier return;
4333e12c5d1SDavid du Colombier }
4343e12c5d1SDavid du Colombier unlock(i);
4353e12c5d1SDavid du Colombier }
4363e12c5d1SDavid du Colombier
4373e12c5d1SDavid du Colombier long
ibrk(ulong addr,int seg)4383e12c5d1SDavid du Colombier ibrk(ulong addr, int seg)
4393e12c5d1SDavid du Colombier {
4403e12c5d1SDavid du Colombier Segment *s, *ns;
4413e12c5d1SDavid du Colombier ulong newtop, newsize;
4427dd7cddfSDavid du Colombier int i, mapsize;
4437dd7cddfSDavid du Colombier Pte **map;
4443e12c5d1SDavid du Colombier
4457dd7cddfSDavid du Colombier s = up->seg[seg];
4463e12c5d1SDavid du Colombier if(s == 0)
4473e12c5d1SDavid du Colombier error(Ebadarg);
4483e12c5d1SDavid du Colombier
4493e12c5d1SDavid du Colombier if(addr == 0)
4503e12c5d1SDavid du Colombier return s->base;
4513e12c5d1SDavid du Colombier
4523e12c5d1SDavid du Colombier qlock(&s->lk);
4533e12c5d1SDavid du Colombier
4543e12c5d1SDavid du Colombier /* We may start with the bss overlapping the data */
4553e12c5d1SDavid du Colombier if(addr < s->base) {
4567dd7cddfSDavid du Colombier if(seg != BSEG || up->seg[DSEG] == 0 || addr < up->seg[DSEG]->base) {
4573e12c5d1SDavid du Colombier qunlock(&s->lk);
4583e12c5d1SDavid du Colombier error(Enovmem);
4593e12c5d1SDavid du Colombier }
4603e12c5d1SDavid du Colombier addr = s->base;
4613e12c5d1SDavid du Colombier }
4623e12c5d1SDavid du Colombier
4633e12c5d1SDavid du Colombier newtop = PGROUND(addr);
4643e12c5d1SDavid du Colombier newsize = (newtop-s->base)/BY2PG;
4653e12c5d1SDavid du Colombier if(newtop < s->top) {
466*d1be6b08SDavid du Colombier /*
467*d1be6b08SDavid du Colombier * do not shrink a segment shared with other procs, as the
468*d1be6b08SDavid du Colombier * to-be-freed address space may have been passed to the kernel
469*d1be6b08SDavid du Colombier * already by another proc and is past the validaddr stage.
470*d1be6b08SDavid du Colombier */
471*d1be6b08SDavid du Colombier if(s->ref > 1){
472*d1be6b08SDavid du Colombier qunlock(&s->lk);
473*d1be6b08SDavid du Colombier error(Einuse);
474*d1be6b08SDavid du Colombier }
4753e12c5d1SDavid du Colombier mfreeseg(s, newtop, (s->top-newtop)/BY2PG);
4764aeffbf5SDavid du Colombier s->top = newtop;
4774aeffbf5SDavid du Colombier s->size = newsize;
4783e12c5d1SDavid du Colombier qunlock(&s->lk);
479bd389b36SDavid du Colombier flushmmu();
4803e12c5d1SDavid du Colombier return 0;
4813e12c5d1SDavid du Colombier }
4823e12c5d1SDavid du Colombier
4833e12c5d1SDavid du Colombier for(i = 0; i < NSEG; i++) {
4847dd7cddfSDavid du Colombier ns = up->seg[i];
4853e12c5d1SDavid du Colombier if(ns == 0 || ns == s)
4863e12c5d1SDavid du Colombier continue;
4873e12c5d1SDavid du Colombier if(newtop >= ns->base && newtop < ns->top) {
4883e12c5d1SDavid du Colombier qunlock(&s->lk);
4893e12c5d1SDavid du Colombier error(Esoverlap);
4903e12c5d1SDavid du Colombier }
4913e12c5d1SDavid du Colombier }
4923e12c5d1SDavid du Colombier
4937dd7cddfSDavid du Colombier if(newsize > (SEGMAPSIZE*PTEPERTAB)) {
4943e12c5d1SDavid du Colombier qunlock(&s->lk);
4953e12c5d1SDavid du Colombier error(Enovmem);
4963e12c5d1SDavid du Colombier }
4977dd7cddfSDavid du Colombier mapsize = ROUND(newsize, PTEPERTAB)/PTEPERTAB;
4987dd7cddfSDavid du Colombier if(mapsize > s->mapsize){
4997dd7cddfSDavid du Colombier map = smalloc(mapsize*sizeof(Pte*));
5007dd7cddfSDavid du Colombier memmove(map, s->map, s->mapsize*sizeof(Pte*));
5017dd7cddfSDavid du Colombier if(s->map != s->ssegmap)
5027dd7cddfSDavid du Colombier free(s->map);
5037dd7cddfSDavid du Colombier s->map = map;
5047dd7cddfSDavid du Colombier s->mapsize = mapsize;
5057dd7cddfSDavid du Colombier }
5063e12c5d1SDavid du Colombier
5073e12c5d1SDavid du Colombier s->top = newtop;
5083e12c5d1SDavid du Colombier s->size = newsize;
5093e12c5d1SDavid du Colombier qunlock(&s->lk);
5103e12c5d1SDavid du Colombier return 0;
5113e12c5d1SDavid du Colombier }
5123e12c5d1SDavid du Colombier
5137dd7cddfSDavid du Colombier /*
5147dd7cddfSDavid du Colombier * called with s->lk locked
5157dd7cddfSDavid du Colombier */
5163e12c5d1SDavid du Colombier void
mfreeseg(Segment * s,ulong start,int pages)5173e12c5d1SDavid du Colombier mfreeseg(Segment *s, ulong start, int pages)
5183e12c5d1SDavid du Colombier {
5197dd7cddfSDavid du Colombier int i, j, size;
5203e12c5d1SDavid du Colombier ulong soff;
5213e12c5d1SDavid du Colombier Page *pg;
5227dd7cddfSDavid du Colombier Page *list;
5233e12c5d1SDavid du Colombier
5243e12c5d1SDavid du Colombier soff = start-s->base;
5253e12c5d1SDavid du Colombier j = (soff&(PTEMAPMEM-1))/BY2PG;
5263e12c5d1SDavid du Colombier
5277dd7cddfSDavid du Colombier size = s->mapsize;
5287dd7cddfSDavid du Colombier list = nil;
5297dd7cddfSDavid du Colombier for(i = soff/PTEMAPMEM; i < size; i++) {
5303e12c5d1SDavid du Colombier if(pages <= 0)
531bd389b36SDavid du Colombier break;
532bd389b36SDavid du Colombier if(s->map[i] == 0) {
533bd389b36SDavid du Colombier pages -= PTEPERTAB-j;
534bd389b36SDavid du Colombier j = 0;
535bd389b36SDavid du Colombier continue;
536bd389b36SDavid du Colombier }
5373e12c5d1SDavid du Colombier while(j < PTEPERTAB) {
538bd389b36SDavid du Colombier pg = s->map[i]->pages[j];
5393ff48bf5SDavid du Colombier /*
5403ff48bf5SDavid du Colombier * We want to zero s->map[i]->page[j] and putpage(pg),
5414de34a7eSDavid du Colombier * but we have to make sure other processors flush the
5423ff48bf5SDavid du Colombier * entry from their TLBs before the page is freed.
5433ff48bf5SDavid du Colombier * We construct a list of the pages to be freed, zero
5443ff48bf5SDavid du Colombier * the entries, then (below) call procflushseg, and call
5453ff48bf5SDavid du Colombier * putpage on the whole list.
5463ff48bf5SDavid du Colombier *
5473ff48bf5SDavid du Colombier * Swapped-out pages don't appear in TLBs, so it's okay
5483ff48bf5SDavid du Colombier * to putswap those pages before procflushseg.
5493ff48bf5SDavid du Colombier */
550bd389b36SDavid du Colombier if(pg){
5513ff48bf5SDavid du Colombier if(onswap(pg))
5523ff48bf5SDavid du Colombier putswap(pg);
5533ff48bf5SDavid du Colombier else{
5547dd7cddfSDavid du Colombier pg->next = list;
5557dd7cddfSDavid du Colombier list = pg;
5563e12c5d1SDavid du Colombier }
5573ff48bf5SDavid du Colombier s->map[i]->pages[j] = 0;
5583ff48bf5SDavid du Colombier }
5593e12c5d1SDavid du Colombier if(--pages == 0)
5607dd7cddfSDavid du Colombier goto out;
5613e12c5d1SDavid du Colombier j++;
5623e12c5d1SDavid du Colombier }
5633e12c5d1SDavid du Colombier j = 0;
5643e12c5d1SDavid du Colombier }
5657dd7cddfSDavid du Colombier out:
5667dd7cddfSDavid du Colombier /* flush this seg in all other processes */
5679a747e4fSDavid du Colombier if(s->ref > 1)
5687dd7cddfSDavid du Colombier procflushseg(s);
5693e12c5d1SDavid du Colombier
5707dd7cddfSDavid du Colombier /* free the pages */
5717dd7cddfSDavid du Colombier for(pg = list; pg != nil; pg = list){
5727dd7cddfSDavid du Colombier list = list->next;
5737dd7cddfSDavid du Colombier putpage(pg);
5747dd7cddfSDavid du Colombier }
5757dd7cddfSDavid du Colombier }
5767dd7cddfSDavid du Colombier
5777dd7cddfSDavid du Colombier Segment*
isoverlap(Proc * p,ulong va,int len)5787dd7cddfSDavid du Colombier isoverlap(Proc *p, ulong va, int len)
579219b2ee8SDavid du Colombier {
580219b2ee8SDavid du Colombier int i;
581219b2ee8SDavid du Colombier Segment *ns;
582219b2ee8SDavid du Colombier ulong newtop;
583219b2ee8SDavid du Colombier
584219b2ee8SDavid du Colombier newtop = va+len;
585219b2ee8SDavid du Colombier for(i = 0; i < NSEG; i++) {
5867dd7cddfSDavid du Colombier ns = p->seg[i];
587219b2ee8SDavid du Colombier if(ns == 0)
588219b2ee8SDavid du Colombier continue;
589219b2ee8SDavid du Colombier if((newtop > ns->base && newtop <= ns->top) ||
590219b2ee8SDavid du Colombier (va >= ns->base && va < ns->top))
5917dd7cddfSDavid du Colombier return ns;
592219b2ee8SDavid du Colombier }
5937dd7cddfSDavid du Colombier return nil;
5947dd7cddfSDavid du Colombier }
5957dd7cddfSDavid du Colombier
5967dd7cddfSDavid du Colombier int
addphysseg(Physseg * new)5977dd7cddfSDavid du Colombier addphysseg(Physseg* new)
5987dd7cddfSDavid du Colombier {
5997dd7cddfSDavid du Colombier Physseg *ps;
6007dd7cddfSDavid du Colombier
6017dd7cddfSDavid du Colombier /*
6027dd7cddfSDavid du Colombier * Check not already entered and there is room
6037dd7cddfSDavid du Colombier * for a new entry and the terminating null entry.
6047dd7cddfSDavid du Colombier */
6057dd7cddfSDavid du Colombier lock(&physseglock);
6067dd7cddfSDavid du Colombier for(ps = physseg; ps->name; ps++){
6077dd7cddfSDavid du Colombier if(strcmp(ps->name, new->name) == 0){
6087dd7cddfSDavid du Colombier unlock(&physseglock);
6097dd7cddfSDavid du Colombier return -1;
6107dd7cddfSDavid du Colombier }
6117dd7cddfSDavid du Colombier }
6127dd7cddfSDavid du Colombier if(ps-physseg >= nelem(physseg)-2){
6137dd7cddfSDavid du Colombier unlock(&physseglock);
6147dd7cddfSDavid du Colombier return -1;
6157dd7cddfSDavid du Colombier }
6167dd7cddfSDavid du Colombier
6177dd7cddfSDavid du Colombier *ps = *new;
6187dd7cddfSDavid du Colombier unlock(&physseglock);
6197dd7cddfSDavid du Colombier
620219b2ee8SDavid du Colombier return 0;
621219b2ee8SDavid du Colombier }
622219b2ee8SDavid du Colombier
6239a747e4fSDavid du Colombier int
isphysseg(char * name)6249a747e4fSDavid du Colombier isphysseg(char *name)
6259a747e4fSDavid du Colombier {
6269a747e4fSDavid du Colombier Physseg *ps;
6279a747e4fSDavid du Colombier int rv = 0;
6289a747e4fSDavid du Colombier
6299a747e4fSDavid du Colombier lock(&physseglock);
6309a747e4fSDavid du Colombier for(ps = physseg; ps->name; ps++){
6319a747e4fSDavid du Colombier if(strcmp(ps->name, name) == 0){
6329a747e4fSDavid du Colombier rv = 1;
6339a747e4fSDavid du Colombier break;
6349a747e4fSDavid du Colombier }
6359a747e4fSDavid du Colombier }
6369a747e4fSDavid du Colombier unlock(&physseglock);
6379a747e4fSDavid du Colombier return rv;
6389a747e4fSDavid du Colombier }
6399a747e4fSDavid du Colombier
6403e12c5d1SDavid du Colombier ulong
segattach(Proc * p,ulong attr,char * name,ulong va,ulong len)6413e12c5d1SDavid du Colombier segattach(Proc *p, ulong attr, char *name, ulong va, ulong len)
6423e12c5d1SDavid du Colombier {
6437dd7cddfSDavid du Colombier int sno;
6447dd7cddfSDavid du Colombier Segment *s, *os;
645219b2ee8SDavid du Colombier Physseg *ps;
6463e12c5d1SDavid du Colombier
6474de34a7eSDavid du Colombier if(va != 0 && va >= USTKTOP)
6483e12c5d1SDavid du Colombier error(Ebadarg);
6493e12c5d1SDavid du Colombier
6503e12c5d1SDavid du Colombier validaddr((ulong)name, 1, 0);
6513e12c5d1SDavid du Colombier vmemchr(name, 0, ~0);
6523e12c5d1SDavid du Colombier
6533e12c5d1SDavid du Colombier for(sno = 0; sno < NSEG; sno++)
6547dd7cddfSDavid du Colombier if(p->seg[sno] == nil && sno != ESEG)
6553e12c5d1SDavid du Colombier break;
6563e12c5d1SDavid du Colombier
6573e12c5d1SDavid du Colombier if(sno == NSEG)
6583e12c5d1SDavid du Colombier error(Enovmem);
6593e12c5d1SDavid du Colombier
6609a747e4fSDavid du Colombier /*
6619a747e4fSDavid du Colombier * first look for a global segment with the
6629a747e4fSDavid du Colombier * same name
6639a747e4fSDavid du Colombier */
6649a747e4fSDavid du Colombier if(_globalsegattach != nil){
6659a747e4fSDavid du Colombier s = (*_globalsegattach)(p, name);
6669a747e4fSDavid du Colombier if(s != nil){
6679a747e4fSDavid du Colombier p->seg[sno] = s;
6689a747e4fSDavid du Colombier return s->base;
6699a747e4fSDavid du Colombier }
6709a747e4fSDavid du Colombier }
6719a747e4fSDavid du Colombier
6723e12c5d1SDavid du Colombier len = PGROUND(len);
6737dd7cddfSDavid du Colombier if(len == 0)
6747dd7cddfSDavid du Colombier error(Ebadarg);
675219b2ee8SDavid du Colombier
6767dd7cddfSDavid du Colombier /*
6777dd7cddfSDavid du Colombier * Find a hole in the address space.
6787dd7cddfSDavid du Colombier * Starting at the lowest possible stack address - len,
6797dd7cddfSDavid du Colombier * check for an overlapping segment, and repeat at the
6807dd7cddfSDavid du Colombier * base of that segment - len until either a hole is found
681*d1be6b08SDavid du Colombier * or the address space is exhausted. Ensure that we don't
682*d1be6b08SDavid du Colombier * map the zero page.
6837dd7cddfSDavid du Colombier */
684219b2ee8SDavid du Colombier if(va == 0) {
685*d1be6b08SDavid du Colombier for (os = p->seg[SSEG]; os != nil; os = isoverlap(p, va, len)) {
6867dd7cddfSDavid du Colombier va = os->base;
687*d1be6b08SDavid du Colombier if(len >= va)
6887dd7cddfSDavid du Colombier error(Enovmem);
689219b2ee8SDavid du Colombier va -= len;
6903e12c5d1SDavid du Colombier }
691*d1be6b08SDavid du Colombier va &= ~(BY2PG-1);
692*d1be6b08SDavid du Colombier } else {
693*d1be6b08SDavid du Colombier va &= ~(BY2PG-1);
694*d1be6b08SDavid du Colombier if(va == 0 || va >= USTKTOP)
695*d1be6b08SDavid du Colombier error(Ebadarg);
696219b2ee8SDavid du Colombier }
697219b2ee8SDavid du Colombier
6987dd7cddfSDavid du Colombier if(isoverlap(p, va, len) != nil)
699219b2ee8SDavid du Colombier error(Esoverlap);
7003e12c5d1SDavid du Colombier
7013e12c5d1SDavid du Colombier for(ps = physseg; ps->name; ps++)
7023e12c5d1SDavid du Colombier if(strcmp(name, ps->name) == 0)
7033e12c5d1SDavid du Colombier goto found;
7043e12c5d1SDavid du Colombier
7053e12c5d1SDavid du Colombier error(Ebadarg);
7063e12c5d1SDavid du Colombier found:
7073e12c5d1SDavid du Colombier if(len > ps->size)
7083e12c5d1SDavid du Colombier error(Enovmem);
7093e12c5d1SDavid du Colombier
7107dd7cddfSDavid du Colombier attr &= ~SG_TYPE; /* Turn off what is not allowed */
7113e12c5d1SDavid du Colombier attr |= ps->attr; /* Copy in defaults */
7123e12c5d1SDavid du Colombier
7133e12c5d1SDavid du Colombier s = newseg(attr, va, len/BY2PG);
714219b2ee8SDavid du Colombier s->pseg = ps;
7157dd7cddfSDavid du Colombier p->seg[sno] = s;
7163e12c5d1SDavid du Colombier
717219b2ee8SDavid du Colombier return va;
7183e12c5d1SDavid du Colombier }
7193e12c5d1SDavid du Colombier
720219b2ee8SDavid du Colombier void
pteflush(Pte * pte,int s,int e)721219b2ee8SDavid du Colombier pteflush(Pte *pte, int s, int e)
722219b2ee8SDavid du Colombier {
723219b2ee8SDavid du Colombier int i;
724219b2ee8SDavid du Colombier Page *p;
725219b2ee8SDavid du Colombier
726219b2ee8SDavid du Colombier for(i = s; i < e; i++) {
727219b2ee8SDavid du Colombier p = pte->pages[i];
728219b2ee8SDavid du Colombier if(pagedout(p) == 0)
729219b2ee8SDavid du Colombier memset(p->cachectl, PG_TXTFLUSH, sizeof(p->cachectl));
730219b2ee8SDavid du Colombier }
731219b2ee8SDavid du Colombier }
732219b2ee8SDavid du Colombier
7333e12c5d1SDavid du Colombier long
syssegflush(ulong * arg)7343e12c5d1SDavid du Colombier syssegflush(ulong *arg)
7357dd7cddfSDavid du Colombier {
7367dd7cddfSDavid du Colombier Segment *s;
737219b2ee8SDavid du Colombier ulong addr, l;
738219b2ee8SDavid du Colombier Pte *pte;
739219b2ee8SDavid du Colombier int chunk, ps, pe, len;
7403e12c5d1SDavid du Colombier
741219b2ee8SDavid du Colombier addr = arg[0];
742219b2ee8SDavid du Colombier len = arg[1];
743219b2ee8SDavid du Colombier
744219b2ee8SDavid du Colombier while(len > 0) {
7457dd7cddfSDavid du Colombier s = seg(up, addr, 1);
7463e12c5d1SDavid du Colombier if(s == 0)
7473e12c5d1SDavid du Colombier error(Ebadarg);
7483e12c5d1SDavid du Colombier
7493e12c5d1SDavid du Colombier s->flushme = 1;
750219b2ee8SDavid du Colombier more:
751219b2ee8SDavid du Colombier l = len;
752219b2ee8SDavid du Colombier if(addr+l > s->top)
753219b2ee8SDavid du Colombier l = s->top - addr;
7543e12c5d1SDavid du Colombier
755219b2ee8SDavid du Colombier ps = addr-s->base;
756219b2ee8SDavid du Colombier pte = s->map[ps/PTEMAPMEM];
757219b2ee8SDavid du Colombier ps &= PTEMAPMEM-1;
758219b2ee8SDavid du Colombier pe = PTEMAPMEM;
759219b2ee8SDavid du Colombier if(pe-ps > l){
760219b2ee8SDavid du Colombier pe = ps + l;
761219b2ee8SDavid du Colombier pe = (pe+BY2PG-1)&~(BY2PG-1);
7623e12c5d1SDavid du Colombier }
763219b2ee8SDavid du Colombier if(pe == ps) {
7643e12c5d1SDavid du Colombier qunlock(&s->lk);
765219b2ee8SDavid du Colombier error(Ebadarg);
766219b2ee8SDavid du Colombier }
767219b2ee8SDavid du Colombier
768219b2ee8SDavid du Colombier if(pte)
769219b2ee8SDavid du Colombier pteflush(pte, ps/BY2PG, pe/BY2PG);
770219b2ee8SDavid du Colombier
771219b2ee8SDavid du Colombier chunk = pe-ps;
772219b2ee8SDavid du Colombier len -= chunk;
773219b2ee8SDavid du Colombier addr += chunk;
774219b2ee8SDavid du Colombier
775219b2ee8SDavid du Colombier if(len > 0 && addr < s->top)
776219b2ee8SDavid du Colombier goto more;
777219b2ee8SDavid du Colombier
778219b2ee8SDavid du Colombier qunlock(&s->lk);
779219b2ee8SDavid du Colombier }
7803e12c5d1SDavid du Colombier flushmmu();
7813e12c5d1SDavid du Colombier return 0;
7823e12c5d1SDavid du Colombier }
7837dd7cddfSDavid du Colombier
7847dd7cddfSDavid du Colombier void
segclock(ulong pc)7857dd7cddfSDavid du Colombier segclock(ulong pc)
7867dd7cddfSDavid du Colombier {
7877dd7cddfSDavid du Colombier Segment *s;
7887dd7cddfSDavid du Colombier
7897dd7cddfSDavid du Colombier s = up->seg[TSEG];
7907dd7cddfSDavid du Colombier if(s == 0 || s->profile == 0)
7917dd7cddfSDavid du Colombier return;
7927dd7cddfSDavid du Colombier
7937dd7cddfSDavid du Colombier s->profile[0] += TK2MS(1);
7947dd7cddfSDavid du Colombier if(pc >= s->base && pc < s->top) {
7957dd7cddfSDavid du Colombier pc -= s->base;
7967dd7cddfSDavid du Colombier s->profile[pc>>LRESPROF] += TK2MS(1);
7977dd7cddfSDavid du Colombier }
7987dd7cddfSDavid du Colombier }
7993c2ddefeSDavid du Colombier
800