/** %jp{サンプルタスク} */ void Sample_Task(VP_INT exinf) { int num; num = (int)exinf; /* %jp{いわゆる哲学者の食事の問題} */ for ( ; ; ) { /* %jp{適当な時間考える} */ print_state(num, "thinking"); rand_wait(); /* %jp{左右のフォークを取るまでループ} */ for ( ; ; ) { /* %jp{左から順に取る} */ wai_sem(LEFT(num)); if ( pol_sem(RIGHT(num)) == E_OK ) { break; /* %jp{両方取れた} */ } sig_sem(LEFT(num)); /* %jp{取れなければ離す} */ /* %jp{適当な時間待つ} */ print_state(num, "hungry"); rand_wait(); /* %jp{右から順に取る} */ wai_sem(RIGHT(num)); if ( pol_sem(LEFT(num)) == E_OK ) { break; /* %jp{両方取れた} */ } sig_sem(RIGHT(num)); /* %jp{取れなければ離す} */ /* %jp{適当な時間待つ} */ print_state(num, "hungry"); rand_wait(); } /* %jp{適当な時間、食べる} */ print_state(num, "eating"); rand_wait(); /* %jp{フォークを置く} */ sig_sem(LEFT(num)); sig_sem(RIGHT(num)); } }
void *producer(void *d) { int ret; struct sched_param param; long id = (long) d; long wait; int item = id; buffer_t *b = &buffer; struct timespec twait, now; cpu_set_t mask; pid_t my_pid = gettid(); pids[id] = my_pid; if (global_args.affinity) { CPU_ZERO(&mask); CPU_SET(0, &mask); ret = sched_setaffinity(0, sizeof(mask), &mask); if (ret != 0) { printf("pthread_setaffinity failed\n"); exit(EXIT_FAILURE); } } param.sched_priority = 92; ret = pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m); if (ret != 0) { printf("pthread_setschedparam failed\n"); exit(EXIT_FAILURE); } if (global_args.pi_cv_enabled) { if (global_args.ftrace) ftrace_write(marker_fd, "Adding helper thread: pid %d," " prio 92\n", my_pid); pthread_cond_helpers_add(&buffer.more, my_pid); if (global_args.ftrace) ftrace_write(marker_fd, "[prod %d] helps on cv %p\n", my_pid, &buffer.more); } while(!shutdown) { pthread_mutex_lock(&b->mutex); while (b->occupied >= BSIZE) pthread_cond_wait(&b->less, &b->mutex); assert(b->occupied < BSIZE); b->buf[b->nextin++] = item; wait = rand_wait() * 1000; twait = usec_to_timespec(wait); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now); twait = timespec_add(&now, &twait); busywait(&twait); if (global_args.ftrace) ftrace_write(marker_fd, "[prod %d] executed for %d usec" " and produced %d\n", my_pid, wait, item); b->nextin %= BSIZE; b->occupied++; /* * now: either b->occupied < BSIZE and b->nextin is the index * of the next empty slot in the buffer, or * b->occupied == BSIZE and b->nextin is the index of the * next (occupied) slot that will be emptied by a consumer * (such as b->nextin == b->nextout) */ pthread_cond_signal(&b->more); pthread_mutex_unlock(&b->mutex); sleep(1); } if (global_args.pi_cv_enabled) { pthread_cond_helpers_del(&buffer.more, my_pid); if (global_args.ftrace) { ftrace_write(marker_fd, "[prod %d] stop helping" " on cv %p\n", my_pid, &buffer.more); ftrace_write(marker_fd, "Removing helper thread:" " pid %d, prio 92\n", my_pid); } } pthread_exit(NULL); }
void *consumer(void *d) { int ret; struct sched_param param; long id = (long) d; long wait; int item; buffer_t *b = &buffer; struct timespec twait, now; cpu_set_t mask; pid_t my_pid = gettid(); pids[id] = my_pid; if (global_args.affinity) { CPU_ZERO(&mask); CPU_SET(0, &mask); ret = sched_setaffinity(0, sizeof(mask), &mask); if (ret != 0) { printf("pthread_setaffinity failed\n"); exit(EXIT_FAILURE); } } param.sched_priority = 94; ret = pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m); if (ret != 0) { printf("pthread_setschedparam failed\n"); exit(EXIT_FAILURE); } /** * Give producers some time to set up. */ sleep(1); while(!shutdown) { pthread_mutex_lock(&b->mutex); while(b->occupied <= 0) { if (global_args.ftrace) ftrace_write(marker_fd, "[cons %d] waits\n", my_pid); pthread_cond_wait(&b->more, &b->mutex); } assert(b->occupied > 0); item = b->buf[b->nextout++]; wait = rand_wait() * 1000; twait = usec_to_timespec(wait); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now); twait = timespec_add(&now, &twait); busywait(&twait); if (global_args.ftrace) ftrace_write(marker_fd, "[cons %d] executed for %d usec" " and consumed %d\n", my_pid, wait, item); b->nextout %= BSIZE; b->occupied--; /* * now: either b->occupied > 0 and b->nextout is the index * of the next occupied slot in the buffer, or * b->occupied == 0 and b->nextout is the index of the next * (empty) slot that will be filled by a producer (such as * b->nextout == b->nextin) */ pthread_cond_signal(&b->less); pthread_mutex_unlock(&b->mutex); } pthread_exit(NULL); }