+++ /dev/null
-/* JSGF: no idea what this is actually doing, but it really gives the
- signals/sigaltstack/threads machinery a working out */
-/**
- * Compile with:
- * gcc -g -Wall -lpthread -o susphello susphello.c
- *
- * Author Magnus Ihse, ihse at bea.com
- */
-
-#include <signal.h>
-
-
-#include <errno.h>
-#include <stddef.h>
-#include <pthread.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/resource.h>
-#include <unistd.h>
-#include <dlfcn.h>
-
-
-#include <pthread.h>
-#include <unistd.h>
-#include <string.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define THREAD_COUNT 10
-#define ITER_COUNT 200
-
-static volatile int finishedArray[THREAD_COUNT];
-static int pKey;
-
-static sigset_t srSigset;
-
-pthread_t main_thread;
-
-int srSignal = SIGUSR1;
-
-
-void
-ptiSrSigHandler(int sig, siginfo_t *sip, void *arg)
-{
- //ucontext_t *ucontext = (ucontext_t *)arg;
-
- long mypos = (long) pthread_getspecific(pKey);
-
-
-// int threadPos = (int)pthread_getspecific(srThreadKey);
-
-// thread->os_context = (OSContextP)&(ucontext->uc_mcontext);
-
- // Notify suspender that we have been suspended
- if (pthread_kill(main_thread, srSignal) == -1) {
- perror("pthread_kill");
- exit(1);
- }
-
- finishedArray[mypos]++;
-
-// printf("this is thread %d: i'm now suspended!\n", mypos);
-
- // Wait until we are resumed
- while (sigwaitinfo(&srSigset, NULL) == -1) {
- // Interrupted by SIGSTOP in gdb
- if(errno != EINTR) {
- perror("sigwaitinfo");
- exit(1);
- }
- }
-
-// printf("this is thread %d: i'm now resumed!\n", mypos);
-
- //thread->os_context = NULL; // just for the sake of it...
-
- // Notify resumer that we have been resumed
- if (pthread_kill(main_thread, srSignal) == -1) {
- perror("pthread_kill");
- exit(1);
- }
-// printf("this is thread %d: and I've told Master!!\n", mypos);
-
-}
-
-
-void
-suspendOrResume(pthread_t thread, int i)
-{
- sigset_t oss;
-
- // Mask out suspend/resume signal until we explicitly wait for it
- sigprocmask(SIG_BLOCK, &srSigset, &oss);
-
- // Send signal to suspend or resume the thread
- if (pthread_kill(thread, srSignal) == -1) {
- perror("pthread_kill");
- exit(1);
- }
-
-// printf("sent signal to %d...", i);
- // Wait for notification from thread being suspended/resumed
- while (sigwaitinfo(&srSigset, NULL) == -1) {
- // Interrupted by SIGSTOP in gdb
- if(errno != EINTR) {
- perror("sigwaitinfo");
- exit(1);
- }
- }
-
- // Restore original signal mask
- sigprocmask(SIG_SETMASK, &oss, NULL);
-
-// printf("... okay, %d suspended\n", i);
-}
-
-
-
-void
-initSignalling(void)
-{
- struct sigaction sa;
-
- // Signal mask for suspend/resume
- sigemptyset(&srSigset);
- sigaddset(&srSigset, srSignal);
-
- // Set up signal handler for suspend/resume
- sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
- sa.sa_sigaction = ptiSrSigHandler;
- sigfillset(&sa.sa_mask);
-
-# if !defined(_AIX)
- /* jrs 20060615: is this important? I don't know. */
- sigdelset(&sa.sa_mask, (__SIGRTMIN+1));
-# endif
-
- if (sigaction(srSignal, &sa, 0) == -1) {
- perror("sigaction");
- exit(1);
- }
-
- // Unblock suspend signal
- sigprocmask(SIG_UNBLOCK, &srSigset, 0);
-
- main_thread = pthread_self();
-}
-
-
-void* setup_altstack(void) {
- stack_t ss;
-
- ss.ss_sp = malloc(20*1024);
- if (ss.ss_sp == 0) {
- return NULL;
- }
- ss.ss_size = 20*1024;
- ss.ss_flags = 0;
-
- if (sigaltstack(&ss, NULL) == -1) {
- perror("sigaltstack");
- return NULL;
- }
- return ss.ss_sp;
-}
-
-void takedown_altstack(void* stack) {
-# if defined(_AIX)
- stack_t ss;
-# else
- struct sigaltstack ss;
-# endif
- int result;
-
- ss.ss_flags = SS_DISABLE;
- ss.ss_sp = (void*)47; // This value should be ignored when ss_flags is SS_DISABLE
- ss.ss_size = 29; // This value should be ignored when ss_flags is SS_DISABLE
-
- {
- result = sigaltstack(&ss, NULL);
- free(stack);
- }
-}
-
-void *threadfunc(void *arg) {
- long mypos = (long)arg;
- long i;
- long square = 1;
- void* altstack = setup_altstack();
-
- pthread_setspecific(pKey, arg);
- for (i=0; i < 1000; i++) {
- square = i*i + square*mypos;
- }
-
-// wait for signal
- while (finishedArray[mypos] == 0) {
- struct timespec req, rem;
-
- req.tv_sec = 0;
- req.tv_nsec = 5 * 1000 * 1000;
-
- nanosleep(&req, &rem);
-
- };
-
- finishedArray[mypos]++;
-
- takedown_altstack(altstack);
-
- return NULL;
-}
-
-
-int main(int argc, char ** argv) {
- pthread_t threads[THREAD_COUNT];
- pthread_attr_t attr;
- long result;
- long i;
- long iteration;
- long finished;
-
- initSignalling();
-
- pthread_attr_init(&attr);
- pthread_attr_setstacksize(&attr, 128*1024);
-
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- pthread_key_create(&pKey, NULL);
-
- for (iteration = 0; iteration < ITER_COUNT; iteration++) {
-#if 0
- if ((iteration % 100) == 0) {
- printf("\nStarting run series %i: ", iteration);
- }
-
- if ((iteration % 10) == 0) {
- printf(".");
- fflush(stdout);
- }
-#endif
-
- // Clear array
- for (i = 0; i< THREAD_COUNT; i++) {
- finishedArray[i] = 0;
- }
-
- // Start threads
- for (i = 0; i< THREAD_COUNT; i++) {
- result = pthread_create(&threads[i], &attr, threadfunc, (void*)i);
- if (result != 0) {
- perror("pthread_create");
- exit(1);
- }
- }
-
-// printf("all threads started\n");
- // suspend threads
- for (i = 0; i< THREAD_COUNT; i++) {
- suspendOrResume(threads[i], i);
- }
-
-// printf("now all threads are suspended\n");
-
- // resume threads
- for (i = 0; i< THREAD_COUNT; i++) {
- suspendOrResume(threads[i], i);
- }
-
-
- // Join threads
-/*
- printf("about to join...");
- for (i = 0; i< THREAD_COUNT; i++) {
- result = pthread_join(threads[i], NULL);
- if (result != 0) {
- perror("pthread_join");
- exit(1);
- }
- }
-
- printf("...joined");
-*/
-// printf("Spin waiting for results\n");
- finished = 1;
- do {
- struct timespec req, rem;
-
- req.tv_sec = 0;
- req.tv_nsec = 5 * 1000 * 1000;
- finished = 1;
-
- nanosleep(&req, &rem);
-
-// sleep(1);
- for (i = 0; i< THREAD_COUNT; i++) {
- if (finishedArray[i] < 2) {
- finished = 0;
-// printf("no result at: %d, value: %d\n", i, finishedArray[i]);
- break;
- }
- }
-// sleep(1);
- } while (!finished);
-
- }
-
- printf("PASSED\n");
- return 0;
-}