ThreadPool.h 14 KB

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