From 5abf3d0c3343809374a116cbe23c808a81a780c4 Mon Sep 17 00:00:00 2001 From: Dave West Date: Wed, 5 Dec 2007 20:17:22 +0000 Subject: [PATCH] Changed the way we do the TSD area. Now this code is in sysdep.c Added an element to the TSD to store a pointer to this threads control structure. This allows a speed up in CtdlThreadSleep(), CtdlThreadCheckStop() and the odd one or two other places since this thread no longer needs to search the list of threads to find its own control ctructure. --- citadel/citserver.c | 4 + citadel/database.h | 7 + citadel/database_sleepycat.c | 63 +------ citadel/include/ctdl_module.h | 14 +- citadel/modules/checkpoint/serv_checkpoint.c | 6 +- citadel/modules/expire/serv_expire.c | 22 ++- citadel/modules/fulltext/serv_fulltext.c | 12 +- citadel/server_main.c | 5 - citadel/sysdep.c | 172 +++++++++++-------- citadel/sysdep_decls.h | 28 ++- 10 files changed, 160 insertions(+), 173 deletions(-) diff --git a/citadel/citserver.c b/citadel/citserver.c index f2c957d78..d04ee38b2 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -135,6 +135,10 @@ void master_startup(void) { lprintf(CTDL_INFO, "Opening databases\n"); open_databases(); + ctdl_thread_internal_init_tsd(); + + CtdlThreadAllocTSD(); + if (do_defrag) { defrag_databases(); } diff --git a/citadel/database.h b/citadel/database.h index c7fe3833e..c4aac796e 100644 --- a/citadel/database.h +++ b/citadel/database.h @@ -1,4 +1,9 @@ /* $Id$ */ + +#ifndef DATABASE_H +#define DATABASE_H + + void defrag_databases (void); void open_databases (void); void close_databases (void); @@ -18,6 +23,7 @@ void cdb_trunc(int cdb); void *checkpoint_thread(void *arg); void cdb_chmod_data(void); void cdb_checkpoint(void); +void check_handles(void *arg); /* * Database records beginning with this magic number are assumed to @@ -36,4 +42,5 @@ struct CtdlCompressHeader { size_t compressed_len; }; +#endif /* DATABASE_H */ diff --git a/citadel/database_sleepycat.c b/citadel/database_sleepycat.c index ddd8edb12..64191dcb9 100644 --- a/citadel/database_sleepycat.c +++ b/citadel/database_sleepycat.c @@ -58,19 +58,11 @@ static DB *dbp[MAXCDB]; /* One DB handle for each Citadel database */ static DB_ENV *dbenv; /* The DB environment (global) */ -struct cdbtsd { /* Thread-specific DB stuff */ - DB_TXN *tid; /* Transaction handle */ - DBC *cursors[MAXCDB]; /* Cursors, for traversals... */ -}; #ifdef HAVE_ZLIB #include #endif -static pthread_key_t tsdkey; - -#define MYCURSORS (((struct cdbtsd*)pthread_getspecific(tsdkey))->cursors) -#define MYTID (((struct cdbtsd*)pthread_getspecific(tsdkey))->tid) /* Verbose logging callback */ void cdb_verbose_log(const DB_ENV *dbenv, const char *msg) @@ -157,10 +149,10 @@ static void bailIfCursor(DBC ** cursors, const char *msg) } } -static void check_handles(void *arg) +void check_handles(void *arg) { if (arg != NULL) { - struct cdbtsd *tsd = (struct cdbtsd *) arg; + ThreadTSD *tsd = (ThreadTSD *) arg; bailIfCursor(tsd->cursors, "in check_handles"); @@ -172,46 +164,9 @@ static void check_handles(void *arg) } } -static void dest_tsd(void *arg) -{ - if (arg != NULL) { - check_handles(arg); - free(arg); - } -} - -/* - * Ensure that we have a key for thread-specific data. We don't - * put anything in here that Citadel cares about; this is just database - * related stuff like cursors and transactions. - * - * This should be called immediately after startup by any thread which wants - * to use database calls, except for whatever thread calls open_databases. - */ -void cdb_allocate_tsd(void) -{ - struct cdbtsd *tsd; - - if (pthread_getspecific(tsdkey) != NULL) - return; - - tsd = malloc(sizeof(struct cdbtsd)); - - tsd->tid = NULL; - - memset(tsd->cursors, 0, sizeof tsd->cursors); - pthread_setspecific(tsdkey, tsd); -} - -void cdb_free_tsd(void) -{ - dest_tsd(pthread_getspecific(tsdkey)); - pthread_setspecific(tsdkey, NULL); -} - void cdb_check_handles(void) { - check_handles(pthread_getspecific(tsdkey)); + check_handles(pthread_getspecific(ThreadKey)); } @@ -434,14 +389,6 @@ void open_databases(void) } } - if ((ret = pthread_key_create(&tsdkey, dest_tsd))) { - lprintf(CTDL_EMERG, "pthread_key_create: %s\n", - strerror(ret)); - exit(CTDLEXIT_DB); - } - - cdb_allocate_tsd(); - } @@ -485,8 +432,8 @@ void close_databases(void) int a; int ret; - cdb_free_tsd(); - + ctdl_thread_internal_free_tsd(); + if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, 0))) { lprintf(CTDL_EMERG, "txn_checkpoint: %s\n", db_strerror(ret)); diff --git a/citadel/include/ctdl_module.h b/citadel/include/ctdl_module.h index 93fbf0212..b0508a96b 100644 --- a/citadel/include/ctdl_module.h +++ b/citadel/include/ctdl_module.h @@ -115,9 +115,9 @@ void CtdlModuleStartCryptoMsgs(char *ok_response, char *nosup_response, char *er struct CtdlThreadNode *CtdlThreadCreate(char *name, long flags, void *(*thread_func) (void *arg), void *args); void CtdlThreadSleep(int secs); void CtdlThreadStop(struct CtdlThreadNode *thread); -int CtdlThreadCheckStop(struct CtdlThreadNode *this_thread); +int CtdlThreadCheckStop(void); void CtdlThreadCancel(struct CtdlThreadNode *thread); -const char *CtdlThreadName(struct CtdlThreadNode *thread, const char *name); +const char *CtdlThreadName(const char *name); struct CtdlThreadNode *CtdlThreadSelf(void); int CtdlThreadGetCount(void); int CtdlThreadGetWorkers(void); @@ -126,11 +126,13 @@ double CtdlThreadGetLoadAvg(void); void CtdlThreadGC(void); void CtdlThreadStopAll(void); int CtdlThreadSelect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout, struct CtdlThreadNode *self); +void CtdlThreadAllocTSD(void); /* Macros to speed up getting outr thread */ -#define CT _this_cit_thread -#define CT_PUSH() \ - struct CtdlThreadNode *_this_cit_thread;\ - _this_cit_thread = CtdlThreadSelf() + +#define MYCURSORS (((ThreadTSD*)pthread_getspecific(ThreadKey))->cursors) +#define MYTID (((ThreadTSD*)pthread_getspecific(ThreadKey))->tid) +#define CT (((ThreadTSD*)pthread_getspecific(ThreadKey))->self) + #endif /* CTDL_MODULE_H */ diff --git a/citadel/modules/checkpoint/serv_checkpoint.c b/citadel/modules/checkpoint/serv_checkpoint.c index 98c685856..32bfad00b 100644 --- a/citadel/modules/checkpoint/serv_checkpoint.c +++ b/citadel/modules/checkpoint/serv_checkpoint.c @@ -44,7 +44,7 @@ void *checkpoint_thread(void *arg) { struct CitContext checkpointCC; - CT_PUSH(); + CtdlThreadAllocTSD(); CtdlLogPrintf(CTDL_DEBUG, "checkpoint_thread() initializing\n"); @@ -53,9 +53,7 @@ void *checkpoint_thread(void *arg) { checkpointCC.cs_pid = 0; pthread_setspecific(MyConKey, (void *)&checkpointCC ); - cdb_allocate_tsd(); - - while (!CtdlThreadCheckStop(CT)) { + while (!CtdlThreadCheckStop()) { cdb_checkpoint(); CtdlThreadSleep(60); } diff --git a/citadel/modules/expire/serv_expire.c b/citadel/modules/expire/serv_expire.c index d856761c8..e807f969b 100644 --- a/citadel/modules/expire/serv_expire.c +++ b/citadel/modules/expire/serv_expire.c @@ -720,11 +720,9 @@ void *purge_databases(void *args) time_t now; struct tm tm; - CT_PUSH(); // Makes it easier to access this threads structure + CtdlThreadAllocTSD(); - cdb_allocate_tsd(); - - while (!CtdlThreadCheckStop(CT)) { + while (!CtdlThreadCheckStop()) { /* Do the auto-purge if the current hour equals the purge hour, * but not if the operation has already been performed in the * last twelve hours. This is usually enough granularity. @@ -739,49 +737,49 @@ void *purge_databases(void *args) lprintf(CTDL_INFO, "Auto-purger: starting.\n"); - if (!CtdlThreadCheckStop(CT)) + if (!CtdlThreadCheckStop()) { retval = PurgeUsers(); lprintf(CTDL_NOTICE, "Purged %d users.\n", retval); } - if (!CtdlThreadCheckStop(CT)) + if (!CtdlThreadCheckStop()) { PurgeMessages(); lprintf(CTDL_NOTICE, "Expired %d messages.\n", messages_purged); } - if (!CtdlThreadCheckStop(CT)) + if (!CtdlThreadCheckStop()) { retval = PurgeRooms(); lprintf(CTDL_NOTICE, "Expired %d rooms.\n", retval); } - if (!CtdlThreadCheckStop(CT)) + if (!CtdlThreadCheckStop()) { retval = PurgeVisits(); lprintf(CTDL_NOTICE, "Purged %d visits.\n", retval); } - if (!CtdlThreadCheckStop(CT)) + if (!CtdlThreadCheckStop()) { retval = PurgeUseTable(); lprintf(CTDL_NOTICE, "Purged %d entries from the use table.\n", retval); } - if (!CtdlThreadCheckStop(CT)) + if (!CtdlThreadCheckStop()) { retval = PurgeEuidIndexTable(); lprintf(CTDL_NOTICE, "Purged %d entries from the EUID index.\n", retval); } - if (!CtdlThreadCheckStop(CT)) + if (!CtdlThreadCheckStop()) { retval = TDAP_ProcessAdjRefCountQueue(); lprintf(CTDL_NOTICE, "Processed %d message reference count adjustments.\n", retval); } - if (!CtdlThreadCheckStop(CT)) + if (!CtdlThreadCheckStop()) { lprintf(CTDL_INFO, "Auto-purger: finished.\n"); last_purge = now; /* So we don't do it again soon */ diff --git a/citadel/modules/fulltext/serv_fulltext.c b/citadel/modules/fulltext/serv_fulltext.c index 4737f66f0..7c76d9d64 100644 --- a/citadel/modules/fulltext/serv_fulltext.c +++ b/citadel/modules/fulltext/serv_fulltext.c @@ -222,8 +222,6 @@ void do_fulltext_indexing(void) { time_t run_time = 0L; time_t end_time = 0L; - CT_PUSH(); - /* * Don't do this if the site doesn't have it enabled. */ @@ -299,7 +297,7 @@ void do_fulltext_indexing(void) { ft_index_message(ft_newmsgs[i], 1); /* Check to see if we need to quit early */ - if (CtdlThreadCheckStop(CT)) { + if (CtdlThreadCheckStop()) { lprintf(CTDL_DEBUG, "Indexer quitting early\n"); ft_newhighest = ft_newmsgs[i]; break; @@ -341,7 +339,7 @@ void do_fulltext_indexing(void) { void *indexer_thread(void *arg) { struct CitContext indexerCC; - CT_PUSH(); + CtdlThreadAllocTSD(); lprintf(CTDL_DEBUG, "indexer_thread() initializing\n"); @@ -350,9 +348,7 @@ void *indexer_thread(void *arg) { indexerCC.cs_pid = 0; pthread_setspecific(MyConKey, (void *)&indexerCC ); - cdb_allocate_tsd(); - - while (!CtdlThreadCheckStop(CT)) { + while (!CtdlThreadCheckStop()) { do_fulltext_indexing(); CtdlThreadSleep(300); } @@ -503,7 +499,7 @@ CTDL_MODULE_INIT(fulltext) } else { - CtdlThreadCreate("indexer", CTDLTHREAD_BIGSTACK, indexer_thread, NULL); + CtdlThreadCreate("Indexer", CTDLTHREAD_BIGSTACK, indexer_thread, NULL); } /* return our Subversion id for the Log */ return "$Id$"; diff --git a/citadel/server_main.c b/citadel/server_main.c index 343d0ae13..20bc5dddf 100644 --- a/citadel/server_main.c +++ b/citadel/server_main.c @@ -347,15 +347,10 @@ void go_threading(void) int i; struct CtdlThreadNode *last_worker; - /* We can't use CT_PUSH() here so we do it the long way - * So we can still use CT for current thread */ - struct CtdlThreadNode *_this_cit_thread; - /* * Initialise the thread system */ ctdl_thread_internal_init(); - _this_cit_thread = CtdlThreadSelf(); /* * Now create a bunch of worker threads. */ diff --git a/citadel/sysdep.c b/citadel/sysdep.c index 268196996..e24af347b 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -1020,6 +1020,8 @@ static pthread_t GC_thread; static char *CtdlThreadStates[CTDL_THREAD_LAST_STATE]; double CtdlThreadLoadAvg = 0; double CtdlThreadWorkerAvg = 0; +pthread_key_t ThreadKey; + /* * Pinched the following bits regarding signals from Kannel.org */ @@ -1076,6 +1078,64 @@ static void ctdl_thread_internal_restore_signals(sigset_t *old_set) } + +/* + * A function to destroy the TSD + */ +static void ctdl_thread_internal_dest_tsd(void *arg) +{ + if (arg != NULL) { + check_handles(arg); + free(arg); + } +} + + +/* + * A function to initialise the thread TSD + */ +void ctdl_thread_internal_init_tsd(void) +{ + int ret; + + if ((ret = pthread_key_create(&ThreadKey, ctdl_thread_internal_dest_tsd))) { + lprintf(CTDL_EMERG, "pthread_key_create: %s\n", + strerror(ret)); + exit(CTDLEXIT_DB); + } +} + +/* + * Ensure that we have a key for thread-specific data. + * + * This should be called immediately after startup by any thread + * + */ +void CtdlThreadAllocTSD(void) +{ + ThreadTSD *tsd; + + if (pthread_getspecific(ThreadKey) != NULL) + return; + + tsd = malloc(sizeof(ThreadTSD)); + + tsd->tid = NULL; + + memset(tsd->cursors, 0, sizeof tsd->cursors); + tsd->self = NULL; + + pthread_setspecific(ThreadKey, tsd); +} + + +void ctdl_thread_internal_free_tsd(void) +{ + ctdl_thread_internal_dest_tsd(pthread_getspecific(ThreadKey)); + pthread_setspecific(ThreadKey, NULL); +} + + void ctdl_thread_internal_cleanup(void) { int i; @@ -1084,6 +1144,7 @@ void ctdl_thread_internal_cleanup(void) { free (CtdlThreadStates[i]); } + ctdl_thread_internal_free_tsd(); } void ctdl_thread_internal_init(void) @@ -1129,6 +1190,7 @@ void ctdl_thread_internal_init(void) this_thread->name = "Garbage Collection Thread"; this_thread->tid = GC_thread; + CT = this_thread; num_threads++; // Increase the count of threads in the system. @@ -1283,34 +1345,6 @@ double CtdlThreadGetLoadAvg(void) return ret; } -/* - * A function to find the thread structure for this thread - */ -struct CtdlThreadNode *CtdlThreadSelf(void) -{ - pthread_t self_tid; - struct CtdlThreadNode *this_thread; - - self_tid = pthread_self(); - - begin_critical_section(S_THREAD_LIST); - this_thread = CtdlThreadList; - while(this_thread) - { - pthread_mutex_lock(&this_thread->ThreadMutex); - if (pthread_equal(self_tid, this_thread->tid)) - { - pthread_mutex_unlock(&this_thread->ThreadMutex); - end_critical_section(S_THREAD_LIST); - return this_thread; - } - pthread_mutex_unlock(&this_thread->ThreadMutex); - this_thread = this_thread->next; - } - end_critical_section(S_THREAD_LIST); - return NULL; -} - @@ -1318,27 +1352,20 @@ struct CtdlThreadNode *CtdlThreadSelf(void) * A function to rename a thread * Returns a const char * */ -const char *CtdlThreadName(struct CtdlThreadNode *thread, const char *name) +const char *CtdlThreadName(const char *name) { - struct CtdlThreadNode *this_thread; const char *old_name; - if (!thread) - this_thread = CtdlThreadSelf(); - else - this_thread = thread; - if (!this_thread) + if (!CT) { CtdlLogPrintf(CTDL_WARNING, "Thread system WARNING. Attempt to CtdlThreadRename() a non thread. %s\n", name); return NULL; } -// begin_critical_section(S_THREAD_LIST); - pthread_mutex_lock(&this_thread->ThreadMutex); - old_name = this_thread->name; + pthread_mutex_lock(&CT->ThreadMutex); + old_name = CT->name; if (name) - this_thread->name = name; - pthread_mutex_unlock(&this_thread->ThreadMutex); -// end_critical_section (S_THREAD_LIST); + CT->name = name; + pthread_mutex_unlock(&CT->ThreadMutex); return (old_name); } @@ -1351,7 +1378,7 @@ void CtdlThreadCancel(struct CtdlThreadNode *thread) struct CtdlThreadNode *this_thread; if (!thread) - this_thread = CtdlThreadSelf(); + this_thread = CT; else this_thread = thread; if (!this_thread) @@ -1379,27 +1406,27 @@ void CtdlThreadCancel(struct CtdlThreadNode *thread) /* * A function for a thread to check if it has been asked to stop */ -int CtdlThreadCheckStop(struct CtdlThreadNode *this_thread) +int CtdlThreadCheckStop(void) { - if (!this_thread) + if (!CT) { CtdlLogPrintf(CTDL_EMERG, "Thread system PANIC, CtdlThreadCheckStop() called by a non thread.\n"); CtdlThreadStopAll(); return -1; } - pthread_mutex_lock(&this_thread->ThreadMutex); - if(this_thread->state == CTDL_THREAD_STOP_REQ) + pthread_mutex_lock(&CT->ThreadMutex); + if(CT->state == CTDL_THREAD_STOP_REQ) { - this_thread->state = CTDL_THREAD_STOPPING; - pthread_mutex_unlock(&this_thread->ThreadMutex); + CT->state = CTDL_THREAD_STOPPING; + pthread_mutex_unlock(&CT->ThreadMutex); return -1; } - else if((this_thread->state < CTDL_THREAD_STOP_REQ) && (this_thread->state > CTDL_THREAD_CREATE)) + else if((CT->state < CTDL_THREAD_STOP_REQ) && (CT->state > CTDL_THREAD_CREATE)) { - pthread_mutex_unlock(&this_thread->ThreadMutex); + pthread_mutex_unlock(&CT->ThreadMutex); return -1; } - pthread_mutex_unlock(&this_thread->ThreadMutex); + pthread_mutex_unlock(&CT->ThreadMutex); return 0; } @@ -1413,7 +1440,7 @@ void CtdlThreadStop(struct CtdlThreadNode *thread) struct CtdlThreadNode *this_thread; if (!thread) - this_thread = CtdlThreadSelf(); + this_thread = CT; else this_thread = thread; if (!this_thread) @@ -1437,11 +1464,9 @@ void CtdlThreadSleep(int secs) { struct timespec wake_time; struct timeval time_now; - struct CtdlThreadNode *self; - self = CtdlThreadSelf(); - if (!self) + if (!CT) { CtdlLogPrintf(CTDL_WARNING, "CtdlThreadSleep() called by something that is not a thread. Should we die?\n"); return; @@ -1453,17 +1478,17 @@ void CtdlThreadSleep(int secs) wake_time.tv_nsec = time_now.tv_usec * 10; // begin_critical_section(S_THREAD_LIST); - ctdl_thread_internal_change_state (self, CTDL_THREAD_SLEEPING); + ctdl_thread_internal_change_state (CT, CTDL_THREAD_SLEEPING); // end_critical_section(S_THREAD_LIST); // pthread_mutex_lock(&self->SleepMutex); /* Prevent something asking us to awaken before we've gone to sleep */ - pthread_mutex_lock(&self->ThreadMutex); /* Prevent something asking us to awaken before we've gone to sleep */ - pthread_cond_timedwait(&self->SleepCond, &self->ThreadMutex, &wake_time); - pthread_mutex_unlock(&self->ThreadMutex); + pthread_mutex_lock(&CT->ThreadMutex); /* Prevent something asking us to awaken before we've gone to sleep */ + pthread_cond_timedwait(&CT->SleepCond, &CT->ThreadMutex, &wake_time); + pthread_mutex_unlock(&CT->ThreadMutex); // pthread_mutex_unlock(&self->SleepMutex); // begin_critical_section(S_THREAD_LIST); - ctdl_thread_internal_change_state (self, CTDL_THREAD_RUNNING); + ctdl_thread_internal_change_state (CT, CTDL_THREAD_RUNNING); // end_critical_section(S_THREAD_LIST); } @@ -1473,20 +1498,18 @@ void CtdlThreadSleep(int secs) */ static void ctdl_internal_thread_cleanup(void *arg) { - struct CtdlThreadNode *this_thread; - this_thread = CtdlThreadSelf(); /* * In here we were called by the current thread because it is exiting * NB. WE ARE THE CURRENT THREAD */ - CtdlLogPrintf(CTDL_NOTICE, "Thread \"%s\" (%ld) exited.\n", this_thread->name, this_thread->tid); + CtdlLogPrintf(CTDL_NOTICE, "Thread \"%s\" (%ld) exited.\n", CT->name, CT->tid); // begin_critical_section(S_THREAD_LIST); #ifdef HAVE_BACKTRACE eCrash_UnregisterThread(); #endif - pthread_mutex_lock(&this_thread->ThreadMutex); - this_thread->state = CTDL_THREAD_EXITED; // needs to be last thing else house keeping will unlink us too early - pthread_mutex_unlock(&this_thread->ThreadMutex); + pthread_mutex_lock(&CT->ThreadMutex); + CT->state = CTDL_THREAD_EXITED; // needs to be last thing else house keeping will unlink us too early + pthread_mutex_unlock(&CT->ThreadMutex); // end_critical_section(S_THREAD_LIST); // CtdlThreadGC(); } @@ -1669,6 +1692,8 @@ static void *ctdl_internal_thread_func (void *arg) // Register the cleanup function to take care of when we exit. pthread_cleanup_push(ctdl_internal_thread_cleanup, NULL); // Get our thread data structure + CtdlThreadAllocTSD(); + CT = this_thread; this_thread->pid = getpid(); memcpy(&this_thread->last_state_change, &this_thread->start_time, sizeof (struct timeval)); /* Changed state so mark it. */ /* Only change to running state if we weren't asked to stop during the create cycle @@ -1677,7 +1702,7 @@ static void *ctdl_internal_thread_func (void *arg) */ pthread_mutex_unlock(&this_thread->ThreadMutex); - if (!CtdlThreadCheckStop(this_thread)) + if (!CtdlThreadCheckStop()) { pthread_mutex_lock(&this_thread->ThreadMutex); this_thread->state = CTDL_THREAD_RUNNING; @@ -1698,7 +1723,7 @@ static void *ctdl_internal_thread_func (void *arg) /* * run the thread to do the work but only if we haven't been asked to stop */ - if (!CtdlThreadCheckStop(this_thread)) + if (!CtdlThreadCheckStop()) ret = (this_thread->thread_func)(this_thread->user_args); /* @@ -1990,11 +2015,8 @@ void *worker_thread(void *arg) { int force_purge = 0; int m; - CT_PUSH(); - - cdb_allocate_tsd(); - while (!CtdlThreadCheckStop(CT)) { + while (!CtdlThreadCheckStop()) { /* make doubly sure we're not holding any stale db handles * which might cause a deadlock. @@ -2040,13 +2062,13 @@ do_select: force_purge = 0; } } - if (!CtdlThreadCheckStop(CT)) { + if (!CtdlThreadCheckStop()) { tv.tv_sec = 1; /* wake up every second if no input */ tv.tv_usec = 0; retval = CtdlThreadSelect(highest + 1, &readfds, NULL, NULL, &tv, CT); } - if (CtdlThreadCheckStop(CT)) return(NULL); + if (CtdlThreadCheckStop()) return(NULL); /* Now figure out who made this select() unblock. * First, check for an error or exit condition. @@ -2060,7 +2082,7 @@ do_select: force_purge = 0; if (errno != EINTR) { CtdlLogPrintf(CTDL_EMERG, "Exiting (%s)\n", strerror(errno)); CtdlThreadStopAll(); - } else if (!CtdlThreadCheckStop(CT)) { + } else if (!CtdlThreadCheckStop()) { CtdlLogPrintf(CTDL_DEBUG, "Un handled select failure.\n"); goto do_select; } diff --git a/citadel/sysdep_decls.h b/citadel/sysdep_decls.h index d2ae1b87a..f2480f47d 100644 --- a/citadel/sysdep_decls.h +++ b/citadel/sysdep_decls.h @@ -14,7 +14,22 @@ #include #include #include "sysdep.h" + +#ifdef HAVE_DB_H +#include +#elif defined(HAVE_DB4_DB_H) +#include +#else +#error Neither nor was found by configure. Install db4-devel. +#endif + + +#if DB_VERSION_MAJOR < 4 || DB_VERSION_MINOR < 1 +#error Citadel requires Berkeley DB v4.1 or newer. Please upgrade. +#endif + #include "server.h" +#include "database.h" #if SIZEOF_SIZE_T == SIZEOF_INT #define SIZE_T_FMT "%d" @@ -96,11 +111,6 @@ extern volatile int restart_server; extern int verbosity; extern int rescan[]; -extern struct worker_node { - pthread_t tid; - struct worker_node *next; -} *worker_list; - /* @@ -150,14 +160,22 @@ extern struct CtdlThreadNode { struct CtdlThreadNode *next; /* Next thread in the thread table */ } *CtdlThreadList; +typedef struct { + DB_TXN *tid; /* Transaction handle */ + DBC *cursors[MAXCDB]; /* Cursors, for traversals... */ + struct CtdlThreadNode *self; /* Pointer to this threads control structure */ +}ThreadTSD ; extern double CtdlThreadLoadAvg; extern double CtdlThreadWorkerAvg; +extern pthread_key_t ThreadKey; +void ctdl_thread_internal_init_tsd(void); void ctdl_internal_thread_gc (void); void ctdl_thread_internal_init(void); void ctdl_thread_internal_cleanup(void); void ctdl_thread_internal_calc_loadavg(void); +void ctdl_thread_internal_free_tsd(void); struct CtdlThreadNode *ctdl_internal_create_thread(char *name, long flags, void *(*thread_func) (void *arg), void *args); -- 2.30.2