X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fthreads.c;h=a9fce4eb471282f59e5cbaf1ff5831496e9c3237;hb=e1270db35d02e0c12db7417c4912451b0c664132;hp=cb216febefa00d24a3339a419c103a46564dd358;hpb=d04e1208cf6c71816adb600c6493c48c7b9610f1;p=citadel.git diff --git a/citadel/threads.c b/citadel/threads.c index cb216febe..a9fce4eb4 100644 --- a/citadel/threads.c +++ b/citadel/threads.c @@ -62,22 +62,12 @@ #include "event_client.h" -/* - * To create a thread you must call one of the create thread functions. - * You must pass it the address of (a pointer to a CtdlThreadNode initialised to NULL) like this - * struct CtdlThreadNode *node = NULL; - * pass in &node - * If the thread is created *node will point to the thread control structure for the created thread. - * If the thread creation fails *node remains NULL - * Do not free the memory pointed to by *node, it doesn't belong to you. - * This new interface duplicates much of the eCrash stuff. We should go for closer integration since that would - * remove the need for the calls to eCrashRegisterThread and friends - */ - -static int num_threads = 0; /* Current number of threads */ +int num_workers = 0; /* Current number of worker threads */ +int active_workers = 0; /* Number of ACTIVE worker threads */ pthread_key_t ThreadKey; pthread_mutex_t Critters[MAX_SEMAPHORES]; /* Things needing locking */ struct thread_tsd masterTSD; +int server_shutting_down = 0; /* set to nonzero during shutdown */ @@ -139,27 +129,6 @@ void end_critical_section(int which_one) } -/* - * A function to tell all threads to exit - */ -void CtdlThreadStopAll(void) -{ - terminate_all_sessions(); /* close all client sockets */ - CtdlShutdownServiceHooks(); /* close all listener sockets to prevent new connections */ - PerformSessionHooks(EVT_SHUTDOWN); /* run any registered shutdown hooks */ -} - - -/* - * A function for a thread to check if it has been asked to stop - */ -int CtdlThreadCheckStop(void) -{ - - /* FIXME this needs to do something useful. moar code pls ! */ - - return 0; -} /* @@ -188,6 +157,7 @@ void *CTC_backend(void *supplied_start_routine) start_routine(NULL); + free(mytsd); return(NULL); } @@ -206,8 +176,6 @@ void CtdlThreadCreate(void *(*start_routine)(void*)) ret = pthread_attr_setstacksize(&attr, THREADSTACKSIZE); ret = pthread_create(&thread, &attr, CTC_backend, (void *)start_routine); if (ret != 0) syslog(LOG_EMERG, "pthread_create() : %s", strerror(errno)); - - ++num_threads; } @@ -229,25 +197,30 @@ void go_threading(void) /* Second call to module init functions now that threading is up */ initialise_modules(1); - CtdlThreadCreate(select_on_master); - - /* FIXME temporary fixed size pool of worker threads */ - CtdlThreadCreate(worker_thread); - CtdlThreadCreate(worker_thread); - CtdlThreadCreate(worker_thread); - CtdlThreadCreate(worker_thread); - CtdlThreadCreate(worker_thread); - CtdlThreadCreate(worker_thread); - CtdlThreadCreate(worker_thread); + /* Begin with one worker thread. We will expand the pool if necessary */ CtdlThreadCreate(worker_thread); - /* At this point I am a union worker and therefore serve no useful purpose. */ - - while(!CtdlThreadCheckStop()) { - sleep(3); + /* The supervisor thread monitors worker threads and spawns more of them if it finds that + * they are all in use. FIXME make the 256 max threads a configurable value. + */ + while (!server_shutting_down) { + if ((active_workers == num_workers) && (num_workers < 256)) { + CtdlThreadCreate(worker_thread); + } + usleep(1000); } - /* Shut down */ - CtdlThreadStopAll(); - exit(0); + /* When we get to this point we are getting ready to shut down our Citadel server */ + + terminate_all_sessions(); /* close all client sockets */ + CtdlShutdownServiceHooks(); /* close all listener sockets to prevent new connections */ + PerformSessionHooks(EVT_SHUTDOWN); /* run any registered shutdown hooks */ + + int countdown = 30; + while ( (num_workers > 0) && (countdown-- > 0)) { + syslog(LOG_DEBUG, "Waiting %d seconds for %d worker threads to exit", + countdown, num_workers + ); + usleep(1000); + } }