Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/kern/kern_time.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/kern/kern_time.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.105 retrieving revision 1.105.4.5 diff -u -p -r1.105 -r1.105.4.5 --- src/sys/kern/kern_time.c 2006/07/23 22:06:11 1.105 +++ src/sys/kern/kern_time.c 2006/12/29 20:27:44 1.105.4.5 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_time.c,v 1.105 2006/07/23 22:06:11 ad Exp $ */ +/* $NetBSD: kern_time.c,v 1.105.4.5 2006/12/29 20:27:44 ad Exp $ */ /*- * Copyright (c) 2000, 2004, 2005 The NetBSD Foundation, Inc. @@ -68,7 +68,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.105 2006/07/23 22:06:11 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.105.4.5 2006/12/29 20:27:44 ad Exp $"); #include "fs_nfs.h" #include "opt_nfs.h" @@ -110,7 +110,6 @@ POOL_INIT(ptimer_pool, sizeof(struct pti POOL_INIT(ptimers_pool, sizeof(struct ptimers), 0, 0, 0, "ptimerspl", &pool_allocator_nointr); -static void timerupcall(struct lwp *, void *); #ifdef __HAVE_TIMECOUNTER static int itimespecfix(struct timespec *); /* XXX move itimerfix to timespecs */ #endif /* __HAVE_TIMECOUNTER */ @@ -149,12 +148,18 @@ settime(struct proc *p, struct timespec * time_t is 32 bits even when atv.tv_sec is 64 bits. */ if (ts->tv_sec > INT_MAX - 365*24*60*60) { - struct proc *pp = p->p_pptr; + struct proc *pp; + + rw_enter(&proclist_lock, RW_READER); + pp = p->p_pptr; + mutex_enter(&pp->p_mutex); log(LOG_WARNING, "pid %d (%s) " "invoked by uid %d ppid %d (%s) " "tried to set clock forward to %ld\n", p->p_pid, p->p_comm, kauth_cred_geteuid(pp->p_cred), pp->p_pid, pp->p_comm, (long)ts->tv_sec); + mutex_exit(&pp->p_mutex); + rw_exit(&proclist_lock); return (EPERM); } TIMESPEC_TO_TIMEVAL(&tv, ts); @@ -167,12 +172,14 @@ settime(struct proc *p, struct timespec #else /* !__HAVE_TIMECOUNTER */ timersub(&tv, &time, &delta); #endif /* !__HAVE_TIMECOUNTER */ - if ((delta.tv_sec < 0 || delta.tv_usec < 0) && securelevel > 1) { + if ((delta.tv_sec < 0 || delta.tv_usec < 0) && + kauth_authorize_system(p->p_cred, KAUTH_SYSTEM_TIME, + KAUTH_REQ_SYSTEM_TIME_BACKWARDS, NULL, NULL, NULL)) { splx(s); return (EPERM); } #ifdef notyet - if ((delta.tv_sec < 86400) && securelevel > 0) { + if ((delta.tv_sec < 86400) && securelevel > 0) { /* XXX elad - notyet */ splx(s); return (EPERM); } @@ -253,8 +260,8 @@ sys_clock_settime(struct lwp *l, void *v } */ *uap = v; int error; - if ((error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, - &l->l_acflag)) != 0) + if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME, + KAUTH_REQ_SYSTEM_TIME_SYSTEM, NULL, NULL, NULL)) != 0) return (error); return clock_settime1(l->l_proc, SCARG(uap, clock_id), SCARG(uap, tp)); @@ -324,7 +331,6 @@ int sys_nanosleep(struct lwp *l, void *v, register_t *retval) { #ifdef __HAVE_TIMECOUNTER - static int nanowait; struct sys_nanosleep_args/* { syscallarg(struct timespec *) rqtp; syscallarg(struct timespec *) rmtp; @@ -348,7 +354,7 @@ sys_nanosleep(struct lwp *l, void *v, re getnanouptime(&rmt); - error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo); + error = sched_pause("nanoslp", TRUE, timo); if (error == ERESTART) error = EINTR; if (error == EWOULDBLOCK) @@ -373,7 +379,6 @@ sys_nanosleep(struct lwp *l, void *v, re return error; #else /* !__HAVE_TIMECOUNTER */ - static int nanowait; struct sys_nanosleep_args/* { syscallarg(struct timespec *) rqtp; syscallarg(struct timespec *) rmtp; @@ -401,7 +406,7 @@ sys_nanosleep(struct lwp *l, void *v, re timo = 1; splx(s); - error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo); + error = sched_pause("nanoslp", TRUE, timo); if (error == ERESTART) error = EINTR; if (error == EWOULDBLOCK) @@ -469,8 +474,8 @@ sys_settimeofday(struct lwp *l, void *v, } */ *uap = v; int error; - if ((error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, - &l->l_acflag)) != 0) + if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME, + KAUTH_REQ_SYSTEM_TIME_SYSTEM, NULL, NULL, NULL)) != 0) return (error); return settimeofday1(SCARG(uap, tv), SCARG(uap, tzp), l->l_proc); @@ -520,8 +525,8 @@ sys_adjtime(struct lwp *l, void *v, regi } */ *uap = v; int error; - if ((error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, - &l->l_acflag)) != 0) + if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME, + KAUTH_REQ_SYSTEM_TIME_ADJTIME, NULL, NULL, NULL)) != 0) return (error); return adjtime1(SCARG(uap, delta), SCARG(uap, olddelta), l->l_proc); @@ -1040,10 +1045,10 @@ sys_timer_getoverrun(struct lwp *l, void } /* Glue function that triggers an upcall; called from userret(). */ -static void -timerupcall(struct lwp *l, void *arg) +void +timerupcall(struct lwp *l) { - struct ptimers *pt = (struct ptimers *)arg; + struct ptimers *pt = l->l_proc->p_timers; unsigned int i, fired, done; KDASSERT(l->l_proc->p_sa); @@ -1051,7 +1056,7 @@ timerupcall(struct lwp *l, void *arg) if (l->l_savp->savp_lwp != l) return ; - KERNEL_PROC_LOCK(l); + KERNEL_LOCK(1, l); fired = pt->pts_fired; done = 0; @@ -1060,8 +1065,10 @@ timerupcall(struct lwp *l, void *arg) int mask = 1 << --i; int f; + lwp_lock(l); f = l->l_flag & L_SA; l->l_flag &= ~L_SA; + lwp_unlock(l); si = siginfo_alloc(PR_WAITOK); si->_info = pt->pts_timers[i]->pt_info.ksi_info; if (sa_upcall(l, SA_UPCALL_SIGEV | SA_UPCALL_DEFER, NULL, l, @@ -1071,13 +1078,15 @@ timerupcall(struct lwp *l, void *arg) } else done |= mask; fired &= ~mask; + lwp_lock(l); l->l_flag |= f; + lwp_unlock(l); } pt->pts_fired &= ~done; if (pt->pts_fired == 0) - l->l_proc->p_userret = NULL; + l->l_proc->p_timerpend = 0; - KERNEL_PROC_UNLOCK(l); + (void)KERNEL_UNLOCK(1, l); } /* @@ -1446,7 +1455,6 @@ itimerfire(struct ptimer *pt) { struct proc *p = pt->pt_proc; struct sadata_vp *vp; - int s; unsigned int i; if (pt->pt_ev.sigev_notify == SIGEV_SIGNAL) { @@ -1455,7 +1463,7 @@ itimerfire(struct ptimer *pt) * just post the signal number and throw away the * value. */ - if (sigismember(&p->p_sigctx.ps_siglist, pt->pt_ev.sigev_signo)) + if (sigismember(&p->p_sigpend.sp_set, pt->pt_ev.sigev_signo)) pt->pt_overruns++; else { ksiginfo_t ksi; @@ -1465,12 +1473,13 @@ itimerfire(struct ptimer *pt) ksi.ksi_sigval = pt->pt_ev.sigev_value; pt->pt_poverruns = pt->pt_overruns; pt->pt_overruns = 0; + mutex_enter(&proclist_mutex); kpsignal(p, &ksi, NULL); + mutex_exit(&proclist_mutex); } - } else if (pt->pt_ev.sigev_notify == SIGEV_SA && (p->p_flag & P_SA)) { + } else if (pt->pt_ev.sigev_notify == SIGEV_SA && (p->p_sflag & PS_SA)) { /* Cause the process to generate an upcall when it returns. */ - - if (p->p_userret == NULL) { + if (!p->p_timerpend) { /* * XXX stop signals can be processed inside tsleep, * which can be inside sa_yield's inner loop, which @@ -1481,19 +1490,22 @@ itimerfire(struct ptimer *pt) pt->pt_overruns = 0; i = 1 << pt->pt_entry; p->p_timers->pts_fired = i; - p->p_userret = timerupcall; - p->p_userret_arg = p->p_timers; + p->p_timerpend = 1; - SCHED_LOCK(s); + mutex_enter(&p->p_smutex); SLIST_FOREACH(vp, &p->p_sa->sa_vps, savp_next) { + lwp_need_userret(vp->savp_lwp); + lwp_lock(vp->savp_lwp); if (vp->savp_lwp->l_flag & L_SA_IDLE) { vp->savp_lwp->l_flag &= ~L_SA_IDLE; - sched_wakeup(vp->savp_lwp); + lwp_unlock(vp->savp_lwp); + wakeup(vp->savp_lwp); break; } + lwp_unlock(vp->savp_lwp); } - SCHED_UNLOCK(s); - } else if (p->p_userret == timerupcall) { + mutex_exit(&p->p_smutex); + } else { i = 1 << pt->pt_entry; if ((p->p_timers->pts_fired & i) == 0) { pt->pt_poverruns = pt->pt_overruns; @@ -1501,16 +1513,8 @@ itimerfire(struct ptimer *pt) p->p_timers->pts_fired |= i; } else pt->pt_overruns++; - } else { - pt->pt_overruns++; - if ((p->p_flag & P_WEXIT) == 0) - printf("itimerfire(%d): overrun %d on timer %x (userret is %p)\n", - p->p_pid, pt->pt_overruns, - pt->pt_ev.sigev_value.sival_int, - p->p_userret); } } - } /*