#include #include #include #include #include #include #include /** * Compile with: * gcc -g -Wall -lpthread -o lphello lphello.c * * Author Magnus Ihse, ihse@bea.com */ #define THREAD_COUNT 100 #define ITER_COUNT 500000 static volatile int finishedArray[THREAD_COUNT]; static int pKey; 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) { struct sigaltstack ss; int result; if (stack == NULL) { return; } 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) { int mypos = (int)(size_t)arg; int i; long square = 1; void* altstack = setup_altstack(); pthread_setspecific(pKey, arg); for (i=0; i < 1000; i++) { square = i*i + square*mypos; } finishedArray[mypos] = 1; takedown_altstack(altstack); return NULL; } int main(int argc, char ** argv) { pthread_t threads[THREAD_COUNT]; pthread_attr_t attr; int result; int i; int iteration; int finished; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 128*1024); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_key_create(&pKey, NULL); for (iteration = 0; iteration < ITER_COUNT; iteration++) { if ((iteration % 100) == 0) { printf("\nStarting run series %i: ", iteration); } if ((iteration % 10) == 0) { printf("."); fflush(stdout); } // 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*)(size_t)i); if (result != 0) { perror("pthread_create"); exit(1); } } // Join threads for (i = 0; i< THREAD_COUNT; i++) { result = pthread_join(threads[i], NULL); if (result != 0) { perror("pthread_join"); exit(EXIT_FAILURE); } } // Spin waiting for results finished = 1; do { struct timespec req, rem; req.tv_sec = 0; req.tv_nsec = 10 * 1000 * 1000; nanosleep(&req, &rem); for (i = 0; i< THREAD_COUNT; i++) { if (finishedArray[i] != 1) { finished = 0; break; } } } while (!finished); } return EXIT_SUCCESS; }