signal handler priority issue
Sean McNeil
sean at mcneil.com
Fri Jun 11 08:16:22 GMT 2004
Now here is something odd....
If I change the program a little, it acts completely different. It
actually works faster and looks correct. I don't get it. This is
pretty much exactly what boehm-gc is doing.
/*
* test_sr.c
*
* Demonstrate use of signals & semaphores for suspending and
* resuming threads.
*/
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
#include <unistd.h>
#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
sighandler1(int sig, siginfo_t *info, ucontext_t *ucp)
{
sigset_t mask;
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());
}
static void
sighandler2(int sig, siginfo_t *info, ucontext_t *ucp)
{
printf("Thread %p got resume signal.\n", pthread_self());
}
/*
* 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);
}
for (i = 0; i < NUM_THREADS; i++) {
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_flags = SA_RESTART;
act.sa_handler = sighandler1;
sigaction(SIGUSR1, &act, NULL);
act.sa_handler = sighandler2;
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);
}
More information about the freebsd-threads
mailing list