📄 tlibvx.cxx
字号:
/*
* tlibvx.cxx
*
* Thread library implementation for VxWorks
*
* Portable Windows Library
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: tlibvx.cxx,v $
* Revision 1.1 2006/06/29 04:18:41 joegenbaclor
* *** empty log message ***
*
* Revision 1.4 2004/07/11 07:56:36 csoutheren
* Applied jumbo VxWorks patch, thanks to Eize Slange
*
*
* Revision 1.3 2003/05/21 00:49:16 csoutheren
* Added PreShutdown to ~PProcess
*
* Revision 1.2 2003/02/26 01:14:27 robertj
* Fixed race condition where thread can terminatebefore an IsSuspeded() call
* occurs and cause an assert, thanks Sebastian Meyer
*
* Revision 1.1 2002/11/05 01:43:39 robertj
* Added missing VxWorks files. Thanks Andreas Sikkema
*
* Revision 1.0 ?????????????
*/
class PProcess;
class PSemaphore;
#include <ptlib.h>
#include <ptlib/socket.h>
#include <trclib.h>
#include <usrlib.h>
// Forward to undocumented system call
extern "C" void dbgPrintCall(INSTR * callAdrs, int funcAdrs, int nargs,
UINT32 * pArgs);
#define VX_LOWEST_PRIORITY 250
#define VX_LOW_PRIORITY 200
#define VX_NORMAL_PRIORITY 150
#define VX_DISPLAY_PRIORITY 100
#define VX_URGENT_DISPLAY_PRIORITY 50
///////////////////////////////////////////////////////////////////////////////
// Critical Section Implementation
// -------------------------------
class CCriticalSection {
public:
CCriticalSection();
~CCriticalSection();
void Lock();
void Unlock();
private:
int intLevel;
STATUS taskLocked;
bool locked;
};
CCriticalSection::CCriticalSection()
{
intLevel = 0;
taskLocked = ERROR;
locked = false;
}
CCriticalSection::~CCriticalSection()
{
// Unlock anyway when someone forgot to call Unlock after Lock
if (locked == true)
Unlock();
}
void CCriticalSection::Lock()
{
if (locked == false) {
if (::intContext() == FALSE)
taskLocked = ::taskLock();
else
taskLocked = ERROR;
intLevel = ::intLock();
locked = true;
}
}
void CCriticalSection::Unlock()
{
if (locked == true) {
::intUnlock(intLevel);
if (taskLocked == OK)
::taskUnlock();
locked = false;
}
}
///////////////////////////////////////////////////////////////////////////////
// Threads
static int const priorities[] = {
VX_LOWEST_PRIORITY,
VX_LOW_PRIORITY,
VX_NORMAL_PRIORITY,
VX_DISPLAY_PRIORITY,
VX_URGENT_DISPLAY_PRIORITY
};
int PThread::ThreadFunction(void *threadPtr)
{
PAssertNULL(threadPtr);
PThread * thread = (PThread *)threadPtr;
PProcess & process = PProcess::Current();
process.activeThreadMutex.Wait();
process.activeThreads.SetAt(thread->PX_threadId, thread);
process.activeThreadMutex.Signal();
process.SignalTimerChange();
if (::semTake(thread->syncPoint, WAIT_FOREVER) == OK) {
if (::semDelete(thread->syncPoint) == OK)
thread->syncPoint = NULL;
thread->Main();
}
else
printf("::ThreadFunction> ::semTake failed, errno=0x%X\n",errno);
// And delete from administration
process.activeThreadMutex.Wait();
process.activeThreads.SetAt(thread->PX_threadId, NULL);
process.activeThreadMutex.Signal();
thread->PX_threadId = 0;
return 0;
}
void PThread::Trace(PThreadIdentifer threadId)
{
if (threadId == 0)
threadId = PThread::GetCurrentThreadId();
printf("Task name=%s\n", ::taskName(threadId));
::taskRegsShow(threadId);
REG_SET regSet;
if (::taskRegsGet(threadId, ®Set) != ERROR)
::trcStack(®Set, (FUNCPTR)dbgPrintCall, threadId);
else
printf("::Terminate> ::taskRegsGet failed, errno=0x%X\n", errno);
::taskShow(0, 2);
printf("\n");
::checkStack(0);
}
PThread::PThread()
: PX_threadId(ERROR),
priority(VX_NORMAL_PRIORITY),
originalStackSize(0)
{
}
PThread::PThread(PINDEX stackSize,
AutoDeleteFlag deletion,
Priority priorityLevel,
const PString & name
)
{
PAssert(stackSize > 0, PInvalidParameter);
autoDelete = (deletion == AutoDeleteThread);
originalStackSize = stackSize;
priority = priorities[priorityLevel];
syncPoint = ::semMCreate(SEM_Q_FIFO);
if (syncPoint != NULL) {
if (::semTake(syncPoint, NO_WAIT) == OK) {
STATUS taskLocked;
taskLocked = ::taskLock();
PX_threadId = ::taskSpawn(name, // Name
priority, // Priority
0, // options
stackSize, // stacksize
(FUNCPTR)ThreadFunction, // entrypoint
(int)this,0,0,0,0,0,0,0,0,0); // arg 1 --- arg 10
if (PX_threadId != ERROR) {
// threads are created suspended
Suspend();
::semGive(syncPoint);
if (taskLocked == OK)
::taskUnlock();
if (autoDelete) {
PProcess & process = PProcess::Current();
process.deleteThreadMutex.Wait();
process.autoDeleteThreads.Append(this);
process.deleteThreadMutex.Signal();
}
}
else {
if (taskLocked == OK)
::taskUnlock();
printf("::PThread> ::taskSpawn failed, errno=0x%X\n", errno);
PX_threadId = 0;
::semDelete(syncPoint);
syncPoint = NULL;
}
}
else {
printf("::PThread> ::semTake failed, errno=0x%X\n", errno);
::semDelete(syncPoint);
syncPoint = NULL;
}
}
}
PThread::~PThread()
{
if (originalStackSize <= 0)
return;
if (!IsTerminated())
Terminate();
}
void PThread::Restart()
{
if (IsTerminated()) {
PX_threadId = ::taskSpawn(NULL, // Auto name tn
priority, // Priority
0, // options
originalStackSize, // stacksize
(FUNCPTR)ThreadFunction, // entrypoint
(int)this,0,0,0,0,0,0,0,0,0); // arg 1 --- arg 10
if (PX_threadId == ERROR) {
printf("::Restart> ::taskSpawn failed, errno=0x%X\n", errno);
PX_threadId = 0;
}
}
else
printf("::Restart> Cannot restart running thread\n");
}
void PThread::Terminate()
{
if (originalStackSize <= 0)
return;
if (!IsTerminated()) {
if (::taskDelete(PX_threadId) == ERROR)
printf("::Terminate> ::taskDelete failed, errno=0x%X\n", errno);
// And delete from administration
PProcess & process = PProcess::Current();
process.activeThreadMutex.Wait();
process.activeThreads.SetAt(PX_threadId, NULL);
process.activeThreadMutex.Signal();
PX_threadId = 0;
}
}
BOOL PThread::IsTerminated() const
{
STATUS stat = ERROR;
if (PX_threadId != 0)
stat = ::taskIdVerify(PX_threadId);
return stat == ERROR;
}
void PThread::WaitForTermination() const
{
while (!IsTerminated()) {
Current()->Sleep(100);
}
}
BOOL PThread::WaitForTermination(const PTimeInterval & maxWait) const
{
if (PX_threadId == 0)
return TRUE;
PTimer timeout = maxWait;
while (!IsTerminated()) {
if (timeout == 0)
return FALSE;
Current()->Sleep(100);
}
return TRUE;
}
void PThread::Suspend(BOOL susp)
{
if (!IsTerminated()) {
if (susp) {
if (::taskSuspend(PX_threadId) == ERROR)
printf("::Suspend> Thread doesn't want to suspend, errno=0x%X\n", errno);
}
else {
if (::taskResume(PX_threadId) == ERROR)
printf("::Suspend> Thread doesn't want to resume, errno=0x%X\n", errno);
}
}
else
printf("::Suspend> Operation on terminated thread\n");
}
void PThread::Resume()
{
if (!IsTerminated()) {
if (::taskResume(PX_threadId) == ERROR)
printf("::Resume> Thread doesn't want to resume, errno=0x%X\n", errno);
}
else
printf("::Resume> Operation on terminated thread\n");
}
BOOL PThread::IsSuspended() const
{
BOOL isSuspended = FALSE;
if (!IsTerminated())
isSuspended = ::taskIsSuspended(PX_threadId);
else
printf("::IsSuspended> Operation on terminated thread\n");
return isSuspended;
}
void PThread::SetAutoDelete(AutoDeleteFlag deletion)
{
PAssert(deletion != AutoDeleteThread || this != &PProcess::Current(), PLogicError);
autoDelete = deletion == AutoDeleteThread;
}
void PThread::SetPriority(Priority priorityLevel)
{
if (!IsTerminated()) {
priority = priorities[priorityLevel];
if (::taskPrioritySet(PX_threadId, priority ) == ERROR)
printf("::SetPriority> ::taskPrioritySet failed, errno: 0x%X\n", errno);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -