1 //==========================================================================
5 // Thread class implementations
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: nickg
46 // Purpose: Thread class implementation
47 // Description: This file contains the definitions of the thread class
48 // member functions that are common to all thread implementations.
50 //####DESCRIPTIONEND####
52 //==========================================================================
54 #include <pkgconf/kernel.h> // kernel configuration file
56 #include <cyg/hal/hal_arch.h> // HAL_REORDER_BARRIER &
57 // CYGNUM_HAL_STACK_SIZE_TYPICAL
59 #include <cyg/kernel/ktypes.h> // base kernel types
60 #include <cyg/infra/cyg_trac.h> // tracing macros
61 #include <cyg/infra/cyg_ass.h> // assertion macros
62 #include <cyg/kernel/instrmnt.h> // instrumentation
64 #include <cyg/kernel/thread.hxx> // our header
66 #include <cyg/kernel/intr.hxx> // Interrupt support
68 #include <cyg/kernel/thread.inl> // thread inlines
69 #include <cyg/kernel/sched.inl> // scheduler inlines
70 #include <cyg/kernel/clock.inl> // clock inlines
72 #ifdef CYGDBG_KERNEL_THREADS_STACK_MEASUREMENT_VERBOSE_EXIT
73 #include <cyg/infra/diag.h>
76 // =========================================================================
77 // Cyg_HardwareThread members
79 // -------------------------------------------------------------------------
80 // Thread entry point.
81 // This is inserted as the PC value in all initial thread contexts.
82 // It does some housekeeping and then calls the real entry point.
85 Cyg_HardwareThread::thread_entry( Cyg_Thread *thread )
87 CYG_REPORT_FUNCTION();
89 // Call the scheduler to do any housekeeping
90 Cyg_Scheduler::scheduler.thread_entry( thread );
92 // Call entry point in a loop.
95 thread->entry_point(thread->entry_data);
100 // =========================================================================
101 // Cyg_Thread members
103 // -------------------------------------------------------------------------
104 // Statics and thread list functions
106 #ifdef CYGVAR_KERNEL_THREADS_LIST
108 // List of all extant threads
109 Cyg_Thread *Cyg_Thread::thread_list = 0;
112 Cyg_Thread::add_to_list( void )
114 // Add thread to housekeeping list
115 Cyg_Scheduler::lock();
117 if( thread_list == 0 )
120 Cyg_Thread *prev = thread_list;
123 break; // found it already!
124 prev = prev->list_next;
125 } while ( prev != thread_list );
126 if ( this != prev ) {
127 // insert it in the list:
128 list_next = thread_list->list_next;
129 thread_list->list_next = this;
134 Cyg_Scheduler::unlock();
138 Cyg_Thread::remove_from_list( void )
140 // remove thread from housekeeping list
141 Cyg_Scheduler::lock();
143 Cyg_Thread *prev = thread_list;
146 if( prev->list_next == this ) {
147 prev->list_next = list_next;
148 if( thread_list == this )
149 thread_list = list_next;
152 prev = prev->list_next;
153 } while ( prev != thread_list );
155 Cyg_Scheduler::unlock();
160 static cyg_uint16 next_unique_id = 1;
162 // -------------------------------------------------------------------------
163 // Magic new operator to allow the thread constructor to be
167 operator new(size_t size, Cyg_Thread *ptr)
168 { return (void *)ptr; };
172 Cyg_Thread::Cyg_Thread(
173 CYG_ADDRWORD sched_info, // Scheduling parameter(s)
174 cyg_thread_entry *entry, // entry point function
175 CYG_ADDRWORD entry_data, // entry data
176 char *name_arg, // thread name cookie
177 CYG_ADDRESS stack_base, // stack base, NULL = allocate
178 cyg_ucount32 stack_size // stack size, 0 = use default
180 : Cyg_HardwareThread(entry, entry_data, stack_size, stack_base),
181 Cyg_SchedThread(this, sched_info)
182 #ifdef CYGFUN_KERNEL_THREADS_TIMER
186 CYG_REPORT_FUNCTION();
188 CYG_INSTRUMENT_THREAD(CREATE,this,0);
190 // Start the thread in suspended state.
195 // Initialize sleep_reason which is used by kill, release
199 // Assign a 16 bit id to the thread.
200 unique_id = next_unique_id++;
202 #ifdef CYGVAR_KERNEL_THREADS_DATA
203 // Zero all per-thread data entries.
204 for( int i = 0; i < CYGNUM_KERNEL_THREADS_DATA_MAX; i++ )
207 #ifdef CYGSEM_KERNEL_THREADS_DESTRUCTORS_PER_THREAD
208 for (int j=0; j<CYGNUM_KERNEL_THREADS_DESTRUCTORS; j++) {
209 destructors[j].fn = NULL;
212 #ifdef CYGVAR_KERNEL_THREADS_NAME
215 #ifdef CYGVAR_KERNEL_THREADS_LIST
216 // Add thread to housekeeping list
220 Cyg_Scheduler::scheduler.register_thread(this);
228 // -------------------------------------------------------------------------
229 // Re-initialize this thread.
230 // We do this by re-invoking the constructor with the original
231 // arguments, which are still available in the object.
234 Cyg_Thread::reinitialize()
236 CYG_REPORT_FUNCTION();
238 CYG_ASSERTCLASS( this, "Bad thread");
239 CYG_ASSERT( this != Cyg_Scheduler::get_current_thread(),
240 "Attempt to reinitialize current thread");
241 CYG_ASSERT( get_current_queue() == NULL , "Thread is still on a queue");
243 #ifdef CYGFUN_KERNEL_THREADS_TIMER
244 // Clear the timeout. It is irrelevant whether there was
245 // actually a timeout pending.
249 // Ensure the scheduler has let go of us.
250 Cyg_Scheduler::scheduler.deregister_thread(this);
252 cyg_priority pri = get_priority();
253 #ifdef CYGVAR_KERNEL_THREADS_NAME
254 char * name_arg = name;
256 char * name_arg = NULL;
259 new(this) Cyg_Thread( pri,
260 entry_point, entry_data,
262 get_stack_base(), get_stack_size() );
263 // the constructor re-registers the thread with the scheduler.
265 CYG_ASSERTCLASS( this, "Thread corrupted by reinitialize");
270 // -------------------------------------------------------------------------
273 Cyg_Thread::~Cyg_Thread()
275 CYG_REPORT_FUNCTION();
277 Cyg_Scheduler::scheduler.deregister_thread(this);
279 #ifdef CYGVAR_KERNEL_THREADS_LIST
280 // Remove thread from housekeeping list.
284 // Zero the unique_id to render this thread inconsistent.
290 // -------------------------------------------------------------------------
291 // Thread consistency checker.
293 #ifdef CYGDBG_USE_ASSERTS
296 Cyg_Thread::check_this( cyg_assert_class_zeal zeal) const
298 // CYG_REPORT_FUNCTION();
300 // check that we have a non-NULL pointer first
301 if( this == NULL ) return false;
305 case cyg_system_test:
308 if( (state & SUSPENDED) && (suspend_count == 0) ) return false;
310 // Check that the stackpointer is within its limits.
311 // Note: This does not check the current stackpointer value
312 // of the executing thread.
313 if( (stack_ptr > (stack_base + stack_size)) ||
314 (stack_ptr < stack_base) ) return false;
315 #ifdef CYGFUN_KERNEL_THREADS_STACK_LIMIT
316 if( stack_ptr < stack_limit ) return false;
329 // -------------------------------------------------------------------------
330 // Put the thread to sleep.
331 // This can only be called by the current thread on itself, hence
332 // it is a static function.
337 CYG_REPORT_FUNCTION();
339 Cyg_Thread *current = Cyg_Scheduler::get_current_thread();
341 CYG_ASSERTCLASS( current, "Bad current thread" );
343 CYG_INSTRUMENT_THREAD(SLEEP,current,0);
345 // Prevent preemption
346 Cyg_Scheduler::lock();
348 // If running, remove from run qs
349 if ( current->state == RUNNING )
350 Cyg_Scheduler::scheduler.rem_thread(current);
353 current->state |= SLEEPING;
355 // Unlock the scheduler and switch threads
356 Cyg_Scheduler::unlock();
361 // -------------------------------------------------------------------------
362 // Awaken the thread from sleep.
367 CYG_REPORT_FUNCTION();
369 CYG_INSTRUMENT_THREAD(WAKE,this,Cyg_Scheduler::current_thread);
371 // Prevent preemption
372 Cyg_Scheduler::lock();
374 if( 0 != (state & SLEEPSET) )
379 // remove from any queue we were on
382 // If the thread is now runnable, return it to run queue
383 if( state == RUNNING )
384 Cyg_Scheduler::scheduler.add_thread(this);
388 // Unlock the scheduler and maybe switch threads
389 Cyg_Scheduler::unlock();
394 // -------------------------------------------------------------------------
395 // Put the thread to sleep, with wakeup count.
396 // This can only be called by the current thread on itself, hence
397 // it is a static function.
400 Cyg_Thread::counted_sleep()
402 CYG_REPORT_FUNCTION();
404 Cyg_Thread *current = Cyg_Scheduler::get_current_thread();
406 CYG_ASSERTCLASS( current, "Bad current thread" );
408 CYG_INSTRUMENT_THREAD(SLEEP,current,0);
410 // Prevent preemption
411 Cyg_Scheduler::lock();
413 if ( 0 == current->wakeup_count ) {
414 set_sleep_reason( Cyg_Thread::WAIT );
415 current->sleep(); // prepare to sleep
416 current->state |= COUNTSLEEP; // Set the state
419 // there is a queued wakeup, do not sleep
420 current->wakeup_count--;
422 // Unlock the scheduler and switch threads
423 Cyg_Scheduler::unlock();
425 // and deal with anything we must do when we return
426 switch( current->wake_reason ) {
439 // -------------------------------------------------------------------------
440 // Put the thread to sleep for a delay, with wakeup count.
441 // This can only be called by the current thread on itself, hence
442 // it is a static function.
444 #ifdef CYGFUN_KERNEL_THREADS_TIMER
446 Cyg_Thread::counted_sleep( cyg_tick_count delay )
448 CYG_REPORT_FUNCTION();
450 Cyg_Thread *current = Cyg_Scheduler::get_current_thread();
452 CYG_ASSERTCLASS( current, "Bad current thread" );
454 CYG_INSTRUMENT_THREAD(SLEEP,current,0);
456 // Prevent preemption
457 Cyg_Scheduler::lock();
459 if ( 0 == current->wakeup_count ) {
461 // Set the timer (once outside any waiting loop.)
462 set_timer( Cyg_Clock::real_time_clock->current_value()+delay,
463 Cyg_Thread::TIMEOUT );
465 // If the timeout is in the past, the wake reason will have been
466 // set to something other than NONE already.
468 if( current->get_wake_reason() == Cyg_Thread::NONE )
470 set_sleep_reason( Cyg_Thread::TIMEOUT );
471 current->sleep(); // prepare to sleep
472 current->state |= COUNTSLEEP; // Set the state
474 Cyg_Scheduler::reschedule();
476 // clear the timer; if it actually fired, no worries.
481 // there is a queued wakeup, do not sleep
482 current->wakeup_count--;
484 // Unlock the scheduler and switch threads
485 Cyg_Scheduler::unlock();
487 // and deal with anything we must do when we return
488 switch( current->wake_reason ) {
502 // -------------------------------------------------------------------------
503 // Awaken the thread from sleep.
506 Cyg_Thread::counted_wake()
508 CYG_REPORT_FUNCTION();
510 CYG_INSTRUMENT_THREAD(WAKE,this,Cyg_Scheduler::current_thread);
512 // Prevent preemption
513 Cyg_Scheduler::lock();
515 if ( 0 == (state & COUNTSLEEP) ) // already awake, or waiting:
516 wakeup_count++; // not in a counted sleep anyway.
520 wake(); // and awaken the thread
523 #ifdef CYGNUM_KERNEL_MAX_COUNTED_WAKE_COUNT_ASSERT
524 CYG_ASSERT( CYGNUM_KERNEL_MAX_COUNTED_WAKE_COUNT_ASSERT > wakeup_count,
525 "wakeup_count overflow" );
528 // Unlock the scheduler and maybe switch threads
529 Cyg_Scheduler::unlock();
534 // -------------------------------------------------------------------------
535 // Cancel wakeups for this thread and return how many were pending
537 Cyg_Thread::cancel_counted_wake()
539 CYG_REPORT_FUNCTION();
541 CYG_INSTRUMENT_THREAD(WAKE,this,Cyg_Scheduler::current_thread);
543 // Prevent preemption
544 Cyg_Scheduler::lock();
546 cyg_uint32 result = wakeup_count;
549 // Unlock the scheduler
550 Cyg_Scheduler::unlock();
552 CYG_REPORT_RETVAL( result );
556 // -------------------------------------------------------------------------
557 // Suspend thread. Increment suspend count and deschedule thread
561 Cyg_Thread::suspend()
563 CYG_REPORT_FUNCTION();
565 CYG_INSTRUMENT_THREAD(SUSPEND,this,Cyg_Scheduler::current_thread);
567 // Prevent preemption
568 Cyg_Scheduler::lock();
572 #ifdef CYGNUM_KERNEL_MAX_SUSPEND_COUNT_ASSERT
573 CYG_ASSERT( CYGNUM_KERNEL_MAX_SUSPEND_COUNT_ASSERT > suspend_count,
574 "suspend_count overflow" );
577 // If running, remove from run qs
578 if( state == RUNNING )
579 Cyg_Scheduler::scheduler.rem_thread(this);
584 // Unlock the scheduler and maybe switch threads
585 Cyg_Scheduler::unlock();
590 // -------------------------------------------------------------------------
591 // Resume thread. Decrement suspend count and reschedule if it
597 CYG_REPORT_FUNCTION();
599 CYG_INSTRUMENT_THREAD(RESUME,this,Cyg_Scheduler::current_thread);
601 // Prevent preemption
602 Cyg_Scheduler::lock();
604 // If we are about to zero the count, clear the state bit and
605 // reschedule the thread if possible.
607 if( suspend_count == 1 )
611 CYG_ASSERT( (state & SUSPENDED) != 0, "SUSPENDED bit not set" );
616 // Return thread to scheduler if runnable
617 if( state == RUNNING )
618 Cyg_Scheduler::scheduler.add_thread(this);
621 if( suspend_count > 0 )
623 // else ignore attempt to resume
625 // Unlock the scheduler and maybe switch threads
626 Cyg_Scheduler::unlock();
631 // -------------------------------------------------------------------------
632 // Forced Resume thread. Zero suspend count and reschedule...
635 Cyg_Thread::force_resume()
637 CYG_REPORT_FUNCTION();
639 CYG_INSTRUMENT_THREAD(RESUME,this,Cyg_Scheduler::current_thread);
641 // Prevent preemption
642 Cyg_Scheduler::lock();
644 // If we are about to zero the count, clear the state bit and
645 // reschedule the thread if possible.
647 if ( 0 < suspend_count ) {
650 CYG_ASSERT( (state & SUSPENDED) != 0, "SUSPENDED bit not set" );
655 // Return thread to scheduler if runnable
656 if( state == RUNNING )
657 Cyg_Scheduler::scheduler.add_thread(this);
660 // Unlock the scheduler and maybe switch threads
661 Cyg_Scheduler::unlock();
665 // -------------------------------------------------------------------------
666 // Force thread to wake up from a sleep with a wake_reason of
667 // BREAK. It is the responsibility of the woken thread to detect
668 // the release() and do the right thing.
671 Cyg_Thread::release()
673 CYG_REPORT_FUNCTION();
674 // Prevent preemption
675 Cyg_Scheduler::lock();
677 // If the thread is in any of the sleep states, set the
678 // wake reason and wake it up.
680 switch( sleep_reason )
684 // The thread is not sleeping for any reason, do nothing.
691 // Do nothing in any of these cases. They are here to
692 // keep the compiler happy.
694 Cyg_Scheduler::unlock();
699 // The thread was waiting for some sync object to do
704 // The thread was waiting on a sync object with a timeout.
708 // The thread was simply delaying, unless it has been
709 // woken up for some other reason, wake it now.
718 Cyg_Scheduler::unlock();
723 // -------------------------------------------------------------------------
724 // Exit thread. This puts the thread into EXITED state.
726 #ifdef CYGPKG_KERNEL_THREADS_DESTRUCTORS
727 #ifndef CYGSEM_KERNEL_THREADS_DESTRUCTORS_PER_THREAD
728 Cyg_Thread::Cyg_Destructor_Entry
729 Cyg_Thread::destructors[ CYGNUM_KERNEL_THREADS_DESTRUCTORS ];
736 CYG_REPORT_FUNCTION();
738 // The thread should never return from this function.
740 Cyg_Thread *self = Cyg_Thread::self();
742 #ifdef CYGPKG_KERNEL_THREADS_DESTRUCTORS
744 for (i=0; i<CYGNUM_KERNEL_THREADS_DESTRUCTORS; i++) {
745 if (NULL != self->destructors[i].fn) {
746 destructor_fn fn = self->destructors[i].fn;
747 CYG_ADDRWORD data = self->destructors[i].data;
752 #ifdef CYGDBG_KERNEL_THREADS_STACK_MEASUREMENT_VERBOSE_EXIT
753 diag_printf( "Stack usage for thread %08x: %d\n", self,
754 self->measure_stack_usage() );
757 Cyg_Scheduler::lock();
759 // clear the timer; if there was none, no worries.
762 // It is possible that we have already been killed by another
763 // thread, in which case we do not want to try and take ourself
764 // out of the scheduler again.
765 if( self->state != EXITED )
767 self->state = EXITED;
769 Cyg_Scheduler::scheduler.rem_thread(self);
772 Cyg_Scheduler::reschedule();
775 // -------------------------------------------------------------------------
776 // Kill thread. Force the thread into EXITED state externally, or
777 // make it wake up and call exit().
782 CYG_REPORT_FUNCTION();
783 // If this is called by the current thread on itself,
784 // just call exit(), which is what he should have done
785 // in the first place.
786 if( this == Cyg_Scheduler::get_current_thread() )
789 // Prevent preemption
790 Cyg_Scheduler::lock();
792 // We are killing someone else. Find out what state he is
793 // in and force him to wakeup and call exit().
795 force_resume(); // this is necessary for when
796 // he is asleep AND suspended.
797 #ifdef CYGFUN_KERNEL_THREADS_TIMER
798 timer.disable(); // and make sure the timer
802 if ( EXIT != wake_reason ) switch( sleep_reason ) {
803 // Only do any of this if the thread is not in pending death already:
806 // The thread is not sleeping for any reason, it must be
808 // We can safely deschedule and set its state.
809 if( state == RUNNING ) Cyg_Scheduler::scheduler.rem_thread(this);
817 // Do nothing in any of these cases. They are here to
818 // keep the compiler happy.
820 Cyg_Scheduler::unlock();
825 // The thread was waiting for some sync object to do
830 // The thread was waiting on a sync object with a timeout.
834 // The thread was simply delaying, unless it has been
835 // woken up for some other reason, wake it now.
844 Cyg_Scheduler::unlock();
848 // -------------------------------------------------------------------------
849 // Set thread priority
851 #ifdef CYGIMP_THREAD_PRIORITY
854 Cyg_Thread::set_priority( cyg_priority new_priority )
856 CYG_REPORT_FUNCTION();
858 // CYG_ASSERT( new_priority >= CYG_THREAD_MAX_PRIORITY, "Priority out of range");
859 // CYG_ASSERT( new_priority <= CYG_THREAD_MIN_PRIORITY, "Priority out of range");
861 CYG_INSTRUMENT_THREAD(PRIORITY,this,new_priority);
863 // Prevent preemption
864 Cyg_Scheduler::lock();
866 Cyg_ThreadQueue *queue = NULL;
868 // If running, remove from run qs
869 if( state == RUNNING )
870 Cyg_Scheduler::scheduler.rem_thread(this);
871 else if( state & SLEEPING )
873 // Remove thread from current queue.
874 queue = get_current_queue();
875 // if indeed we are on a queue
876 if ( NULL != queue ) {
877 CYG_CHECK_DATA_PTR(queue, "Bad queue pointer");
882 Cyg_Scheduler::scheduler.deregister_thread(this);
884 #if CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES
886 // Check that there are no other threads at this priority.
887 // If so, leave is as it is.
889 CYG_ASSERT( Cyg_Scheduler::scheduler.unique(new_priority), "Priority not unique");
891 if( Cyg_Scheduler::scheduler.unique(new_priority) )
892 priority = new_priority;
894 #else // !CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES
896 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_SIMPLE
898 // When we have priority inheritance, we must update the original
899 // priority and not the inherited one. If the new priority is
900 // better than the current inherited one, then use that
901 // immediately. We remain in inherited state to avoid problems
902 // with multiple mutex inheritances.
904 if( priority_inherited )
906 original_priority = new_priority;
907 if( priority > new_priority ) priority = new_priority;
909 else priority = new_priority;
913 priority = new_priority;
917 #endif // CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES
919 Cyg_Scheduler::scheduler.register_thread(this);
921 // Return thread to scheduler if runnable
922 if( state == RUNNING )
923 Cyg_Scheduler::scheduler.add_thread(this);
924 else if ( state & SLEEPING )
926 // return to current queue
927 // if indeed we are on a queue
928 if ( NULL != queue ) {
929 CYG_CHECK_DATA_PTR(queue, "Bad queue pointer");
930 queue->enqueue(this);
934 // If the current thread is being reprioritized, set the
935 // reschedule flag to ensure that it gets rescheduled if
936 // necessary. (Strictly we only need to do this if the new
937 // priority is less than that of some other runnable thread, in
938 // practice checking that is as expensive as what the scheduler
940 // If it is not the current thread then we need to see whether
941 // it is more worthy of execution than any current thread and
942 // rescheduled if necessary.
944 if( this == Cyg_Scheduler::get_current_thread() )
945 Cyg_Scheduler::set_need_reschedule();
946 else Cyg_Scheduler::set_need_reschedule(this);
948 // Unlock the scheduler and maybe switch threads
949 Cyg_Scheduler::unlock();
956 // -------------------------------------------------------------------------
957 // Thread delay function
960 Cyg_Thread::delay( cyg_tick_count delay)
962 CYG_REPORT_FUNCTION();
964 #ifdef CYGFUN_KERNEL_THREADS_TIMER
966 CYG_INSTRUMENT_THREAD(DELAY,this,delay);
968 // Prevent preemption
969 Cyg_Scheduler::lock();
973 set_timer( Cyg_Clock::real_time_clock->current_value()+delay, DELAY );
975 // Unlock the scheduler and maybe switch threads
976 Cyg_Scheduler::unlock();
978 // Clear the timeout. It is irrelevant whether the alarm has
979 // actually gone off or not.
982 // and deal with anything else we must do when we return
983 switch( wake_reason ) {
996 // -------------------------------------------------------------------------
999 #ifdef CYGPKG_KERNEL_EXCEPTIONS
1002 Cyg_Thread::deliver_exception(
1003 cyg_code exception_number, // exception being raised
1004 CYG_ADDRWORD exception_info // exception specific info
1007 if( this == Cyg_Scheduler::get_current_thread() )
1009 // Delivering to current thread, probably as a result
1010 // of a real hardware exception. Simply invoke the appropriate
1013 exception_control.deliver_exception( exception_number, exception_info );
1015 #ifdef CYGIMP_EXCEPTION_ASYNC
1018 // Delivering to another thread, probably as a result of one thread
1019 // invoking this function on another thread. Adjust the other thread's
1020 // state to make it execute the exception routine when it next runs.
1022 // At present there is an unresolved problem here. We do not know what
1023 // state the destination thread is in. It may not be a suitable point at
1024 // which to invoke an exception routine. In most cases the exception
1025 // routine will be run in the scheduler thread switch code, where the world is
1026 // in an inconsistent state. We really need to run the routine at the
1027 // end of unlock_inner(). However this would add extra code to the scheduler,
1028 // and require a way of storing pending exceptions. So for now this option is
1029 // disabled and not yet implemented, it may never be.
1037 // -------------------------------------------------------------------------
1038 // Per-thread data support
1040 #ifdef CYGVAR_KERNEL_THREADS_DATA
1042 // Set the data map bits for each free slot in the data array.
1043 cyg_ucount32 Cyg_Thread::thread_data_map = (~CYGNUM_KERNEL_THREADS_DATA_ALL) &
1044 (1+(((cyg_ucount32)(1<<(CYGNUM_KERNEL_THREADS_DATA_MAX-1))-1)<<1));
1045 // the second expression is equivalent to ((1<<CYGNUM_KERNEL_THREADS_DATA_MAX)-1);
1046 // but avoids overflow. The compiler will compile to a constant just fine.
1048 Cyg_Thread::cyg_data_index
1049 Cyg_Thread::new_data_index()
1051 Cyg_Scheduler::lock();
1053 Cyg_Thread::cyg_data_index index;
1055 if (0 == thread_data_map)
1059 HAL_LSBIT_INDEX( index, thread_data_map );
1062 thread_data_map &= ~(1<<index);
1064 Cyg_Scheduler::unlock();
1069 void Cyg_Thread::free_data_index( Cyg_Thread::cyg_data_index index )
1071 Cyg_Scheduler::lock();
1073 thread_data_map |= (1<<index);
1075 Cyg_Scheduler::unlock();
1081 // -------------------------------------------------------------------------
1082 // Allocate some memory at the lower end of the stack
1083 // by moving the stack limit pointer.
1085 #if defined(CYGFUN_KERNEL_THREADS_STACK_LIMIT) && \
1086 defined(CYGFUN_KERNEL_THREADS_STACK_CHECKING)
1087 // if not doing stack checking, implementation can be found in thread.inl
1088 // This implementation puts the magic buffer area (to watch for overruns
1089 // *above* the stack limit, i.e. there is no official demarcation between
1090 // the stack and the buffer. But that's okay if you think about it... having
1091 // a demarcation would not accomplish anything more.
1092 void *Cyg_HardwareThread::increment_stack_limit( cyg_ucount32 size )
1094 void *ret = (void *)stack_limit;
1096 // First lock the scheduler because we're going to be tinkering with
1098 Cyg_Scheduler::lock();
1100 // if we've inc'd the limit before, it will be off by the check data
1101 // size, so lets correct it
1102 if (stack_limit != stack_base)
1103 stack_limit -= CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE;
1104 stack_limit += size;
1106 // determine base of check data by rounding up to nearest word aligned
1107 // address if not already aligned
1108 cyg_uint32 *p = (cyg_uint32 *)((stack_limit + 3) & ~3);
1109 // i.e. + sizeof(cyg_uint32)-1) & ~(sizeof(cyg_uint32)-1);
1111 cyg_uint32 sig = (cyg_uint32)this;
1114 i < CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE/sizeof(cyg_uint32);
1116 p[i] = (sig ^ (i * 0x01010101));
1119 // increment limit by the check size. Note this will not necessarily
1120 // reach the end of the check data. But that doesn't really matter.
1121 // Doing this allows better checking of the saved stack pointer in
1122 // Cyg_Thread::check_this()
1123 stack_limit += CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE;
1125 Cyg_Scheduler::unlock();
1131 // =========================================================================
1132 // Cyg_ThreadTimer member functions
1134 // -------------------------------------------------------------------------
1135 // Timer alarm function. Inspect the sleep_reason and if necessary wake
1136 // up the thread with an appropriate wake_reason.
1138 #ifdef CYGFUN_KERNEL_THREADS_TIMER
1141 Cyg_ThreadTimer::alarm(
1146 CYG_REPORT_FUNCTION();
1148 Cyg_ThreadTimer *self = (Cyg_ThreadTimer *)data;
1149 Cyg_Thread *thread = self->thread;
1151 CYG_INSTRUMENT_THREAD(ALARM, 0, 0);
1153 Cyg_Scheduler::lock();
1155 Cyg_Thread::cyg_reason sleep_reason = thread->get_sleep_reason();
1157 switch( sleep_reason ) {
1159 case Cyg_Thread::DESTRUCT:
1160 case Cyg_Thread::BREAK:
1161 case Cyg_Thread::EXIT:
1162 case Cyg_Thread::NONE:
1163 case Cyg_Thread::WAIT:
1164 case Cyg_Thread::DONE:
1165 // Do nothing in any of these cases. Most are here to
1166 // keep the compiler happy.
1167 Cyg_Scheduler::unlock();
1168 CYG_REPORT_RETURN();
1171 case Cyg_Thread::DELAY:
1172 // The thread was simply delaying, unless it has been
1173 // woken up for some other reason, wake it now.
1174 thread->set_wake_reason(Cyg_Thread::DONE);
1177 case Cyg_Thread::TIMEOUT:
1178 // The thread has timed out, set the wake reason to
1179 // TIMEOUT and restart.
1180 thread->set_wake_reason(Cyg_Thread::TIMEOUT);
1186 Cyg_Scheduler::unlock();
1187 CYG_REPORT_RETURN();
1192 // =========================================================================
1194 // The idle thread is implemented as a single instance of the
1195 // Cyg_IdleThread class. This is so that it can be initialized before
1196 // main in a static constructor.
1198 // -------------------------------------------------------------------------
1202 #ifdef CYGNUM_HAL_STACK_SIZE_MINIMUM
1203 # ifdef CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE
1204 # if CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE < CYGNUM_HAL_STACK_SIZE_MINIMUM
1206 // then override the configured stack size
1207 # undef CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE
1208 # define CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUM
1210 # endif // CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE < CYGNUM_HAL_STACK_SIZE_MINIMUM
1211 # endif // CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE
1212 #endif // CYGNUM_HAL_STACK_SIZE_MINIMUM
1214 // Loop counter for debugging/housekeeping
1215 cyg_uint32 idle_thread_loops[CYGNUM_KERNEL_CPU_MAX];
1217 static char idle_thread_stack[CYGNUM_KERNEL_CPU_MAX][CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE];
1219 // -------------------------------------------------------------------------
1220 // Idle thread code.
1223 idle_thread_main( CYG_ADDRESS data )
1225 CYG_REPORT_FUNCTION();
1229 idle_thread_loops[CYG_KERNEL_CPU_THIS()]++;
1231 HAL_IDLE_THREAD_ACTION(idle_thread_loops[CYG_KERNEL_CPU_THIS()]);
1233 CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 0, "Scheduler lock not zero" );
1235 // For testing, it is useful to be able to fake
1236 // clock interrupts in the idle thread.
1238 Cyg_Clock::real_time_clock->tick();
1240 #ifdef CYGIMP_IDLE_THREAD_YIELD
1241 // In single priority and non-preemptive systems,
1242 // the idle thread should yield repeatedly to
1244 Cyg_Thread::yield();
1249 // -------------------------------------------------------------------------
1250 // Idle thread class
1252 class Cyg_IdleThread : public Cyg_Thread
1259 // -------------------------------------------------------------------------
1260 // Instantiate the idle thread
1262 Cyg_IdleThread idle_thread[CYGNUM_KERNEL_CPU_MAX] CYG_INIT_PRIORITY( IDLE_THREAD );
1264 // -------------------------------------------------------------------------
1265 // Idle threads constructor
1267 Cyg_IdleThread::Cyg_IdleThread()
1268 : Cyg_Thread( CYG_THREAD_MIN_PRIORITY,
1271 (char *)"Idle Thread",
1272 (CYG_ADDRESS)idle_thread_stack[this-&idle_thread[0]],
1273 CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE)
1275 CYG_REPORT_FUNCTION();
1277 // Call into scheduler to set up this thread as the default
1278 // current thread for its CPU.
1280 Cyg_Scheduler::scheduler.set_idle_thread( this, this-&idle_thread[0] );
1282 CYG_REPORT_RETURN();
1285 // -------------------------------------------------------------------------
1286 // EOF common/thread.cxx