From owner-freebsd-threads@FreeBSD.ORG Fri Jun 11 07:16:12 2004 Return-Path: Delivered-To: freebsd-threads@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 9640F16A4CE; Fri, 11 Jun 2004 07:16:12 +0000 (GMT) Received: from mail.pcnet.com (mail.pcnet.com [204.213.232.4]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3FFB443D2F; Fri, 11 Jun 2004 07:16:12 +0000 (GMT) (envelope-from eischen@vigrid.com) Received: from mail.pcnet.com (mail.pcnet.com [204.213.232.4]) by mail.pcnet.com (8.12.10/8.12.1) with ESMTP id i5B7G16x003864; Fri, 11 Jun 2004 03:16:01 -0400 (EDT) Date: Fri, 11 Jun 2004 03:16:00 -0400 (EDT) From: Daniel Eischen X-Sender: eischen@pcnet5.pcnet.com To: Sean McNeil In-Reply-To: Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII cc: David Xu cc: freebsd-threads@freebsd.org Subject: Re: signal handler priority issue X-BeenThere: freebsd-threads@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Threading on FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 11 Jun 2004 07:16:12 -0000 Here is a simple test program. -- Dan Eischen /* * test_sr.c * * Demonstrate use of signals & semaphores for suspending and * resuming threads. */ #include #include #include #include #include #include #include #include #ifndef NUM_THREADS #define NUM_THREADS 5 #endif static sem_t semaphore; static int done = 0; static pthread_t tids[NUM_THREADS]; static void errno_abort(char *msg) { printf("%s, errno %d\n", msg, errno); abort(); } static void err_abort(int status, char *msg) { printf("%s, status %d\n", msg, status); abort(); } static void sighandler(int sig, siginfo_t *info, ucontext_t *ucp) { sigset_t mask; switch (sig) { case SIGUSR1: printf("Thread %p pausing.\n", pthread_self()); sigfillset(&mask); sigdelset(&mask, SIGUSR2); sem_post(&semaphore); sigsuspend(&mask); printf("Thread %p successfully resumed.\n", pthread_self()); break; case SIGUSR2: printf("Thread %p got resume signal.\n", pthread_self()); break; } } /* * Thread start routine to wait on a semaphore. */ static void * worker(void *arg) { int num = (int)arg; int x; num = (int)arg; x = num * 10; printf ("Thread %d starting.\n", num); while (!done) { x = x + 1; x = x - 1; } printf("Thread %d stopping.\n", num); return (NULL); } static void pause_threads(void) { int i; printf("Master: pausing all threads.\n"); for (i = 0; i < NUM_THREADS; i++) { pthread_kill(tids[i], SIGUSR1); if (sem_wait(&semaphore) == -1) errno_abort("Wait on semaphore"); } } static void resume_threads(void) { int i; printf("Master: resuming all threads.\n"); for (i = 0; i < NUM_THREADS; i++) { pthread_kill(tids[i], SIGUSR2); } } int main(int argc, char *argv[]) { struct sigaction act; int status; int i; if (sem_init (&semaphore, 0, 0) == -1) errno_abort ("Init semaphore"); /* Mask all signals while in the signal handler. */ sigfillset(&act.sa_mask); act.sa_handler = sighandler; act.sa_flags = SA_SIGINFO | SA_RESTART; sigaction(SIGUSR1, &act, NULL); sigaction(SIGUSR2, &act, NULL); /* * Create some worker threads. */ for (i = 0; i < NUM_THREADS; i++) { status = pthread_create(&tids[i], NULL, worker, (void *)i); if (status != 0) err_abort (status, "Create thread"); } sleep (1); for (i = 0; i < 5; i++) { pause_threads(); resume_threads(); } done = 1; /* * Wait for all threads to complete. */ for (i = 0; i < NUM_THREADS; i++) { status = pthread_join(tids[i], NULL); if (status != 0) err_abort(status, "Join thread"); } return (0); }