1///////////////////////////////////////////////////////////////////////////
2//
3// Copyright (c) 2000-2003 Intel Corporation
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are met:
8//
9// * Redistributions of source code must retain the above copyright notice,
10// this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above copyright notice,
12// this list of conditions and the following disclaimer in the documentation
13// and/or other materials provided with the distribution.
14// * Neither name of Intel Corporation nor the names of its contributors
15// may be used to endorse or promote products derived from this software
16// without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
22// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30///////////////////////////////////////////////////////////////////////////
31
32#ifndef THREADPOOL_H
33#define THREADPOOL_H
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38
39//Size of job free list
40#define JOBFREELISTSIZE 100
41
42#define INFINITE_THREADS -1
43
44#define EMAXTHREADS (-8 & 1<<29)
45
46//Invalid Policy
47#define INVALID_POLICY (-9 & 1<<29)
48
49//Invalid JOB Id
50#define INVALID_JOB_ID (-2 & 1<<29)
51
52typedef enum duration {SHORT_TERM,PERSISTENT} Duration;
53
54typedef enum priority {LOW_PRIORITY,
55		       MED_PRIORITY,
56		       HIGH_PRIORITY} ThreadPriority;
57
58#define DEFAULT_PRIORITY MED_PRIORITY //default priority used by TPJobInit
59#define DEFAULT_MIN_THREADS 1	      //default minimum used by TPAttrInit
60#define DEFAULT_MAX_THREADS 10	      //default max used by TPAttrInit
61#define DEFAULT_JOBS_PER_THREAD 10    //default jobs per thread used by TPAttrInit
62#define DEFAULT_STARVATION_TIME	500   //default starvation time used by TPAttrInit
63#define DEFAULT_IDLE_TIME 10 * 1000   //default idle time used by TPAttrInit
64#define DEFAULT_FREE_ROUTINE NULL     //default free routine used TPJobInit
65
66#define STATS 1 //always include stats because code change is minimal
67
68
69//Statistics
70#ifdef STATS
71#define STATSONLY(x) x
72#else
73#define STATSONLY(x)
74#endif
75
76#ifdef _DEBUG
77#define DEBUG 1
78#endif
79
80//DEBUGGING
81#ifdef DEBUG
82#define DBGONLY(x) x
83#else
84#define DBGONLY(x)
85#endif
86
87#include "LinkedList.h"
88#include <sys/timeb.h>
89#include "FreeList.h"
90
91#include "ithread.h"
92#include <errno.h>
93#include <sys/timeb.h>
94#define EXPORT
95typedef int PolicyType;
96#define DEFAULT_POLICY SCHED_OTHER
97#define DEFAULT_SCHED_PARAM 0 //default priority
98
99/****************************************************************************
100 * Name: free_routine
101 *
102 *  Description:
103 *     Function for freeing a thread argument
104 *****************************************************************************/
105typedef void (*free_routine)(void *arg);
106
107/****************************************************************************
108 * Name: ThreadPoolAttr
109 *
110 *  Description:
111 *     Attributes for thread pool. Used to set and change parameters of
112 *     thread pool
113 *****************************************************************************/
114typedef struct THREADPOOLATTR
115{
116  int minThreads; //minThreads, ThreadPool will always maintain at least
117                  //this many threads
118
119  int maxThreads; //maxThreads, ThreadPool will never have more than this
120                  //number of threads
121
122  int maxIdleTime;   //maxIdleTime (in milliseconds)
123                     // this is the maximum time a thread will remain idle
124                     // before dying
125
126  int jobsPerThread; //jobs per thread to maintain
127
128  int starvationTime;   //the time a low priority or med priority
129	                    //job waits before getting bumped
130                        //up a priority (in milliseconds)
131
132  PolicyType schedPolicy; //scheduling policy to use
133
134} ThreadPoolAttr;
135
136/****************************************************************************
137 * Name: ThreadPool
138 *
139 *  Description:
140 *     Internal ThreadPool Job
141 *****************************************************************************/
142typedef struct THREADPOOLJOB
143{
144  start_routine func; //function
145  void *arg;          //arg
146  free_routine free_func; //free function
147  struct timeb requestTime; //time of request
148  int priority;       //priority of request
149  int jobId;         //id
150} ThreadPoolJob;
151
152/****************************************************************************
153 * Name: ThreadPoolStats
154 *
155 *  Description:
156 *     Structure to hold statistics
157 *****************************************************************************/
158
159STATSONLY(
160
161typedef struct TPOOLSTATS
162{
163  double totalTimeHQ; //total time spent by all jobs in high priority Q
164  int totalJobsHQ;    //total jobs in HQ run so far
165  double avgWaitHQ;   //average wait in HQ
166  double totalTimeMQ; //total time spent by all jobs in med priority Q
167  int totalJobsMQ;    //total jobs in MQ run so far
168  double avgWaitMQ;   //average wait in MQ
169  double totalTimeLQ; //total time spent by all jobs in low priority Q
170  int totalJobsLQ;    //total jobs in LQ run so far
171  double avgWaitLQ;	//average wait in LQ
172  double totalWorkTime; //total time spent working for all threads
173  double totalIdleTime; //total time spent idle for all threads
174  int workerThreads; //number of current workerThreads
175  int idleThreads;   //number of current idle threads
176  int persistentThreads; //number of persistent threads
177  int totalThreads; //total number of current threads
178  int maxThreads; //max threads so far
179  int currentJobsHQ; // current jobs in Q
180  int currentJobsLQ; //current jobs in Q
181  int currentJobsMQ; //current jobs in Q
182}ThreadPoolStats;
183
184)
185
186
187/****************************************************************************
188 * Name: ThreadPool
189 *
190 *  Description:
191 *     A thread pool similar to the thread pool in the UPnP SDK.
192 *     Allows jobs to be scheduled for running by threads in a
193 *     thread pool. The thread pool is initialized with a
194 *     minimum and maximum thread number as well as a
195 *	   max idle time
196 *     and a jobs per thread ratio. If a worker thread waits the whole
197 *     max idle time without receiving a job and the thread pool
198 *     currently has more threads running than the minimum
199 *     then the worker thread will exit. If when
200 *     scheduling a job the current job to thread ratio
201 *     becomes greater than the set ratio and the thread pool currently has
202 *     less than the maximum threads then a new thread will
203 *     be created.
204 *
205 *****************************************************************************/
206
207typedef struct THREADPOOL
208{
209  ithread_mutex_t mutex; //mutex to protect job qs
210  ithread_cond_t condition; //condition variable to signal Q
211  ithread_cond_t start_and_shutdown; //condition variable for start
212                                     //and stop
213  int lastJobId; //ids for jobs
214  int shutdown;   //whether or not we are shutting down
215  int totalThreads;       //total number of threads
216  int persistentThreads; //number of persistent threads
217  FreeList jobFreeList; //free list of jobs
218  LinkedList lowJobQ;    //low priority job Q
219  LinkedList medJobQ;    //med priority job Q
220  LinkedList highJobQ;   //high priority job Q
221  ThreadPoolJob *persistentJob; //persistent job
222
223  ThreadPoolAttr attr; //thread pool attributes
224
225  //statistics
226  STATSONLY(ThreadPoolStats stats;)
227
228} ThreadPool;
229
230
231
232/****************************************************************************
233 * Function: ThreadPoolInit
234 *
235 *  Description:
236 *      Initializes and starts ThreadPool. Must be called first.
237 *      And only once for ThreadPool.
238 *  Parameters:
239 *      tp  - must be valid, non null, pointer to ThreadPool.
240 *      attr - can be null
241 *
242 *       if not null then attr contains the following fields:
243 *
244 *      minWorkerThreads - minimum number of worker threads
245 *                                 thread pool will never have less than this
246 *                                  number of threads.
247 *      maxWorkerThreads - maximum number of worker threads
248 *                         thread pool will never have more than this
249 *                         number of threads.
250 *      maxIdleTime      - maximum time that a worker thread will spend
251 *                         idle. If a worker is idle longer than this
252 *                         time and there are more than the min
253 *                         number of workers running, than the
254 *                         worker thread exits.
255 *      jobsPerThread    - ratio of jobs to thread to try and maintain
256 *                         if a job is scheduled and the number of jobs per
257 *                         thread is greater than this number,and
258 *                         if less than the maximum number of
259 *                         workers are running then a new thread is
260 *                         started to help out with efficiency.
261 *      schedPolicy      - scheduling policy to try and set (OS dependent)
262 *  Returns:
263 *      0 on success, nonzero on failure.
264 *      EAGAIN if not enough system resources to create minimum threads.
265 *      INVALID_POLICY if schedPolicy can't be set
266 *      EMAXTHREADS if minimum threads is greater than maximum threads
267 *****************************************************************************/
268int ThreadPoolInit(ThreadPool *tp,
269  ThreadPoolAttr *attr);
270
271/****************************************************************************
272 * Function: ThreadPoolAddPersistent
273 *
274 *  Description:
275 *      Adds a persistent job to the thread pool.
276 *      Job will be run as soon as possible.
277 *      Call will block until job is scheduled.
278 *  Parameters:
279 *      tp - valid thread pool pointer
280 *      ThreadPoolJob - valid thread pool job with the following fields:
281 *
282 *        func - ThreadFunction to run
283 *        arg - argument to function.
284 *        priority - priority of job.
285 *
286 *  Returns:
287 *      0 on success, nonzero on failure
288 *      EOUTOFMEM not enough memory to add job.
289 *      EMAXTHREADS not enough threads to add persistent job.
290 *****************************************************************************/
291int ThreadPoolAddPersistent (ThreadPool*tp,
292  ThreadPoolJob *job,
293  int *jobId);
294
295/****************************************************************************
296 * Function: ThreadPoolGetAttr
297 *
298 *  Description:
299 *      Gets the current set of attributes
300 *      associated with the thread pool.
301 *  Parameters:
302 *      tp - valid thread pool pointer
303 *      out - non null pointer to store attributes
304 *  Returns:
305 *      0 on success, nonzero on failure
306 *      Always returns 0.
307 *****************************************************************************/
308int ThreadPoolGetAttr(ThreadPool *tp,
309  ThreadPoolAttr *out);
310/****************************************************************************
311 * Function: ThreadPoolSetAttr
312 *
313 *  Description:
314 *      Sets the attributes for the thread pool.
315 *      Only affects future calculations.
316 *  Parameters:
317 *      tp - valid thread pool pointer
318 *      attr - pointer to attributes, null sets attributes to default.
319 *  Returns:
320 *      0 on success, nonzero on failure
321 *      Returns INVALID_POLICY if policy can not be set.
322 *****************************************************************************/
323int ThreadPoolSetAttr(ThreadPool *tp,
324  ThreadPoolAttr *attr);
325
326/****************************************************************************
327 * Function: ThreadPoolAdd
328 *
329 *  Description:
330 *      Adds a job to the thread pool.
331 *      Job will be run as soon as possible.
332 *  Parameters:
333 *      tp - valid thread pool pointer
334 *      func - ThreadFunction to run
335 *      arg - argument to function.
336 *      priority - priority of job.
337 *      poolid - id of job
338 *      free_function - function to use when freeing argument
339 *  Returns:
340 *      0 on success, nonzero on failure
341 *      EOUTOFMEM if not enough memory to add job.
342 *****************************************************************************/
343int ThreadPoolAdd (ThreadPool*tp,
344  ThreadPoolJob *job,
345  int *jobId);
346
347/****************************************************************************
348 * Function: ThreadPoolRemove
349 *
350 *  Description:
351 *      Removes a job from the thread pool.
352 *      Can only remove jobs which are not
353 *      currently running.
354 *  Parameters:
355 *      tp - valid thread pool pointer
356 *      jobid - id of job
357 *      out - space for removed job.
358 *  Returns:
359 *      0 on success, nonzero on failure.
360 *      INVALID_JOB_ID if job not found.
361 *****************************************************************************/
362int ThreadPoolRemove(ThreadPool *tp,
363  int jobId, ThreadPoolJob *out);
364
365
366
367/****************************************************************************
368 * Function: ThreadPoolShutdown
369 *
370 *  Description:
371 *      Shuts the thread pool down.
372 *      Waits for all threads to finish.
373 *      May block indefinitely if jobs do not
374 *      exit.
375 *  Parameters:
376 *      tp - must be valid tp
377 *  Returns:
378 *      0 on success, nonzero on failure
379 *      Always returns 0.
380 *****************************************************************************/
381int ThreadPoolShutdown(ThreadPool *tp);
382
383
384/****************************************************************************
385 * Function: TPJobInit
386 *
387 *  Description:
388 *      Initializes thread pool job.
389 *      Sets the priority to default defined in ThreadPool.h.
390 *      Sets the free_routine to default defined in ThreadPool.h
391 *  Parameters:
392 *      ThreadPoolJob *job - must be valid thread pool attributes.
393 *      start_routine func - function to run, must be valid
394 *      void * arg - argument to pass to function.
395 *  Returns:
396 *      Always returns 0.
397 *****************************************************************************/
398int TPJobInit(ThreadPoolJob *job, start_routine func, void *arg);
399
400/****************************************************************************
401 * Function: TPJobSetPriority
402 *
403 *  Description:
404 *      Sets the max threads for the thread pool attributes.
405 *  Parameters:
406 *      attr - must be valid thread pool attributes.
407 *      maxThreads - value to set
408 *  Returns:
409 *      Always returns 0.
410 *****************************************************************************/
411int TPJobSetPriority(ThreadPoolJob *job, ThreadPriority priority);
412
413/****************************************************************************
414 * Function: TPJobSetFreeFunction
415 *
416 *  Description:
417 *      Sets the max threads for the thread pool attributes.
418 *  Parameters:
419 *      attr - must be valid thread pool attributes.
420 *      maxThreads - value to set
421 *  Returns:
422 *      Always returns 0.
423 *****************************************************************************/
424int TPJobSetFreeFunction(ThreadPoolJob *job, free_routine func);
425
426
427/****************************************************************************
428 * Function: TPAttrInit
429 *
430 *  Description:
431 *      Initializes thread pool attributes.
432 *      Sets values to defaults defined in ThreadPool.h.
433 *  Parameters:
434 *      attr - must be valid thread pool attributes.
435 *  Returns:
436 *      Always returns 0.
437 *****************************************************************************/
438int TPAttrInit(ThreadPoolAttr *attr);
439
440/****************************************************************************
441 * Function: TPAttrSetMaxThreads
442 *
443 *  Description:
444 *      Sets the max threads for the thread pool attributes.
445 *  Parameters:
446 *      attr - must be valid thread pool attributes.
447 *      maxThreads - value to set
448 *  Returns:
449 *      Always returns 0.
450 *****************************************************************************/
451int TPAttrSetMaxThreads(ThreadPoolAttr *attr, int maxThreads);
452
453/****************************************************************************
454 * Function: TPAttrSetMinThreads
455 *
456 *  Description:
457 *      Sets the min threads for the thread pool attributes.
458 *  Parameters:
459 *      attr - must be valid thread pool attributes.
460 *      minThreads - value to set
461 *  Returns:
462 *      Always returns 0.
463 *****************************************************************************/
464int TPAttrSetMinThreads(ThreadPoolAttr *attr, int minThreads);
465
466/****************************************************************************
467 * Function: TPAttrSetIdleTime
468 *
469 *  Description:
470 *      Sets the idle time for the thread pool attributes.
471 *  Parameters:
472 *      attr - must be valid thread pool attributes.
473 *  Returns:
474 *      Always returns 0.
475 *****************************************************************************/
476int TPAttrSetIdleTime(ThreadPoolAttr *attr, int idleTime);
477
478/****************************************************************************
479 * Function: TPAttrSetJobsPerThread
480 *
481 *  Description:
482 *      Sets the jobs per thread ratio
483 *  Parameters:
484 *      attr - must be valid thread pool attributes.
485 *      jobsPerThread - number of jobs per thread to maintain
486 *  Returns:
487 *      Always returns 0.
488 *****************************************************************************/
489int TPAttrSetJobsPerThread(ThreadPoolAttr *attr, int jobsPerThread);
490
491/****************************************************************************
492 * Function: TPAttrSetStarvationTime
493 *
494 *  Description:
495 *      Sets the starvation time for the thread pool attributes.
496 *  Parameters:
497 *      attr - must be valid thread pool attributes.
498 *      int starvationTime - milliseconds
499 *  Returns:
500 *      Always returns 0.
501 *****************************************************************************/
502int TPAttrSetStarvationTime(ThreadPoolAttr *attr, int starvationTime);
503
504/****************************************************************************
505 * Function: TPAttrSetSchedPolicy
506 *
507 *  Description:
508 *      Sets the scheduling policy for the thread pool attributes.
509 *  Parameters:
510 *      attr - must be valid thread pool attributes.
511 *      PolicyType schedPolicy - must be a valid policy type.
512 *  Returns:
513 *      Always returns 0.
514 *****************************************************************************/
515int TPAttrSetSchedPolicy(ThreadPoolAttr *attr, PolicyType schedPolicy);
516
517
518/****************************************************************************
519 * Function: ThreadPoolGetStats
520 *
521 *  Description:
522 *      Returns various statistics about the
523 *      thread pool.
524 *      Only valid if STATS has been defined.
525 *  Parameters:
526 *      ThreadPool *tp - valid initialized threadpool
527 *      ThreadPoolStats *stats - valid stats, out parameter
528 *  Returns:
529 *      Always returns 0.
530 *****************************************************************************/
531STATSONLY( EXPORT int ThreadPoolGetStats(ThreadPool *tp, ThreadPoolStats *stats););
532
533STATSONLY(EXPORT void ThreadPoolPrintStats(ThreadPoolStats *stats););
534
535#ifdef __cplusplus
536}
537#endif
538
539#endif //ThreadPool
540