From owner-freebsd-current Thu Jun 11 04:39:31 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id EAA26278 for freebsd-current-outgoing; Thu, 11 Jun 1998 04:39:31 -0700 (PDT) (envelope-from owner-freebsd-current@FreeBSD.ORG) Received: from godzilla.zeta.org.au (godzilla.zeta.org.au [203.15.68.22]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id EAA26270 for ; Thu, 11 Jun 1998 04:39:27 -0700 (PDT) (envelope-from bde@godzilla.zeta.org.au) Received: (from bde@localhost) by godzilla.zeta.org.au (8.8.7/8.8.7) id VAA06458; Thu, 11 Jun 1998 21:39:25 +1000 Date: Thu, 11 Jun 1998 21:39:25 +1000 From: Bruce Evans Message-Id: <199806111139.VAA06458@godzilla.zeta.org.au> To: bde@zeta.org.au, phk@critter.freebsd.dk Subject: Re: Spurious SIGXCPU Cc: current@FreeBSD.ORG, jb@cimlogic.com.au, jdp@polstra.com, rb@gid.co.uk Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG >>>>Another sign of the bug is that accounting for rapid context switches >>>>is broken again: >>>> >>>> $ time ./fork-benchmark 10000 >>>> 6.10 real 0.01 user 8.33 sys >>> >>>if you make it always call >>> microuptime(&p->p_switchtime); >>> >>>after cpu_switch() in kern_synch, does that make it any different ? >> >>Probably. I fixed it by clearing switchtime.tv_sec in fork_trampoline() >>and am now trying to figure out why that works :-). > >huh ??? exit() doesn't switch off via mi_switch(), so a stale switchtime was often used after exit(). Clearing switchtime.tv_sec in fork_trampoline() fixed the problem in the particular case of child processes that exit() immediately after the fork(). Ignoring switchtime of course fixes the problem. Except both clearing and ignoring lose track of a little time. I fixed this in calcru() by setting switchtime. calcru() is called by exit1() just before it leaves the kernel, and the value for switchtime set by this call will be used for the next process unless the system goes idle. The value won't be used in other cases (since everything except exit() switches via mi_switch() which reinitializes switchtime). Setting switchtime in a natural place (later in exit1()) would leave the time between the calls to microuptime() unaccounted for. The other changes in calcru() are cosmetic. The changes in fork_trampoline() are to avoid leaving the time between another pair of calls to microtime() unnaccounted for. switchtime seems to always be set in fork_trampoline(). Bruce diff -c2 i386/i386/exception.s~ i386/i386/exception.s *** i386/i386/exception.s~ Fri May 29 12:52:34 1998 --- i386/i386/exception.s Thu Jun 11 11:40:44 1998 *************** *** 346,352 **** --- 431,446 ---- movl _curproc,%eax addl $P_SWITCHTIME,%eax + movl _switchtime,%ecx + testl %ecx,%ecx + jne 1f pushl %eax call _microuptime popl %eax + jmp 2f + 1: + movl %ecx,(%eax) + movl _switchtime+4,%edx + movl %edx,4(%eax) + 2: /* diff -c2 kern/kern_resource.c~ kern/kern_resource.c *** kern/kern_resource.c~ Fri May 29 13:02:39 1998 --- kern/kern_resource.c Thu Jun 11 11:36:39 1998 /* can't set someone else's */ *************** *** 511,517 **** } - totusec = p->p_runtime; #ifdef SMP if (p->p_oncpu != (char)0xff) { #else if (p == curproc) { --- 511,516 ---- } #ifdef SMP if (p->p_oncpu != (char)0xff) { #else if (p == curproc) { *************** *** 523,529 **** */ microuptime(&tv); ! totusec += (tv.tv_usec - p->p_switchtime.tv_usec) + ! (tv.tv_sec - p->p_switchtime.tv_sec) * (int64_t)1000000; ! } if (totusec < 0) { /* XXX no %qd in kernel. Truncate. */ --- 522,531 ---- */ microuptime(&tv); ! switchtime = tv; /* XXX */ ! totusec = p->p_runtime + ! (tv.tv_sec - p->p_switchtime.tv_sec) * (int64_t)1000000 + ! (tv.tv_usec - p->p_switchtime.tv_usec); ! } else ! totusec = p->p_runtime; if (totusec < 0) { /* XXX no %qd in kernel. Truncate. */ To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message