/* * CS170: rr_condvar.c * this code is a modification of race3.c to use condition variables to ensure * round robin scheduling using condition variables */ #include #include #include #include int MyTurn = 0; typedef struct { pthread_mutex_t *lock; pthread_cond_t wait; int id; int size; int iterations; char *s; int nthreads; } Thread_struct; Thread_struct *T; void *infloop(void *x) { int i, j, k; Thread_struct *t; int next_id; Thread_struct *next_t; t = (Thread_struct *) x; for (i = 0; i < t->iterations; i++) { /* * do try this at home */ pthread_mutex_lock(t->lock); while((MyTurn % t->nthreads) != t->id) { pthread_cond_wait(&t->wait,t->lock); } for (j = 0; j < t->size-1; j++) { t->s[j] = 'A'+t->id; for(k=0; k < 50000; k++); /* delay loop */ } t->s[j] = '\0'; printf("Thread %d: %s\n", t->id, t->s); MyTurn = (MyTurn + 1) % t->nthreads; next_id = MyTurn; next_t = &(T[next_id]); pthread_cond_signal(&next_t->wait); pthread_mutex_unlock(t->lock); } return(NULL); } int main(int argc, char **argv) { pthread_t *tid; pthread_attr_t *attr; void *retval; int nthreads, size, iterations, i; char *s; pthread_mutex_t lock; if (argc != 4) { fprintf(stderr, "usage: race nthreads stringsize iterations\n"); exit(1); } pthread_mutex_init(&lock, NULL); nthreads = atoi(argv[1]); size = atoi(argv[2]); iterations = atoi(argv[3]); tid = (pthread_t *) malloc(sizeof(pthread_t) * nthreads); attr = (pthread_attr_t *) malloc(sizeof(pthread_attr_t) * nthreads); T = (Thread_struct *) malloc(sizeof(Thread_struct) * nthreads); s = (char *) malloc(sizeof(char *) * size); for (i = 0; i < nthreads; i++) { T[i].nthreads = nthreads; T[i].id = i; T[i].size = size; T[i].iterations = iterations; T[i].s = s; T[i].lock = &lock; pthread_cond_init(&T[i].wait, NULL); pthread_attr_init(&(attr[i])); pthread_attr_setscope(&(attr[i]), PTHREAD_SCOPE_SYSTEM); pthread_create(&(tid[i]), &(attr[i]), infloop, (void *)&(T[i])); } for (i = 0; i < nthreads; i++) { pthread_join(tid[i], &retval); } return(0); }