ThreadPool.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2000-2003 Intel Corporation 
00004  * All rights reserved. 
00005  *
00006  * Redistribution and use in source and binary forms, with or without 
00007  * modification, are permitted provided that the following conditions are met: 
00008  *
00009  * * Redistributions of source code must retain the above copyright notice, 
00010  * this list of conditions and the following disclaimer. 
00011  * * Redistributions in binary form must reproduce the above copyright notice, 
00012  * this list of conditions and the following disclaimer in the documentation 
00013  * and/or other materials provided with the distribution. 
00014  * * Neither name of Intel Corporation nor the names of its contributors 
00015  * may be used to endorse or promote products derived from this software 
00016  * without specific prior written permission.
00017  * 
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00019  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
00021  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR 
00022  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00023  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00024  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
00025  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
00026  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00027  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  ******************************************************************************/
00031 
00032 
00033 #ifndef THREADPOOL_H
00034 #define THREADPOOL_H
00035 
00036 
00042 #include "FreeList.h"
00043 #include "ithread.h"
00044 #include "LinkedList.h"
00045 #include "UpnpInet.h"
00046 #include "UpnpGlobal.h" /* for UPNP_INLINE, EXPORT_SPEC */
00047 
00048 
00049 #include <errno.h>
00050 
00051 
00052 #ifdef WIN32
00053         #include <time.h>
00054         struct timezone
00055         {
00056                 int  tz_minuteswest; /* minutes W of Greenwich */
00057                 int  tz_dsttime;     /* type of dst correction */
00058         };
00059         int gettimeofday(struct timeval *tv, struct timezone *tz);
00060 #else /* WIN32 */
00061         #include <sys/param.h>
00062         #include <sys/time.h> /* for gettimeofday() */
00063         #if defined(__OSX__) || defined(__APPLE__) || defined(__NetBSD__)
00064                 #include <sys/resource.h>       /* for setpriority() */
00065         #endif
00066 
00067 #endif
00068 
00069 
00070 #ifdef __cplusplus
00071 extern "C" {
00072 #endif
00073 
00074 
00076 #define JOBFREELISTSIZE 100
00077 
00078 
00079 #define INFINITE_THREADS -1
00080 
00081 
00082 #define EMAXTHREADS (-8 & 1<<29)
00083 
00084 
00086 #define INVALID_POLICY (-9 & 1<<29)
00087 
00088 
00090 #define INVALID_JOB_ID (-2 & 1<<29)
00091 
00092 
00093 typedef enum duration {
00094         SHORT_TERM,
00095         PERSISTENT
00096 } Duration;
00097 
00098 
00099 typedef enum priority {
00100         LOW_PRIORITY,
00101         MED_PRIORITY,
00102         HIGH_PRIORITY
00103 } ThreadPriority;
00104 
00105 
00107 #define DEFAULT_PRIORITY MED_PRIORITY
00108 
00109 
00111 #define DEFAULT_MIN_THREADS 1
00112 
00113 
00115 #define DEFAULT_MAX_THREADS 10
00116 
00117 
00119 #define DEFAULT_JOBS_PER_THREAD 10
00120 
00121 
00123 #define DEFAULT_STARVATION_TIME 500
00124 
00125 
00127 #define DEFAULT_IDLE_TIME 10 * 1000
00128 
00129 
00131 #define DEFAULT_FREE_ROUTINE NULL
00132 
00133 
00135 #define DEFAULT_MAX_JOBS_TOTAL 100
00136 
00137 
00143 #define STATS 1
00144 
00145 
00146 #ifdef _DEBUG
00147         #define DEBUG 1
00148 #endif
00149 
00150 
00151 typedef int PolicyType;
00152 
00153 
00154 #define DEFAULT_POLICY SCHED_OTHER
00155 
00156 
00158 #define DEFAULT_SCHED_PARAM 0
00159 
00160 
00161 /****************************************************************************
00162  * Name: free_routine
00163  *
00164  *  Description:
00165  *     Function for freeing a thread argument
00166  *****************************************************************************/
00167 typedef void (*free_routine)(void *arg);
00168 
00169 
00170 /****************************************************************************
00171  * Name: ThreadPoolAttr
00172  *
00173  *  Description:
00174  *     Attributes for thread pool. Used to set and change parameters of
00175  *     thread pool
00176  *****************************************************************************/
00177 typedef struct THREADPOOLATTR
00178 {
00179         /* minThreads, ThreadPool will always maintain at least this many threads */
00180         int minThreads;
00181 
00182         /* maxThreads, ThreadPool will never have more than this number of threads */
00183         int maxThreads;
00184 
00185         /* maxIdleTime (in milliseconds) this is the maximum time a thread will
00186          * remain idle before dying */
00187         int maxIdleTime;
00188 
00189         /* jobs per thread to maintain */
00190         int jobsPerThread;
00191 
00192         /* maximum number of jobs that can be queued totally. */
00193         int maxJobsTotal;
00194 
00195         /* the time a low priority or med priority job waits before getting bumped
00196          * up a priority (in milliseconds) */
00197         int starvationTime;
00198 
00199         /* scheduling policy to use */
00200         PolicyType schedPolicy;
00201 } ThreadPoolAttr;
00202 
00203 
00204 /****************************************************************************
00205  * Name: ThreadPool
00206  *
00207  *  Description:
00208  *     Internal ThreadPool Job
00209  *****************************************************************************/
00210 typedef struct THREADPOOLJOB
00211 {
00212         start_routine func;
00213         void *arg;
00214         free_routine free_func;
00215         struct timeval requestTime;
00216         int priority;
00217         int jobId;
00218 } ThreadPoolJob;
00219 
00220 
00221 /****************************************************************************
00222  * Name: ThreadPoolStats
00223  *
00224  *  Description:
00225  *     Structure to hold statistics
00226  *****************************************************************************/
00227 typedef struct TPOOLSTATS
00228 {
00229         double totalTimeHQ;
00230         int totalJobsHQ;
00231         double avgWaitHQ;
00232         double totalTimeMQ;
00233         int totalJobsMQ;
00234         double avgWaitMQ;
00235         double totalTimeLQ;
00236         int totalJobsLQ;
00237         double avgWaitLQ;
00238         double totalWorkTime;
00239         double totalIdleTime;
00240         int workerThreads;
00241         int idleThreads;
00242         int persistentThreads;
00243         int totalThreads;
00244         int maxThreads;
00245         int currentJobsHQ;
00246         int currentJobsLQ;
00247         int currentJobsMQ;
00248 } ThreadPoolStats;
00249 
00250 
00266 typedef struct THREADPOOL
00267 {
00268         ithread_mutex_t mutex;          /* mutex to protect job qs */
00269         ithread_cond_t condition;       /* condition variable to signal Q */
00270         ithread_cond_t start_and_shutdown; /* condition variable for start and stop */
00271         int lastJobId;                  /* ids for jobs */
00272         int shutdown;                   /* whether or not we are shutting down */
00273         int totalThreads;               /* total number of threads */
00274         int busyThreads;                /* number of threads that are currently executing jobs */
00275         int persistentThreads;          /* number of persistent threads */
00276         FreeList jobFreeList;           /* free list of jobs */
00277         LinkedList lowJobQ;             /* low priority job Q */
00278         LinkedList medJobQ;             /* med priority job Q */
00279         LinkedList highJobQ;            /* high priority job Q */
00280         ThreadPoolJob *persistentJob;   /* persistent job */
00281         ThreadPoolAttr attr;            /* thread pool attributes */
00282 
00283         /* statistics */
00284         ThreadPoolStats stats;
00285 } ThreadPool;
00286 
00287 
00288 /****************************************************************************
00289  * Function: ThreadPoolInit
00290  *
00291  *  Description:
00292  *      Initializes and starts ThreadPool. Must be called first.
00293  *      And only once for ThreadPool.
00294  *  Parameters:
00295  *      tp  - must be valid, non null, pointer to ThreadPool.
00296  *      attr - can be null
00297  *
00298  *       if not null then attr contains the following fields:
00299  *
00300  *      minWorkerThreads - minimum number of worker threads
00301  *                                 thread pool will never have less than this
00302  *                                  number of threads.
00303  *      maxWorkerThreads - maximum number of worker threads
00304  *                         thread pool will never have more than this
00305  *                         number of threads.
00306  *      maxIdleTime      - maximum time that a worker thread will spend
00307  *                         idle. If a worker is idle longer than this
00308  *                         time and there are more than the min
00309  *                         number of workers running, than the
00310  *                         worker thread exits.
00311  *      jobsPerThread    - ratio of jobs to thread to try and maintain
00312  *                         if a job is scheduled and the number of jobs per
00313  *                         thread is greater than this number,and  
00314  *                         if less than the maximum number of
00315  *                         workers are running then a new thread is 
00316  *                         started to help out with efficiency.
00317  *      schedPolicy      - scheduling policy to try and set (OS dependent)
00318  *  Returns:
00319  *      0 on success, nonzero on failure.
00320  *      EAGAIN if not enough system resources to create minimum threads.
00321  *      INVALID_POLICY if schedPolicy can't be set
00322  *      EMAXTHREADS if minimum threads is greater than maximum threads
00323  *****************************************************************************/
00324 int ThreadPoolInit(ThreadPool *tp, ThreadPoolAttr *attr);
00325 
00326 
00327 /****************************************************************************
00328  * Function: ThreadPoolAddPersistent
00329  *
00330  *  Description:
00331  *      Adds a persistent job to the thread pool.
00332  *      Job will be run as soon as possible.
00333  *      Call will block until job is scheduled.
00334  *  Parameters:
00335  *      tp - valid thread pool pointer
00336  *      ThreadPoolJob - valid thread pool job with the following fields:
00337  *
00338  *        func - ThreadFunction to run
00339  *        arg - argument to function.
00340  *        priority - priority of job.
00341  * 
00342  *  Returns:
00343  *      0 on success, nonzero on failure
00344  *      EOUTOFMEM not enough memory to add job.
00345  *      EMAXTHREADS not enough threads to add persistent job.
00346  *****************************************************************************/
00347 int ThreadPoolAddPersistent(ThreadPool*tp, ThreadPoolJob *job, int *jobId);
00348 
00349 
00350 /****************************************************************************
00351  * Function: ThreadPoolGetAttr
00352  *
00353  *  Description:
00354  *      Gets the current set of attributes
00355  *      associated with the thread pool.
00356  *  Parameters:
00357  *      tp - valid thread pool pointer
00358  *      out - non null pointer to store attributes
00359  *  Returns:
00360  *      0 on success, nonzero on failure
00361  *      Always returns 0.
00362  *****************************************************************************/
00363 int ThreadPoolGetAttr(ThreadPool *tp, ThreadPoolAttr *out);
00364 
00365 
00366 /****************************************************************************
00367  * Function: ThreadPoolSetAttr
00368  *
00369  *  Description:
00370  *      Sets the attributes for the thread pool.
00371  *      Only affects future calculations. 
00372  *  Parameters:
00373  *      tp - valid thread pool pointer
00374  *      attr - pointer to attributes, null sets attributes to default.
00375  *  Returns:
00376  *      0 on success, nonzero on failure
00377  *      Returns INVALID_POLICY if policy can not be set.
00378  *****************************************************************************/
00379 int ThreadPoolSetAttr(ThreadPool *tp, ThreadPoolAttr *attr);
00380 
00381 
00382 /****************************************************************************
00383  * Function: ThreadPoolAdd
00384  *
00385  *  Description:
00386  *      Adds a job to the thread pool.
00387  *      Job will be run as soon as possible.
00388  *  Parameters:
00389  *      tp - valid thread pool pointer
00390  *      func - ThreadFunction to run
00391  *      arg - argument to function.
00392  *      priority - priority of job.
00393  *      poolid - id of job
00394  *      free_function - function to use when freeing argument 
00395  *  Returns:
00396  *      0 on success, nonzero on failure
00397  *      EOUTOFMEM if not enough memory to add job.
00398  *****************************************************************************/
00399 int ThreadPoolAdd (ThreadPool*tp, ThreadPoolJob *job, int *jobId);
00400 
00401 
00402 /****************************************************************************
00403  * Function: ThreadPoolRemove
00404  *
00405  *  Description:
00406  *      Removes a job from the thread pool.
00407  *      Can only remove jobs which are not
00408  *      currently running.
00409  *  Parameters:
00410  *      tp - valid thread pool pointer
00411  *      jobid - id of job
00412  *      out - space for removed job.
00413  *  Returns:
00414  *      0 on success, nonzero on failure.
00415  *      INVALID_JOB_ID if job not found. 
00416  *****************************************************************************/
00417 int ThreadPoolRemove(ThreadPool *tp, int jobId, ThreadPoolJob *out);
00418 
00419 
00420 
00421 /****************************************************************************
00422  * Function: ThreadPoolShutdown
00423  *
00424  *  Description:
00425  *      Shuts the thread pool down.
00426  *      Waits for all threads to finish. 
00427  *      May block indefinitely if jobs do not
00428  *      exit.
00429  *  Parameters:
00430  *      tp - must be valid tp     
00431  *  Returns:
00432  *      0 on success, nonzero on failure
00433  *      Always returns 0.
00434  *****************************************************************************/
00435 int ThreadPoolShutdown(ThreadPool *tp);
00436 
00437 
00438 /****************************************************************************
00439  * Function: TPJobInit
00440  *
00441  *  Description:
00442  *      Initializes thread pool job.
00443  *      Sets the priority to default defined in ThreadPool.h.
00444  *      Sets the free_routine to default defined in ThreadPool.h
00445  *  Parameters:
00446  *      ThreadPoolJob *job - must be valid thread pool attributes.    
00447  *      start_routine func - function to run, must be valid
00448  *      void * arg - argument to pass to function.
00449  *  Returns:
00450  *      Always returns 0.
00451  *****************************************************************************/
00452 int TPJobInit(ThreadPoolJob *job, start_routine func, void *arg);
00453 
00454 
00455 /****************************************************************************
00456  * Function: TPJobSetPriority
00457  *
00458  *  Description:
00459  *      Sets the max threads for the thread pool attributes.
00460  *  Parameters:
00461  *      attr - must be valid thread pool attributes. 
00462  *      maxThreads - value to set
00463  *  Returns:
00464  *      Always returns 0.
00465  *****************************************************************************/
00466 int TPJobSetPriority(ThreadPoolJob *job, ThreadPriority priority);
00467 
00468 
00469 /****************************************************************************
00470  * Function: TPJobSetFreeFunction
00471  *
00472  *  Description:
00473  *      Sets the max threads for the thread pool attributes.
00474  *  Parameters:
00475  *      attr - must be valid thread pool attributes. 
00476  *      maxThreads - value to set
00477  *  Returns:
00478  *      Always returns 0.
00479  *****************************************************************************/
00480 int TPJobSetFreeFunction(ThreadPoolJob *job, free_routine func);
00481 
00482 
00483 /****************************************************************************
00484  * Function: TPAttrInit
00485  *
00486  *  Description:
00487  *      Initializes thread pool attributes.
00488  *      Sets values to defaults defined in ThreadPool.h.
00489  *  Parameters:
00490  *      attr - must be valid thread pool attributes.    
00491  *  Returns:
00492  *      Always returns 0.
00493  *****************************************************************************/
00494 int TPAttrInit(ThreadPoolAttr *attr);
00495 
00496 
00497 /****************************************************************************
00498  * Function: TPAttrSetMaxThreads
00499  *
00500  *  Description:
00501  *      Sets the max threads for the thread pool attributes.
00502  *  Parameters:
00503  *      attr - must be valid thread pool attributes. 
00504  *      maxThreads - value to set
00505  *  Returns:
00506  *      Always returns 0.
00507  *****************************************************************************/
00508 int TPAttrSetMaxThreads(ThreadPoolAttr *attr, int maxThreads);
00509 
00510 
00511 /****************************************************************************
00512  * Function: TPAttrSetMinThreads
00513  *
00514  *  Description:
00515  *      Sets the min threads for the thread pool attributes.
00516  *  Parameters:
00517  *      attr - must be valid thread pool attributes. 
00518  *      minThreads - value to set
00519  *  Returns:
00520  *      Always returns 0.
00521  *****************************************************************************/
00522 int TPAttrSetMinThreads(ThreadPoolAttr *attr, int minThreads);
00523 
00524 
00525 /****************************************************************************
00526  * Function: TPAttrSetIdleTime
00527  *
00528  *  Description:
00529  *      Sets the idle time for the thread pool attributes.
00530  *  Parameters:
00531  *      attr - must be valid thread pool attributes.    
00532  *  Returns:
00533  *      Always returns 0.
00534  *****************************************************************************/
00535 int TPAttrSetIdleTime(ThreadPoolAttr *attr, int idleTime);
00536 
00537 
00538 /****************************************************************************
00539  * Function: TPAttrSetJobsPerThread
00540  *
00541  *  Description:
00542  *      Sets the jobs per thread ratio
00543  *  Parameters:
00544  *      attr - must be valid thread pool attributes.
00545  *      jobsPerThread - number of jobs per thread to maintain
00546  *  Returns:
00547  *      Always returns 0.
00548  *****************************************************************************/
00549 int TPAttrSetJobsPerThread(ThreadPoolAttr *attr, int jobsPerThread);
00550 
00551 
00552 /****************************************************************************
00553  * Function: TPAttrSetStarvationTime
00554  *
00555  *  Description:
00556  *      Sets the starvation time for the thread pool attributes.
00557  *  Parameters:
00558  *      attr - must be valid thread pool attributes.    
00559  *      int starvationTime - milliseconds
00560  *  Returns:
00561  *      Always returns 0.
00562  *****************************************************************************/
00563 int TPAttrSetStarvationTime(ThreadPoolAttr *attr, int starvationTime);
00564 
00565 
00566 /****************************************************************************
00567  * Function: TPAttrSetSchedPolicy
00568  *
00569  *  Description:
00570  *      Sets the scheduling policy for the thread pool attributes.
00571  *  Parameters:
00572  *      attr - must be valid thread pool attributes.    
00573  *      PolicyType schedPolicy - must be a valid policy type.
00574  *  Returns:
00575  *      Always returns 0.
00576  *****************************************************************************/
00577 int TPAttrSetSchedPolicy(ThreadPoolAttr *attr, PolicyType schedPolicy);
00578 
00579 
00580 /****************************************************************************
00581  * Function: TPAttrSetMaxJobsTotal
00582  *
00583  *  Description:
00584  *      Sets the maximum number jobs that can be qeued totally.
00585  *  Parameters:
00586  *      attr - must be valid thread pool attributes.
00587  *      maxJobsTotal - maximum number of jobs
00588  *  Returns:
00589  *      Always returns 0.
00590  *****************************************************************************/
00591 int TPAttrSetMaxJobsTotal(ThreadPoolAttr *attr, int maxJobsTotal);
00592 
00593 
00594 /****************************************************************************
00595  * Function: ThreadPoolGetStats
00596  *
00597  *  Description:
00598  *      Returns various statistics about the
00599  *      thread pool.
00600  *      Only valid if STATS has been defined.
00601  *  Parameters:
00602  *      ThreadPool *tp - valid initialized threadpool    
00603  *      ThreadPoolStats *stats - valid stats, out parameter
00604  *  Returns:
00605  *      Always returns 0.
00606  *****************************************************************************/
00607 #ifdef STATS
00608         EXPORT_SPEC int ThreadPoolGetStats(ThreadPool *tp, ThreadPoolStats *stats);
00609 
00610         EXPORT_SPEC void ThreadPoolPrintStats(ThreadPoolStats *stats);
00611 #else
00612         static UPNP_INLINE int ThreadPoolGetStats(ThreadPool *tp, ThreadPoolStats *stats) {}
00613 
00614         static UPNP_INLINE void ThreadPoolPrintStats(ThreadPoolStats *stats) {}
00615 #endif
00616 
00617 
00618 #ifdef __cplusplus
00619 }
00620 #endif
00621 
00622 
00623 #endif /* THREADPOOL_H */
00624