00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "include/logging.h"
00025 #include "lib/safeclib.h"
00026
00027
00028 #include "backend/threadpool.h"
00029
00030
00031 static lumiera_threadpool threadpool;
00032
00033
00034 #include <pthread.h>
00035
00041 LUMIERA_ERROR_DEFINE(THREADPOOL_OFFLINE, "tried to acquire thread while threadpool is not available");
00042
00043
00044
00045 void
00046 lumiera_threadpool_init(void)
00047 {
00048 TRACE (threadpool);
00049
00050 for (int i = 0; i < LUMIERA_THREADCLASS_COUNT; ++i)
00051 {
00052 llist_init (&threadpool.pool[i].working_list);
00053 llist_init (&threadpool.pool[i].idle_list);
00054 threadpool.pool[i].status = LUMIERA_THREADPOOL_ONLINE;
00055
00056
00057 pthread_attr_init (&threadpool.pool[i].pthread_attrs);
00058
00059
00060 lumiera_condition_init (&threadpool.pool[i].sync,"pool of threads", &NOBUG_FLAG (threadpool), NOBUG_CONTEXT);
00061 }
00062 }
00063
00064 void
00065 lumiera_threadpool_destroy(void)
00066 {
00067 TRACE (threadpool);
00068
00069
00070 for (int i = 0; i < LUMIERA_THREADCLASS_COUNT; ++i)
00071 LUMIERA_CONDITION_SECTION (cond_sync, &threadpool.pool[i].sync)
00072 threadpool.pool[i].status = LUMIERA_THREADPOOL_OFFLINE;
00073
00074
00075 for (int i = 0; i < LUMIERA_THREADCLASS_COUNT; ++i)
00076 {
00077 LUMIERA_CONDITION_SECTION (cond_sync, &threadpool.pool[i].sync)
00078 {
00079 TODO ("check threads deadlines, kill them when they are stalled");
00080 TODO ("for threads without deadline use a timeout from config system, 500ms or so by default");
00081 LUMIERA_CONDITION_WAIT(llist_is_empty (&threadpool.pool[i].working_list));
00082 }
00083 }
00084
00085
00086 for (int i = 0; i < LUMIERA_THREADCLASS_COUNT; ++i)
00087 {
00088 TRACE (threadpool, "destroying individual pool #%d", i);
00089
00090 LUMIERA_CONDITION_SECTION (cond_sync, &threadpool.pool[i].sync)
00091 {
00092 ENSURE (llist_is_empty (&threadpool.pool[i].working_list),
00093 "threads are still running");
00094
00095 LLIST_WHILE_HEAD (&threadpool.pool[i].idle_list, t)
00096 {
00097 lumiera_thread_delete ((LumieraThread)t);
00098 }
00099 }
00100 lumiera_condition_destroy (&threadpool.pool[i].sync, &NOBUG_FLAG (threadpool), NOBUG_CONTEXT);
00101 pthread_attr_destroy (&threadpool.pool[i].pthread_attrs);
00102 }
00103 }
00104
00109 LumieraThread
00110 lumiera_threadpool_acquire_thread (enum lumiera_thread_class kind,
00111 const char* purpose,
00112 struct nobug_flag* flag)
00113 {
00114 TRACE (threadpool);
00115 LumieraThread ret = NULL;
00116
00117 REQUIRE (kind < LUMIERA_THREADCLASS_COUNT, "unknown pool kind specified: %d", kind);
00118
00119 LUMIERA_CONDITION_SECTION (cond_sync, &threadpool.pool[kind].sync)
00120 {
00121 if (threadpool.pool[kind].status != LUMIERA_THREADPOOL_ONLINE)
00122 LUMIERA_ERROR_SET_WARNING (threadpool, THREADPOOL_OFFLINE, purpose);
00123 else
00124 {
00125 if (llist_is_empty (&threadpool.pool[kind].idle_list))
00126 {
00127 ret = lumiera_thread_new (kind, purpose, flag,
00128 &threadpool.pool[kind].pthread_attrs);
00129 TRACE (threadpool, "created thread %p", ret);
00130
00131
00132
00133
00134
00135
00136 llist_insert_head (&threadpool.pool[kind].working_list, &ret->node);
00137
00138 ENSURE (ret, "did not create a valid thread");
00139 TODO ("no error handing, let the resourcecollector do it, no need when returning the thread");
00140 LUMIERA_CONDITION_WAIT (!llist_is_empty (&threadpool.pool[kind].idle_list));
00141 }
00142
00143
00144 ret = (LumieraThread) (llist_head (&threadpool.pool[kind].idle_list));
00145 TRACE (threadpool, "got thread %p", ret);
00146
00147 REQUIRE (ret->state == LUMIERA_THREADSTATE_IDLE, "trying to return a non-idle thread (state=%s)", lumiera_threadstate_names[ret->state]);
00148
00149
00150 llist_insert_head (&threadpool.pool[kind].working_list, &ret->node);
00151 }
00152 }
00153 return ret;
00154 }
00155
00156 void
00157 lumiera_threadpool_release_thread(LumieraThread thread)
00158 {
00159 TRACE (threadpool);
00160 REQUIRE (thread, "invalid thread given");
00161 thread->kind = thread->kind&0xff;
00162 REQUIRE (thread->kind < LUMIERA_THREADCLASS_COUNT, "thread belongs to an unknown pool kind: %d", thread->kind);
00163
00164 REQUIRE (thread->state != LUMIERA_THREADSTATE_IDLE, "trying to park an already idle thread");
00165 LUMIERA_CONDITION_SECTION (cond_sync, &threadpool.pool[thread->kind].sync)
00166 {
00167 REQUIRE (!llist_is_member (&threadpool.pool[thread->kind].idle_list, &thread->node), "thread is already in the idle list");
00168 REQUIRE (llist_is_member (&threadpool.pool[thread->kind].working_list, &thread->node)
00169 || thread->state == LUMIERA_THREADSTATE_STARTUP,
00170 "thread is not in the working list (state=%s)",
00171 lumiera_threadstate_names[thread->state]);
00172 thread->state = LUMIERA_THREADSTATE_IDLE;
00173
00174 llist_insert_head (&threadpool.pool[thread->kind].idle_list, &thread->node);
00175
00176 LUMIERA_CONDITION_BROADCAST;
00177 }
00178 }
00179
00180
00181
00182
00183
00184
00185
00186