[BACK]Return to kern_resource.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/kern_resource.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: kern_resource.c,v 1.32 2007/04/12 22:14:15 tedu Exp $ */
        !             2: /*     $NetBSD: kern_resource.c,v 1.38 1996/10/23 07:19:38 matthias Exp $      */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1982, 1986, 1991, 1993
        !             6:  *     The Regents of the University of California.  All rights reserved.
        !             7:  * (c) UNIX System Laboratories, Inc.
        !             8:  * All or some portions of this file are derived from material licensed
        !             9:  * to the University of California by American Telephone and Telegraph
        !            10:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
        !            11:  * the permission of UNIX System Laboratories, Inc.
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer.
        !            18:  * 2. Redistributions in binary form must reproduce the above copyright
        !            19:  *    notice, this list of conditions and the following disclaimer in the
        !            20:  *    documentation and/or other materials provided with the distribution.
        !            21:  * 3. Neither the name of the University nor the names of its contributors
        !            22:  *    may be used to endorse or promote products derived from this software
        !            23:  *    without specific prior written permission.
        !            24:  *
        !            25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            35:  * SUCH DAMAGE.
        !            36:  *
        !            37:  *     @(#)kern_resource.c     8.5 (Berkeley) 1/21/94
        !            38:  */
        !            39:
        !            40: #include <sys/param.h>
        !            41: #include <sys/systm.h>
        !            42: #include <sys/kernel.h>
        !            43: #include <sys/file.h>
        !            44: #include <sys/resourcevar.h>
        !            45: #include <sys/pool.h>
        !            46: #include <sys/proc.h>
        !            47: #include <sys/sched.h>
        !            48:
        !            49: #include <sys/mount.h>
        !            50: #include <sys/syscallargs.h>
        !            51:
        !            52: #include <uvm/uvm_extern.h>
        !            53:
        !            54: /*
        !            55:  * Patchable maximum data and stack limits.
        !            56:  */
        !            57: rlim_t maxdmap = MAXDSIZ;
        !            58: rlim_t maxsmap = MAXSSIZ;
        !            59:
        !            60: /*
        !            61:  * Resource controls and accounting.
        !            62:  */
        !            63:
        !            64: int
        !            65: sys_getpriority(struct proc *curp, void *v, register_t *retval)
        !            66: {
        !            67:        struct sys_getpriority_args /* {
        !            68:                syscallarg(int) which;
        !            69:                syscallarg(id_t) who;
        !            70:        } */ *uap = v;
        !            71:        struct proc *p;
        !            72:        int low = NZERO + PRIO_MAX + 1;
        !            73:
        !            74:        switch (SCARG(uap, which)) {
        !            75:
        !            76:        case PRIO_PROCESS:
        !            77:                if (SCARG(uap, who) == 0)
        !            78:                        p = curp;
        !            79:                else
        !            80:                        p = pfind(SCARG(uap, who));
        !            81:                if (p == 0)
        !            82:                        break;
        !            83:                low = p->p_nice;
        !            84:                break;
        !            85:
        !            86:        case PRIO_PGRP: {
        !            87:                struct pgrp *pg;
        !            88:
        !            89:                if (SCARG(uap, who) == 0)
        !            90:                        pg = curp->p_pgrp;
        !            91:                else if ((pg = pgfind(SCARG(uap, who))) == NULL)
        !            92:                        break;
        !            93:                LIST_FOREACH(p, &pg->pg_members, p_pglist) {
        !            94:                        if (p->p_nice < low)
        !            95:                                low = p->p_nice;
        !            96:                }
        !            97:                break;
        !            98:        }
        !            99:
        !           100:        case PRIO_USER:
        !           101:                if (SCARG(uap, who) == 0)
        !           102:                        SCARG(uap, who) = curp->p_ucred->cr_uid;
        !           103:                for (p = LIST_FIRST(&allproc); p; p = LIST_NEXT(p, p_list))
        !           104:                        if (p->p_ucred->cr_uid == SCARG(uap, who) &&
        !           105:                            p->p_nice < low)
        !           106:                                low = p->p_nice;
        !           107:                break;
        !           108:
        !           109:        default:
        !           110:                return (EINVAL);
        !           111:        }
        !           112:        if (low == NZERO + PRIO_MAX + 1)
        !           113:                return (ESRCH);
        !           114:        *retval = low - NZERO;
        !           115:        return (0);
        !           116: }
        !           117:
        !           118: /* ARGSUSED */
        !           119: int
        !           120: sys_setpriority(struct proc *curp, void *v, register_t *retval)
        !           121: {
        !           122:        struct sys_setpriority_args /* {
        !           123:                syscallarg(int) which;
        !           124:                syscallarg(id_t) who;
        !           125:                syscallarg(int) prio;
        !           126:        } */ *uap = v;
        !           127:        struct proc *p;
        !           128:        int found = 0, error = 0;
        !           129:
        !           130:        switch (SCARG(uap, which)) {
        !           131:
        !           132:        case PRIO_PROCESS:
        !           133:                if (SCARG(uap, who) == 0)
        !           134:                        p = curp;
        !           135:                else
        !           136:                        p = pfind(SCARG(uap, who));
        !           137:                if (p == 0)
        !           138:                        break;
        !           139:                error = donice(curp, p, SCARG(uap, prio));
        !           140:                found++;
        !           141:                break;
        !           142:
        !           143:        case PRIO_PGRP: {
        !           144:                struct pgrp *pg;
        !           145:
        !           146:                if (SCARG(uap, who) == 0)
        !           147:                        pg = curp->p_pgrp;
        !           148:                else if ((pg = pgfind(SCARG(uap, who))) == NULL)
        !           149:                        break;
        !           150:                LIST_FOREACH(p, &pg->pg_members, p_pglist) {
        !           151:                        error = donice(curp, p, SCARG(uap, prio));
        !           152:                        found++;
        !           153:                }
        !           154:                break;
        !           155:        }
        !           156:
        !           157:        case PRIO_USER:
        !           158:                if (SCARG(uap, who) == 0)
        !           159:                        SCARG(uap, who) = curp->p_ucred->cr_uid;
        !           160:                for (p = LIST_FIRST(&allproc); p; p = LIST_NEXT(p, p_list))
        !           161:                        if (p->p_ucred->cr_uid == SCARG(uap, who)) {
        !           162:                                error = donice(curp, p, SCARG(uap, prio));
        !           163:                                found++;
        !           164:                        }
        !           165:                break;
        !           166:
        !           167:        default:
        !           168:                return (EINVAL);
        !           169:        }
        !           170:        if (found == 0)
        !           171:                return (ESRCH);
        !           172:        return (error);
        !           173: }
        !           174:
        !           175: int
        !           176: donice(struct proc *curp, struct proc *chgp, int n)
        !           177: {
        !           178:        struct pcred *pcred = curp->p_cred;
        !           179:        int s;
        !           180:
        !           181:        if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
        !           182:            pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
        !           183:            pcred->p_ruid != chgp->p_ucred->cr_uid)
        !           184:                return (EPERM);
        !           185:        if (n > PRIO_MAX)
        !           186:                n = PRIO_MAX;
        !           187:        if (n < PRIO_MIN)
        !           188:                n = PRIO_MIN;
        !           189:        n += NZERO;
        !           190:        if (n < chgp->p_nice && suser(curp, 0))
        !           191:                return (EACCES);
        !           192:        chgp->p_nice = n;
        !           193:        SCHED_LOCK(s);
        !           194:        (void)resetpriority(chgp);
        !           195:        SCHED_UNLOCK(s);
        !           196:        return (0);
        !           197: }
        !           198:
        !           199: /* ARGSUSED */
        !           200: int
        !           201: sys_setrlimit(struct proc *p, void *v, register_t *retval)
        !           202: {
        !           203:        struct sys_setrlimit_args /* {
        !           204:                syscallarg(int) which;
        !           205:                syscallarg(const struct rlimit *) rlp;
        !           206:        } */ *uap = v;
        !           207:        struct rlimit alim;
        !           208:        int error;
        !           209:
        !           210:        error = copyin((caddr_t)SCARG(uap, rlp), (caddr_t)&alim,
        !           211:                       sizeof (struct rlimit));
        !           212:        if (error)
        !           213:                return (error);
        !           214:        return (dosetrlimit(p, SCARG(uap, which), &alim));
        !           215: }
        !           216:
        !           217: int
        !           218: dosetrlimit(struct proc *p, u_int which, struct rlimit *limp)
        !           219: {
        !           220:        struct rlimit *alimp;
        !           221:        rlim_t maxlim;
        !           222:        int error;
        !           223:
        !           224:        if (which >= RLIM_NLIMITS)
        !           225:                return (EINVAL);
        !           226:
        !           227:        alimp = &p->p_rlimit[which];
        !           228:        if (limp->rlim_cur > alimp->rlim_max ||
        !           229:            limp->rlim_max > alimp->rlim_max)
        !           230:                if ((error = suser(p, 0)) != 0)
        !           231:                        return (error);
        !           232:        if (p->p_p->ps_limit->p_refcnt > 1 &&
        !           233:            (p->p_p->ps_limit->p_lflags & PL_SHAREMOD) == 0) {
        !           234:                p->p_p->ps_limit->p_refcnt--;
        !           235:                p->p_p->ps_limit = limcopy(p->p_p->ps_limit);
        !           236:                alimp = &p->p_rlimit[which];
        !           237:        }
        !           238:
        !           239:        switch (which) {
        !           240:        case RLIMIT_DATA:
        !           241:                maxlim = maxdmap;
        !           242:                break;
        !           243:        case RLIMIT_STACK:
        !           244:                maxlim = maxsmap;
        !           245:                break;
        !           246:        case RLIMIT_NOFILE:
        !           247:                maxlim = maxfiles;
        !           248:                break;
        !           249:        case RLIMIT_NPROC:
        !           250:                maxlim = maxproc;
        !           251:                break;
        !           252:        default:
        !           253:                maxlim = RLIM_INFINITY;
        !           254:                break;
        !           255:        }
        !           256:
        !           257:        if (limp->rlim_max > maxlim)
        !           258:                limp->rlim_max = maxlim;
        !           259:        if (limp->rlim_cur > limp->rlim_max)
        !           260:                limp->rlim_cur = limp->rlim_max;
        !           261:
        !           262:        if (which == RLIMIT_STACK) {
        !           263:                /*
        !           264:                 * Stack is allocated to the max at exec time with only
        !           265:                 * "rlim_cur" bytes accessible.  If stack limit is going
        !           266:                 * up make more accessible, if going down make inaccessible.
        !           267:                 */
        !           268:                if (limp->rlim_cur != alimp->rlim_cur) {
        !           269:                        vaddr_t addr;
        !           270:                        vsize_t size;
        !           271:                        vm_prot_t prot;
        !           272:
        !           273:                        if (limp->rlim_cur > alimp->rlim_cur) {
        !           274:                                prot = VM_PROT_READ|VM_PROT_WRITE;
        !           275:                                size = limp->rlim_cur - alimp->rlim_cur;
        !           276: #ifdef MACHINE_STACK_GROWS_UP
        !           277:                                addr = USRSTACK + alimp->rlim_cur;
        !           278: #else
        !           279:                                addr = USRSTACK - limp->rlim_cur;
        !           280: #endif
        !           281:                        } else {
        !           282:                                prot = VM_PROT_NONE;
        !           283:                                size = alimp->rlim_cur - limp->rlim_cur;
        !           284: #ifdef MACHINE_STACK_GROWS_UP
        !           285:                                addr = USRSTACK + limp->rlim_cur;
        !           286: #else
        !           287:                                addr = USRSTACK - alimp->rlim_cur;
        !           288: #endif
        !           289:                        }
        !           290:                        addr = trunc_page(addr);
        !           291:                        size = round_page(size);
        !           292:                        (void) uvm_map_protect(&p->p_vmspace->vm_map,
        !           293:                                              addr, addr+size, prot, FALSE);
        !           294:                }
        !           295:        }
        !           296:
        !           297:        *alimp = *limp;
        !           298:        return (0);
        !           299: }
        !           300:
        !           301: /* ARGSUSED */
        !           302: int
        !           303: sys_getrlimit(struct proc *p, void *v, register_t *retval)
        !           304: {
        !           305:        struct sys_getrlimit_args /* {
        !           306:                syscallarg(int) which;
        !           307:                syscallarg(struct rlimit *) rlp;
        !           308:        } */ *uap = v;
        !           309:
        !           310:        if (SCARG(uap, which) < 0 || SCARG(uap, which) >= RLIM_NLIMITS)
        !           311:                return (EINVAL);
        !           312:        return (copyout((caddr_t)&p->p_rlimit[SCARG(uap, which)],
        !           313:            (caddr_t)SCARG(uap, rlp), sizeof (struct rlimit)));
        !           314: }
        !           315:
        !           316: /*
        !           317:  * Transform the running time and tick information in proc p into user,
        !           318:  * system, and interrupt time usage.
        !           319:  */
        !           320: void
        !           321: calcru(struct proc *p, struct timeval *up, struct timeval *sp,
        !           322:     struct timeval *ip)
        !           323: {
        !           324:        u_quad_t st, ut, it;
        !           325:        int freq;
        !           326:        int s;
        !           327:
        !           328:        s = splstatclock();
        !           329:        st = p->p_sticks;
        !           330:        ut = p->p_uticks;
        !           331:        it = p->p_iticks;
        !           332:        splx(s);
        !           333:
        !           334:        if (st + ut + it == 0) {
        !           335:                timerclear(up);
        !           336:                timerclear(sp);
        !           337:                if (ip != NULL)
        !           338:                        timerclear(ip);
        !           339:                return;
        !           340:        }
        !           341:
        !           342:        freq = stathz ? stathz : hz;
        !           343:
        !           344:        st = st * 1000000 / freq;
        !           345:        sp->tv_sec = st / 1000000;
        !           346:        sp->tv_usec = st % 1000000;
        !           347:        ut = ut * 1000000 / freq;
        !           348:        up->tv_sec = ut / 1000000;
        !           349:        up->tv_usec = ut % 1000000;
        !           350:        if (ip != NULL) {
        !           351:                it = it * 1000000 / freq;
        !           352:                ip->tv_sec = it / 1000000;
        !           353:                ip->tv_usec = it % 1000000;
        !           354:        }
        !           355: }
        !           356:
        !           357: /* ARGSUSED */
        !           358: int
        !           359: sys_getrusage(struct proc *p, void *v, register_t *retval)
        !           360: {
        !           361:        struct sys_getrusage_args /* {
        !           362:                syscallarg(int) who;
        !           363:                syscallarg(struct rusage *) rusage;
        !           364:        } */ *uap = v;
        !           365:        struct rusage *rup;
        !           366:
        !           367:        switch (SCARG(uap, who)) {
        !           368:
        !           369:        case RUSAGE_SELF:
        !           370:                rup = &p->p_stats->p_ru;
        !           371:                calcru(p, &rup->ru_utime, &rup->ru_stime, NULL);
        !           372:                break;
        !           373:
        !           374:        case RUSAGE_CHILDREN:
        !           375:                rup = &p->p_stats->p_cru;
        !           376:                break;
        !           377:
        !           378:        default:
        !           379:                return (EINVAL);
        !           380:        }
        !           381:        return (copyout((caddr_t)rup, (caddr_t)SCARG(uap, rusage),
        !           382:            sizeof (struct rusage)));
        !           383: }
        !           384:
        !           385: void
        !           386: ruadd(struct rusage *ru, struct rusage *ru2)
        !           387: {
        !           388:        long *ip, *ip2;
        !           389:        int i;
        !           390:
        !           391:        timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
        !           392:        timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
        !           393:        if (ru->ru_maxrss < ru2->ru_maxrss)
        !           394:                ru->ru_maxrss = ru2->ru_maxrss;
        !           395:        ip = &ru->ru_first; ip2 = &ru2->ru_first;
        !           396:        for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
        !           397:                *ip++ += *ip2++;
        !           398: }
        !           399:
        !           400: struct pool plimit_pool;
        !           401:
        !           402: /*
        !           403:  * Make a copy of the plimit structure.
        !           404:  * We share these structures copy-on-write after fork,
        !           405:  * and copy when a limit is changed.
        !           406:  */
        !           407: struct plimit *
        !           408: limcopy(struct plimit *lim)
        !           409: {
        !           410:        struct plimit *newlim;
        !           411:        static int initialized;
        !           412:
        !           413:        if (!initialized) {
        !           414:                pool_init(&plimit_pool, sizeof(struct plimit), 0, 0, 0,
        !           415:                    "plimitpl", &pool_allocator_nointr);
        !           416:                initialized = 1;
        !           417:        }
        !           418:
        !           419:        newlim = pool_get(&plimit_pool, PR_WAITOK);
        !           420:        bcopy(lim->pl_rlimit, newlim->pl_rlimit,
        !           421:            sizeof(struct rlimit) * RLIM_NLIMITS);
        !           422:        newlim->p_lflags = 0;
        !           423:        newlim->p_refcnt = 1;
        !           424:        return (newlim);
        !           425: }
        !           426:
        !           427: void
        !           428: limfree(struct plimit *lim)
        !           429: {
        !           430:        if (--lim->p_refcnt > 0)
        !           431:                return;
        !           432:        pool_put(&plimit_pool, lim);
        !           433: }

CVSweb