Remove advertising clause from all that isn't contrib or userland bin.
[dragonfly.git] / sys / kern / kern_resource.c
1 /*-
2  * Copyright (c) 1982, 1986, 1991, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 4. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *      @(#)kern_resource.c     8.5 (Berkeley) 1/21/94
35  * $FreeBSD: src/sys/kern/kern_resource.c,v 1.55.2.5 2001/11/03 01:41:08 ps Exp $
36  */
37
38 #include "opt_compat.h"
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/sysproto.h>
43 #include <sys/file.h>
44 #include <sys/kern_syscall.h>
45 #include <sys/kernel.h>
46 #include <sys/resourcevar.h>
47 #include <sys/malloc.h>
48 #include <sys/proc.h>
49 #include <sys/priv.h>
50 #include <sys/time.h>
51 #include <sys/lockf.h>
52
53 #include <vm/vm.h>
54 #include <vm/vm_param.h>
55 #include <sys/lock.h>
56 #include <vm/pmap.h>
57 #include <vm/vm_map.h>
58
59 #include <sys/thread2.h>
60 #include <sys/spinlock2.h>
61
62 static int donice (struct proc *chgp, int n);
63 static int doionice (struct proc *chgp, int n);
64
65 static MALLOC_DEFINE(M_UIDINFO, "uidinfo", "uidinfo structures");
66 #define UIHASH(uid)     (&uihashtbl[(uid) & uihash])
67 static struct spinlock uihash_lock;
68 static LIST_HEAD(uihashhead, uidinfo) *uihashtbl;
69 static u_long uihash;           /* size of hash table - 1 */
70
71 static struct uidinfo   *uicreate (uid_t uid);
72 static struct uidinfo   *uilookup (uid_t uid);
73
74 /*
75  * Resource controls and accounting.
76  */
77
78 struct getpriority_info {
79         int low;
80         int who;
81 };
82
83 static int getpriority_callback(struct proc *p, void *data);
84
85 /*
86  * MPALMOSTSAFE
87  */
88 int
89 sys_getpriority(struct getpriority_args *uap)
90 {
91         struct getpriority_info info;
92         struct proc *curp = curproc;
93         struct proc *p;
94         int low = PRIO_MAX + 1;
95         int error;
96
97         switch (uap->which) {
98         case PRIO_PROCESS:
99                 if (uap->who == 0) {
100                         p = curp;
101                         PHOLD(p);
102                 } else {
103                         p = pfind(uap->who);
104                 }
105                 if (p) {
106                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred)) {
107                                 low = p->p_nice;
108                         }
109                         PRELE(p);
110                 }
111                 break;
112
113         case PRIO_PGRP: 
114         {
115                 struct pgrp *pg;
116
117                 if (uap->who == 0) {
118                         pg = curp->p_pgrp;
119                         pgref(pg);
120                 } else if ((pg = pgfind(uap->who)) == NULL) {
121                         break;
122                 } /* else ref held from pgfind */
123
124                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
125                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred) &&
126                             p->p_nice < low) {
127                                 low = p->p_nice;
128                         }
129                 }
130                 pgrel(pg);
131                 break;
132         }
133         case PRIO_USER:
134                 if (uap->who == 0)
135                         uap->who = curp->p_ucred->cr_uid;
136                 info.low = low;
137                 info.who = uap->who;
138                 allproc_scan(getpriority_callback, &info);
139                 low = info.low;
140                 break;
141
142         default:
143                 error = EINVAL;
144                 goto done;
145         }
146         if (low == PRIO_MAX + 1) {
147                 error = ESRCH;
148                 goto done;
149         }
150         uap->sysmsg_result = low;
151         error = 0;
152 done:
153         return (error);
154 }
155
156 /*
157  * Figure out the current lowest nice priority for processes owned
158  * by the specified user.
159  */
160 static
161 int
162 getpriority_callback(struct proc *p, void *data)
163 {
164         struct getpriority_info *info = data;
165
166         if (PRISON_CHECK(curproc->p_ucred, p->p_ucred) &&
167             p->p_ucred->cr_uid == info->who &&
168             p->p_nice < info->low) {
169                 info->low = p->p_nice;
170         }
171         return(0);
172 }
173
174 struct setpriority_info {
175         int prio;
176         int who;
177         int error;
178         int found;
179 };
180
181 static int setpriority_callback(struct proc *p, void *data);
182
183 /*
184  * MPALMOSTSAFE
185  */
186 int
187 sys_setpriority(struct setpriority_args *uap)
188 {
189         struct setpriority_info info;
190         struct proc *curp = curproc;
191         struct proc *p;
192         int found = 0, error = 0;
193
194         lwkt_gettoken(&proc_token);
195
196         switch (uap->which) {
197         case PRIO_PROCESS:
198                 if (uap->who == 0) {
199                         p = curp;
200                         PHOLD(p);
201                 } else {
202                         p = pfind(uap->who);
203                 }
204                 if (p) {
205                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred)) {
206                                 error = donice(p, uap->prio);
207                                 found++;
208                         }
209                         PRELE(p);
210                 }
211                 break;
212
213         case PRIO_PGRP: 
214         {
215                 struct pgrp *pg;
216
217                 if (uap->who == 0) {
218                         pg = curp->p_pgrp;
219                         pgref(pg);
220                 } else if ((pg = pgfind(uap->who)) == NULL) {
221                         break;
222                 } /* else ref held from pgfind */
223
224                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
225                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred)) {
226                                 error = donice(p, uap->prio);
227                                 found++;
228                         }
229                 }
230                 pgrel(pg);
231                 break;
232         }
233         case PRIO_USER:
234                 if (uap->who == 0)
235                         uap->who = curp->p_ucred->cr_uid;
236                 info.prio = uap->prio;
237                 info.who = uap->who;
238                 info.error = 0;
239                 info.found = 0;
240                 allproc_scan(setpriority_callback, &info);
241                 error = info.error;
242                 found = info.found;
243                 break;
244
245         default:
246                 error = EINVAL;
247                 found = 1;
248                 break;
249         }
250
251         lwkt_reltoken(&proc_token);
252
253         if (found == 0)
254                 error = ESRCH;
255         return (error);
256 }
257
258 static
259 int
260 setpriority_callback(struct proc *p, void *data)
261 {
262         struct setpriority_info *info = data;
263         int error;
264
265         if (p->p_ucred->cr_uid == info->who &&
266             PRISON_CHECK(curproc->p_ucred, p->p_ucred)) {
267                 error = donice(p, info->prio);
268                 if (error)
269                         info->error = error;
270                 ++info->found;
271         }
272         return(0);
273 }
274
275 static int
276 donice(struct proc *chgp, int n)
277 {
278         struct proc *curp = curproc;
279         struct ucred *cr = curp->p_ucred;
280         struct lwp *lp;
281
282         if (cr->cr_uid && cr->cr_ruid &&
283             cr->cr_uid != chgp->p_ucred->cr_uid &&
284             cr->cr_ruid != chgp->p_ucred->cr_uid)
285                 return (EPERM);
286         if (n > PRIO_MAX)
287                 n = PRIO_MAX;
288         if (n < PRIO_MIN)
289                 n = PRIO_MIN;
290         if (n < chgp->p_nice && priv_check_cred(cr, PRIV_SCHED_SETPRIORITY, 0))
291                 return (EACCES);
292         chgp->p_nice = n;
293         FOREACH_LWP_IN_PROC(lp, chgp) {
294                 LWPHOLD(lp);
295                 chgp->p_usched->resetpriority(lp);
296                 LWPRELE(lp);
297         }
298         return (0);
299 }
300
301
302 struct ioprio_get_info {
303         int high;
304         int who;
305 };
306
307 static int ioprio_get_callback(struct proc *p, void *data);
308
309 /*
310  * MPALMOSTSAFE
311  */
312 int
313 sys_ioprio_get(struct ioprio_get_args *uap)
314 {
315         struct ioprio_get_info info;
316         struct proc *curp = curproc;
317         struct proc *p;
318         int high = IOPRIO_MIN-2;
319         int error;
320
321         lwkt_gettoken(&proc_token);
322
323         switch (uap->which) {
324         case PRIO_PROCESS:
325                 if (uap->who == 0) {
326                         p = curp;
327                         PHOLD(p);
328                 } else {
329                         p = pfind(uap->who);
330                 }
331                 if (p) {
332                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred))
333                                 high = p->p_ionice;
334                         PRELE(p);
335                 }
336                 break;
337
338         case PRIO_PGRP:
339         {
340                 struct pgrp *pg;
341
342                 if (uap->who == 0) {
343                         pg = curp->p_pgrp;
344                         pgref(pg);
345                 } else if ((pg = pgfind(uap->who)) == NULL) {
346                         break;
347                 } /* else ref held from pgfind */
348
349                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
350                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred) &&
351                             p->p_nice > high)
352                                 high = p->p_ionice;
353                 }
354                 pgrel(pg);
355                 break;
356         }
357         case PRIO_USER:
358                 if (uap->who == 0)
359                         uap->who = curp->p_ucred->cr_uid;
360                 info.high = high;
361                 info.who = uap->who;
362                 allproc_scan(ioprio_get_callback, &info);
363                 high = info.high;
364                 break;
365
366         default:
367                 error = EINVAL;
368                 goto done;
369         }
370         if (high == IOPRIO_MIN-2) {
371                 error = ESRCH;
372                 goto done;
373         }
374         uap->sysmsg_result = high;
375         error = 0;
376 done:
377         lwkt_reltoken(&proc_token);
378
379         return (error);
380 }
381
382 /*
383  * Figure out the current lowest nice priority for processes owned
384  * by the specified user.
385  */
386 static
387 int
388 ioprio_get_callback(struct proc *p, void *data)
389 {
390         struct ioprio_get_info *info = data;
391
392         if (PRISON_CHECK(curproc->p_ucred, p->p_ucred) &&
393             p->p_ucred->cr_uid == info->who &&
394             p->p_ionice > info->high) {
395                 info->high = p->p_ionice;
396         }
397         return(0);
398 }
399
400
401 struct ioprio_set_info {
402         int prio;
403         int who;
404         int error;
405         int found;
406 };
407
408 static int ioprio_set_callback(struct proc *p, void *data);
409
410 /*
411  * MPALMOSTSAFE
412  */
413 int
414 sys_ioprio_set(struct ioprio_set_args *uap)
415 {
416         struct ioprio_set_info info;
417         struct proc *curp = curproc;
418         struct proc *p;
419         int found = 0, error = 0;
420
421         lwkt_gettoken(&proc_token);
422
423         switch (uap->which) {
424         case PRIO_PROCESS:
425                 if (uap->who == 0) {
426                         p = curp;
427                         PHOLD(p);
428                 } else {
429                         p = pfind(uap->who);
430                 }
431                 if (p) {
432                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred)) {
433                                 error = doionice(p, uap->prio);
434                                 found++;
435                         }
436                         PRELE(p);
437                 }
438                 break;
439
440         case PRIO_PGRP:
441         {
442                 struct pgrp *pg;
443
444                 if (uap->who == 0) {
445                         pg = curp->p_pgrp;
446                         pgref(pg);
447                 } else if ((pg = pgfind(uap->who)) == NULL) {
448                         break;
449                 } /* else ref held from pgfind */
450
451                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
452                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred)) {
453                                 error = doionice(p, uap->prio);
454                                 found++;
455                         }
456                 }
457                 pgrel(pg);
458                 break;
459         }
460         case PRIO_USER:
461                 if (uap->who == 0)
462                         uap->who = curp->p_ucred->cr_uid;
463                 info.prio = uap->prio;
464                 info.who = uap->who;
465                 info.error = 0;
466                 info.found = 0;
467                 allproc_scan(ioprio_set_callback, &info);
468                 error = info.error;
469                 found = info.found;
470                 break;
471
472         default:
473                 error = EINVAL;
474                 found = 1;
475                 break;
476         }
477
478         lwkt_reltoken(&proc_token);
479
480         if (found == 0)
481                 error = ESRCH;
482         return (error);
483 }
484
485 static
486 int
487 ioprio_set_callback(struct proc *p, void *data)
488 {
489         struct ioprio_set_info *info = data;
490         int error;
491
492         if (p->p_ucred->cr_uid == info->who &&
493             PRISON_CHECK(curproc->p_ucred, p->p_ucred)) {
494                 error = doionice(p, info->prio);
495                 if (error)
496                         info->error = error;
497                 ++info->found;
498         }
499         return(0);
500 }
501
502 int
503 doionice(struct proc *chgp, int n)
504 {
505         struct proc *curp = curproc;
506         struct ucred *cr = curp->p_ucred;
507
508         if (cr->cr_uid && cr->cr_ruid &&
509             cr->cr_uid != chgp->p_ucred->cr_uid &&
510             cr->cr_ruid != chgp->p_ucred->cr_uid)
511                 return (EPERM);
512         if (n > IOPRIO_MAX)
513                 n = IOPRIO_MAX;
514         if (n < IOPRIO_MIN)
515                 n = IOPRIO_MIN;
516         if (n < chgp->p_ionice && priv_check_cred(cr, PRIV_SCHED_SETPRIORITY, 0))
517                 return (EACCES);
518         chgp->p_ionice = n;
519
520         return (0);
521
522 }
523
524 /*
525  * MPALMOSTSAFE
526  */
527 int
528 sys_lwp_rtprio(struct lwp_rtprio_args *uap)
529 {
530         struct proc *p;
531         struct lwp *lp;
532         struct rtprio rtp;
533         struct ucred *cr = curthread->td_ucred;
534         int error;
535
536         error = copyin(uap->rtp, &rtp, sizeof(struct rtprio));
537         if (error)
538                 return error;
539         if (uap->pid < 0)
540                 return EINVAL;
541
542         lwkt_gettoken(&proc_token);
543
544         if (uap->pid == 0) {
545                 p = curproc;
546                 PHOLD(p);
547         } else {
548                 p = pfind(uap->pid);
549         }
550
551         if (p == NULL) {
552                 error = ESRCH;
553                 goto done;
554         }
555
556         if (uap->tid < -1) {
557                 error = EINVAL;
558                 goto done;
559         }
560         if (uap->tid == -1) {
561                 /*
562                  * sadly, tid can be 0 so we can't use 0 here
563                  * like sys_rtprio()
564                  */
565                 lp = curthread->td_lwp;
566         } else {
567                 lp = lwp_rb_tree_RB_LOOKUP(&p->p_lwp_tree, uap->tid);
568                 if (lp == NULL) {
569                         error = ESRCH;
570                         goto done;
571                 }
572         }
573
574         switch (uap->function) {
575         case RTP_LOOKUP:
576                 error = copyout(&lp->lwp_rtprio, uap->rtp,
577                                 sizeof(struct rtprio));
578                 break;
579         case RTP_SET:
580                 if (cr->cr_uid && cr->cr_ruid &&
581                     cr->cr_uid != p->p_ucred->cr_uid &&
582                     cr->cr_ruid != p->p_ucred->cr_uid) {
583                         error = EPERM;
584                         break;
585                 }
586                 /* disallow setting rtprio in most cases if not superuser */
587                 if (priv_check_cred(cr, PRIV_SCHED_RTPRIO, 0)) {
588                         /* can't set someone else's */
589                         if (uap->pid) { /* XXX */
590                                 error = EPERM;
591                                 break;
592                         }
593                         /* can't set realtime priority */
594 /*
595  * Realtime priority has to be restricted for reasons which should be
596  * obvious. However, for idle priority, there is a potential for
597  * system deadlock if an idleprio process gains a lock on a resource
598  * that other processes need (and the idleprio process can't run
599  * due to a CPU-bound normal process). Fix me! XXX
600  */
601                         if (RTP_PRIO_IS_REALTIME(rtp.type)) {
602                                 error = EPERM;
603                                 break;
604                         }
605                 }
606                 switch (rtp.type) {
607 #ifdef RTP_PRIO_FIFO
608                 case RTP_PRIO_FIFO:
609 #endif
610                 case RTP_PRIO_REALTIME:
611                 case RTP_PRIO_NORMAL:
612                 case RTP_PRIO_IDLE:
613                         if (rtp.prio > RTP_PRIO_MAX) {
614                                 error = EINVAL;
615                         } else {
616                                 lp->lwp_rtprio = rtp;
617                                 error = 0;
618                         }
619                         break;
620                 default:
621                         error = EINVAL;
622                         break;
623                 }
624                 break;
625         default:
626                 error = EINVAL;
627                 break;
628         }
629
630 done:
631         if (p)
632                 PRELE(p);
633         lwkt_reltoken(&proc_token);
634
635         return (error);
636 }
637
638 /*
639  * Set realtime priority
640  *
641  * MPALMOSTSAFE
642  */
643 int
644 sys_rtprio(struct rtprio_args *uap)
645 {
646         struct proc *p;
647         struct lwp *lp;
648         struct ucred *cr = curthread->td_ucred;
649         struct rtprio rtp;
650         int error;
651
652         error = copyin(uap->rtp, &rtp, sizeof(struct rtprio));
653         if (error)
654                 return (error);
655
656         lwkt_gettoken(&proc_token);
657
658         if (uap->pid == 0) {
659                 p = curproc;
660                 PHOLD(p);
661         } else {
662                 p = pfind(uap->pid);
663         }
664
665         if (p == NULL) {
666                 error = ESRCH;
667                 goto done;
668         }
669
670         /* XXX lwp */
671         lp = FIRST_LWP_IN_PROC(p);
672         switch (uap->function) {
673         case RTP_LOOKUP:
674                 error = copyout(&lp->lwp_rtprio, uap->rtp,
675                                 sizeof(struct rtprio));
676                 break;
677         case RTP_SET:
678                 if (cr->cr_uid && cr->cr_ruid &&
679                     cr->cr_uid != p->p_ucred->cr_uid &&
680                     cr->cr_ruid != p->p_ucred->cr_uid) {
681                         error = EPERM;
682                         break;
683                 }
684                 /* disallow setting rtprio in most cases if not superuser */
685                 if (priv_check_cred(cr, PRIV_SCHED_RTPRIO, 0)) {
686                         /* can't set someone else's */
687                         if (uap->pid) {
688                                 error = EPERM;
689                                 break;
690                         }
691                         /* can't set realtime priority */
692 /*
693  * Realtime priority has to be restricted for reasons which should be
694  * obvious. However, for idle priority, there is a potential for
695  * system deadlock if an idleprio process gains a lock on a resource
696  * that other processes need (and the idleprio process can't run
697  * due to a CPU-bound normal process). Fix me! XXX
698  */
699                         if (RTP_PRIO_IS_REALTIME(rtp.type)) {
700                                 error = EPERM;
701                                 break;
702                         }
703                 }
704                 switch (rtp.type) {
705 #ifdef RTP_PRIO_FIFO
706                 case RTP_PRIO_FIFO:
707 #endif
708                 case RTP_PRIO_REALTIME:
709                 case RTP_PRIO_NORMAL:
710                 case RTP_PRIO_IDLE:
711                         if (rtp.prio > RTP_PRIO_MAX) {
712                                 error = EINVAL;
713                                 break;
714                         }
715                         lp->lwp_rtprio = rtp;
716                         error = 0;
717                         break;
718                 default:
719                         error = EINVAL;
720                         break;
721                 }
722                 break;
723         default:
724                 error = EINVAL;
725                 break;
726         }
727 done:
728         if (p)
729                 PRELE(p);
730         lwkt_reltoken(&proc_token);
731
732         return (error);
733 }
734
735 /*
736  * MPSAFE
737  */
738 int
739 sys_setrlimit(struct __setrlimit_args *uap)
740 {
741         struct rlimit alim;
742         int error;
743
744         error = copyin(uap->rlp, &alim, sizeof(alim));
745         if (error)
746                 return (error);
747
748         error = kern_setrlimit(uap->which, &alim);
749
750         return (error);
751 }
752
753 /*
754  * MPSAFE
755  */
756 int
757 sys_getrlimit(struct __getrlimit_args *uap)
758 {
759         struct rlimit lim;
760         int error;
761
762         error = kern_getrlimit(uap->which, &lim);
763
764         if (error == 0)
765                 error = copyout(&lim, uap->rlp, sizeof(*uap->rlp));
766         return error;
767 }
768
769 /*
770  * Transform the running time and tick information in lwp lp's thread into user,
771  * system, and interrupt time usage.
772  *
773  * Since we are limited to statclock tick granularity this is a statisical
774  * calculation which will be correct over the long haul, but should not be
775  * expected to measure fine grained deltas.
776  *
777  * It is possible to catch a lwp in the midst of being created, so
778  * check whether lwp_thread is NULL or not.
779  */
780 void
781 calcru(struct lwp *lp, struct timeval *up, struct timeval *sp)
782 {
783         struct thread *td;
784
785         /*
786          * Calculate at the statclock level.  YYY if the thread is owned by
787          * another cpu we need to forward the request to the other cpu, or
788          * have a token to interlock the information in order to avoid racing
789          * thread destruction.
790          */
791         if ((td = lp->lwp_thread) != NULL) {
792                 crit_enter();
793                 up->tv_sec = td->td_uticks / 1000000;
794                 up->tv_usec = td->td_uticks % 1000000;
795                 sp->tv_sec = td->td_sticks / 1000000;
796                 sp->tv_usec = td->td_sticks % 1000000;
797                 crit_exit();
798         }
799 }
800
801 /*
802  * Aggregate resource statistics of all lwps of a process.
803  *
804  * proc.p_ru keeps track of all statistics directly related to a proc.  This
805  * consists of RSS usage and nswap information and aggregate numbers for all
806  * former lwps of this proc.
807  *
808  * proc.p_cru is the sum of all stats of reaped children.
809  *
810  * lwp.lwp_ru contains the stats directly related to one specific lwp, meaning
811  * packet, scheduler switch or page fault counts, etc.  This information gets
812  * added to lwp.lwp_proc.p_ru when the lwp exits.
813  */
814 void
815 calcru_proc(struct proc *p, struct rusage *ru)
816 {
817         struct timeval upt, spt;
818         long *rip1, *rip2;
819         struct lwp *lp;
820
821         *ru = p->p_ru;
822
823         FOREACH_LWP_IN_PROC(lp, p) {
824                 calcru(lp, &upt, &spt);
825                 timevaladd(&ru->ru_utime, &upt);
826                 timevaladd(&ru->ru_stime, &spt);
827                 for (rip1 = &ru->ru_first, rip2 = &lp->lwp_ru.ru_first;
828                      rip1 <= &ru->ru_last;
829                      rip1++, rip2++)
830                         *rip1 += *rip2;
831         }
832 }
833
834
835 /*
836  * MPALMOSTSAFE
837  */
838 int
839 sys_getrusage(struct getrusage_args *uap)
840 {
841         struct rusage ru;
842         struct rusage *rup;
843         int error;
844
845         lwkt_gettoken(&proc_token);
846
847         switch (uap->who) {
848         case RUSAGE_SELF:
849                 rup = &ru;
850                 calcru_proc(curproc, rup);
851                 error = 0;
852                 break;
853         case RUSAGE_CHILDREN:
854                 rup = &curproc->p_cru;
855                 error = 0;
856                 break;
857         default:
858                 error = EINVAL;
859                 break;
860         }
861         if (error == 0)
862                 error = copyout(rup, uap->rusage, sizeof(struct rusage));
863         lwkt_reltoken(&proc_token);
864         return (error);
865 }
866
867 void
868 ruadd(struct rusage *ru, struct rusage *ru2)
869 {
870         long *ip, *ip2;
871         int i;
872
873         timevaladd(&ru->ru_utime, &ru2->ru_utime);
874         timevaladd(&ru->ru_stime, &ru2->ru_stime);
875         if (ru->ru_maxrss < ru2->ru_maxrss)
876                 ru->ru_maxrss = ru2->ru_maxrss;
877         ip = &ru->ru_first; ip2 = &ru2->ru_first;
878         for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
879                 *ip++ += *ip2++;
880 }
881
882 /*
883  * Find the uidinfo structure for a uid.  This structure is used to
884  * track the total resource consumption (process count, socket buffer
885  * size, etc.) for the uid and impose limits.
886  */
887 void
888 uihashinit(void)
889 {
890         spin_init(&uihash_lock);
891         uihashtbl = hashinit(maxproc / 16, M_UIDINFO, &uihash);
892 }
893
894 /*
895  * NOTE: Must be called with uihash_lock held
896  *
897  * MPSAFE
898  */
899 static struct uidinfo *
900 uilookup(uid_t uid)
901 {
902         struct  uihashhead *uipp;
903         struct  uidinfo *uip;
904
905         uipp = UIHASH(uid);
906         LIST_FOREACH(uip, uipp, ui_hash) {
907                 if (uip->ui_uid == uid)
908                         break;
909         }
910         return (uip);
911 }
912
913 /*
914  * Helper function to creat ea uid that could not be found.
915  * This function will properly deal with races.
916  *
917  * MPSAFE
918  */
919 static struct uidinfo *
920 uicreate(uid_t uid)
921 {
922         struct  uidinfo *uip, *tmp;
923
924         /*
925          * Allocate space and check for a race
926          */
927         uip = kmalloc(sizeof(*uip), M_UIDINFO, M_WAITOK|M_ZERO);
928
929         /*
930          * Initialize structure and enter it into the hash table
931          */
932         spin_init(&uip->ui_lock);
933         uip->ui_uid = uid;
934         uip->ui_ref = 1;        /* we're returning a ref */
935         varsymset_init(&uip->ui_varsymset, NULL);
936
937         /*
938          * Somebody may have already created the uidinfo for this
939          * uid. If so, return that instead.
940          */
941         spin_lock(&uihash_lock);
942         tmp = uilookup(uid);
943         if (tmp != NULL) {
944                 uihold(tmp);
945                 spin_unlock(&uihash_lock);
946
947                 spin_uninit(&uip->ui_lock);
948                 varsymset_clean(&uip->ui_varsymset);
949                 kfree(uip, M_UIDINFO);
950                 uip = tmp;
951         } else {
952                 LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash);
953                 spin_unlock(&uihash_lock);
954         }
955         return (uip);
956 }
957
958 /*
959  *
960  *
961  * MPSAFE
962  */
963 struct uidinfo *
964 uifind(uid_t uid)
965 {
966         struct  uidinfo *uip;
967
968         spin_lock(&uihash_lock);
969         uip = uilookup(uid);
970         if (uip == NULL) {
971                 spin_unlock(&uihash_lock);
972                 uip = uicreate(uid);
973         } else {
974                 uihold(uip);
975                 spin_unlock(&uihash_lock);
976         }
977         return (uip);
978 }
979
980 /*
981  * Helper funtion to remove a uidinfo whos reference count is
982  * transitioning from 1->0.  The reference count is 1 on call.
983  *
984  * Zero is returned on success, otherwise non-zero and the
985  * uiphas not been removed.
986  *
987  * MPSAFE
988  */
989 static __inline int
990 uifree(struct uidinfo *uip)
991 {
992         /*
993          * If we are still the only holder after acquiring the uihash_lock
994          * we can safely unlink the uip and destroy it.  Otherwise we lost
995          * a race and must fail.
996          */
997         spin_lock(&uihash_lock);
998         if (uip->ui_ref != 1) {
999                 spin_unlock(&uihash_lock);
1000                 return(-1);
1001         }
1002         LIST_REMOVE(uip, ui_hash);
1003         spin_unlock(&uihash_lock);
1004
1005         /*
1006          * The uip is now orphaned and we can destroy it at our
1007          * leisure.
1008          */
1009         if (uip->ui_sbsize != 0)
1010                 kprintf("freeing uidinfo: uid = %d, sbsize = %jd\n",
1011                     uip->ui_uid, (intmax_t)uip->ui_sbsize);
1012         if (uip->ui_proccnt != 0)
1013                 kprintf("freeing uidinfo: uid = %d, proccnt = %ld\n",
1014                     uip->ui_uid, uip->ui_proccnt);
1015         
1016         varsymset_clean(&uip->ui_varsymset);
1017         lockuninit(&uip->ui_varsymset.vx_lock);
1018         spin_uninit(&uip->ui_lock);
1019         kfree(uip, M_UIDINFO);
1020         return(0);
1021 }
1022
1023 /*
1024  * MPSAFE
1025  */
1026 void
1027 uihold(struct uidinfo *uip)
1028 {
1029         atomic_add_int(&uip->ui_ref, 1);
1030         KKASSERT(uip->ui_ref >= 0);
1031 }
1032
1033 /*
1034  * NOTE: It is important for us to not drop the ref count to 0
1035  *       because this can cause a 2->0/2->0 race with another
1036  *       concurrent dropper.  Losing the race in that situation
1037  *       can cause uip to become stale for one of the other
1038  *       threads.
1039  *
1040  * MPSAFE
1041  */
1042 void
1043 uidrop(struct uidinfo *uip)
1044 {
1045         int ref;
1046
1047         KKASSERT(uip->ui_ref > 0);
1048
1049         for (;;) {
1050                 ref = uip->ui_ref;
1051                 cpu_ccfence();
1052                 if (ref == 1) {
1053                         if (uifree(uip) == 0)
1054                                 break;
1055                 } else if (atomic_cmpset_int(&uip->ui_ref, ref, ref - 1)) {
1056                         break;
1057                 }
1058                 /* else retry */
1059         }
1060 }
1061
1062 void
1063 uireplace(struct uidinfo **puip, struct uidinfo *nuip)
1064 {
1065         uidrop(*puip);
1066         *puip = nuip;
1067 }
1068
1069 /*
1070  * Change the count associated with number of processes
1071  * a given user is using.  When 'max' is 0, don't enforce a limit
1072  */
1073 int
1074 chgproccnt(struct uidinfo *uip, int diff, int max)
1075 {
1076         int ret;
1077         spin_lock(&uip->ui_lock);
1078         /* don't allow them to exceed max, but allow subtraction */
1079         if (diff > 0 && uip->ui_proccnt + diff > max && max != 0) {
1080                 ret = 0;
1081         } else {
1082                 uip->ui_proccnt += diff;
1083                 if (uip->ui_proccnt < 0)
1084                         kprintf("negative proccnt for uid = %d\n", uip->ui_uid);
1085                 ret = 1;
1086         }
1087         spin_unlock(&uip->ui_lock);
1088         return ret;
1089 }
1090
1091 /*
1092  * Change the total socket buffer size a user has used.
1093  */
1094 int
1095 chgsbsize(struct uidinfo *uip, u_long *hiwat, u_long to, rlim_t max)
1096 {
1097         rlim_t new;
1098
1099         spin_lock(&uip->ui_lock);
1100         new = uip->ui_sbsize + to - *hiwat;
1101         KKASSERT(new >= 0);
1102
1103         /*
1104          * If we are trying to increase the socket buffer size
1105          * Scale down the hi water mark when we exceed the user's
1106          * allowed socket buffer space.
1107          *
1108          * We can't scale down too much or we will blow up atomic packet
1109          * operations.
1110          */
1111         if (to > *hiwat && to > MCLBYTES && new > max) {
1112                 to = to * max / new;
1113                 if (to < MCLBYTES)
1114                         to = MCLBYTES;
1115         }
1116         uip->ui_sbsize = new;
1117         *hiwat = to;
1118         spin_unlock(&uip->ui_lock);
1119         return (1);
1120 }
1121