From e61de13666add6863abf8a5d2b03603a8a221bfa Mon Sep 17 00:00:00 2001 From: Dave West Date: Mon, 26 Nov 2007 20:38:41 +0000 Subject: [PATCH] Now we have a thread state for blocked. Only works for the select in the worker thread at the moment. --- citadel/server_main.c | 2 ++ citadel/sysdep.c | 75 ++++++++++++++++++++++++++++-------------- citadel/sysdep_decls.h | 2 ++ 3 files changed, 55 insertions(+), 24 deletions(-) diff --git a/citadel/server_main.c b/citadel/server_main.c index e0f3e5c61..74c282673 100644 --- a/citadel/server_main.c +++ b/citadel/server_main.c @@ -349,6 +349,8 @@ int main(int argc, char **argv) /* * If the above loop exits we must be shutting down since we obviously have no threads */ + ctdl_thread_internal_cleanup(); + master_cleanup(exit_signal); return(0); } diff --git a/citadel/sysdep.c b/citadel/sysdep.c index 4d6fb0976..e8b7363c5 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -1054,6 +1054,16 @@ static void ctdl_thread_internal_restore_signals(sigset_t *old_set) } +void ctdl_thread_internal_cleanup(void) +{ + int i; + + for (i=0; inext->prev = this_thread; } + + +/* + * A function to chenge the state of a thread + */ +void ctdl_thread_internal_change_state (struct CtdlThreadNode *this_thread, enum CtdlThreadState new_state) +{ + + pthread_mutex_lock(&this_thread->ThreadMutex); /* To prevent race condition of a sleeping thread */ + if ((new_state == CTDL_THREAD_STOP_REQ) && (this_thread->state > CTDL_THREAD_STOP_REQ)) + this_thread->state = new_state; + if (((new_state == CTDL_THREAD_SLEEPING) || (new_state == CTDL_THREAD_BLOCKED)) && (this_thread->state == CTDL_THREAD_RUNNING)) + this_thread->state = new_state; + if ((new_state == CTDL_THREAD_RUNNING) && ((this_thread->state == CTDL_THREAD_SLEEPING) || (this_thread->state == CTDL_THREAD_BLOCKED))) + this_thread->state = new_state; + pthread_mutex_unlock(&this_thread->ThreadMutex); +} + + /* * A function to tell all threads to exit */ @@ -1117,10 +1146,7 @@ void CtdlThreadStopAll(void) { if (this_thread->thread_func) // Don't tell garbage collector to stop { - pthread_mutex_lock(&this_thread->ThreadMutex); /* To prevent race condition of a sleeping thread */ - if (this_thread->state > CTDL_THREAD_STOP_REQ) - this_thread->state = CTDL_THREAD_STOP_REQ; - pthread_mutex_unlock(&this_thread->ThreadMutex); + ctdl_thread_internal_change_state (this_thread, CTDL_THREAD_STOP_REQ); pthread_cond_signal(&this_thread->ThreadCond); CtdlLogPrintf(CTDL_DEBUG, "Thread system stopping thread \"%s\" (%ld).\n", this_thread->name, this_thread->tid); } @@ -1245,7 +1271,7 @@ void CtdlThreadCancel(struct CtdlThreadNode *thread) } begin_critical_section(S_THREAD_LIST); - this_thread->state = CTDL_THREAD_CANCELLED; + ctdl_thread_internal_change_state (this_thread, CTDL_THREAD_CANCELLED); pthread_cancel(this_thread->tid); end_critical_section (S_THREAD_LIST); } @@ -1296,10 +1322,7 @@ void CtdlThreadStop(struct CtdlThreadNode *thread) return; // Don't stop garbage collector begin_critical_section (S_THREAD_LIST); - pthread_mutex_lock(&this_thread->ThreadMutex); /* To prevent race condition of a sleeping thread */ - if (this_thread->state > CTDL_THREAD_STOP_REQ) - this_thread->state = CTDL_THREAD_STOP_REQ; - pthread_mutex_unlock(&this_thread->ThreadMutex); + ctdl_thread_internal_change_state (this_thread, CTDL_THREAD_STOP_REQ); pthread_cond_signal(&this_thread->ThreadCond); end_critical_section(S_THREAD_LIST); } @@ -1312,7 +1335,6 @@ void CtdlThreadSleep(int secs) struct timespec wake_time; struct timeval time_now; struct CtdlThreadNode *self; - int state; self = CtdlThreadSelf(); @@ -1323,28 +1345,18 @@ void CtdlThreadSleep(int secs) } begin_critical_section(S_THREAD_LIST); + ctdl_thread_internal_change_state (self, CTDL_THREAD_SLEEPING); pthread_mutex_lock(&self->ThreadMutex); /* Prevent something asking us to awaken before we've gone to sleep */ - state = self->state; - if (state == CTDL_THREAD_RUNNING) - self->state = CTDL_THREAD_SLEEPING; end_critical_section(S_THREAD_LIST); - if(state != CTDL_THREAD_RUNNING) - { - CtdlLogPrintf(CTDL_DEBUG, "CtdlThreadSleep() called by a thread that is not running.\n"); - pthread_mutex_unlock(&self->ThreadMutex); - return; - } - memset (&wake_time, 0, sizeof(struct timespec)); gettimeofday(&time_now, NULL); wake_time.tv_sec = time_now.tv_sec + secs; wake_time.tv_nsec = time_now.tv_usec * 10; pthread_cond_timedwait(&self->ThreadCond, &self->ThreadMutex, &wake_time); begin_critical_section(S_THREAD_LIST); - if (self->state == CTDL_THREAD_SLEEPING) /* Don't change state if something else changed it while we were asleep */ - self->state = state; pthread_mutex_unlock(&self->ThreadMutex); + ctdl_thread_internal_change_state (self, CTDL_THREAD_RUNNING); end_critical_section(S_THREAD_LIST); } @@ -1659,6 +1671,20 @@ struct CtdlThreadNode *CtdlThreadCreate(char *name, long flags, void *(*thread_f +/* + * A warapper function for select so we can show a thread as blocked + */ +int CtdlThreadSelect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout) +{ + struct CtdlThreadNode *self; + int ret; + + self = CtdlThreadSelf(); + ctdl_thread_internal_change_state(self, CTDL_THREAD_BLOCKED); + ret = select(n, readfds, writefds, exceptfds, timeout); + ctdl_thread_internal_change_state(self, CTDL_THREAD_RUNNING); + return ret; +} /* * Purge all sessions which have the 'kill_me' flag set. @@ -1828,7 +1854,8 @@ do_select: force_purge = 0; if (!CtdlThreadCheckStop()) { tv.tv_sec = 1; /* wake up every second if no input */ tv.tv_usec = 0; - retval = select(highest + 1, &readfds, NULL, NULL, &tv); + retval = CtdlThreadSelect(highest + 1, &readfds, NULL, NULL, &tv); +// retval = select(highest + 1, &readfds, NULL, NULL, &tv); } if (CtdlThreadCheckStop()) return(NULL); diff --git a/citadel/sysdep_decls.h b/citadel/sysdep_decls.h index d7953b99f..cb40fb0e0 100644 --- a/citadel/sysdep_decls.h +++ b/citadel/sysdep_decls.h @@ -111,6 +111,7 @@ extern struct worker_node { void ctdl_internal_thread_gc (void); void ctdl_thread_internal_init(void); +void ctdl_thread_internal_cleanup(void); struct CtdlThreadNode *ctdl_internal_create_thread(char *name, long flags, void *(*thread_func) (void *arg), void *args); enum CtdlThreadState { @@ -122,6 +123,7 @@ enum CtdlThreadState { CTDL_THREAD_STOPPING, CTDL_THREAD_STOP_REQ, /* Do NOT put any running states before this state */ CTDL_THREAD_SLEEPING, + CTDL_THREAD_BLOCKED, CTDL_THREAD_RUNNING, CTDL_THREAD_LAST_STATE }; -- 2.30.2