From owner-svn-src-head@FreeBSD.ORG Wed Mar 6 22:40:47 2013 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id BFE4F9BF; Wed, 6 Mar 2013 22:40:47 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id B1160D6F; Wed, 6 Mar 2013 22:40:47 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r26MelrE095464; Wed, 6 Mar 2013 22:40:47 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r26MelaH095463; Wed, 6 Mar 2013 22:40:47 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201303062240.r26MelaH095463@svn.freebsd.org> From: Alexander Motin Date: Wed, 6 Mar 2013 22:40:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r247903 - head/sys/kern X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 06 Mar 2013 22:40:47 -0000 Author: mav Date: Wed Mar 6 22:40:47 2013 New Revision: 247903 URL: http://svnweb.freebsd.org/changeset/base/247903 Log: Reduce minimal time intervals of setitimer(2) from 1/HZ to 1/(16*HZ) by using callout_reset_sbt() instead of callout_reset(). We can't remove lower limit completely in this case because of significant processing overhead, caused by unability to use direct callout execution due to using process mutex in callout handler for sending SEGALRM signal. With support of periodic events that would allow unprivileged user to abuse the system. Reviewed by: davide Modified: head/sys/kern/kern_time.c Modified: head/sys/kern/kern_time.c ============================================================================== --- head/sys/kern/kern_time.c Wed Mar 6 22:12:45 2013 (r247902) +++ head/sys/kern/kern_time.c Wed Mar 6 22:40:47 2013 (r247903) @@ -691,7 +691,7 @@ kern_getitimer(struct thread *td, u_int *aitv = p->p_realtimer; PROC_UNLOCK(p); if (timevalisset(&aitv->it_value)) { - getmicrouptime(&ctv); + microuptime(&ctv); if (timevalcmp(&aitv->it_value, &ctv, <)) timevalclear(&aitv->it_value); else @@ -736,28 +736,33 @@ kern_setitimer(struct thread *td, u_int { struct proc *p = td->td_proc; struct timeval ctv; + sbintime_t sbt, pr; if (aitv == NULL) return (kern_getitimer(td, which, oitv)); if (which > ITIMER_PROF) return (EINVAL); - if (itimerfix(&aitv->it_value)) + if (itimerfix(&aitv->it_value) || + aitv->it_value.tv_sec > INT32_MAX / 2) return (EINVAL); if (!timevalisset(&aitv->it_value)) timevalclear(&aitv->it_interval); - else if (itimerfix(&aitv->it_interval)) + else if (itimerfix(&aitv->it_interval) || + aitv->it_interval.tv_sec > INT32_MAX / 2) return (EINVAL); if (which == ITIMER_REAL) { PROC_LOCK(p); if (timevalisset(&p->p_realtimer.it_value)) callout_stop(&p->p_itcallout); - getmicrouptime(&ctv); + microuptime(&ctv); if (timevalisset(&aitv->it_value)) { - callout_reset(&p->p_itcallout, tvtohz(&aitv->it_value), - realitexpire, p); + pr = tvtosbt(aitv->it_value) >> tc_precexp; timevaladd(&aitv->it_value, &ctv); + sbt = tvtosbt(aitv->it_value); + callout_reset_sbt(&p->p_itcallout, sbt, pr, + realitexpire, p, C_ABSOLUTE); } *oitv = p->p_realtimer; p->p_realtimer = *aitv; @@ -793,7 +798,8 @@ void realitexpire(void *arg) { struct proc *p; - struct timeval ctv, ntv; + struct timeval ctv; + sbintime_t isbt; p = (struct proc *)arg; kern_psignal(p, SIGALRM); @@ -803,19 +809,17 @@ realitexpire(void *arg) wakeup(&p->p_itcallout); return; } - for (;;) { + isbt = tvtosbt(p->p_realtimer.it_interval); + if (isbt >= sbt_timethreshold) + getmicrouptime(&ctv); + else + microuptime(&ctv); + do { timevaladd(&p->p_realtimer.it_value, &p->p_realtimer.it_interval); - getmicrouptime(&ctv); - if (timevalcmp(&p->p_realtimer.it_value, &ctv, >)) { - ntv = p->p_realtimer.it_value; - timevalsub(&ntv, &ctv); - callout_reset(&p->p_itcallout, tvtohz(&ntv) - 1, - realitexpire, p); - return; - } - } - /*NOTREACHED*/ + } while (timevalcmp(&p->p_realtimer.it_value, &ctv, <=)); + callout_reset_sbt(&p->p_itcallout, tvtosbt(p->p_realtimer.it_value), + isbt >> tc_precexp, realitexpire, p, C_ABSOLUTE); } /* @@ -830,8 +834,9 @@ itimerfix(struct timeval *tv) if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000) return (EINVAL); - if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) - tv->tv_usec = tick; + if (tv->tv_sec == 0 && tv->tv_usec != 0 && + tv->tv_usec < (u_int)tick / 16) + tv->tv_usec = (u_int)tick / 16; return (0); }