Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Jun 2004 03:16:00 -0400 (EDT)
From:      Daniel Eischen <eischen@vigrid.com>
To:        Sean McNeil <sean@mcneil.com>
Cc:        freebsd-threads@freebsd.org
Subject:   Re: signal handler priority issue
Message-ID:  <Pine.GSO.4.10.10406110313540.3491-100000@pcnet5.pcnet.com>
In-Reply-To: <Pine.GSO.4.10.10406110242160.26412-100000@pcnet5.pcnet.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Here is a simple test program.

-- 
Dan Eischen

/*
 * 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
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);
}




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.GSO.4.10.10406110313540.3491-100000>