⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thread.cxx

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 CXX
📖 第 1 页 / 共 3 页
字号:

    // Unlock the scheduler and switch threads
    Cyg_Scheduler::unlock();

    // and deal with anything we must do when we return
    switch( current->wake_reason ) {
    case DESTRUCT:
    case EXIT:            
        current->exit();
        break;
        
    default:
        break;
    }

    CYG_REPORT_RETURN();
}

// -------------------------------------------------------------------------
// Put the thread to sleep for a delay, with wakeup count.
// This can only be called by the current thread on itself, hence
// it is a static function.

#ifdef CYGFUN_KERNEL_THREADS_TIMER
void
Cyg_Thread::counted_sleep( cyg_tick_count delay )
{
    CYG_REPORT_FUNCTION();

    Cyg_Thread *current = Cyg_Scheduler::get_current_thread();

    CYG_ASSERTCLASS( current, "Bad current thread" );
    
    CYG_INSTRUMENT_THREAD(SLEEP,current,0);
    
    // Prevent preemption
    Cyg_Scheduler::lock();

    if ( 0 == current->wakeup_count ) {

        // Set the timer (once outside any waiting loop.)
        set_timer( Cyg_Clock::real_time_clock->current_value()+delay,
                         Cyg_Thread::TIMEOUT  );

        // If the timeout is in the past, the wake reason will have been
        // set to something other than NONE already.
    
        if( current->get_wake_reason() == Cyg_Thread::NONE )
        {
            set_sleep_reason( Cyg_Thread::TIMEOUT );
            current->sleep();               // prepare to sleep
            current->state |= COUNTSLEEP;   // Set the state

            Cyg_Scheduler::reschedule();
    
            // clear the timer; if it actually fired, no worries.
            clear_timer();
        }
    }
    else
        // there is a queued wakeup, do not sleep
        current->wakeup_count--;

    // Unlock the scheduler and switch threads
    Cyg_Scheduler::unlock();

    // and deal with anything we must do when we return
    switch( current->wake_reason ) {
    case DESTRUCT:
    case EXIT:            
        current->exit();
        break;
        
    default:
        break;
    }

    CYG_REPORT_RETURN();
}
#endif

// -------------------------------------------------------------------------
// Awaken the thread from sleep.

void
Cyg_Thread::counted_wake()
{
    CYG_REPORT_FUNCTION();

    CYG_INSTRUMENT_THREAD(WAKE,this,Cyg_Scheduler::current_thread);
    
    // Prevent preemption
    Cyg_Scheduler::lock();

    if ( 0 == (state & COUNTSLEEP) )    // already awake, or waiting:
        wakeup_count++;                 // not in a counted sleep anyway.
    else {
        sleep_reason = NONE;
        wake_reason = DONE;
        wake();                         // and awaken the thread
    }

#ifdef CYGNUM_KERNEL_MAX_COUNTED_WAKE_COUNT_ASSERT
    CYG_ASSERT( CYGNUM_KERNEL_MAX_COUNTED_WAKE_COUNT_ASSERT > wakeup_count,
                "wakeup_count overflow" );
#endif

    // Unlock the scheduler and maybe switch threads
    Cyg_Scheduler::unlock();

    CYG_REPORT_RETURN();
}

// -------------------------------------------------------------------------
// Cancel wakeups for this thread and return how many were pending
cyg_uint32
Cyg_Thread::cancel_counted_wake()
{
    CYG_REPORT_FUNCTION();

    CYG_INSTRUMENT_THREAD(WAKE,this,Cyg_Scheduler::current_thread);
    
    // Prevent preemption
    Cyg_Scheduler::lock();

    cyg_uint32 result = wakeup_count;
    wakeup_count = 0;

    // Unlock the scheduler
    Cyg_Scheduler::unlock();

    CYG_REPORT_RETVAL( result );
    return result;
}

// -------------------------------------------------------------------------
// Suspend thread. Increment suspend count and deschedule thread
// if still running.

void
Cyg_Thread::suspend()
{
    CYG_REPORT_FUNCTION();

    CYG_INSTRUMENT_THREAD(SUSPEND,this,Cyg_Scheduler::current_thread);
    
    // Prevent preemption
    Cyg_Scheduler::lock();

    suspend_count++;
    
#ifdef CYGNUM_KERNEL_MAX_SUSPEND_COUNT_ASSERT
    CYG_ASSERT( CYGNUM_KERNEL_MAX_SUSPEND_COUNT_ASSERT > suspend_count,
                "suspend_count overflow" );
#endif

    // If running, remove from run qs
    if( state == RUNNING )
        Cyg_Scheduler::scheduler.rem_thread(this);

    // Set the state
    state |= SUSPENDED;
    
    // Unlock the scheduler and maybe switch threads
    Cyg_Scheduler::unlock();

    CYG_REPORT_RETURN();
}

// -------------------------------------------------------------------------
// Resume thread. Decrement suspend count and reschedule if it
// is zero.

void
Cyg_Thread::resume()
{
    CYG_REPORT_FUNCTION();

    CYG_INSTRUMENT_THREAD(RESUME,this,Cyg_Scheduler::current_thread);
 
    // Prevent preemption
    Cyg_Scheduler::lock();

    // If we are about to zero the count, clear the state bit and
    // reschedule the thread if possible.
    
    if( suspend_count == 1 )
    {
        suspend_count = 0;

        CYG_ASSERT( (state & SUSPENDED) != 0, "SUSPENDED bit not set" );
        
        // Set the state
        state &= ~SUSPENDED;

        // Return thread to scheduler if runnable
        if( state == RUNNING )
            Cyg_Scheduler::scheduler.add_thread(this);
    }
    else
        if( suspend_count > 0 )
            suspend_count--;
    // else ignore attempt to resume

    // Unlock the scheduler and maybe switch threads
    Cyg_Scheduler::unlock();

    CYG_REPORT_RETURN();
}

// -------------------------------------------------------------------------
// Forced Resume thread.  Zero suspend count and reschedule...

void
Cyg_Thread::force_resume()
{
    CYG_REPORT_FUNCTION();

    CYG_INSTRUMENT_THREAD(RESUME,this,Cyg_Scheduler::current_thread);
            
    // Prevent preemption
    Cyg_Scheduler::lock();

    // If we are about to zero the count, clear the state bit and
    // reschedule the thread if possible.
    
    if ( 0 < suspend_count ) {
        suspend_count = 0;

        CYG_ASSERT( (state & SUSPENDED) != 0, "SUSPENDED bit not set" );
        
        // Set the state
        state &= ~SUSPENDED;

        // Return thread to scheduler if runnable
        if( state == RUNNING )
            Cyg_Scheduler::scheduler.add_thread(this);
    }

    // Unlock the scheduler and maybe switch threads
    Cyg_Scheduler::unlock();
    CYG_REPORT_RETURN();
}

// -------------------------------------------------------------------------
// Force thread to wake up from a sleep with a wake_reason of
// BREAK. It is the responsibility of the woken thread to detect
// the release() and do the right thing.

void
Cyg_Thread::release()
{
    CYG_REPORT_FUNCTION();
    // Prevent preemption
    Cyg_Scheduler::lock();

    // If the thread is in any of the sleep states, set the
    // wake reason and wake it up.

    switch( sleep_reason )
    {

    case NONE:
        // The thread is not sleeping for any reason, do nothing.
        // drop through...
        
    case DESTRUCT:
    case BREAK:
    case EXIT:
    case DONE:
        // Do nothing in any of these cases. They are here to
        // keep the compiler happy.
        
        Cyg_Scheduler::unlock();
        CYG_REPORT_RETURN();
        return;

    case WAIT:
        // The thread was waiting for some sync object to do
        // something.
        // drop through...
        
    case TIMEOUT:
        // The thread was waiting on a sync object with a timeout.
        // drop through...
        
    case DELAY:
        // The thread was simply delaying, unless it has been
        // woken up for some other reason, wake it now.
        sleep_reason = NONE;
        wake_reason = BREAK;
        break;
    }

    wake();
    
    // Allow preemption
    Cyg_Scheduler::unlock();

    CYG_REPORT_RETURN();
}

// -------------------------------------------------------------------------
// Exit thread. This puts the thread into EXITED state.

#ifdef CYGPKG_KERNEL_THREADS_DESTRUCTORS
#ifndef CYGSEM_KERNEL_THREADS_DESTRUCTORS_PER_THREAD
Cyg_Thread::Cyg_Destructor_Entry
Cyg_Thread::destructors[ CYGNUM_KERNEL_THREADS_DESTRUCTORS ];
#endif
#endif

void
Cyg_Thread::exit()
{
    CYG_REPORT_FUNCTION();
    
    // The thread should never return from this function.

    Cyg_Thread *self = Cyg_Thread::self();

#ifdef CYGPKG_KERNEL_THREADS_DESTRUCTORS
    cyg_ucount16 i;
    for (i=0; i<CYGNUM_KERNEL_THREADS_DESTRUCTORS; i++) {
        if (NULL != self->destructors[i].fn) {
            destructor_fn fn = self->destructors[i].fn;
            CYG_ADDRWORD data = self->destructors[i].data;
            fn(data);
        }        
    }
#endif
#ifdef CYGDBG_KERNEL_THREADS_STACK_MEASUREMENT_VERBOSE_EXIT
    diag_printf( "Stack usage for thread %08x: %d\n", self,
		 self->measure_stack_usage() );
#endif

    Cyg_Scheduler::lock();

    // clear the timer; if there was none, no worries.
    clear_timer();

    // It is possible that we have already been killed by another
    // thread, in which case we do not want to try and take ourself
    // out of the scheduler again.
    if( self->state != EXITED )
    {
        self->state = EXITED;

        Cyg_Scheduler::scheduler.rem_thread(self);
    }

    Cyg_Scheduler::reschedule();
}

// -------------------------------------------------------------------------
// Kill thread. Force the thread into EXITED state externally, or
// make it wake up and call exit().

void
Cyg_Thread::kill()
{
    CYG_REPORT_FUNCTION();
    // If this is called by the current thread on itself,
    // just call exit(), which is what he should have done
    // in the first place.
    if( this == Cyg_Scheduler::get_current_thread() )
        exit();

    // Prevent preemption
    Cyg_Scheduler::lock();

    // We are killing someone else. Find out what state he is
    // in and force him to wakeup and call exit().

    force_resume();                     // this is necessary for when
                                        // he is asleep AND suspended.
#ifdef CYGFUN_KERNEL_THREADS_TIMER
    timer.disable();                    // and make sure the timer
                                        // does not persist.
#endif

    if ( EXIT != wake_reason ) switch( sleep_reason ) {
        // Only do any of this if the thread is not in pending death already:

    case NONE:
        // The thread is not sleeping for any reason, it must be
        // on a run queue.
        // We can safely deschedule and set its state.
        if( state == RUNNING ) Cyg_Scheduler::scheduler.rem_thread(this);
        state = EXITED;
        break;
        
    case DESTRUCT:
    case BREAK:
    case EXIT:
    case DONE:
        // Do nothing in any of these cases. They are here to
        // keep the compiler happy.
        
        Cyg_Scheduler::unlock();
        CYG_REPORT_RETURN();
        return;

    case WAIT:
        // The thread was waiting for some sync object to do
        // something.
        // drop through...
        
    case TIMEOUT:
        // The thread was waiting on a sync object with a timeout.
        // drop through...
        
    case DELAY:
        // The thread was simply delaying, unless it has been
        // woken up for some other reason, wake it now.
        sleep_reason = NONE;
        wake_reason = EXIT;
        break;
    }

    wake();

    // Allow preemption
    Cyg_Scheduler::unlock();
    CYG_REPORT_RETURN();
}

// -------------------------------------------------------------------------
// Set thread priority

#ifdef CYGIMP_THREAD_PRIORITY

void
Cyg_Thread::set_priority( cyg_priority new_priority )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -