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