Index: sys/resourcevar.h =================================================================== RCS file: /usr/repo/src/sys/sys/resourcevar.h,v retrieving revision 1.52 diff -u -p -r1.52 resourcevar.h --- sys/resourcevar.h 9 Jun 2007 21:48:44 -0000 1.52 +++ sys/resourcevar.h 18 Aug 2007 10:47:54 -0000 @@ -89,16 +89,12 @@ struct plimit { */ struct uidinfo { LIST_ENTRY(uidinfo) ui_hash; /* (c) hash chain of uidinfos */ - rlim_t ui_sbsize; /* (b) socket buffer space consumed */ + long ui_sbsize; /* (b) socket buffer space consumed */ long ui_proccnt; /* (b) number of processes */ uid_t ui_uid; /* (a) uid */ u_int ui_ref; /* (b) reference count */ - struct mtx *ui_mtxp; /* protect all counts/limits */ }; -#define UIDINFO_LOCK(ui) mtx_lock((ui)->ui_mtxp) -#define UIDINFO_UNLOCK(ui) mtx_unlock((ui)->ui_mtxp) - struct proc; struct rusage_ext; struct thread; @@ -107,7 +103,7 @@ void addupc_intr(struct thread *td, uin void addupc_task(struct thread *td, uintfptr_t pc, u_int ticks); void calccru(struct proc *p, struct timeval *up, struct timeval *sp); void calcru(struct proc *p, struct timeval *up, struct timeval *sp); -int chgproccnt(struct uidinfo *uip, int diff, int maxval); +int chgproccnt(struct uidinfo *uip, int diff, rlim_t maxval); int chgsbsize(struct uidinfo *uip, u_int *hiwat, u_int to, rlim_t maxval); int fuswintr(void *base); Index: kern/kern_resource.c =================================================================== RCS file: /usr/repo/src/sys/kern/kern_resource.c,v retrieving revision 1.180 diff -u -p -r1.180 kern_resource.c --- kern/kern_resource.c 17 Jul 2007 01:08:09 -0000 1.180 +++ kern/kern_resource.c 18 Aug 2007 22:30:41 -0000 @@ -56,6 +56,7 @@ __FBSDID("$FreeBSD: src/sys/kern/kern_re #include #include #include +#include #include #include @@ -1219,7 +1220,7 @@ uifind(uid) free(uip, M_UIDINFO); uip = old_uip; } else { - uip->ui_mtxp = mtx_pool_alloc(mtxpool_sleep); + refcount_init(&uip->ui_ref, 0); uip->ui_uid = uid; LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash); } @@ -1237,9 +1238,7 @@ uihold(uip) struct uidinfo *uip; { - UIDINFO_LOCK(uip); - uip->ui_ref++; - UIDINFO_UNLOCK(uip); + refcount_acquire(&uip->ui_ref); } /*- @@ -1262,42 +1261,26 @@ uifree(uip) struct uidinfo *uip; { - /* Prepare for optimal case. */ - UIDINFO_LOCK(uip); - - if (--uip->ui_ref != 0) { - UIDINFO_UNLOCK(uip); + if (!refcount_release(&uip->ui_ref)) return; - } - - /* Prepare for suboptimal case. */ - uip->ui_ref++; - UIDINFO_UNLOCK(uip); mtx_lock(&uihashtbl_mtx); - UIDINFO_LOCK(uip); - - /* - * We must subtract one from the count again because we backed out - * our initial subtraction before dropping the lock. - * Since another thread may have added a reference after we dropped the - * initial lock we have to test for zero again. - */ - if (--uip->ui_ref == 0) { - LIST_REMOVE(uip, ui_hash); + if (uip->ui_ref > 0) { + /* + * Someone added a reference after refcount_release(), but + * before mtx_lock(&uihashtbl_mtx). + */ mtx_unlock(&uihashtbl_mtx); - if (uip->ui_sbsize != 0) - printf("freeing uidinfo: uid = %d, sbsize = %jd\n", - uip->ui_uid, (intmax_t)uip->ui_sbsize); - if (uip->ui_proccnt != 0) - printf("freeing uidinfo: uid = %d, proccnt = %ld\n", - uip->ui_uid, uip->ui_proccnt); - UIDINFO_UNLOCK(uip); - FREE(uip, M_UIDINFO); return; } - + LIST_REMOVE(uip, ui_hash); mtx_unlock(&uihashtbl_mtx); - UIDINFO_UNLOCK(uip); + if (uip->ui_sbsize != 0) + printf("freeing uidinfo: uid = %d, sbsize = %ld\n", + uip->ui_uid, uip->ui_sbsize); + if (uip->ui_proccnt != 0) + printf("freeing uidinfo: uid = %d, proccnt = %ld\n", + uip->ui_uid, uip->ui_proccnt); + FREE(uip, M_UIDINFO); } /* @@ -1308,19 +1291,21 @@ int chgproccnt(uip, diff, max) struct uidinfo *uip; int diff; - int max; + rlim_t max; { + long old; - UIDINFO_LOCK(uip); - /* Don't allow them to exceed max, but allow subtraction. */ - if (diff > 0 && uip->ui_proccnt + diff > max && max != 0) { - UIDINFO_UNLOCK(uip); - return (0); - } - uip->ui_proccnt += diff; - if (uip->ui_proccnt < 0) - printf("negative proccnt for uid = %d\n", uip->ui_uid); - UIDINFO_UNLOCK(uip); + if (diff > 0 && max != 0) { + do { + old = uip->ui_proccnt; + if (old + diff > max) + return (0); + } while (atomic_cmpset_long(&uip->ui_proccnt, old, old + diff) == 0); + } else { + atomic_add_long(&uip->ui_proccnt, (long)diff); + if (uip->ui_proccnt < 0) + printf("negative proccnt for uid = %d\n", uip->ui_uid); + } return (1); } @@ -1334,19 +1319,21 @@ chgsbsize(uip, hiwat, to, max) u_int to; rlim_t max; { - rlim_t new; - - UIDINFO_LOCK(uip); - new = uip->ui_sbsize + to - *hiwat; - /* Don't allow them to exceed max, but allow subtraction. */ - if (to > *hiwat && new > max) { - UIDINFO_UNLOCK(uip); - return (0); + long old; + int diff; + + diff = to - *hiwat; + if (diff > 0) { + do { + old = uip->ui_sbsize; + if (old + diff > max) + return (0); + } while (atomic_cmpset_long(&uip->ui_sbsize, old, old + diff) == 0); + } else { + atomic_add_long(&uip->ui_sbsize, (long)diff); + if (uip->ui_sbsize < 0) + printf("negative sbsize for uid = %d\n", uip->ui_uid); } - uip->ui_sbsize = new; - UIDINFO_UNLOCK(uip); *hiwat = to; - if (new < 0) - printf("negative sbsize for uid = %d\n", uip->ui_uid); return (1); }