void *block_thread(void* arg) { assert(!in_vcore_context()); for (int i = 0; i < NUM_TEST_LOOPS; i++) { printf_safe("[A] pthread %d on vcore %d\n", pthread_self()->id, vcore_id()); sys_block(5000 + pthread_self()->id); } return (void*)(long)pthread_self()->id; }
static void *timer_thread(void *arg) { struct futex_element *e,*n = NULL; struct futex_queue q = TAILQ_HEAD_INITIALIZER(q); // Do this forever... for(;;) { // Block for 1 millisecond sys_block(1000); // Then atomically do the following... mcs_pdr_lock(&__futex.lock); // Up the time __futex.time++; // Find all futexes that have timed out on this iteration, // and count those still waiting int waiting = 0; e = TAILQ_FIRST(&__futex.queue); while(e != NULL) { n = TAILQ_NEXT(e, link); if(e->ms_timeout == __futex.time) { e->timedout = true; TAILQ_REMOVE(&__futex.queue, e, link); TAILQ_INSERT_TAIL(&q, e, link); } else if(e->ms_timeout != (uint64_t)-1) waiting++; e = n; } // If there are no more waiting, disable the timer if(waiting == 0) { __futex.time = 0; __futex.timer_enabled = false; } mcs_pdr_unlock(&__futex.lock); // Unblock any futexes that have timed out outside the lock e = TAILQ_FIRST(&q); while(e != NULL) { n = TAILQ_NEXT(e, link); TAILQ_REMOVE(&q, e, link); while(e->pthread == NULL) cpu_relax(); uthread_runnable((struct uthread*)e->pthread); e = n; } // If we have disabled the timer, park this thread futex_wait(&__futex.timer_enabled, false, -1); } }
int main(int argc, char **argv) { int sleep_time; if (argc < 2) { printf("Usage: %s SEC\n", argv[0]); exit(-1); } sleep_time = atoi(argv[1]); if (sleep_time < 0) exit(-1); sys_block(sleep_time * 1000000); return 0; }