From owner-freebsd-arch Mon Jan 7 1:43:38 2002 Delivered-To: freebsd-arch@freebsd.org Received: from pcnet1.pcnet.com (pcnet1.pcnet.com [204.213.232.3]) by hub.freebsd.org (Postfix) with ESMTP id EDDBD37B41A for ; Mon, 7 Jan 2002 01:43:33 -0800 (PST) Received: from vigrid.com (pm3-pt20.pcnet.net [206.105.29.94]) by pcnet1.pcnet.com (8.12.1/8.12.1) with ESMTP id g079gHrU007334; Mon, 7 Jan 2002 04:42:18 -0500 (EST) Message-ID: <3C396F9F.A53049E4@vigrid.com> Date: Mon, 07 Jan 2002 04:51:27 -0500 From: Dan Eischen X-Mailer: Mozilla 4.74 [en] (X11; U; FreeBSD 5.0-CURRENT i386) X-Accept-Language: en MIME-Version: 1.0 To: Bruce Evans Cc: Peter Wemm , Archie Cobbs , Alfred Perlstein , arch@FreeBSD.ORG Subject: Re: Request for review: getcontext, setcontext, etc References: <20020107164848.J468-100000@gamplex.bde.org> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Sender: owner-freebsd-arch@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Bruce Evans wrote: > > On Sun, 6 Jan 2002, Peter Wemm wrote: > > > The context argument passed in to signal handlers should be able to be used > > with setcontext() to return from the signal handler as an alternative to > > sigreturn(). Doing it in libc wont work there because you race with > > restoring the signal mask before you've finished setting the application > > state. > > The i386 siglongjmp() gets this wrong despite using a syscall (sigprocmask): > > %%% > #define _POSIX_SOURCE 1 > > #include > #include > #include > #include > > sigjmp_buf jb; + static int jb_valid = 0; > > static void > catch(int sig) > { > char buf[4 * 1024 * 1024]; /* Large to use up stack fast. */ > sigset_t omask; > + if (jb_valid != 0) { + jb_valid = 0; > sigprocmask(SIG_BLOCK, NULL, &omask); > sprintf(buf, "caught signal %d @ %p; signal mask %#x\n", > sig, (void *)&buf[0], *(unsigned *)&omask); /* XXX */ > write(1, buf, strlen(buf)); > kill(getpid(), sig); /* Simulate a race. */ > sprintf(buf, "signals apparently masked correctly before siglongjmp\n"); > write(1, buf, strlen(buf)); > siglongjmp(jb, 1); + } > } > > int > main(void) > { > struct sigaction sa; > > sa.sa_flags = 0; > sigemptyset(&sa.sa_mask); > sa.sa_handler = catch; > sigaction(SIGUSR1, &sa, NULL); /* here a signal can occur with jb uninitialized! */ > if (sigsetjmp(jb, 1) == 0) + { + jb_valid = 1; > kill(getpid(), SIGUSR1); } > return (0); > } > %%% > > Myabe this can be fixed by restoring %esp before calling sigprocmask; > otherwise siglongjmp needs to use sigreturn (or the corresponding syscall > that restores the whole ucontext). I don't really see how having the *context() or *jmp() routines be a syscall helps. You still have to protect the accesses to the jmp_buf or ucontext for race conditions regardless of whether these functions are syscalls or not. There's a few instructions to be executed after leaving the kernel via a system call anyways, right? You could always get preempted there and have another signal be delivered. > > Also, I noticed that the i386 patch doesn't save FP state (!) which is > > one of the primary reasons for get/setcontext(). I'm not sure if this > > can be efficiently done since this user-level function will not know if > > the current context has touched the FPU yet.. > > I think doing it in userland basically forces you to do physical FPU > accesses using fnsave/frstor (and something different for the SSE case?). We do this in libc_r right now. When a signal is caught, we use fnsave to save the FP regs to the ucontext area (knowing the kernel doesn't do it for us -- shouldn't it be saving the FP regs?). We remember that the threads context has FP regs saved in this case and use frstor when it is resumed. Threads interrupted by signals are the only case (for i386) that FP regs are saved and restored. > The case where a syscall would be most efficient (when the FPU is not used) > will be especially inefficient since it will have to trap to the kernel > anyway to access the state. > > Bruce -- Dan Eischen To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-arch" in the body of the message