21 #include "JackPosixThread.h"
22 #include "JackError.h"
24 #include "JackGlobals.h"
29 #define JACK_SCHED_POLICY SCHED_FIFO
31 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
32 # define SCHED_RESET_ON_FORK 0x40000000
38 void* JackPosixThread::ThreadHandler(
void* arg)
40 JackPosixThread* obj = (JackPosixThread*)arg;
41 JackRunnableInterface* runnable = obj->fRunnable;
44 if ((err = pthread_setcanceltype(obj->fCancellation, NULL)) != 0) {
45 jack_error(
"pthread_setcanceltype err = %s", strerror(err));
49 jack_log(
"JackPosixThread::ThreadHandler : start");
50 obj->fStatus = kIniting;
53 if (!runnable->Init()) {
58 obj->fStatus = kRunning;
62 while (obj->fStatus == kRunning && res) {
63 res = runnable->Execute();
66 jack_log(
"JackPosixThread::ThreadHandler : exit");
71 int JackPosixThread::Start()
76 if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler,
this) < 0) {
84 int JackPosixThread::StartSync()
88 if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler,
this) < 0) {
93 while (fStatus == kStarting && ++count < 1000) {
96 return (count == 1000) ? -1 : 0;
100 int JackPosixThread::StartImp(jack_native_thread_t* thread,
int priority,
int realtime,
void*(*start_routine)(
void*),
void* arg)
102 pthread_attr_t attributes;
103 struct sched_param rt_param;
104 pthread_attr_init(&attributes);
107 if ((res = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE))) {
108 jack_error(
"Cannot request joinable thread creation for thread res = %d", res);
112 if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) {
113 jack_error(
"Cannot set scheduling scope for thread res = %d", res);
119 jack_log(
"JackPosixThread::StartImp : create RT thread");
121 if ((res = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED))) {
122 jack_error(
"Cannot request explicit scheduling for RT thread res = %d", res);
126 if ((res = pthread_attr_setschedpolicy(&attributes, JACK_SCHED_POLICY))) {
127 jack_error(
"Cannot set RR scheduling class for RT thread res = %d", res);
131 memset(&rt_param, 0,
sizeof(rt_param));
132 rt_param.sched_priority = priority;
134 if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) {
135 jack_error(
"Cannot set scheduling priority for RT thread res = %d", res);
140 jack_log(
"JackPosixThread::StartImp : create non RT thread");
141 if ((res = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED))) {
142 jack_log(
"Cannot request explicit scheduling for non RT thread res = %d", res);
146 if ((res = pthread_attr_setstacksize(&attributes, THREAD_STACK))) {
147 jack_error(
"Cannot set thread stack size res = %d", res);
151 if ((res = JackGlobals::fJackThreadCreator(thread, &attributes, start_routine, arg))) {
152 jack_error(
"Cannot create thread res = %d", res);
156 pthread_attr_destroy(&attributes);
160 int JackPosixThread::Kill()
162 if (fThread != (jack_native_thread_t)NULL) {
165 pthread_cancel(fThread);
166 pthread_join(fThread, &status);
168 fThread = (jack_native_thread_t)NULL;
175 int JackPosixThread::Stop()
177 if (fThread != (jack_native_thread_t)NULL) {
181 pthread_join(fThread, &status);
182 fThread = (jack_native_thread_t)NULL;
189 int JackPosixThread::KillImp(jack_native_thread_t thread)
191 if (thread != (jack_native_thread_t)NULL) {
194 pthread_cancel(thread);
195 pthread_join(thread, &status);
202 int JackPosixThread::StopImp(jack_native_thread_t thread)
204 if (thread != (jack_native_thread_t)NULL) {
207 pthread_join(thread, &status);
214 int JackPosixThread::AcquireRealTime()
216 return (fThread != (jack_native_thread_t)NULL) ? AcquireRealTimeImp(fThread, fPriority) : -1;
219 int JackPosixThread::AcquireSelfRealTime()
221 return AcquireRealTimeImp(pthread_self(), fPriority);
224 int JackPosixThread::AcquireRealTime(
int priority)
226 fPriority = priority;
227 return AcquireRealTime();
230 int JackPosixThread::AcquireSelfRealTime(
int priority)
232 fPriority = priority;
233 return AcquireSelfRealTime();
235 int JackPosixThread::AcquireRealTimeImp(jack_native_thread_t thread,
int priority)
237 struct sched_param rtparam;
239 memset(&rtparam, 0,
sizeof(rtparam));
240 rtparam.sched_priority = priority;
242 jack_log(
"JackPosixThread::AcquireRealTimeImp priority = %d", priority);
244 if ((res = pthread_setschedparam(thread, JACK_SCHED_POLICY, &rtparam)) == 0)
247 #ifdef SCHED_RESET_ON_FORK
248 jack_log(
"pthread_setschedparam() failed (%d), trying with SCHED_RESET_ON_FORK.", res);
249 if ((res = pthread_setschedparam(thread, JACK_SCHED_POLICY|SCHED_RESET_ON_FORK, &rtparam)) == 0)
253 jack_error(
"Cannot use real-time scheduling (RR/%d)"
254 " (%d: %s)", rtparam.sched_priority, res,
259 int JackPosixThread::DropRealTime()
261 return (fThread != (jack_native_thread_t)NULL) ? DropRealTimeImp(fThread) : -1;
264 int JackPosixThread::DropSelfRealTime()
266 return DropRealTimeImp(pthread_self());
269 int JackPosixThread::DropRealTimeImp(jack_native_thread_t thread)
271 struct sched_param rtparam;
273 memset(&rtparam, 0,
sizeof(rtparam));
274 rtparam.sched_priority = 0;
276 if ((res = pthread_setschedparam(thread, SCHED_OTHER, &rtparam)) != 0) {
277 jack_error(
"Cannot switch to normal scheduling priority(%s)", strerror(errno));
283 jack_native_thread_t JackPosixThread::GetThreadID()
288 bool JackPosixThread::IsThread()
290 return pthread_self() == fThread;
293 void JackPosixThread::Terminate()
295 jack_log(
"JackPosixThread::Terminate");
299 SERVER_EXPORT
void ThreadExit()
307 bool jack_get_thread_realtime_priority_range(
int * min_ptr,
int * max_ptr)
309 #if defined(_POSIX_PRIORITY_SCHEDULING) && !defined(__APPLE__)
312 min = sched_get_priority_min(JACK_SCHED_POLICY);
315 jack_error(
"sched_get_priority_min() failed.");
319 max = sched_get_priority_max(JACK_SCHED_POLICY);
322 jack_error(
"sched_get_priority_max() failed.");
335 bool jack_tls_allocate_key(jack_tls_key *key_ptr)
339 ret = pthread_key_create(key_ptr, NULL);
342 jack_error(
"pthread_key_create() failed with error %d", ret);
349 bool jack_tls_free_key(jack_tls_key key)
353 ret = pthread_key_delete(key);
356 jack_error(
"pthread_key_delete() failed with error %d", ret);
363 bool jack_tls_set(jack_tls_key key,
void *data_ptr)
367 ret = pthread_setspecific(key, (
const void *)data_ptr);
370 jack_error(
"pthread_setspecific() failed with error %d", ret);
377 void *jack_tls_get(jack_tls_key key)
379 return pthread_getspecific(key);
SERVER_EXPORT void jack_error(const char *fmt,...)
SERVER_EXPORT void jack_log(const char *fmt,...)