00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <vpr/vprConfig.h>
00043
00044 #include <iomanip>
00045 #include <boost/concept_check.hpp>
00046
00047 #include <vpr/Util/Assert.h>
00048
00049 #include <vpr/md/NSPR/NSPRHelpers.h>
00050 #include <vpr/md/NSPR/Thread/ThreadNSPR.h>
00051
00052
00053 namespace vpr
00054 {
00055
00056 ThreadNSPR::staticWrapper ThreadNSPR::statics;
00057 PRUint32 ThreadNSPR::mTicksPerSec = PR_TicksPerSecond();
00058
00059
00060 ThreadNSPR::ThreadNSPR(VPRThreadPriority priority, VPRThreadScope scope,
00061 VPRThreadState state, PRUint32 stackSize)
00062 : mThread(NULL)
00063 , mUserThreadFunctor(NULL)
00064 , mDeleteFunctor(false)
00065 , mStartFunctor(NULL)
00066 , mPriority(priority)
00067 , mScope(scope)
00068 , mState(state)
00069 , mStackSize(stackSize)
00070 {
00071 }
00072
00073
00074
00075 ThreadNSPR::ThreadNSPR(thread_func_t func, void* arg,
00076 VPRThreadPriority priority, VPRThreadScope scope,
00077 VPRThreadState state, PRUint32 stackSize)
00078 : mThread(NULL)
00079 , mUserThreadFunctor(NULL)
00080 , mDeleteFunctor(false)
00081 , mStartFunctor(NULL)
00082 , mPriority(priority)
00083 , mScope(scope)
00084 , mState(state)
00085 , mStackSize(stackSize)
00086 {
00087 mDeleteFunctor = true;
00088 setFunctor(new ThreadNonMemberFunctor(func, arg));
00089 start();
00090 }
00091
00092
00093
00094 ThreadNSPR::ThreadNSPR(BaseThreadFunctor* functorPtr,
00095 VPRThreadPriority priority, VPRThreadScope scope,
00096 VPRThreadState state, PRUint32 stackSize)
00097 : mThread(NULL)
00098 , mUserThreadFunctor(NULL)
00099 , mDeleteFunctor(false)
00100 , mStartFunctor(NULL)
00101 , mPriority(priority)
00102 , mScope(scope)
00103 , mState(state)
00104 , mStackSize(stackSize)
00105 {
00106 setFunctor(functorPtr);
00107 start();
00108 }
00109
00110
00111 ThreadNSPR::~ThreadNSPR()
00112 {
00113 ThreadManager::instance()->lock();
00114 {
00115 unregisterThread();
00116 }
00117 ThreadManager::instance()->unlock();
00118
00119 if ( NULL != mStartFunctor )
00120 {
00121 delete mStartFunctor;
00122 mStartFunctor = NULL;
00123 }
00124
00125 if ( mDeleteFunctor )
00126 {
00127 delete mUserThreadFunctor;
00128 mUserThreadFunctor = NULL;
00129 }
00130 }
00131
00132 void ThreadNSPR::setFunctor(BaseThreadFunctor* functorPtr)
00133 {
00134 vprASSERT(mThread == NULL && "Thread already running");
00135 vprASSERT(functorPtr->isValid());
00136
00137 mUserThreadFunctor = functorPtr;
00138 }
00139
00140
00141 vpr::ReturnStatus ThreadNSPR::start()
00142 {
00143 vpr::ReturnStatus status;
00144
00145 if ( NULL != mThread )
00146 {
00147 vprASSERT(false && "Thread already running");
00148 status.setCode(vpr::ReturnStatus::Fail);
00149 }
00150 else if ( NULL == mUserThreadFunctor )
00151 {
00152 vprASSERT(false && "No functor set");
00153 status.setCode(vpr::ReturnStatus::Fail);
00154 }
00155 else
00156 {
00157 PRThreadPriority nspr_prio;
00158 PRThreadScope nspr_scope;
00159 PRThreadState nspr_state;
00160
00161 nspr_prio = vprThreadPriorityToNSPR(mPriority);
00162 nspr_scope = vprThreadScopeToNSPR(mScope);
00163 nspr_state = vprThreadStateToNSPR(mState);
00164
00165 vprASSERT(mUserThreadFunctor->isValid());
00166
00167
00168
00169 mStartFunctor =
00170 new ThreadMemberFunctor<ThreadNSPR>(this, &ThreadNSPR::startThread,
00171 NULL);
00172
00173
00174
00175 mThreadStartCompleted = false;
00176 PRThread* ret_thread =
00177 PR_CreateThread(PR_USER_THREAD, vprThreadFunctorFunction,
00178 (void*) mStartFunctor, nspr_prio, nspr_scope,
00179 nspr_state, (PRUint32) mStackSize);
00180
00181
00182 if ( NULL == ret_thread )
00183 {
00184 ThreadManager::instance()->lock();
00185 {
00186 registerThread(false);
00187 }
00188 ThreadManager::instance()->unlock();
00189
00190 NSPR_PrintError("vpr::ThreadNSPR::spawn() - Cannot create thread");
00191 status.setCode(vpr::ReturnStatus::Fail);
00192 }
00193 else
00194 {
00195
00196
00197 mThreadStartCondVar.acquire();
00198 {
00199
00200 while ( !mThreadStartCompleted )
00201 {
00202 mThreadStartCondVar.wait();
00203 }
00204 }
00205 mThreadStartCondVar.release();
00206
00207 vprASSERT(NULL != mThread && "Thread registration failed");
00208 vprASSERT(-1 != getTID() && "Thread id is invalid for successful thread");
00209
00210
00211 status.setCode(vpr::ReturnStatus::Succeed);
00212 }
00213 }
00214
00215 return status;
00216 }
00217
00218 int ThreadNSPR::join(void** status)
00219 {
00220 boost::ignore_unused_variable_warning(status);
00221 return PR_JoinThread(mThread);
00222 }
00223
00224 Thread* ThreadNSPR::self()
00225 {
00226 vprASSERT((statics.mStaticsInitialized==1221) && "Trying to call vpr::ThreadNSPR::self before statics are initialized. Don't do that");
00227
00228 Thread* my_thread;
00229 threadIdKey().getspecific((void**)&my_thread);
00230
00231 return my_thread;
00232 }
00233
00234 std::ostream& Thread::outStream(std::ostream& out)
00235 {
00236 out.setf(std::ios::right);
00237 out << std::setw(7) << std::setfill('0')
00238 #ifdef VPR_OS_Windows
00239 << _getpid()
00240 #else
00241 << getpid()
00242 #endif
00243 << "/";
00244 out.unsetf(std::ios::right);
00245 BaseThread::outStream(out);
00246 out << std::setfill(' ');
00247 return out;
00248 }
00249
00259 void ThreadNSPR::startThread(void* nullParam)
00260 {
00261 boost::ignore_unused_variable_warning(nullParam);
00262
00263
00264
00265 mThread = PR_GetCurrentThread();
00266 vprASSERT(NULL != mThread && "Invalid thread");
00267 ThreadManager::instance()->lock();
00268 {
00269 threadIdKey().setspecific((void*)this);
00270 registerThread(true);
00271 }
00272 ThreadManager::instance()->unlock();
00273
00274
00275 mThreadStartCondVar.acquire();
00276 {
00277 mThreadStartCompleted = true;
00278 mThreadStartCondVar.signal();
00279 }
00280 mThreadStartCondVar.release();
00281
00282
00283 (*mUserThreadFunctor)();
00284 }
00285
00286
00287
00288 int ThreadNSPR::setPrio(VPRThreadPriority prio)
00289 {
00290 int retval(0);
00291
00292 if ( prio > 3 )
00293 {
00294 retval = -1;
00295 }
00296 else
00297 {
00298 PR_SetThreadPriority(mThread, vprThreadPriorityToNSPR(prio));
00299 }
00300
00301 return retval;
00302 }
00303
00304
00305
00306
00307
00308
00309 PRThreadPriority ThreadNSPR::vprThreadPriorityToNSPR(const VPRThreadPriority priority)
00310 {
00311 PRThreadPriority nspr_prio;
00312
00313 switch ( priority )
00314 {
00315 case VPR_PRIORITY_LOW:
00316 nspr_prio = PR_PRIORITY_LOW;
00317 break;
00318 case VPR_PRIORITY_NORMAL:
00319 nspr_prio = PR_PRIORITY_NORMAL;
00320 break;
00321 case VPR_PRIORITY_HIGH:
00322 nspr_prio = PR_PRIORITY_HIGH;
00323 break;
00324 case VPR_PRIORITY_URGENT:
00325 nspr_prio = PR_PRIORITY_URGENT;
00326 break;
00327 };
00328
00329 return nspr_prio;
00330 }
00331
00332 PRThreadScope ThreadNSPR::vprThreadScopeToNSPR(const VPRThreadScope scope)
00333 {
00334 PRThreadScope nspr_scope;
00335
00336 switch ( scope )
00337 {
00338 case VPR_LOCAL_THREAD:
00339 nspr_scope = PR_LOCAL_THREAD;
00340 break;
00341 case VPR_GLOBAL_THREAD:
00342 nspr_scope = PR_GLOBAL_THREAD;
00343 break;
00344 };
00345
00346 return nspr_scope;
00347 }
00348
00349 PRThreadState ThreadNSPR::vprThreadStateToNSPR(const VPRThreadState state)
00350 {
00351 PRThreadState nspr_state;
00352
00353 switch ( state )
00354 {
00355 case VPR_JOINABLE_THREAD:
00356 nspr_state = PR_JOINABLE_THREAD;
00357 break;
00358 case VPR_UNJOINABLE_THREAD:
00359 nspr_state = PR_UNJOINABLE_THREAD;
00360 break;
00361 };
00362
00363 return nspr_state;
00364 }
00365
00366 BaseThread::VPRThreadPriority ThreadNSPR::nsprThreadPriorityToVPR(const PRThreadPriority priority)
00367 {
00368 VPRThreadPriority vpr_prio;
00369
00370 switch ( priority )
00371 {
00372 case PR_PRIORITY_LOW:
00373 vpr_prio = VPR_PRIORITY_LOW;
00374 break;
00375 case PR_PRIORITY_NORMAL:
00376 vpr_prio = VPR_PRIORITY_NORMAL;
00377 break;
00378 case PR_PRIORITY_HIGH:
00379 vpr_prio = VPR_PRIORITY_HIGH;
00380 break;
00381 case PR_PRIORITY_URGENT:
00382 vpr_prio = VPR_PRIORITY_URGENT;
00383 break;
00384 };
00385
00386 return vpr_prio;
00387 }
00388
00389 BaseThread::VPRThreadScope ThreadNSPR::nsprThreadScopeToVPR(const PRThreadScope scope)
00390 {
00391 VPRThreadScope vpr_scope;
00392
00393 switch ( scope )
00394 {
00395 case PR_LOCAL_THREAD:
00396 vpr_scope = VPR_LOCAL_THREAD;
00397 break;
00398 case PR_GLOBAL_THREAD:
00399 case PR_GLOBAL_BOUND_THREAD:
00400 vpr_scope = VPR_GLOBAL_THREAD;
00401 break;
00402 };
00403
00404 return vpr_scope;
00405 }
00406
00407 BaseThread::VPRThreadState ThreadNSPR::nsprThreadStateToVPR(const PRThreadState state)
00408 {
00409 VPRThreadState vpr_state;
00410
00411 switch ( state )
00412 {
00413 case PR_JOINABLE_THREAD:
00414 vpr_state = VPR_JOINABLE_THREAD;
00415 break;
00416 case PR_UNJOINABLE_THREAD:
00417 vpr_state = VPR_UNJOINABLE_THREAD;
00418 break;
00419 };
00420
00421 return vpr_state;
00422 }
00423
00424 }