📄 usersync.cpp
字号:
{
UserThread *pTheThread = tWaiting.SelectNextThread();
if ( !pTheThread )
{ break; };
pTheThread->MakeRunnable( this );
};
/* --- abort any blocks --- */
AbortBlocks( 0 );
/* --- clear other values --- */
ulData = 0;
#if DEBUG>=20
CERR << "User Thread end of Cleanup(): " << (void *)this << endl;
DbgWrite( CERR );
CERR << endl;
#endif
}
/*___________________________________________________________________________*\
*
Function:
Synopsis: virtual, public
Description:
\*___________________________________________________________________________*/
bool UserThread::SetPriority( int iThePriority )
{
if (!( iThePriority <= PITHREAD_PRIORITY_HIGHEST &&
iThePriority >= PITHREAD_PRIORITY_LOW ) )
{ return false; };
int iOldPriority = iPriority;
InternalSetPriority( iThePriority );
if ( ___pTheCurrentThread != this )
{
___pLatentThreads->ChangeThreadPriority( this, iOldPriority,
iPriority );
};
/* --- assume correct priorities --- */
StackContextSwitch();
return true;
}
/*___________________________________________________________________________*\
*
Function:
Synopsis: private
Description:
Return true if the priority was changed, else false.
\*___________________________________________________________________________*/
bool UserThread::InternalSetPriority( int iNewPriority )
{
if ( iNewPriority == iPriority )
{ return false; };
#if DEBUG>=20
CERR << (void *)this
<< "UserThread::InternalSetPriority(): changing priority from "
<< iPriority << " to " << iNewPriority << endl;
#endif
/* ---
Change the priority of this thread wherever else it is
recorded
--- */
if ( pThread )
{
pThread->tWaiting.ChangeThreadPriority( this, iPriority,
iNewPriority );
};
if ( pSemaphore )
{
pSemaphore->tWaiting.ChangeThreadPriority( this, iPriority,
iNewPriority );
};
iPriority = iNewPriority;
return true;
}
/*___________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*___________________________________________________________________________*/
bool UserThread::InternalTerminate( unsigned long ulTheStatus )
{
ulStatus = ulTheStatus;
assert( !bIsTerminated );
if ( ___pTheCurrentThread == this )
{
StackUnwind();
return true; /* this is never reached */
}
else
{
___pLatentThreads->RemoveThread( this );
___pExitingThread = this;
StackContextSwitch();
return true;
};
}
/*___________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*___________________________________________________________________________*/
int UserThread::PutToSleep( int iFD, int iFlags, int iTimeout )
{
pPoll = PI_NEW( PollInfo( iFD, iFlags, iTimeout ) );
___pThePoller->AddThread( this );
StackContextSwitch();
int iTmp = iNextReturnCode;
iNextReturnCode = 0;
return iTmp;
}
/*___________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*___________________________________________________________________________*/
void UserThread::MakeRunnable( int iThePollResult )
{
assert( pPoll );
___pThePoller->RemoveThread( this );
PI_DELETE( pPoll );
pPoll = 0;
iNextReturnCode = iThePollResult;
}
/*___________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*___________________________________________________________________________*/
void UserThread::AbortBlocks( int iWhy )
{
/* --- notify any objects that we are blocking on --- */
/* --- thread --- */
if ( pThread )
{ pThread->GaveUpWaiting( this ); };
pThread = 0;
/* --- mutex and semaphores --- */
if ( pSemaphore )
{ pSemaphore->GaveUpWaiting( this ); };
pSemaphore = 0;
/* --- sleep, file descriptor poll --- */
if ( pPoll )
{ MakeRunnable( iWhy ); };
/* --- suspension --- */
bSuspended = false;
iNextReturnCode = iWhy;
}
/*___________________________________________________________________________*\
*
Function:
Synopsis:
Description:
Get the register context block for a thread
\*___________________________________________________________________________*/
size_t *__Pi_GetThreadContext( void *pThread )
{
return ((UserThread *)pThread )->GetContext();
}
/*___________________________________________________________________________*\
*
Function:
Synopsis:
Description:
Add a thread into the pool of latent threads
\*___________________________________________________________________________*/
void __Pi_AddLatentThread( void *pThread )
{
___pLatentThreads->AddThread( (UserThread *)pThread );
}
/*___________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*___________________________________________________________________________*/
void __Pi_BeginThread( void *pThread )
{
UserThread *pNewThread = (UserThread *)pThread;
pNewThread->BeginThread();
}
/*___________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*___________________________________________________________________________*/
void __Pi_UnwindThreadStack( void *pThread )
{
((UserThread *)pThread)->StackUnwind();
}
/*___________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*___________________________________________________________________________*/
void *__Pi_SelectNextRunnableThread()
{
/* ---
Must get another thread or cause deadlock
--- */
return ___pLatentThreads->SelectNextRunnableThread( 1 );
}
/*___________________________________________________________________________*\
*
Function: StackContextSwitch()
Synopsis:
Description:
This is a very specical function. It swaps out the stack and so does
a 'return' into another thread
See Asm.cpp for an explaination.
Returns non-zero if the thread was changed. This is useful internally
for optimizing yield.
NOTE: That optimization is disable for this entire file because of
bad things that happen when ___pTheCurrent and ___pPlaceholer are
optimized into local variables with __Pi_StackContextSwitch() in the
middle.
\*___________________________________________________________________________*/
/* NOTE: temporary */
static UserThread *___pPlaceholder;
/* NOTE: end temporary */
int StackContextSwitch( void )
{
int iFlag;
UserThread *pNextThread = 0;
if ( ___pNewThread )
{
iFlag = SCHED_BEGIN;
pNextThread = ___pNewThread;
___pNewThread = 0;
}
else if ( ___pExitingThread )
{
iFlag = SCHED_EXIT;
pNextThread = ___pExitingThread;
___pExitingThread = 0;
}
else
{
iFlag = SCHED_NEXT;
#if 0
pNextThread = ___pLatentThreads->SelectNextRunnableThread( 0 );
if ( !pNextThread )
{
/* --- don't switch context --- */
return 0;
};
#endif
};
___pPlaceholder = ___pTheCurrentThread;
#if DEBUG>=15
CERR << "Before __Pi_StackContextSwitch()" << endl;
DbgWriteAllThreads( CERR );
#endif
__Pi_StackContextSwitch(
(void **)&( ___pTheCurrentThread ), /* address of thread pointer */
pNextThread,
iFlag ); /* action to take */
#if DEBUG>=15
CERR << "After __Pi_StackContextSwitch()" << endl;
DbgWriteAllThreads( CERR );
#endif
#if 0
return 1;
#else
return ___pPlaceholder==___pTheCurrentThread ? 0 : 1;
#endif
}
/*___________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*___________________________________________________________________________*/
void Internal_InitThreads()
{
if ( ___pLatentThreads )
assert( !___pLatentThreads );
if ( ___pLatentThreads )
{ return; /* already initialized */ };
memset( aUsedKeys, 0, sizeof( int ) * PI_MAXTHREADKEYS );
___pLatentThreads = PI_NEW( ThreadScheduler );
/* ---
create a structure for the current thread (the main thread)
and set the global thread pointer
--- */
___pTheMainThread = PI_NEW( UserThread(
Platform::GetGlobalAllocator(), 0 ) );
___pTheCurrentThread = ___pTheMainThread;
___pThePoller = PI_NEW( Poller );
assert( ___pThePoller );
}
/*___________________________________________________________________________*\
*
Function:
Synopsis:
Description:
This function assumes that the main thread is executing this function.
\*___________________________________________________________________________*/
void Internal_CleanupThreads()
{
assert( ___pLatentThreads );
if ( !___pLatentThreads )
{ return; /* never initialized */ };
PI_DELETE( ___pThePoller );
___pThePoller = 0;
/* --- this must be the main thread --- */
PIMUSTBETRUE( ___pTheMainThread == ___pTheCurrentThread );
while( ___pLatentThreads->Size() )
{ PI_DELETE( (UserThread *)___pLatentThreads->SelectNextThread() ); };
PI_DELETE( ___pLatentThreads );
___pLatentThreads = 0;
/* --- destroy the main thread object --- */
PI_DELETE( ___pTheMainThread );
___pTheMainThread = 0;
___pTheCurrentThread = 0;
}
/*___________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*___________________________________________________________________________*/
void Platform::Internal_EnterThreads( void (* fn)(void) )
{
/* ---
Initialize global values, even tough there are declared static and
so must be zero initialized on startup, the threads initialization
could happen multiple times, say because of hangup restart
--- */
___pLatentThreads = 0; /* global thread scheduler */
___pThePoller = 0; /* polls on sockets/files */
___pTheMainThread = 0; /* the main thread */
___pTheCurrentThread = 0; /* the current thread */
___pNewThread = 0; /* a newly created thread */
___pExitingThread = 0; /* an exiting thread */
iThreadsCreated = 0; /* since initialization */
Internal_InitThreads();
if ( fn )
{
___pTheMainThread->Begin( (ThreadFn)fn,
(unsigned long)0, PITHREAD_PRIORITY_MED, 0 );
};
Internal_CleanupThreads();
}
/*___________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*___________________________________________________________________________*/
Allocator *Platform::GetCurrentAllocator()
{
return Platform::GetGlobalAllocator();
}
/*___________________________________________________________________________*\
*
Function:
Synopsis: static, public:
Description:
\*___________________________________________________________________________*/
Semaphore *Platform::AllocLocalMutex()
{
return PI_NEW( UserLocalSemaphore( 1, 1) );
}
/*___________________________________________________________________________*\
*
Function:
Synopsis: static, public:
Description:
\*___________________________________________________________________________*/
Semaphore *Platform::AllocLocalSemaphore( int iInitialCount, int iMaxCount )
{
return PI_NEW( UserLocalSemaphore( iInitialCount, iMaxCount ) );
}
/*___________________________________________________________________________*\
*
Function:
Synopsis: static, public:
Description:
\*___________________________________________________________________________*/
Thread *Platform::AllocThread(
void *pV,
int iStackSize )
{
Allocator *pAllocator = (Allocator *)pV; /* LATER, for MSVC4.2 */
Thread *pNewThread = PI_NEW( UserThread(
pAllocator ? pAllocator : Platform::GetGlobalAllocator(),
iStackSize ? iStackSize : PI_DEFAULTSTACKSIZE ) );
return pNewThread;
}
/*___________________________________________________________________________*\
*
Function:
Synopsis: static, public:
Description:
\*___________________________________________________________________________*/
void Platform::YieldThread()
{
/*
** It would be good at some point to get a more sophisticated yield
** with a flag to indicate different flavours
**
**
** For Example
** -----------
** Add code to make this sleep( 0 ) to yield the process
** timeslice if no threads are available.......Done
**
*/
if ( !StackContextSwitch() )
{
/* ---
Thread was not switched out, yield process timeslice
--- */
#if defined(CONFIG_OS_POSIX)
# if !defined(CONFIG_NO_YIELD)
::yield();
# endif
#else
# if defined(CONFIG_OS_WIN32)
::Sleep( 0 );
# elif defined(CONFIG_OS_WIN16)
::Yield();
# endif
#endif
};
}
/*___________________________________________________________________________*\
*
Function:
Synopsis: static, public:
Description:
\*___________________________________________________________________________*/
int Platform::WaitForThread( Thread *pThread )
{
int iRet = ___pTheCurrentThread->WaitForThread( (UserThread *)pThread );
if ( iRet!=0 )
{ PIERROR(iRet); };
return iRet;
}
/*___________________________________________________________________________*\
*
Function:
Synopsis: static, public:
Description:
\*___________________________________________________________________________*/
Thread *Platform::GetCurrentThread()
{
return ___pTheCurrentThread;
}
/*___________________________________________________________________________*\
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -