📄 mboxt2.inl
字号:
// Set the timer
self->set_timer( abs_timeout, Cyg_Thread::TIMEOUT );
// If the timeout is in the past, the wake reason will have been set to
// something other than NONE already. If so, skip the wait and go
// straight to unlock.
if( Cyg_Thread::NONE == self->get_wake_reason() ) {
self->set_wait_info( (CYG_ADDRWORD)&ritem );
self->sleep();
get_threadq.enqueue( self );
CYG_INSTRUMENT_MBOXT(WAIT, this, count);
}
// Unlock scheduler and allow other threads to run
Cyg_Scheduler::unlock_reschedule();
// clear the timer; if it actually fired, no worries.
self->clear_timer();
CYG_ASSERTCLASS( this, "Bad this pointer");
cyg_bool result = true;
switch( self->get_wake_reason() )
{
case Cyg_Thread::TIMEOUT:
result = false;
CYG_INSTRUMENT_MBOXT(TIMEOUT, this, count);
break;
case Cyg_Thread::DESTRUCT:
case Cyg_Thread::BREAK:
result = false;
break;
case Cyg_Thread::EXIT:
self->exit();
break;
default:
break;
}
CYG_REPORT_RETVAL( result );
return result;
}
#endif // CYGFUN_KERNEL_THREADS_TIMER
// -------------------------------------------------------------------------
// Try to get an item and return success.
template <class T, cyg_count32 QUEUE_SIZE>
CYG_MBOXT_INLINE cyg_bool
Cyg_Mboxt2<T,QUEUE_SIZE>::tryget( T &ritem )
{
CYG_REPORT_FUNCTION();
CYG_ASSERTCLASS( this, "Bad this pointer");
// Prevent preemption
Cyg_Scheduler::lock();
CYG_INSTRUMENT_MBOXT(TRY, this, count);
cyg_bool result = ( 0 < count );
// If the mboxt2 is not empty, grab an item and return it.
if ( result ) {
ritem = itemqueue[ (count--, base++) ];
CYG_ASSERT( 0 <= count, "Count went -ve" );
CYG_ASSERT( size >= base, "Base overflow" );
if ( size <= base )
base = 0;
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
wakeup_putter();
#endif
}
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
CYG_REPORT_RETVAL( result );
return result;
}
// -------------------------------------------------------------------------
// get next item without removing it
template <class T, cyg_count32 QUEUE_SIZE>
CYG_MBOXT_INLINE cyg_bool
Cyg_Mboxt2<T,QUEUE_SIZE>::peek_item( T &ritem )
{
CYG_REPORT_FUNCTION();
CYG_ASSERTCLASS( this, "Bad this pointer");
// Prevent preemption
Cyg_Scheduler::lock();
CYG_INSTRUMENT_MBOXT(TRY, this, count);
cyg_bool result = ( 0 < count );
// If the mboxt2 is not empty, grab an item and return it.
if ( result )
ritem = itemqueue[ base ];
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
CYG_REPORT_RETVAL( result );
return result;
}
// -------------------------------------------------------------------------
// Put an item in the queue; wait if full.
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
template <class T, cyg_count32 QUEUE_SIZE>
CYG_MBOXT_INLINE cyg_bool
Cyg_Mboxt2<T,QUEUE_SIZE>::put( const T item )
{
CYG_REPORT_FUNCTION();
Cyg_Thread *self = Cyg_Thread::self();
// Prevent preemption
Cyg_Scheduler::lock();
CYG_INSTRUMENT_MBOXT(PUT, this, count);
CYG_ASSERTCLASS( this, "Bad this pointer");
if ( size == count ) {
CYG_ASSERT( get_threadq.empty(), "Threads waiting AND queue full?" );
self->set_wait_info( (CYG_ADDRWORD)&item );
self->set_sleep_reason( Cyg_Thread::WAIT );
self->sleep();
put_threadq.enqueue( self );
CYG_INSTRUMENT_MBOXT(WAIT, this, count);
// when this returns, our item is in the queue.
Cyg_Scheduler::unlock_reschedule(); // unlock, switch threads
CYG_ASSERTCLASS( this, "Bad this pointer");
cyg_bool result = true;
switch( self->get_wake_reason() )
{
case Cyg_Thread::DESTRUCT:
case Cyg_Thread::BREAK:
result = false;
break;
case Cyg_Thread::EXIT:
self->exit();
break;
default:
break;
}
CYG_REPORT_RETVAL( result );
return result;
}
if ( !get_threadq.empty() ) {
wakeup_winner( item );
Cyg_Scheduler::unlock(); // unlock, maybe switch threads
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_REPORT_RETVAL( true );
return true;
}
cyg_count32 in = base + (count++);
if ( size <= in )
in -= size;
CYG_ASSERT( size > in, "in overflow" );
CYG_ASSERT( 0 <= in, "in overflow" );
CYG_ASSERT( size >= count, "count overflow" );
itemqueue[ in ] = item;
CYG_ASSERTCLASS( this, "Bad this pointer");
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
CYG_REPORT_RETVAL( true );
return true;
}
// -------------------------------------------------------------------------
// Put an item in the queue; wait if full, with an absolute timeout;
// return success.
#ifdef CYGFUN_KERNEL_THREADS_TIMER
template <class T, cyg_count32 QUEUE_SIZE>
CYG_MBOXT_INLINE cyg_bool
Cyg_Mboxt2<T,QUEUE_SIZE>::put( const T item, cyg_tick_count abs_timeout )
{
CYG_REPORT_FUNCTION();
Cyg_Thread *self = Cyg_Thread::self();
// Prevent preemption
Cyg_Scheduler::lock();
CYG_INSTRUMENT_MBOXT(PUT, this, count);
CYG_ASSERTCLASS( this, "Bad this pointer");
if ( size == count ) {
CYG_ASSERT( get_threadq.empty(), "Threads waiting AND queue full?" );
// Set the timer
self->set_timer( abs_timeout, Cyg_Thread::TIMEOUT );
// If the timeout is in the past, the wake reason will have been set to
// something other than NONE already. If so, skip the wait and go
// straight to unlock.
if( Cyg_Thread::NONE == self->get_wake_reason() ) {
self->set_wait_info( (CYG_ADDRWORD)&item );
self->sleep();
put_threadq.enqueue( self );
CYG_INSTRUMENT_MBOXT(WAIT, this, count);
}
// when this returns, our item is in the queue.
Cyg_Scheduler::unlock_reschedule(); // unlock, switch threads
// clear the timer; if it actually fired, no worries.
self->clear_timer();
cyg_bool result = true;
switch( self->get_wake_reason() )
{
case Cyg_Thread::TIMEOUT:
result = false;
CYG_INSTRUMENT_MBOXT(TIMEOUT, this, count);
break;
case Cyg_Thread::DESTRUCT:
case Cyg_Thread::BREAK:
result = false;
break;
case Cyg_Thread::EXIT:
self->exit();
break;
default:
break;
}
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_REPORT_RETVAL( result );
return result;
}
if ( !get_threadq.empty() ) {
wakeup_winner( item );
Cyg_Scheduler::unlock(); // unlock, maybe switch threads
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_REPORT_RETVAL( true );
return true;
}
cyg_count32 in = base + (count++);
if ( size <= in )
in -= size;
CYG_ASSERT( size > in, "in overflow" );
CYG_ASSERT( 0 <= in, "in overflow" );
CYG_ASSERT( size >= count, "count overflow" );
itemqueue[ in ] = item;
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
CYG_ASSERTCLASS( this, "Bad this pointer");
CYG_REPORT_RETVAL( true );
return true;
}
#endif // CYGFUN_KERNEL_THREADS_TIMER
#endif // CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
// -------------------------------------------------------------------------
// Try to put an item in the queue and return success; queue may be full.
template <class T, cyg_count32 QUEUE_SIZE>
CYG_MBOXT_INLINE cyg_bool
Cyg_Mboxt2<T,QUEUE_SIZE>::tryput( const T item )
{
CYG_REPORT_FUNCTION();
// Prevent preemption
Cyg_Scheduler::lock();
CYG_INSTRUMENT_MBOXT(PUT, this, count);
CYG_ASSERTCLASS( this, "Bad this pointer");
if ( size == count ) {
CYG_ASSERT( get_threadq.empty(), "Threads waiting AND queue full?" );
Cyg_Scheduler::unlock(); // unlock, maybe switch threads
CYG_REPORT_RETVAL( false );
return false; // the mboxt2 is full
}
if ( !get_threadq.empty() ) {
CYG_ASSERT( 0 == count, "Threads waiting AND queue not empty" );
wakeup_winner( item );
Cyg_Scheduler::unlock(); // unlock, maybe switch threads
CYG_REPORT_RETVAL( true );
return true;
}
cyg_count32 in = base + (count++);
if ( size <= in )
in -= size;
CYG_ASSERT( size > in, "in overflow" );
CYG_ASSERT( 0 <= in, "in overflow" );
CYG_ASSERT( size >= count, "count overflow" );
itemqueue[ in ] = item;
CYG_ASSERTCLASS( this, "Bad this pointer");
// Unlock the scheduler and maybe switch threads
Cyg_Scheduler::unlock();
CYG_REPORT_RETVAL( true );
return true;
}
// -------------------------------------------------------------------------
#endif // ifndef CYGONCE_KERNEL_MBOXT2_INL
// EOF mboxt2.inl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -