Annotation of researchv10no/sys/os/limits.C, revision 1.1.1.1

1.1       root        1: /*
                      2:  * limits routines
                      3:  */
                      4: 
                      5: #include "sys/param.h"
                      6: #include "sys/systm.h"
                      7: #include "sys/user.h"
                      8: #include "sys/file.h"
                      9: #include "sys/inode.h"
                     10: #include "sys/lnode.h"
                     11: #include "sys/proc.h"
                     12: #include "sys/share.h"
                     13: 
                     14: #ifndef        ETOOMANYU
                     15: #define        ETOOMANYU       ENOSPC  /* Must go in errno.h or lnode.h */
                     16: #endif
                     17: 
                     18: float  NiceDecays[2*NZERO];    /* Table for pre-calculated priority decays */
                     19: float  NiceRates[2*NZERO];     /* Table for pre-calculated rate increments */
                     20: long   NiceTicks[2*NZERO];     /* Array of costs for a cpu tick biased by p_nice */
                     21: KL_p   lastlnode;
                     22: 
                     23: /*
                     24:  * limits system call
                     25:  *
                     26:  * Functions
                     27:  *
                     28:  *     0 - L_MYLIM
                     29:  *     9 - L_MYKN
                     30:  *         return own limit struct
                     31:  *         return number of processes attached to node
                     32:  *
                     33:  *     1 - L_OTHLIM
                     34:  *     10- L_OTHKN
                     35:  *         return limit struct of l_uid
                     36:  *         return number of processes attached to node or ESRCH
                     37:  *
                     38:  *     2 - L_ALLLIM
                     39:  *     11- L_ALLKN
                     40:  *         return all active limit structs
                     41:  *         return number of structs returned
                     42:  *
                     43:  *     3 - L_SETLIM super-user only
                     44:  *         initialize limit struct for l_uid
                     45:  *         ETOOMANYU   - no spare limit structs
                     46:  *         ESRCH       - group not installed
                     47:  *
                     48:  *     4 - L_DEADLIM
                     49:  *         wait for a dead child, return limit struct and proc entry,
                     50:  *         and if LASTREF, remove dead limit struct from the active list.
                     51:  *         LASTREF set for dead limit struct
                     52:  *         ECHILD      - no children to wait for
                     53:  *         return number of processes attached to node
                     54:  *
                     55:  *     5 - L_CHNGLIM super-user only
                     56:  *         change limits for active limit struct
                     57:  *         ESRCH       - l_uid not found
                     58:  *
                     59:  *     6 - L_DEADGROUP
                     60:  *         return limit struct for a dead group and remove group
                     61:  *         ESRCH       - no dead groups
                     62:  *
                     63:  *     7 - L_GETCOSTS
                     64:  *         return share constants
                     65:  *
                     66:  *     8 - L_SETCOSTS  super-user only
                     67:  *         set share constants
                     68:  */
                     69: limits()
                     70: {
                     71:        register struct a {
                     72:                struct lnode *lp;
                     73:                int select;
                     74:        } *uap;
                     75:        register KL_p ol;
                     76:        register KL_p nl;
                     77:        register KL_p gl;
                     78:        register int i;
                     79:        register struct proc *up;
                     80:        register int size;
                     81:        static struct kern_lnode kl;
                     82: 
                     83:        up = u.u_procp;
                     84:        size = sizeof(struct kern_lnode);
                     85: 
                     86:        uap = (struct a *)u.u_ap;
                     87:        switch(uap->select) {
                     88:        case L_MYLIM:
                     89:                if(copyout((caddr_t)&up->p_lnode->kl, (caddr_t)uap->lp, sizeof(struct lnode)))
                     90:                        u.u_error = EFAULT;
                     91:                u.u_r.r_val1 = up->p_lnode->kl_refcount;
                     92:                return;
                     93: 
                     94:        case L_MYKN:
                     95:                if(copyout((caddr_t)up->p_lnode, (caddr_t)uap->lp, size))
                     96:                        u.u_error = EFAULT;
                     97:                u.u_r.r_val1 = up->p_lnode->kl_refcount;
                     98:                return;
                     99: 
                    100:        case L_OTHLIM:
                    101:                size = sizeof(struct lnode);
                    102:        case L_OTHKN:
                    103:                if(copyin((caddr_t)uap->lp, (uap->select == L_OTHLIM)?(caddr_t)&kl.kl:(caddr_t)&kl, size)) {
                    104:                        u.u_error = EFAULT;
                    105:                        return;
                    106:                }
                    107:                for(ol = lnodes; ol != (KL_p)0; ol = ol->kl_next) {
                    108:                        if(ol->kl.l_uid == kl.kl.l_uid) {
                    109:                                if(copyout((uap->select == L_OTHLIM)?(caddr_t)&ol->kl:(caddr_t)ol, (caddr_t)uap->lp, size))
                    110:                                        u.u_error = EFAULT;
                    111:                                u.u_r.r_val1 = ol->kl_refcount;
                    112:                                return;
                    113:                        }
                    114:                }
                    115:                u.u_error = ESRCH;
                    116:                return;
                    117: 
                    118:        case L_ALLLIM:
                    119:                size = sizeof(struct lnode);
                    120:        case L_ALLKN:
                    121:                i = 0;
                    122:                for(ol = lnodes; ol != (KL_p)0; ol = ol->kl_next) {
                    123:                        if(copyout((uap->select == L_ALLLIM)?(caddr_t)&ol->kl:(caddr_t)ol, (caddr_t)uap->lp, size)) {
                    124:                                u.u_error = EFAULT;
                    125:                                return;
                    126:                        }
                    127:                        *(caddr_t *)&uap->lp += size;
                    128:                        i++;
                    129:                }
                    130:                u.u_r.r_val1 = i;
                    131:                return;
                    132: 
                    133:        case L_SETLIM:
                    134:                if(!suser())
                    135:                        return;
                    136:                if(copyin((caddr_t)uap->lp, (caddr_t)&kl.kl, sizeof(struct lnode))) {
                    137:                        u.u_error = EFAULT;
                    138:                        return;
                    139:                }
                    140:                if(kl.kl.l_uid == up->p_lnode->kl.l_uid)
                    141:                        return;
                    142:                nl = gl = (KL_p)0;
                    143:                for(ol = lnodes, i = 0; ol < lnodesMAXUSERS; ol++) {
                    144:                        if(!(ol->kl.l_flags & ACTIVELNODE)) {
                    145:                                if(nl == NULL)
                    146:                                        nl = ol;
                    147:                                continue;
                    148:                        }
                    149:                        if(ol->kl.l_uid == kl.kl.l_uid) {
                    150:                                nl = ol;
                    151:                                goto found;
                    152:                        }
                    153:                        if(!(ol->kl.l_flags & NOTSHARED) && ++i >= MAXUSERS) {
                    154:                                u.u_error = ETOOMANYU;
                    155:                                return;
                    156:                        }
                    157:                        if(ol->kl.l_uid == kl.kl.l_group)
                    158:                                gl = ol;        /* my group */
                    159:                }
                    160:                if(nl == NULL) {
                    161:                        u.u_error = ETOOMANYU;
                    162:                        return;
                    163:                }
                    164:                if(gl == (KL_p)0) {
                    165:                        u.u_error = ESRCH;      /* No group installed yet */
                    166:                        return;
                    167:                }
                    168:                if(grouplevel(gl)>=MAXGROUPS) {
                    169:                        u.u_error = ESRCH;      /* ETOODEEPFORME? */
                    170:                        return;
                    171:                }
                    172:                nl->kl = kl.kl;
                    173:                nl->kl.l_flags &= ~CHNGDLIMITS;
                    174:                nl->kl_ghead = (KL_p)0;
                    175:                if(nl->kl.l_flags & NOTSHARED)
                    176:                        nl->kl_gshares = zerof;
                    177:                else
                    178:                        nl->kl_gshares = nl->kl.l_shares;
                    179:                nl->kl_temp = zerof;
                    180:                nl->kl_children = 0;
                    181:                nl->kl_cost = 0;
                    182:                nl->kl_refcount = 0;
                    183:                nl->kl_muse = 0;
                    184:                nl->kl_rate = onef;
                    185:                splshsched();   /* Hopefully, this locks out the clock scan too */
                    186:                addgroup(gl, nl);
                    187:                normshares(gl, 0);
                    188:                fixusage(nl);
                    189:                nl->kl_prev = gl;       /* insert into active list */
                    190:                if((nl->kl_next = gl->kl_next) == (KL_p)0)
                    191:                        lastlnode = nl;
                    192:                else
                    193:                        gl->kl_next->kl_prev = nl;
                    194:                gl->kl_next = nl;
                    195:                spl0();
                    196:        found:
                    197:                nl->kl.l_flags &= ~(LASTREF|DEADGROUP);
                    198:                nl->kl.l_flags |= ACTIVELNODE;
                    199:                ol = up->p_lnode;
                    200:                if(--ol->kl_refcount == 0) {
                    201:                        if(ol->kl_children == 0)
                    202:                                ol->kl.l_flags |= DEADGROUP;
                    203:                }
                    204:                nl->kl_refcount++;
                    205:                i = up->p_dsize + up->p_ssize;
                    206:                ol->kl_muse -= i;
                    207:                nl->kl_muse += i;
                    208:                up->p_lnode = nl;
                    209:                return;
                    210: 
                    211: #if NOTDEF             /* unused and unpleasant */
                    212:        case L_DEADLIM:
                    213:                wait1(WRETLIM, NULL);   /* will call retlimits() */
                    214:                return;
                    215: #endif
                    216:        case L_DEADGROUP:
                    217:                if(!suser())
                    218:                        return;
                    219:                for(ol = lnodes[0].kl_next; ol != (KL_p)0; ol = ol->kl_next)
                    220:                        if(ol->kl_refcount == 0 && ol->kl_children == 0) {
                    221:                                remlnode(ol);
                    222:                                if(copyout((caddr_t)&ol->kl, (caddr_t)uap->lp, sizeof(struct lnode)))
                    223:                                        u.u_error = EFAULT;
                    224:                                return;
                    225:                        }
                    226:                u.u_error = ESRCH;
                    227:                return;
                    228: 
                    229:        case L_CHNGLIM:
                    230:                if(!suser())
                    231:                        return;
                    232:                if(copyin((caddr_t)uap->lp, (caddr_t)&kl.kl, sizeof(struct lnode))) {
                    233:                        u.u_error = EFAULT;
                    234:                        return;
                    235:                }
                    236:                if(kl.kl.l_uid == 0) {
                    237:                        u.u_error = EINVAL;
                    238:                        return;
                    239:                }
                    240:                for(ol = lnodes, gl = (KL_p)0; ol != (KL_p)0; ol = ol->kl_next) {
                    241:                        if(ol->kl.l_uid == kl.kl.l_uid) {
                    242:                                if(ol->kl.l_group != kl.kl.l_group) {
                    243:                                        if(gl==(KL_p)0)
                    244:                                                break;  /* ESRCH */
                    245:                                        else {
                    246:                                                splshsched();
                    247:                                                remgroup(ol);
                    248:                                                ol->kl.l_group = kl.kl.l_group;
                    249:                                                addgroup(gl, ol);
                    250:                                        }
                    251:                                } else if(gl==(KL_p)0)
                    252:                                        panic("lost group");
                    253: 
                    254:                                if(ol->kl_norms && ol->kl_usage < MAXUSAGE)
                    255:                                        TotUsage -= onef / ol->kl_usage;
                    256:                                ol->kl.l_usage = kl.kl.l_usage;
                    257: 
                    258:                                if(ol->kl.l_shares != kl.kl.l_shares
                    259:                                || ((ol->kl.l_flags^kl.kl.l_flags) & NOTSHARED)) {
                    260:                                        gl->kl_gshares -= ol->kl.l_shares;
                    261:                                        if(!(ol->kl.l_flags & NOTSHARED))
                    262:                                                ol->kl_gshares -= ol->kl.l_shares;
                    263:                                        ol->kl.l_shares = kl.kl.l_shares;
                    264:                                        gl->kl_gshares += ol->kl.l_shares;
                    265:                                        if(!(kl.kl.l_flags & NOTSHARED))
                    266:                                                ol->kl_gshares += ol->kl.l_shares;
                    267:                                }
                    268:                                ol->kl.l_flags &= (ACTIVELNODE|LASTREF|DEADGROUP);
                    269:                                ol->kl.l_flags |= (kl.kl.l_flags & ~(ACTIVELNODE|LASTREF|DEADGROUP)) | CHNGDLIMITS;
                    270:                                normshares(gl, 0);
                    271:                                fixusage(ol);
                    272:                                spl0();
                    273:                                return;
                    274:                        } else if(ol->kl.l_uid == kl.kl.l_group)
                    275:                                gl = ol;        /* Remember [new] group */
                    276:                }
                    277:                u.u_error = ESRCH;
                    278:                return;
                    279: 
                    280:        case L_GETCOSTS:
                    281:                if(copyout((caddr_t)&shconsts, (caddr_t)uap->lp, sizeof shconsts))
                    282:                        u.u_error = EFAULT;
                    283:                return;
                    284: 
                    285:        case L_SETCOSTS:
                    286:                if(!suser())
                    287:                        return;
                    288:                splshsched();
                    289:                if(copyin((caddr_t)uap->lp, (caddr_t)&shconsts, (caddr_t)&LASTPARAM - (caddr_t)&shconsts))
                    290:                        u.u_error = EFAULT;
                    291:                setcosts();
                    292:                spl0();
                    293:                return;
                    294:                        
                    295:        default:
                    296:                u.u_error = EINVAL;
                    297:                return;
                    298:        }
                    299: }
                    300: 
                    301: /*
                    302:  * Add to group list
                    303:  */
                    304: 
                    305: addgroup(gl, kl)
                    306: register KL_p gl;
                    307: register KL_p kl;
                    308: {
                    309:        kl->kl_parent = gl;
                    310:        kl->kl_gnext = gl->kl_ghead;
                    311:        gl->kl_ghead = kl;
                    312:        gl->kl_children++;
                    313:        gl->kl_gshares += kl->kl.l_shares;
                    314:        gl->kl.l_flags &= ~DEADGROUP;
                    315: }
                    316: 
                    317: #if NOTDEF
                    318: 
                    319: /*
                    320:  * Return dead proc and limits to init for accounting.
                    321:  */
                    322: 
                    323: retlimits(p)
                    324: register struct proc *p;
                    325: {
                    326:        register KL_p lp;
                    327:        register struct a {
                    328:                struct retlim *rp;
                    329:        } *uap;
                    330: 
                    331:        lp = p->p_lnode;
                    332:        if(lp->kl_refcount == 0) {
                    333:                lp->kl.l_flags |= LASTREF;
                    334:                if(lp->kl_children == 0)
                    335:                        remlnode(lp);
                    336:        }
                    337: 
                    338:        uap = (struct a *)u.u_ap;
                    339:        if(copyout((caddr_t)p, (caddr_t)&uap->rp->r_proc, sizeof(struct xproc))
                    340:        || copyout((caddr_t)&lp->kl, (caddr_t)&uap->rp->r_lnode, sizeof(struct lnode)))
                    341:                u.u_error = EFAULT;
                    342: 
                    343:        u.u_r.r_val1 = lp->kl_refcount;
                    344: }
                    345: 
                    346: #endif
                    347: 
                    348: /*
                    349:  * Remove lnode from active and group lists.
                    350:  */
                    351: 
                    352: remlnode(lp)
                    353: register KL_p lp;
                    354: {
                    355:        splshsched();
                    356: 
                    357:        if((lp->kl_prev->kl_next = lp->kl_next) == (KL_p)0)
                    358:                lastlnode = lp->kl_prev;
                    359:        else
                    360:                lp->kl_next->kl_prev = lp->kl_prev;
                    361: 
                    362:        remgroup(lp);
                    363: 
                    364:        spl0();
                    365: 
                    366:        if(lp->kl_temp += lp->kl_cost) {
                    367:                lp->kl.l_charge += lp->kl_temp;
                    368:                lp->kl_parent->kl_temp += lp->kl_temp;
                    369:                lp->kl.l_usage += lp->kl_temp;
                    370:        }
                    371: 
                    372:        lp->kl.l_flags &= ~ACTIVELNODE;
                    373: 
                    374:        if(lp->kl_parent->kl.l_flags & DEADGROUP)
                    375:                lp->kl.l_flags |= DEADGROUP;    /* init should pick up group */
                    376: }
                    377: 
                    378: /*
                    379:  * Remove lnode from group list.
                    380:  */
                    381: 
                    382: remgroup(lp)
                    383: register KL_p lp;
                    384: {
                    385:        register KL_p gl, ol;
                    386: 
                    387:        for(ol = lp->kl_parent, gl = ol->kl_ghead; gl != (KL_p)0; ol = gl, gl = gl->kl_gnext)
                    388:                if(gl == lp) {
                    389:                        /* remove from group list */
                    390:                        if(ol == lp->kl_parent)
                    391:                                ol->kl_ghead = lp->kl_gnext;
                    392:                        else
                    393:                                ol->kl_gnext = lp->kl_gnext;
                    394:                        break;
                    395:                }
                    396: 
                    397:        if(gl==(KL_p)0) panic("remgroup");
                    398: 
                    399:        gl = lp->kl_parent;
                    400: 
                    401:        if(--gl->kl_children == 0 && gl->kl_refcount == 0)
                    402:                gl->kl.l_flags |= DEADGROUP;
                    403: 
                    404:        gl->kl_gshares -= lp->kl.l_shares;
                    405:        normshares(gl, 0);
                    406: }
                    407: 
                    408: /*
                    409:  * Adjust effective shares for group.
                    410:  */
                    411: 
                    412: normshares(gl, d)
                    413: register KL_p gl;
                    414: {
                    415:        register KL_p lp;
                    416:        register float es;
                    417:        register float gs;
                    418: 
                    419:        if((gs = gl->kl_gshares) && !(gl->kl.l_flags & NOTSHARED)) {
                    420:                es = gl->kl_eshare * gl->kl.l_shares;
                    421:                es /= gs;
                    422:                gl->kl_norms = es * es;
                    423:        } else if(gl->kl.l_uid == 0)
                    424:                gl->kl_norms = onef;
                    425:        else
                    426:                gl->kl_norms = zerof;
                    427: 
                    428:        for(lp = gl->kl_ghead; lp != (KL_p)0; lp = lp->kl_gnext) {
                    429:                if(gs) {
                    430:                        es = gl->kl_eshare * lp->kl.l_shares;
                    431:                        es /= gs;
                    432:                } else
                    433:                        es = zerof;
                    434: 
                    435:                lp->kl_eshare = es;
                    436: 
                    437:                if(lp->kl_ghead) {
                    438:                        if(d >= MAXGROUPS)
                    439:                                printf("MAXGROUPS(%d) exceeded for group %d\n", MAXGROUPS, lp->kl.l_uid);
                    440:                        else
                    441:                                normshares(lp, d+1);
                    442:                } else
                    443:                        lp->kl_norms = es * es;
                    444:        }
                    445: }
                    446: 
                    447: /*
                    448:  * Count group nesting
                    449:  */
                    450: 
                    451: grouplevel(gl)
                    452: register KL_p gl;
                    453: {
                    454:        register int i;
                    455: 
                    456:        for(i = 0; (gl = gl->kl_parent) != (KL_p)0; i++);
                    457:        return i;
                    458: }
                    459: 
                    460: /*
                    461:  * Check and set cost dependent variables
                    462:  */
                    463: 
                    464: setcosts()
                    465: {
                    466:        register int i;
                    467:        register float f = onef;
                    468:        register float g;
                    469: 
                    470:        if(MAXUSERS > lnodecnt)
                    471:                MAXUSERS = lnodecnt;
                    472:        if(MAXGROUPS > (lnodecnt-3))
                    473:                MAXGROUPS = lnodecnt-3;
                    474:        if(MAXUSHARE < f)
                    475:                MAXUSHARE = f;
                    476:        if(MINGSHARE > f)
                    477:                MINGSHARE = f;
                    478: 
                    479:        f -= DecayRate;
                    480:        g = PriDecay / (PriDecayBase + (2*NZERO) - 1);
                    481:        for(i = 0; i < (2*NZERO); i++) {
                    482:                NiceDecays[i] = g * (PriDecayBase + i);
                    483:                NiceRates[i] = i <= NZERO ? f : (f * NZERO) / i;
                    484:                NiceTicks[i] = (shconsts.sc_tick * ((3*NZERO) - i)) / (2*NZERO);
                    485:        }
                    486: 
                    487:        if(NiceTicks[2*NZERO-1] > 0)
                    488:                NiceTicks[2*NZERO-1] = 1;       /* nice -19 is almost free */
                    489:        NiceRates[2*NZERO-1] = zerof;
                    490: }
                    491: 
                    492: /*
                    493:  *     Initialise lnodes
                    494:  */
                    495: 
                    496: initlnodes(root)
                    497: register KL_p root;
                    498: {
                    499:        lastlnode = root;
                    500:        MAXUSERS = lnodecnt;
                    501:        MaxSharePri = onef;
                    502: 
                    503:        setcosts();
                    504: 
                    505:        root->kl.l_shares = 1;
                    506:        root->kl.l_flags = ACTIVELNODE|NOTSHARED;
                    507:        root->kl_norms = onef;
                    508:        root->kl_eshare = onef;
                    509:        root->kl_gshares = zerof;
                    510:        root->kl_temp = zerof;
                    511:        root->kl_usage = onef;
                    512:        root->kl_rate = onef;
                    513: }
                    514: 
                    515: /*
                    516:  *     Adjust usage variables for new value.
                    517:  */
                    518: 
                    519: fixusage(lp)
                    520:        register KL_p   lp;
                    521: {
                    522:        register float  f;
                    523: 
                    524:        if(f = lp->kl_norms) {
                    525:                if((f = lp->kl.l_usage / f) < twof || (Shareflags & NOSHARE))
                    526:                        f = twof;
                    527:                if(f > MaxUsage && f < MAXUSAGE)
                    528:                        MaxUsage = f;
                    529:                TotUsage += onef / f;
                    530:                lp->kl_usage = f;
                    531:        } else
                    532:                lp->kl_usage = MAXUSAGE;
                    533: }

unix.superglobalmegacorp.com

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