/* view the head of the list */ void* pl_view_head(pointer_list_t *pl) { pointer_list_entry_t *e; e = (pointer_list_entry_t*) ll_view_head(pl); if(e == NULL) return (void *) -1; return (void*)e->data; }
/** * remove a specific pointer */ void pl_remove_pointer(pointer_list_t *pl, const void *data) { pointer_list_entry_t *e; e = (pointer_list_entry_t *) ll_view_head(pl); while (e && (e->data != data)) e = (pointer_list_entry_t *) e->e.p.next; if (e) ll_remove_entry(pl, (linked_list_entry_t *)e); }
void dump_thread_state() { void *bt[100]; int count, i; linked_list_entry_t *e; output("\n-- State of all threads --\n"); e = ll_view_head(threadlist); while (e) { char sleepstr[80]; thread_t *t = (thread_t *) pl_get_pointer(e); output("Thread %2d (%s) %s %d file %d sock %ld KB heap ? KB stack %s%s%s\n", thread_tid(t), t->name, THREAD_STATES[t->state], t->curr_stats.files, t->curr_stats.sockets, t->curr_stats.heap / 1024, //(long)-1, // FIXME: add total stack numbers after incorporating Jeremy's code t->joinable ? "joinable " : "", t->daemon ? "daemon " : "", t->sleep > 0 ? (sprintf(sleepstr,"sleep=%lld ",t->sleep), sleepstr) : ""); if( conf_show_thread_stacks ) { count = co_backtrace(t->coro, bt, 100); if (count == 100) output("WARN: only output first 100 stack frames.\n"); #if (0) { void **frame; frame = bt; while( count-- ) output(" %p\n",*(frame++)); } #else { // NOTE: backtrace_symbols_fd causes a loop w/ our IO functions. char **p = backtrace_symbols(bt, count); for (i = 0; i < count; i++) output(" %s\n", *(p+i)); free(p); } #endif output("\n"); } e = ll_view_next(threadlist, e); } return; }
// check sleep queue to wake up all timed-out threads // sync == TRUE -> synchronize last_check_time static void sleepq_check(int sync) { unsigned long long now; long long interval; linked_list_entry_t *e; if (!sync && max_sleep_time == 0) { // shortcut to return first_wake_usecs = 0; // FIXME: don't write to it every time return; } sleepq_sanity_check(); now = current_usecs(); if( now > last_check_time ) interval = now-last_check_time; else interval = 0; last_check_time = now; // adjust max_sleep_time if (max_sleep_time < (unsigned long long)interval) max_sleep_time = 0; else max_sleep_time -= interval; while (interval > 0 && (e = ll_view_head(sleepq))) { thread_t *t = (thread_t *)pl_get_pointer(e); if (t->sleep > interval) { t->sleep -= interval; first_wake_usecs = now + t->sleep; break; } interval -= t->sleep; t->sleep = -1; t->timeout = 1; //output(" %10llu: thread %d timeout\n", current_usecs(), t->tid); _thread_resume(t); // this doesn't deal with sleep queue ll_free_entry(sleepq, ll_remove_head(sleepq)); } if (ll_size(sleepq) == 0) { // the sleepq is empty again first_wake_usecs = 0; } sleepq_sanity_check(); }
int print_sleep_queue(void) { linked_list_entry_t *e; unsigned long long _total = 0; e = ll_view_head(sleepq); while (e) { thread_t *tt = (thread_t *)pl_get_pointer(e); _total += tt->sleep; output(" %s: %lld (%lld)\n", tt->name ? tt->name : "null", tt->sleep, _total ); e = ll_view_next(sleepq, e); } return 1; }
// remove the timer associated with the thread inline static void sleepq_remove_thread(thread_t *t) { linked_list_entry_t *e; assert(t->sleep >= 0); // the thread must be in the sleep queue sleepq_sanity_check(); // let's find the thread in the queue e = ll_view_head(sleepq); while (e) { thread_t *tt = (thread_t *)pl_get_pointer(e); if (tt == t) { linked_list_entry_t *nexte = ll_view_next(sleepq, e); if (nexte) { // e is not the last thread in the queue // we need to lengthen the time the next thread will sleep thread_t *nextt = (thread_t *)pl_get_pointer(nexte); nextt->sleep += t->sleep; } else { // e is the last thread, so we need to adjust max_sleep_time max_sleep_time -= t->sleep; } // remove t ll_remove_entry(sleepq, e); ll_free_entry(sleepq, e); t->sleep = -1; assert (!t->timeout); // if this fails, someone must has // forgot to reset timeout some time ago break; } e = ll_view_next(sleepq, e); } assert( t->sleep == -1); assert (e != NULL); // we must find t in sleep queue sleepq_sanity_check(); }