static void tester(long a0, void *a1) { int i = 0, ret; char pbuffer[SBUFSZ]; while (i < 10) { sprintf(pbuffer, "thread %i: hello! (%i)\n", uthread_self(), i++); ret = write(STDOUT_FILENO, pbuffer, strlen(pbuffer)); if (ret < 0) { perror("uthreads_test"); /* XXX: we should really cleanup here */ exit(1); } uthread_mtx_lock(&mtx); uthread_cond_signal(&cond); uthread_cond_wait(&cond, &mtx); uthread_mtx_unlock(&mtx); } sprintf(pbuffer, "thread %i exiting.\n", uthread_self()); ret = write(STDOUT_FILENO, pbuffer, strlen(pbuffer)); if (ret < 0) { perror("uthreads_test"); /* XXX: we should really cleanup here */ exit(1); } uthread_exit(a0); }
/** * This is the agent procedure. It is complete and you shouldn't change it in * any material way. You can re-write it if you like, but be sure that all it does * is choose 2 random reasources, signal their condition variables, and then wait * wait for a smoker to smoke. */ void* agent (void* av) { struct Agent* a = av; static const int choices[] = {MATCH|PAPER, MATCH|TOBACCO, PAPER|TOBACCO}; static const int matching_smoker[] = {TOBACCO, PAPER, MATCH}; uthread_mutex_lock (a->mutex); for (int i = 0; i < NUM_ITERATIONS; i++) { int r = random() % 3; signal_count [matching_smoker [r]] ++; int c = choices [r]; if (c & MATCH) { VERBOSE_PRINT ("match available\n"); uthread_cond_signal (a->match); } if (c & PAPER) { VERBOSE_PRINT ("paper available\n"); uthread_cond_signal (a->paper); } if (c & TOBACCO) { VERBOSE_PRINT ("tobacco available\n"); uthread_cond_signal (a->tobacco); } VERBOSE_PRINT ("agent is waiting for smoker to smoke\n"); uthread_cond_wait (a->smoke); } uthread_mutex_unlock (a->mutex); return NULL; }
void consume() { uthread_mutex_lock(mx); while (items <= 0) { consumer_wait_count++; uthread_cond_wait(not_empty); } items--; histogram[items]++; assert (items >= 0); uthread_cond_signal(not_full); uthread_mutex_unlock(mx); }
void produce() { uthread_mutex_lock(mx); while (items >= MAX_ITEMS) { producer_wait_count++; uthread_cond_wait(not_full); } items++; histogram[items]++; assert(items <= MAX_ITEMS); uthread_cond_signal(not_empty); uthread_mutex_unlock(mx); }
void consume(struct Pool* pool) { uthread_mutex_lock(pool->mutex); while (pool->items == 0) { consumer_wait_count++; uthread_cond_wait(pool->notEmpty); } assert (pool->items > 0); pool->items--; histogram [pool->items]++; uthread_cond_signal (pool->notFull); uthread_mutex_unlock (pool->mutex); }
void produce(struct Pool* pool) { uthread_mutex_lock(pool->mutex); while (pool->items == MAX_ITEMS) { producer_wait_count++; uthread_cond_wait(pool->notFull); } assert (pool->items < MAX_ITEMS); pool->items++; histogram [pool->items]++; uthread_cond_signal (pool->notEmpty); uthread_mutex_unlock (pool->mutex); }
void* agent() { srand(time(NULL)); uthread_mutex_lock(mx); for (int i = 0; i < NUM_ITERATIONS; i++) { int random = rand() % 3; histo_expected[(random+2) % 3]++; uthread_cond_signal(resource[random]); uthread_cond_signal(resource[(random+1) % 3]); uthread_cond_wait(done_smoking); } uthread_mutex_unlock(mx); return NULL; }
void* match(void* aa) { struct Agent* a = aa; uthread_mutex_lock(a->mutex); while(1) { uthread_cond_wait(a->match_ready); smoke_count[1]++; a->t--; a->p--; uthread_cond_signal(a->smoke); } uthread_mutex_unlock(a->mutex); return NULL; }
int main (int argc, char** argv) { // setup mutex and condition variables mx = uthread_mutex_create(); smoker_waiting = uthread_cond_create(mx); for (int i = 0; i < 3; i++) { resource[i] = uthread_cond_create(mx); } done_smoking = uthread_cond_create(mx); // setup threads and start agent uthread_init(1); uthread_mutex_lock(mx); for (int i = 0; i < 3; i++) { threads[i] = uthread_create(smoker, (void*)(intptr_t) i); uthread_cond_wait(smoker_waiting); } uthread_mutex_unlock(mx); threads[3] = uthread_create(agent, NULL); // wait for threads to finish for (int i = 3; i >= 0; i--) { uthread_join(threads[i], NULL); } // verify that the histograms of actual/expected match for (int i = 0; i < 3; i++) { assert(histo_expected[i] == histo_actual[i]); } // print histograms of expected and actual smoke counts int sum; printf("Expected: [ "); sum = 0; for (int i = 0; i < 3; i++) { sum += histo_expected[i]; printf("%d ", histo_expected[i]); } printf("]\tSum: %d\n", sum); sum = 0; printf("Actual: [ "); for (int i = 0; i < 3; i++) { sum += histo_actual[i]; printf("%d ", histo_actual[i]); } printf("]\tSum: %d\n", sum); }
void* match_track(void* aa) { struct Agent* a = aa; uthread_mutex_lock(a->mutex); while(1) { uthread_cond_wait(a->match); a->m++; if (a->p > 0) { uthread_cond_signal(a->tobacco_ready); } if (a->t > 0) { uthread_cond_signal(a->paper_ready); } } uthread_mutex_unlock(a->mutex); return NULL; }
void* producer (void* pv) { struct Pool* p = pv; for (int i=0; i<NUM_ITERATIONS; i++) { // TODO uthread_mutex_lock(p->mutex); while (p->items == MAX_ITEMS){ producer_wait_count++; uthread_cond_wait(p->notFull); } p->items++; histogram[p->items]++; uthread_cond_signal(p->notEmpty); uthread_mutex_unlock(p->mutex); } return NULL; }
void* thread1(void *arg) { long i; uthread_mutex_lock(&mut); for (i = 0; i < 1000; ++ i) { while (!have) { uthread_cond_wait(&c1, &mut); } cnt += buf; have = 0; uthread_cond_signal(&c2); } uthread_mutex_unlock(&mut); return NULL; }
void* thread2(void *arg) { long t = (long) arg; long i; uthread_mutex_lock(&mut); for (i = t; i < t + 1000; ++ i) { while (have) { uthread_cond_wait(&c2, &mut); } buf = i; have = 1; uthread_cond_signal(&c1); } uthread_mutex_unlock(&mut); return NULL; }
void* smoker(void* resource_type_vp) { int resource_type = (intptr_t) resource_type_vp; uthread_mutex_lock(mx); uthread_cond_signal(smoker_waiting); for (int i = 0; i < NUM_ITERATIONS; i++) { uthread_cond_wait(resource[resource_type]); switch (num_woken) { case 0: num_woken++; resource_of_first = resource_type; break; case 1: num_woken++; switch(resource_of_first * 10 + resource_type) { case 01: case 10: uthread_cond_signal(resource[2]); break; case 02: case 20: uthread_cond_signal(resource[1]); break; case 12: case 21: uthread_cond_signal(resource[0]); break; } break; case 2: num_woken = 0; resource_of_first = -1; smoke(resource_type); uthread_cond_signal(done_smoking); break; } } uthread_mutex_unlock(mx); return NULL; }
static void tester2(long a0, void* a1){ int i = 0, ret; char pbuffer[SBUFSZ]; //uthread_mtx_lock(&mtx); while (i < 1) { i ++; uthread_mtx_lock(&mtx1); pprintf("thread2 about to block\n"); //uthread_mtx_lock(&mtx3); uthread_cond_wait(&cond,&mtx1); sprintf(pbuffer, "thread 2 out of wait\n"); ret = write(STDOUT_FILENO, pbuffer, strlen(pbuffer)); if (ret < 0) { perror("uthreads_test"); /* XXX: we should really cleanup here */ exit(1); } uthread_mtx_unlock(&mtx1); //uthread_mtx_unlock(&mtx3); } sprintf(pbuffer, "thread 2 exiting.\n"); ret = write(STDOUT_FILENO, pbuffer, strlen(pbuffer)); if (ret < 0) { perror("uthreads_test"); /* XXX: we should really cleanup here */ exit(1); } uthread_exit(a0); }