4 * Thread library implementation for VxWorks
13 #define VX_LOWEST_PRIORITY 250
14 #define VX_LOW_PRIORITY 200
15 #define VX_NORMAL_PRIORITY 150
16 #define VX_DISPLAY_PRIORITY 100
17 #define VX_URGENT_DISPLAY_PRIORITY 50
19 ///////////////////////////////////////////////////////////////////////////////
21 static int const priorities
[] = {
26 VX_URGENT_DISPLAY_PRIORITY
29 int PThread::ThreadFunction(void *threadPtr
)
31 PAssertNULL(threadPtr
);
33 PThread
* thread
= (PThread
*)threadPtr
;
35 PProcess
& process
= PProcess::Current();
36 process
.activeThreadMutex
.Wait();
37 process
.activeThreads
.SetAt(thread
->PX_threadId
, thread
);
38 process
.activeThreadMutex
.Signal();
40 process
.SignalTimerChange();
50 priority(VX_NORMAL_PRIORITY
),
55 PThread::PThread(PINDEX stackSize
,
56 AutoDeleteFlag deletion
,
57 Priority priorityLevel
,
61 PAssert(stackSize
> 0, PInvalidParameter
);
62 autoDelete
= deletion
== AutoDeleteThread
;
63 originalStackSize
= stackSize
;
65 priority
= priorities
[priorityLevel
];
67 PX_threadId
= ::taskSpawn(
71 stackSize
, // stacksize
72 (FUNCPTR
)ThreadFunction
, // entrypoint
73 (int)this,0,0,0,0,0,0,0,0,0); // arg 1 --- arg 10
76 PAssertOS(PX_threadId
!= ERROR
);
77 // threads are created suspended
80 PProcess
& process
= PProcess::Current();
81 process
.deleteThreadMutex
.Wait();
82 process
.autoDeleteThreads
.Append(this);
83 process
.deleteThreadMutex
.Signal();
90 if (originalStackSize
<= 0)
93 PProcess
& process
= PProcess::Current();
94 process
.activeThreadMutex
.Wait();
95 process
.activeThreads
.SetAt(PX_threadId
, NULL
);
96 process
.activeThreadMutex
.Signal();
103 void PThread::Restart()
105 char *name
= ::taskName(PX_threadId
);
106 PAssert(IsTerminated(), "Cannot restart running thread");
108 PX_threadId
= ::taskSpawn(
110 priority
, // Priority
112 originalStackSize
, // stacksize
113 (FUNCPTR
)ThreadFunction
, // entrypoint
114 (int)this,0,0,0,0,0,0,0,0,0); // arg 1 --- arg 10
116 PAssertOS(PX_threadId
!= ERROR
);
120 void PThread::Terminate()
122 PAssert(!IsTerminated(), "Cannot terminate a thread which is already terminated");
123 PAssert(originalStackSize
> 0, PLogicError
);
125 ::taskDelete(PX_threadId
);
129 BOOL
PThread::IsTerminated() const
131 STATUS stat
= taskIdVerify(PX_threadId
);
132 return stat
== ERROR
;
136 void PThread::WaitForTermination() const
138 while (!IsTerminated()) {
139 Current()->Sleep(100);
144 BOOL
PThread::WaitForTermination(const PTimeInterval
& maxWait
) const
146 if (PX_threadId
== 0)
149 PTimer timeout
= maxWait
;
150 while (!IsTerminated()) {
154 Current()->Sleep(100);
160 void PThread::Suspend(BOOL susp
)
162 PAssert(!IsTerminated(), "Operation on terminated thread");
165 STATUS result
= ::taskSuspend(PX_threadId
);
167 PAssert(result
!= ERROR
, "Thread don't want to be suspended");
175 void PThread::Resume()
177 PAssert(!IsTerminated(), "Operation on terminated thread");
178 if (!IsTerminated()) {
179 STATUS result
= ::taskResume(PX_threadId
);
180 PAssert(result
!= ERROR
, "Thread doesn't want to resume");
185 BOOL
PThread::IsSuspended() const
187 struct TASK_DESC info
;
188 STATUS result
= ::taskInfoGet(PX_threadId
, &info
);
190 PAssert(result
!= ERROR
|| PX_threadId
!= info
.td_id
, "Thread info inaccessible");
191 return taskIsSuspended(PX_threadId
);
194 void PThread::SetAutoDelete(AutoDeleteFlag deletion
)
196 PAssert(deletion
!= AutoDeleteThread
|| this != &PProcess::Current(), PLogicError
);
197 autoDelete
= deletion
== AutoDeleteThread
;
200 void PThread::SetPriority(Priority priorityLevel
)
202 PAssert(!IsTerminated(), "Operation on terminated thread");
204 priority
= priorities
[priorityLevel
];
205 STATUS result
= ::taskPrioritySet(PX_threadId
, priority
);
207 PAssert(result
!= ERROR
, "Thread priority change error");
211 PThread::Priority
PThread::GetPriority() const
213 PAssert(!IsTerminated(), "Operation on terminated thread");
216 taskPriorityGet(PX_threadId
, &prio
);
219 case VX_LOWEST_PRIORITY
:
220 return LowestPriority
;
221 case VX_LOW_PRIORITY
:
223 case VX_NORMAL_PRIORITY
:
224 return NormalPriority
;
225 case VX_DISPLAY_PRIORITY
:
227 case VX_URGENT_DISPLAY_PRIORITY
:
228 return HighestPriority
;
230 PAssertAlways(POperatingSystemError
);
231 return LowestPriority
;
234 void PThread::Yield()
239 void PThread::Sleep( const PTimeInterval
& delay
) // Time interval to sleep for in microsec.
241 taskDelay(delay
.GetInterval()*sysClkRateGet()/1000);
244 void PThread::InitialiseProcessThread()
246 originalStackSize
= 0;
249 PX_threadId
= ::taskIdSelf();
250 PAssertOS(PX_threadId
>= OK
);
252 ((PProcess
*)this)->activeThreads
.DisallowDeleteObjects();
253 ((PProcess
*)this)->activeThreads
.SetAt(PX_threadId
, this);
257 PThread
* PThread::Current()
259 PProcess
& process
= PProcess::Current();
260 process
.activeThreadMutex
.Wait();
262 PThread
* thread
= process
.activeThreads
.GetAt( taskIdSelf() );
264 process
.activeThreadMutex
.Signal();
268 int PThread::PXBlockOnChildTerminate(int pid
, const PTimeInterval
& /*timeout*/) // Fix timeout
271 while (!IsTerminated()) {
272 Current()->Sleep(100);
277 int PThread::PXBlockOnIO(int handle
, int type
, const PTimeInterval
& timeout
)
280 // make sure we flush the buffer before doing a write
281 fd_set tmp_rfd
, tmp_wfd
, tmp_efd
;
282 fd_set
* read_fds
= &tmp_rfd
;
283 fd_set
* write_fds
= &tmp_wfd
;
284 fd_set
* exception_fds
= &tmp_efd
;
288 FD_ZERO (exception_fds
);
291 case PChannel::PXReadBlock
:
292 case PChannel::PXAcceptBlock
:
293 FD_SET (handle
, read_fds
);
295 case PChannel::PXWriteBlock
:
296 FD_SET (handle
, write_fds
);
298 case PChannel::PXConnectBlock
:
299 FD_SET (handle
, write_fds
);
300 FD_SET (handle
, exception_fds
);
303 PAssertAlways(PLogicError
);
307 struct timeval
* tptr
= NULL
;
308 struct timeval timeout_val
;
309 if (timeout
!= PMaxTimeInterval
) { // Clean up for infinite timeout
310 static const PTimeInterval
oneDay(0, 0, 0, 0, 1);
312 if (timeout
< oneDay
) {
314 timeout_val
.tv_usec
= (timeout
.GetMilliSeconds() % 1000) * 1000;
315 timeout_val
.tv_sec
= timeout
.GetSeconds();
319 int retval
= ::select(handle
+1, read_fds
, write_fds
, exception_fds
, tptr
);
324 int PThread::PXBlockOnIO(int maxHandles
,
327 fd_set
* exceptionBits
,
328 const PTimeInterval
& timeout
,
329 const PIntArray
& /*osHandles*/)
331 // make sure we flush the buffer before doing a write
332 fd_set
* read_fds
= readBits
;
333 fd_set
* write_fds
= writeBits
;
334 fd_set
* exception_fds
= exceptionBits
;
336 struct timeval
* tptr
= NULL
;
337 struct timeval timeout_val
;
338 if (timeout
!= PMaxTimeInterval
) { // Clean up for infinite timeout
339 static const PTimeInterval
oneDay(0, 0, 0, 0, 1);
340 if (timeout
< oneDay
) {
341 timeout_val
.tv_usec
= (timeout
.GetMilliSeconds() % 1000) * 1000;
342 timeout_val
.tv_sec
= timeout
.GetSeconds();
346 int retval
= ::select(maxHandles
, read_fds
, write_fds
, exception_fds
, tptr
);
351 void PThread::PXAbortBlock() const
355 ///////////////////////////////////////////////////////////////////////////////
356 // PProcess::HouseKeepingThread
358 void PProcess::Construct()
360 // hard coded value, change this to handle more sockets at once with the select call
366 PProcess::HouseKeepingThread::HouseKeepingThread()
367 : PThread(5000, NoAutoDeleteThread
, LowPriority
)
372 void PProcess::HouseKeepingThread::Main()
374 PProcess
& process
= PProcess::Current();
377 process
.deleteThreadMutex
.Wait();
378 for (PINDEX i
= 0; i
< process
.autoDeleteThreads
.GetSize(); i
++)
380 PThread
* pThread
= (PThread
*) process
.autoDeleteThreads
.GetAt(i
);
381 if( pThread
->IsTerminated() )
383 process
.autoDeleteThreads
.RemoveAt(i
--);
386 process
.deleteThreadMutex
.Signal();
387 PTimeInterval nextTimer
= process
.timers
.Process();
388 if (nextTimer
!= PMaxTimeInterval
)
390 if ( nextTimer
.GetInterval() > 10000 )
395 breakBlock
.Wait( nextTimer
);
399 void PProcess::SignalTimerChange()
401 if (houseKeeper
== NULL
)
402 houseKeeper
= new HouseKeepingThread
;
404 houseKeeper
->breakBlock
.Signal();
408 ///////////////////////////////////////////////////////////////////////////////
411 PProcess::~PProcess()
413 Sleep(100); // Give threads time to die a natural death
417 // OK, if there are any left we get really insistent...
418 activeThreadMutex
.Wait();
419 for (PINDEX i
= 0; i
< activeThreads
.GetSize(); i
++) {
420 PThread
& thread
= activeThreads
.GetDataAt(i
);
421 if (this != &thread
&& !thread
.IsTerminated())
422 thread
.Terminate(); // With extreme prejudice
424 activeThreadMutex
.Signal();
426 deleteThreadMutex
.Wait();
427 autoDeleteThreads
.RemoveAll();
428 deleteThreadMutex
.Signal();
433 ///////////////////////////////////////////////////////////////////////////////
436 PSemaphore::PSemaphore(SEM_ID anId
)
439 PAssertOS(semId
!= 0);
442 PSemaphore::PSemaphore(unsigned initial
, unsigned maxCount
)
444 semId
= semCCreate(SEM_Q_FIFO
, initial
);
445 PAssertOS(semId
!= NULL
);
448 PSemaphore::~PSemaphore()
456 void PSemaphore::Wait()
458 STATUS result
= semTake(semId
, WAIT_FOREVER
);
459 PAssertOS(result
!= ERROR
);
463 BOOL
PSemaphore::Wait(const PTimeInterval
& timeout
)
466 if (timeout
== PMaxTimeInterval
) {
470 int ticks
= sysClkRateGet();
471 wait
= (timeout
.GetInterval() * ticks
);
475 STATUS result
= semTake(semId
, wait
);
477 return result
== ERROR
;
480 void PSemaphore::Signal()
485 BOOL
PSemaphore::WillBlock() const
487 STATUS result
= semTake(semId
, WAIT_FOREVER
);
488 PAssertOS(result
!= ERROR
);
489 return result
== ERROR
;
492 ///////////////////////////////////////////////////////////////////////////////
495 : PSemaphore( ::semMCreate(SEM_Q_FIFO
) )
501 PAssertOS(::semDelete(semId
) == 0);
506 STATUS result
= semTake(semId
, WAIT_FOREVER
); // wait forever
507 PAssertOS(result
== OK
);
510 BOOL
PMutex::Wait(const PTimeInterval
& timeout
)
513 if (timeout
== PMaxTimeInterval
) {
517 int ticks
= sysClkRateGet();
518 wait
= (timeout
.GetMilliSeconds() * ticks
);
521 STATUS result
= semTake(semId
, wait
);
522 return result
== ERROR
;
525 void PMutex::Signal()
530 BOOL
PMutex::WillBlock() const
532 STATUS result
= semTake(semId
, WAIT_FOREVER
); // wait forever
533 PAssertOS(result
== OK
);
534 return result
== ERROR
;
537 ///////////////////////////////////////////////////////////////////////////////
540 PSyncPoint::PSyncPoint()
545 // End Of File ///////////////////////////////////////////////////////////////