#include #include #include #include #include #include static void say_hello_expecting(const char *title, int n, int kept) { int keeper = prctl(PR_GET_KEEPCAPS); printf("hello, %s<%d> %lx (keepcaps=%d vs. want=%d)\n", title, n, pthread_self(), keeper, kept); if (keeper != kept) { printf("--> FAILURE %s thread=%lx has wrong keepcaps: got=%d want=%d\n", title, pthread_self(), keeper, kept); exit(1); } } pthread_mutex_t mu; pthread_cond_t cond; int global_kept = 0; int step = 0; int replies = 0; int launched = 0; int started = 0; static void *say_hello(void *args) { int count = 0; pthread_mutex_lock(&mu); started++; pthread_cond_broadcast(&cond); int this_step = step+1; do { while (this_step > step) { pthread_cond_wait(&cond, &mu); } this_step++; say_hello_expecting("thread", count, global_kept); replies++; pthread_cond_broadcast(&cond); } while (++count != 3); pthread_mutex_unlock(&mu); return NULL; } int main(int argc, char **argv) { pthread_t tid[3]; int i; for (i = 0; i<10; i++) { printf("iteration: %d\n", i); pthread_mutex_lock(&mu); global_kept = !global_kept; replies = 0; step = i; pthread_mutex_unlock(&mu); psx_syscall(SYS_prctl, PR_SET_KEEPCAPS, global_kept); step++; pthread_cond_broadcast(&cond); say_hello_expecting("main", i, global_kept); pthread_mutex_lock(&mu); while (replies < launched) { pthread_cond_wait(&cond, &mu); } pthread_mutex_unlock(&mu); if (i < 3) { launched++; if (i == 1) { /* Confirm this works whether or not we are WRAPPING. */ psx_pthread_create(&tid[i], NULL, say_hello, NULL); } else if (i < 3) { #ifdef NOWRAP psx_pthread_create(&tid[i], NULL, say_hello, NULL); #else pthread_create(&tid[i], NULL, say_hello, NULL); #endif } /* Confirm that the thread is started. */ pthread_mutex_lock(&mu); while (started < launched) { pthread_cond_wait(&cond, &mu); } pthread_mutex_unlock(&mu); } else if (i < 6) { /* Confirm one thread has finished. */ pthread_join(tid[i-3], NULL); launched--; } } printf("%s PASSED\n", argv[0]); exit(0); } #ifdef NOWRAP PSX_NO_LINKER_WRAPPING #endif