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