"Fossies" - the Fresh Open Source Software Archive

Member "citadel/threads.c" (5 Jun 2021, 4730 Bytes) of package /linux/www/citadel.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "threads.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 9.01_vs_902.

    1 /*
    2  * Thread handling stuff for Citadel server
    3  *
    4  * Copyright (c) 1987-2021 by the citadel.org team
    5  *
    6  * This program is open source software; you can redistribute it and/or modify
    7  * it under the terms of the GNU General Public License, version 3.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  */
   14 
   15 #include <errno.h>
   16 #include <stdio.h>
   17 #include <syslog.h>
   18 #include <libcitadel.h>
   19 #include "modules_init.h"
   20 #include "serv_extensions.h"
   21 #include "ctdl_module.h"
   22 #include "config.h"
   23 #include "context.h"
   24 #include "threads.h"
   25 
   26 int num_workers = 0;                /* Current number of worker threads */
   27 int active_workers = 0;             /* Number of ACTIVE worker threads */
   28 pthread_key_t ThreadKey;
   29 pthread_mutex_t Critters[MAX_SEMAPHORES];   /* Things needing locking */
   30 struct thread_tsd masterTSD;
   31 int server_shutting_down = 0;           /* set to nonzero during shutdown */
   32 pthread_mutex_t ThreadCountMutex;
   33 
   34 void InitializeSemaphores(void)
   35 {
   36     int i;
   37 
   38     /* Set up a bunch of semaphores to be used for critical sections */
   39     for (i=0; i<MAX_SEMAPHORES; ++i) {
   40         pthread_mutex_init(&Critters[i], NULL);
   41     }
   42 }
   43 
   44 
   45 /*
   46  * Obtain a semaphore lock to begin a critical section.
   47  * but only if no one else has one
   48  */
   49 int try_critical_section(int which_one)
   50 {
   51     /* For all types of critical sections except those listed here,
   52      * ensure nobody ever tries to do a critical section within a
   53      * transaction; this could lead to deadlock.
   54      */
   55     if (    (which_one != S_FLOORCACHE)
   56         && (which_one != S_NETCONFIGS)
   57     ) {
   58         cdb_check_handles();
   59     }
   60     return (pthread_mutex_trylock(&Critters[which_one]));
   61 }
   62 
   63 
   64 /*
   65  * Obtain a semaphore lock to begin a critical section.
   66  */
   67 void begin_critical_section(int which_one)
   68 {
   69     /* For all types of critical sections except those listed here,
   70      * ensure nobody ever tries to do a critical section within a
   71      * transaction; this could lead to deadlock.
   72      */
   73     if (    (which_one != S_FLOORCACHE)
   74         && (which_one != S_NETCONFIGS)
   75     ) {
   76         cdb_check_handles();
   77     }
   78     pthread_mutex_lock(&Critters[which_one]);
   79 }
   80 
   81 
   82 /*
   83  * Release a semaphore lock to end a critical section.
   84  */
   85 void end_critical_section(int which_one)
   86 {
   87     pthread_mutex_unlock(&Critters[which_one]);
   88 }
   89 
   90 
   91 /*
   92  * Return a pointer to our thread-specific (not session-specific) data.
   93  */ 
   94 struct thread_tsd *MyThread(void) {
   95         struct thread_tsd *c = (struct thread_tsd *) pthread_getspecific(ThreadKey) ;
   96     if (!c) {
   97         return &masterTSD;
   98     }
   99     return c;
  100 }
  101 
  102 
  103 /* 
  104  * Called by CtdlThreadCreate()
  105  * We have to pass through here before starting our thread in order to create a set of data
  106  * that is thread-specific rather than session-specific.
  107  */
  108 void *CTC_backend(void *supplied_start_routine)
  109 {
  110     struct thread_tsd *mytsd;
  111     void *(*start_routine)(void*) = supplied_start_routine;
  112 
  113     mytsd = (struct thread_tsd *) malloc(sizeof(struct thread_tsd));
  114     memset(mytsd, 0, sizeof(struct thread_tsd));
  115     pthread_setspecific(ThreadKey, (const void *) mytsd);
  116 
  117     start_routine(NULL);
  118     // free(mytsd);
  119     return(NULL);
  120 }
  121 
  122  
  123 /*
  124  * Function to create a thread.
  125  */ 
  126 void CtdlThreadCreate(void *(*start_routine)(void*))
  127 {
  128     pthread_t thread;
  129     pthread_attr_t attr;
  130     int ret = 0;
  131 
  132     ret = pthread_attr_init(&attr);
  133     ret = pthread_attr_setstacksize(&attr, THREADSTACKSIZE);
  134     ret = pthread_create(&thread, &attr, CTC_backend, (void *)start_routine);
  135     if (ret != 0) syslog(LOG_ERR, "pthread_create() : %m");
  136 }
  137 
  138 
  139 void InitializeMasterTSD(void) {
  140     memset(&masterTSD, 0, sizeof(struct thread_tsd));
  141 }
  142 
  143 
  144 /*
  145  * Initialize the thread system
  146  */
  147 void go_threading(void) {
  148     pthread_mutex_init(&ThreadCountMutex, NULL);
  149 
  150     /* Second call to module init functions now that threading is up */
  151     initialise_modules(1);
  152 
  153     /* Begin with one worker thread.  We will expand the pool if necessary */
  154     CtdlThreadCreate(worker_thread);
  155 
  156     /* The supervisor thread monitors worker threads and spawns more of them if it finds that
  157      * they are all in use.
  158      */
  159     while (!server_shutting_down) {
  160         if ((active_workers == num_workers) && (num_workers < CtdlGetConfigInt("c_max_workers"))) {
  161             CtdlThreadCreate(worker_thread);
  162         }
  163         usleep(1000000);
  164     }
  165 
  166     /* When we get to this point we are getting ready to shut down our Citadel server */
  167     terminate_all_sessions();       /* close all client sockets */
  168     CtdlShutdownServiceHooks();     /* close all listener sockets to prevent new connections */
  169     PerformSessionHooks(EVT_SHUTDOWN);  /* run any registered shutdown hooks */
  170 
  171     /* We used to wait for all threads to exit.  Fuck that.  The only thing important is that the databases are
  172      * cleanly unmounted.  After that, exit the whole program.
  173      */
  174 }