From owner-freebsd-bugs Mon May 11 04:03:24 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id EAA20255 for freebsd-bugs-outgoing; Mon, 11 May 1998 04:03:24 -0700 (PDT) (envelope-from owner-freebsd-bugs@FreeBSD.ORG) Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id EAA20241 for ; Mon, 11 May 1998 04:03:22 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.8.8/8.8.5) id EAA28733; Mon, 11 May 1998 04:00:02 -0700 (PDT) Received: (from nobody@localhost) by hub.freebsd.org (8.8.8/8.8.8) id DAA19200; Mon, 11 May 1998 03:54:42 -0700 (PDT) (envelope-from nobody) Message-Id: <199805111054.DAA19200@hub.freebsd.org> Date: Mon, 11 May 1998 03:54:42 -0700 (PDT) From: will@iki.fi To: freebsd-gnats-submit@FreeBSD.ORG X-Send-Pr-Version: www-1.0 Subject: kern/6587: SMP idle cpl breaks signal forwarding Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 6587 >Category: kern >Synopsis: SMP idle cpl breaks signal forwarding >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon May 11 04:00:02 PDT 1998 >Last-Modified: >Originator: Ville-Pertti Keinonen >Organization: >Release: -current >Environment: Should occur on any SMP machine. Current versions to at least May 4th. >Description: The cpl either should always be 0 when entering the kernel from user mode or no code should rely on it being 0. Currently, some code relies on it, some doesn't, and at least in the case where the other cpu is idle, it may not correspond to what is set when going to user mode. This sometimes breaks signal forwarding if the signal occurs in an interrupt handler. What seems to be happening is this: - A clock interrupt occurs on an idle cpu. - The signal is set and forwarded. - Xcpuast is entered by the cpu running the process (waits on lock). - The idle cpu returns from the interrupt to an idle state, leaving the cpl as SWI_AST_MASK. - Xcpuast continues, sets the ast in ipending and branches to _doreti with the cpl left by the other cpu -- the ast isn't processed. - The cpl eventually gets cleared, the ast in ipending is probably processed by the cpu that was idle. I'm not sure where exactly the cpl becomes SWI_AST_MASK (I only looked at what was going on with the cpu that was running the process that was supposed to get the signal, the rest is speculation), but my guess is it's restored when returning from the interrupt to the idle state (it seems that in the idle state the cpl is set by a call to spl0). >How-To-Repeat: On a mostly idle SMP machine, run the following program: #include #include #include void handler(int signo) { printf("got signal\n"); exit(0); } int main(int argc, char **argv) { signal(SIGALRM, handler); alarm(1); for (;;) ; } Repeat several times, run it using time(1) to verify that it's definitely not doing what it's supposed to (it should be obvious enough, in any case -- for me it usually takes ten seconds or more for the signal to arrive if I do nothing). >Fix: One workaround (this could be done many ways) is to always return the cpl to 0 before returning from an exception to user mode in _doreti. This is not the correct way to fix the problem. Adding the following lines to _doreti (in sys/i386/isa/ipl.s) seems to work. (From memory, not a real patch, sorry) _doreti: #ifdef SMP TEST_CIL #endif FAKE_MCOUNT(_bintr) /* init "from" _bintr -> _doreti */ addl $4,%esp /* discard unit number */ popl %eax /* cpl or cml to restore */ + testb $3,52(%esp) /* going back to user mode? */ + jz 1f + xorl %eax,%eax /* yup, cpl should be 0. */ +1: doreti_next: Note that this makes the equivalent tests done for some traps redundant. >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message