1/* 2 * This is a demonstration program to test pthreads on rumprun. 3 * It's not very complete ... 4 */ 5 6#include <sys/types.h> 7 8#include <err.h> 9#include <errno.h> 10#include <fcntl.h> 11#include <pthread.h> 12#include <unistd.h> 13#include <stdlib.h> 14#include <stdio.h> 15#include <string.h> 16 17#include <rumprun/tester.h> 18 19static pthread_mutex_t mtx; 20static pthread_cond_t cv, cv2; 21 22static int nthreads = 4; 23 24static pthread_key_t thrnumkey; 25 26static void 27threxit(void *arg) 28{ 29 30 pthread_mutex_lock(&mtx); 31 if (--nthreads == 0) { 32 printf("signalling\n"); 33 pthread_cond_signal(&cv2); 34 } 35 pthread_mutex_unlock(&mtx); 36 37 if (pthread_getspecific(thrnumkey) != arg) { 38 printf("ERROR: specificdata fail"); 39 abort(); 40 } 41 42 printf("thread %p EXIT %d\n", arg, nthreads); 43} 44 45static void * 46mythread(void *arg) 47{ 48 49 printf("thread %p\n", arg); 50 pthread_setspecific(thrnumkey, arg); 51 52 pthread_mutex_lock(&mtx); 53 printf("got lock %p\n", arg); 54 sched_yield(); 55 pthread_mutex_unlock(&mtx); 56 printf("unlocked lock %p\n", arg); 57 sched_yield(); 58 59 threxit(arg); 60 61 return NULL; 62} 63 64static int predicate; 65 66static void * 67waitthread(void *arg) 68{ 69 70 printf("thread %p\n", arg); 71 pthread_setspecific(thrnumkey, arg); 72 pthread_mutex_lock(&mtx); 73 while (!predicate) { 74 printf("no good, need to wait %p\n", arg); 75 pthread_cond_wait(&cv, &mtx); 76 } 77 pthread_mutex_unlock(&mtx); 78 printf("condvar complete %p!\n", arg); 79 80 threxit(arg); 81 82 return NULL; 83} 84 85static void * 86wakeupthread(void *arg) 87{ 88 89 printf("thread %p\n", arg); 90 pthread_setspecific(thrnumkey, arg); 91 pthread_mutex_lock(&mtx); 92 predicate = 1; 93 printf("rise and shine %p!\n", arg); 94 pthread_cond_signal(&cv); 95 pthread_mutex_unlock(&mtx); 96 97 threxit(arg); 98 99 return NULL; 100} 101 102static void * 103jointhread(void *arg) 104{ 105 106 return (void *)37; 107} 108 109/* verify that a fd created in the main thread is accessible in another */ 110static void * 111fdthread(void *arg) 112{ 113 int fd = *(int *)arg; 114 char buf[1]; 115 116 if (read(fd, buf, 1) != 0) 117 err(1, "fdthread read"); 118 if (close(fd) != 0) 119 err(1, "fdthread close"); 120 return (void *)0; 121} 122 123int 124rumprun_test(int argc, char *argv[]) 125{ 126 struct timespec ts; 127 pthread_t pt; 128 void *rv; 129 int nullfd; 130 131 pthread_key_create(&thrnumkey, NULL); 132 133 pthread_mutex_init(&mtx, NULL); 134 pthread_cond_init(&cv, NULL); 135 pthread_cond_init(&cv2, NULL); 136 137 printf("testing pthread_join\n"); 138 if (pthread_create(&pt, NULL, jointhread, NULL) != 0) 139 errx(1, "pthread jointhread create"); 140 if (pthread_join(pt, &rv) != 0) 141 errx(1, "pthread_join()"); 142 if (rv != (void *)37) 143 errx(1, "joiner returned incorrect value"); 144 printf("success\n"); 145 146 if (pthread_create(&pt, NULL, mythread, (void *)0x01) != 0) 147 errx(1, "pthread_create()"); 148 149 clock_gettime(CLOCK_REALTIME, &ts); 150 ts.tv_nsec += 100*1000*1000; 151 pthread_mutex_lock(&mtx); 152 if (pthread_cond_timedwait(&cv2, &mtx, &ts) != ETIMEDOUT) { 153 printf("cond_timedwait fail\n"); 154 abort(); 155 } 156 pthread_mutex_unlock(&mtx); 157 158 if (pthread_create(&pt, NULL, mythread, (void *)0x02) != 0) 159 errx(1, "pthread_create()"); 160 if (pthread_create(&pt, NULL, waitthread, (void *)0x03) != 0) 161 errx(1, "pthread_create()"); 162 if (pthread_create(&pt, NULL, wakeupthread, (void *)0x04) != 0) 163 errx(1, "pthread_create()"); 164 165 pthread_mutex_lock(&mtx); 166 /* get time after locking => ensure loop runs before threads finish */ 167 clock_gettime(CLOCK_REALTIME, &ts); 168 ts.tv_sec++; 169 while (nthreads) { 170 int rv; 171 172 printf("mainthread condwaiting\n"); 173 if ((rv = pthread_cond_timedwait(&cv2, &mtx, &ts)) != 0) { 174 printf("drain condwait fail %d %d\n", rv, nthreads); 175 } 176 } 177 pthread_mutex_unlock(&mtx); 178 179 if ((nullfd = open("/dev/null", O_RDONLY)) < 0) 180 err(1, "open(/dev/null)"); 181 if (pthread_create(&pt, NULL, fdthread, (void *)&nullfd) != 0) 182 errx(1, "pthread_create()"); 183 if (pthread_join(pt, &rv) != 0) 184 errx(1, "pthread_join()"); 185 186 printf("main thread done\n"); 187 188 return 0; 189} 190