00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "JackPosixThread.h"
00022 #include "JackError.h"
00023 #include <string.h>
00024
00025 namespace Jack
00026 {
00027
00028 void* JackPosixThread::ThreadHandler(void* arg)
00029 {
00030 JackPosixThread* obj = (JackPosixThread*)arg;
00031 JackRunnableInterface* runnable = obj->fRunnable;
00032 int err;
00033
00034 if ((err = pthread_setcanceltype(obj->fCancellation, NULL)) != 0) {
00035 jack_error("pthread_setcanceltype err = %s", strerror(err));
00036 }
00037
00038
00039 if (!runnable->Init()) {
00040 jack_error("Thread init fails: thread quits");
00041 return 0;
00042 }
00043
00044 JackLog("ThreadHandler: start\n");
00045
00046
00047 bool res = true;
00048 while (obj->fRunning && res) {
00049 res = runnable->Execute();
00050 }
00051
00052 JackLog("ThreadHandler: exit\n");
00053 return 0;
00054 }
00055
00056 int JackPosixThread::Start()
00057 {
00058 fRunning = true;
00059
00060
00061 if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) {
00062 fRunning = false;
00063 return -1;
00064 } else {
00065 return 0;
00066 }
00067 }
00068
00069 int JackPosixThread::StartImp(pthread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg)
00070 {
00071 int res;
00072
00073 if (realtime) {
00074
00075 JackLog("Create RT thread\n");
00076
00077
00078
00079
00080 pthread_attr_t attributes;
00081 struct sched_param rt_param;
00082 pthread_attr_init(&attributes);
00083
00084 if ((res = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED))) {
00085 jack_error("Cannot request explicit scheduling for RT thread %d %s", res, strerror(errno));
00086 return -1;
00087 }
00088
00089 if ((res = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE))) {
00090 jack_error("Cannot request joinable thread creation for RT thread %d %s", res, strerror(errno));
00091 return -1;
00092 }
00093
00094 if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) {
00095 jack_error("Cannot set scheduling scope for RT thread %d %s", res, strerror(errno));
00096 return -1;
00097 }
00098
00099
00100
00101 if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_RR))) {
00102 jack_error("Cannot set FIFO scheduling class for RT thread %d %s", res, strerror(errno));
00103 return -1;
00104 }
00105
00106 if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) {
00107 jack_error("Cannot set scheduling scope for RT thread %d %s", res, strerror(errno));
00108 return -1;
00109 }
00110
00111 memset(&rt_param, 0, sizeof(rt_param));
00112 rt_param.sched_priority = priority;
00113
00114 if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) {
00115 jack_error("Cannot set scheduling priority for RT thread %d %s", res, strerror(errno));
00116 return -1;
00117 }
00118
00119 if ((res = pthread_attr_setstacksize(&attributes, THREAD_STACK))) {
00120 jack_error("setting thread stack size%d %s", res, strerror(errno));
00121 return -1;
00122 }
00123
00124 if ((res = pthread_create(thread, &attributes, start_routine, arg))) {
00125 jack_error("Cannot set create thread %d %s", res, strerror(errno));
00126 return -1;
00127 }
00128
00129 return 0;
00130 } else {
00131 JackLog("Create non RT thread\n");
00132
00133 if ((res = pthread_create(thread, 0, start_routine, arg))) {
00134 jack_error("Cannot set create thread %d %s", res, strerror(errno));
00135 return -1;
00136 }
00137 return 0;
00138 }
00139 }
00140
00141 int JackPosixThread::StartSync()
00142 {
00143 jack_error("Not implemented yet");
00144 return -1;
00145 }
00146
00147 int JackPosixThread::Kill()
00148 {
00149 if (fThread) {
00150 JackLog("JackPosixThread::Kill\n");
00151 void* status;
00152 pthread_cancel(fThread);
00153 pthread_join(fThread, &status);
00154 fRunning = false;
00155 fThread = (pthread_t)NULL;
00156 return 0;
00157 } else {
00158 return -1;
00159 }
00160 }
00161
00162 int JackPosixThread::Stop()
00163 {
00164 if (fThread) {
00165 JackLog("JackPosixThread::Stop\n");
00166 void* status;
00167 fRunning = false;
00168 pthread_join(fThread, &status);
00169 fThread = (pthread_t)NULL;
00170 return 0;
00171 } else {
00172 return -1;
00173 }
00174 }
00175
00176 int JackPosixThread::AcquireRealTime()
00177 {
00178 return (fThread) ? AcquireRealTimeImp(fThread, fPriority) : -1;
00179 }
00180
00181 int JackPosixThread::AcquireRealTime(int priority)
00182 {
00183 fPriority = priority;
00184 return AcquireRealTime();
00185 }
00186
00187 int JackPosixThread::AcquireRealTimeImp(pthread_t thread, int priority)
00188 {
00189 struct sched_param rtparam;
00190 int res;
00191 memset(&rtparam, 0, sizeof(rtparam));
00192 rtparam.sched_priority = priority;
00193
00194
00195
00196 if ((res = pthread_setschedparam(thread, SCHED_RR, &rtparam)) != 0) {
00197 jack_error("Cannot use real-time scheduling (FIFO/%d) "
00198 "(%d: %s)", rtparam.sched_priority, res,
00199 strerror(res));
00200 return -1;
00201 }
00202 return 0;
00203 }
00204
00205 int JackPosixThread::DropRealTime()
00206 {
00207 return (fThread) ? DropRealTimeImp(fThread) : -1;
00208 }
00209
00210 int JackPosixThread::DropRealTimeImp(pthread_t thread)
00211 {
00212 struct sched_param rtparam;
00213 int res;
00214 memset(&rtparam, 0, sizeof(rtparam));
00215 rtparam.sched_priority = 0;
00216
00217 if ((res = pthread_setschedparam(thread, SCHED_OTHER, &rtparam)) != 0) {
00218 jack_error("Cannot switch to normal scheduling priority(%s)\n", strerror(errno));
00219 return -1;
00220 }
00221 return 0;
00222 }
00223
00224 pthread_t JackPosixThread::GetThreadID()
00225 {
00226 return fThread;
00227 }
00228
00229 void JackPosixThread::Terminate()
00230 {
00231 JackLog("JackPosixThread::Terminate\n");
00232 pthread_exit(0);
00233 }
00234
00235 }
00236