comparison packages/kernel/current/src/common/thread.cxx @ 0:3111d98ba7b3 ecos-v1_1-release

Initial commit of eCos version 1.1
author jlarmour
date Tue, 11 May 1999 11:16:07 +0000
parents
children 443894e2e912
comparison
equal deleted inserted replaced
-1:000000000000 0:3111d98ba7b3
1 //==========================================================================
2 //
3 // common/thread.cxx
4 //
5 // Thread class implementations
6 //
7 //==========================================================================
8 //####COPYRIGHTBEGIN####
9 //
10 // -------------------------------------------
11 // The contents of this file are subject to the Cygnus eCos Public License
12 // Version 1.0 (the "License"); you may not use this file except in
13 // compliance with the License. You may obtain a copy of the License at
14 // http://sourceware.cygnus.com/ecos
15 //
16 // Software distributed under the License is distributed on an "AS IS"
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
18 // License for the specific language governing rights and limitations under
19 // the License.
20 //
21 // The Original Code is eCos - Embedded Cygnus Operating System, released
22 // September 30, 1998.
23 //
24 // The Initial Developer of the Original Code is Cygnus. Portions created
25 // by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved.
26 // -------------------------------------------
27 //
28 //####COPYRIGHTEND####
29 //==========================================================================
30 //#####DESCRIPTIONBEGIN####
31 //
32 // Author(s): nickg
33 // Contributors: nickg
34 // Date: 1997-09-15
35 // Purpose: Thread class implementation
36 // Description: This file contains the definitions of the thread class
37 // member functions that are common to all thread implementations.
38 //
39 //####DESCRIPTIONEND####
40 //
41 //==========================================================================
42
43 #include <pkgconf/kernel.h> // kernel configuration file
44
45 #include <cyg/kernel/ktypes.h> // base kernel types
46 #include <cyg/infra/cyg_trac.h> // tracing macros
47 #include <cyg/infra/cyg_ass.h> // assertion macros
48 #include <cyg/kernel/instrmnt.h> // instrumentation
49
50 #include <cyg/kernel/thread.hxx> // our header
51
52 #include <cyg/kernel/intr.hxx> // Interrupt support
53
54 #include <cyg/kernel/thread.inl> // thread inlines
55 #include <cyg/kernel/sched.inl> // scheduler inlines
56 #include <cyg/kernel/clock.inl> // clock inlines
57
58 // =========================================================================
59 // Cyg_HardwareThread members
60
61 // -------------------------------------------------------------------------
62 // Thread entry point.
63 // This is inserted as the PC value in all initial thread contexts.
64 // It does some housekeeping and then calls the real entry point.
65
66 void
67 Cyg_HardwareThread::thread_entry( Cyg_Thread *thread )
68 {
69 CYG_REPORT_FUNCTION();
70
71 Cyg_Scheduler::scheduler.need_reschedule = false; // finished rescheduling
72 Cyg_Scheduler::scheduler.current_thread = thread; // restore current thread pointer
73
74 #ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
75 // Reset the timeslice counter so that this thread gets a full
76 // quantum.
77 Cyg_Scheduler::reset_timeslice_count();
78 #endif
79
80 // Zero the lock
81 Cyg_Scheduler::sched_lock = 0;
82
83 // Call entry point in a loop.
84
85 for(;;)
86 {
87 thread->entry_point(thread->entry_data);
88 thread->exit();
89 }
90 }
91
92 // =========================================================================
93 // Cyg_Thread members
94
95 // -------------------------------------------------------------------------
96 // Statics and thread list functions
97
98 #ifdef CYGVAR_KERNEL_THREADS_LIST
99
100 // List of all extant threads
101 Cyg_Thread *Cyg_Thread::thread_list = 0;
102
103 inline void
104 Cyg_Thread::add_to_list( void )
105 {
106 // Add thread to housekeeping list
107 Cyg_Scheduler::lock();
108
109 if( thread_list == 0 )
110 list_next = this;
111 else {
112 Cyg_Thread *prev = thread_list;
113 do {
114 if ( this == prev )
115 break; // found it already!
116 prev = prev->list_next;
117 } while ( prev != thread_list );
118 if ( this != prev ) {
119 // insert it in the list:
120 list_next = thread_list->list_next;
121 thread_list->list_next = this;
122 }
123 }
124 thread_list = this;
125
126 Cyg_Scheduler::unlock();
127 }
128
129 inline void
130 Cyg_Thread::remove_from_list( void )
131 {
132 // remove thread from housekeeping list
133 Cyg_Scheduler::lock();
134
135 Cyg_Thread *prev = thread_list;
136
137 do {
138 if( prev->list_next == this ) {
139 prev->list_next = list_next;
140 if( thread_list == this )
141 thread_list = list_next;
142 break;
143 }
144 prev = prev->list_next;
145 } while ( prev != thread_list );
146
147 Cyg_Scheduler::unlock();
148 }
149
150 #endif
151
152 static cyg_uint16 next_unique_id = 1;
153
154 // -------------------------------------------------------------------------
155 // Magic new operator to allow the thread constructor to be
156 // recalled.
157
158 inline void *
159 operator new(size_t size, Cyg_Thread *ptr)
160 { return (void *)ptr; };
161
162 // Constructor
163 // This constructor is deprecated and should be replaced with the new
164 // one below. Until that happens, any changes must be made to both
165 // constructors.
166
167 Cyg_Thread::Cyg_Thread(
168 cyg_thread_entry *entry, // entry point function
169 CYG_ADDRWORD entry_data, // entry data
170 cyg_ucount32 stack_size, // stack size, 0 = use default
171 CYG_ADDRESS stack_base // stack base, NULL = allocate
172 )
173 : Cyg_HardwareThread(entry, entry_data, stack_size, stack_base),
174 Cyg_SchedThread(this, CYG_SCHED_DEFAULT_INFO)
175 #ifdef CYGFUN_KERNEL_THREADS_TIMER
176 ,timer(this)
177 #endif
178 {
179 CYG_REPORT_FUNCTION();
180
181 // Start the thread in suspended state.
182 state = SUSPENDED;
183 suspend_count = 1;
184
185 // Initialize sleep_reason which is used by kill, release
186 sleep_reason = NONE;
187 wake_reason = NONE;
188
189 // Assign a 16 bit id to the thread.
190 unique_id = next_unique_id++;
191
192 #ifdef CYGVAR_KERNEL_THREADS_DATA
193 // Zero all per-thread data entries.
194 for( int i = 0; i < CYGNUM_KERNEL_THREADS_DATA_MAX; i++ )
195 thread_data[i] = 0;
196 #endif
197 #ifdef CYGVAR_KERNEL_THREADS_NAME
198 name = 0;
199 #endif
200 #ifdef CYGVAR_KERNEL_THREADS_LIST
201 // Add thread to housekeeping list
202 add_to_list();
203 #endif
204
205 Cyg_Scheduler::scheduler.register_thread(this);
206
207 init_context(this);
208
209 CYG_REPORT_RETURN();
210 }
211
212 // -------------------------------------------------------------------------
213 // Constructor
214 // This is an alternative constructor that will become the default
215 // eventually.
216
217 Cyg_Thread::Cyg_Thread(
218 CYG_ADDRWORD sched_info, // Scheduling parameter(s)
219 cyg_thread_entry *entry, // entry point function
220 CYG_ADDRWORD entry_data, // entry data
221 char *name_arg, // thread name cookie
222 CYG_ADDRESS stack_base, // stack base, NULL = allocate
223 cyg_ucount32 stack_size // stack size, 0 = use default
224 )
225 : Cyg_HardwareThread(entry, entry_data, stack_size, stack_base),
226 Cyg_SchedThread(this, sched_info)
227 #ifdef CYGFUN_KERNEL_THREADS_TIMER
228 ,timer(this)
229 #endif
230 {
231 CYG_REPORT_FUNCTION();
232
233 // Start the thread in suspended state.
234 state = SUSPENDED;
235 suspend_count = 1;
236
237 // Initialize sleep_reason which is used by kill, release
238 sleep_reason = NONE;
239 wake_reason = NONE;
240
241 // Assign a 16 bit id to the thread.
242 unique_id = next_unique_id++;
243
244 #ifdef CYGVAR_KERNEL_THREADS_DATA
245 // Zero all per-thread data entries.
246 for( int i = 0; i < CYGNUM_KERNEL_THREADS_DATA_MAX; i++ )
247 thread_data[i] = 0;
248 #endif
249 #ifdef CYGVAR_KERNEL_THREADS_NAME
250 name = name_arg;
251 #endif
252 #ifdef CYGVAR_KERNEL_THREADS_LIST
253 // Add thread to housekeeping list
254 add_to_list();
255 #endif
256
257 Cyg_Scheduler::scheduler.register_thread(this);
258
259 init_context(this);
260
261 CYG_REPORT_RETURN();
262 }
263
264
265 // -------------------------------------------------------------------------
266 // Re-initialize this thread.
267 // We do this by re-invoking the constructor with the original
268 // arguments, which are still available in the object.
269
270 void
271 Cyg_Thread::reinitialize()
272 {
273 CYG_REPORT_FUNCTION();
274
275 CYG_ASSERTCLASS( this, "Bad thread");
276 CYG_ASSERT( this != Cyg_Scheduler::get_current_thread(),
277 "Attempt to reinitialize current thread");
278 CYG_ASSERT( get_current_queue() == NULL , "Thread is still on a queue");
279
280 #ifdef CYGFUN_KERNEL_THREADS_TIMER
281 // Clear the timeout. It is irrelevant whether there was
282 // actually a timeout pending.
283 timer.disable();
284 #endif
285
286 // Ensure the scheduler has let go of us.
287 Cyg_Scheduler::scheduler.deregister_thread(this);
288
289 cyg_priority pri = get_priority();
290 #ifdef CYGVAR_KERNEL_THREADS_NAME
291 char * name_arg = name;
292 #else
293 char * name_arg = NULL;
294 #endif
295
296 new(this) Cyg_Thread( pri,
297 entry_point, entry_data,
298 name_arg,
299 stack_base, stack_size );
300 // the constructor re-registers the thread with the scheduler.
301
302 CYG_ASSERTCLASS( this, "Thread corrupted by reinitialize");
303
304 CYG_REPORT_RETURN();
305 }
306
307 // -------------------------------------------------------------------------
308 // Destructor.
309
310 Cyg_Thread::~Cyg_Thread()
311 {
312 CYG_REPORT_FUNCTION();
313
314 Cyg_Scheduler::scheduler.deregister_thread(this);
315
316 #ifdef CYGVAR_KERNEL_THREADS_LIST
317 // Remove thread from housekeeping list.
318 remove_from_list();
319 #endif
320
321 CYG_REPORT_RETURN();
322 }
323
324 // -------------------------------------------------------------------------
325 // Thread consistency checker.
326
327 #ifdef CYGDBG_USE_ASSERTS
328
329 bool
330 Cyg_Thread::check_this( cyg_assert_class_zeal zeal)
331 {
332 // CYG_REPORT_FUNCTION();
333
334 // check that we have a non-NULL pointer first
335 if( this == NULL ) return false;
336
337 switch( zeal )
338 {
339 case cyg_system_test:
340 case cyg_extreme:
341 case cyg_thorough:
342 if( (state & SUSPENDED) && (suspend_count == 0) ) return false;
343 case cyg_quick:
344 case cyg_trivial:
345 case cyg_none:
346 default:
347 break;
348 };
349
350 return true;
351 }
352
353 #endif
354
355 // -------------------------------------------------------------------------
356 // Put the thread to sleep.
357 // This can only be called by the current thread on itself, hence
358 // it is a static function.
359
360 void
361 Cyg_Thread::sleep()
362 {
363 CYG_REPORT_FUNCTION();
364
365 Cyg_Thread *current = Cyg_Scheduler::get_current_thread();
366
367 CYG_ASSERTCLASS( current, "Bad current thread" );
368
369 CYG_INSTRUMENT_THREAD(SLEEP,current,0);
370
371 // Prevent preemption
372 Cyg_Scheduler::lock();
373
374 // If running, remove from run qs
375 if ( current->state == RUNNING )
376 Cyg_Scheduler::scheduler.rem_thread(current);
377
378 // Set the state
379 current->state |= SLEEPING;
380
381 // Unlock the scheduler and switch threads
382 Cyg_Scheduler::unlock();
383
384 CYG_REPORT_RETURN();
385 }
386
387 // -------------------------------------------------------------------------
388 // Awaken the thread from sleep.
389
390 void
391 Cyg_Thread::wake()
392 {
393 CYG_REPORT_FUNCTION();
394
395 CYG_INSTRUMENT_THREAD(WAKE,this,Cyg_Scheduler::current_thread);
396
397 // Prevent preemption
398 Cyg_Scheduler::lock();
399
400 if( 0 != (state & SLEEPSET) )
401 {
402 // Set the state
403 state &= ~SLEEPSET;
404
405 // remove from any queue we were on
406 remove();
407
408 // If the thread is now runnable, return it to run queue
409 if( state == RUNNING )
410 Cyg_Scheduler::scheduler.add_thread(this);
411
412 }
413
414 // Unlock the scheduler and maybe switch threads
415 Cyg_Scheduler::unlock();
416
417 CYG_REPORT_RETURN();
418 }
419
420 // -------------------------------------------------------------------------
421 // Put the thread to sleep, with wakeup count.
422 // This can only be called by the current thread on itself, hence
423 // it is a static function.
424
425 void
426 Cyg_Thread::counted_sleep()
427 {
428 CYG_REPORT_FUNCTION();
429
430 Cyg_Thread *current = Cyg_Scheduler::get_current_thread();
431
432 CYG_ASSERTCLASS( current, "Bad current thread" );
433
434 CYG_INSTRUMENT_THREAD(SLEEP,current,0);
435
436 // Prevent preemption
437 Cyg_Scheduler::lock();
438
439 if ( 0 == current->wakeup_count ) {
440 set_sleep_reason( Cyg_Thread::WAIT );
441 current->sleep(); // prepare to sleep
442 current->state |= COUNTSLEEP; // Set the state
443 }
444 else
445 // there is a queued wakeup, do not sleep
446 current->wakeup_count--;
447
448 // Unlock the scheduler and switch threads
449 Cyg_Scheduler::unlock();
450
451 // and deal with anything we must do when we return
452 switch( current->wake_reason ) {
453 case DESTRUCT:
454 case EXIT:
455 current->exit();
456 break;
457
458 default:
459 break;
460 }
461
462 CYG_REPORT_RETURN();
463 }
464
465 // -------------------------------------------------------------------------
466 // Put the thread to sleep for a delay, with wakeup count.
467 // This can only be called by the current thread on itself, hence
468 // it is a static function.
469
470 #ifdef CYGFUN_KERNEL_THREADS_TIMER
471 void
472 Cyg_Thread::counted_sleep( cyg_tick_count delay )
473 {
474 CYG_REPORT_FUNCTION();
475
476 Cyg_Thread *current = Cyg_Scheduler::get_current_thread();
477
478 CYG_ASSERTCLASS( current, "Bad current thread" );
479
480 CYG_INSTRUMENT_THREAD(SLEEP,current,0);
481
482 // Prevent preemption
483 Cyg_Scheduler::lock();
484
485 if ( 0 == current->wakeup_count ) {
486
487 // Set the timer (once outside any waiting loop.)
488 set_timer( Cyg_Clock::real_time_clock->current_value()+delay,
489 Cyg_Thread::TIMEOUT );
490
491 // If the timeout is in the past, the wake reason will have been
492 // set to something other than NONE already.
493
494 if( current->get_wake_reason() == Cyg_Thread::NONE )
495 {
496 set_sleep_reason( Cyg_Thread::TIMEOUT );
497 current->sleep(); // prepare to sleep
498 current->state |= COUNTSLEEP; // Set the state
499
500 CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 1,
501 "Called with non-zero scheduler lock");
502
503 Cyg_Scheduler::unlock();
504 Cyg_Scheduler::lock();
505
506 // clear the timer; if it actually fired, no worries.
507 clear_timer();
508 }
509 }
510 else
511 // there is a queued wakeup, do not sleep
512 current->wakeup_count--;
513
514 // Unlock the scheduler and switch threads
515 Cyg_Scheduler::unlock();
516
517 // and deal with anything we must do when we return
518 switch( current->wake_reason ) {
519 case DESTRUCT:
520 case EXIT:
521 current->exit();
522 break;
523
524 default:
525 break;
526 }
527
528 CYG_REPORT_RETURN();
529 }
530 #endif
531
532 // -------------------------------------------------------------------------
533 // Awaken the thread from sleep.
534
535 void
536 Cyg_Thread::counted_wake()
537 {
538 CYG_REPORT_FUNCTION();
539
540 CYG_INSTRUMENT_THREAD(WAKE,this,Cyg_Scheduler::current_thread);
541
542 // Prevent preemption
543 Cyg_Scheduler::lock();
544
545 if ( 0 == (state & COUNTSLEEP) ) // already awake, or waiting:
546 wakeup_count++; // not in a counted sleep anyway.
547 else {
548 sleep_reason = NONE;
549 wake_reason = DONE;
550 wake(); // and awaken the thread
551 }
552
553 #ifdef CYGNUM_KERNEL_MAX_COUNTED_WAKE_COUNT_ASSERT
554 CYG_ASSERT( CYGNUM_KERNEL_MAX_COUNTED_WAKE_COUNT_ASSERT > wakeup_count,
555 "wakeup_count overflow" );
556 #endif
557
558 // Unlock the scheduler and maybe switch threads
559 Cyg_Scheduler::unlock();
560
561 CYG_REPORT_RETURN();
562 }
563
564 // -------------------------------------------------------------------------
565 // Cancel wakeups for this thread and return how many were pending
566 cyg_uint32
567 Cyg_Thread::cancel_counted_wake()
568 {
569 CYG_REPORT_FUNCTION();
570
571 CYG_INSTRUMENT_THREAD(WAKE,this,Cyg_Scheduler::current_thread);
572
573 // Prevent preemption
574 Cyg_Scheduler::lock();
575
576 cyg_uint32 result = wakeup_count;
577 wakeup_count = 0;
578
579 // Unlock the scheduler
580 Cyg_Scheduler::unlock();
581
582 CYG_REPORT_RETVAL( result );
583 return result;
584 }
585
586 // -------------------------------------------------------------------------
587 // Suspend thread. Increment suspend count and deschedule thread
588 // if still running.
589
590 void
591 Cyg_Thread::suspend()
592 {
593 CYG_REPORT_FUNCTION();
594
595 CYG_INSTRUMENT_THREAD(SUSPEND,this,Cyg_Scheduler::current_thread);
596
597 // Prevent preemption
598 Cyg_Scheduler::lock();
599
600 suspend_count++;
601
602 #ifdef CYGNUM_KERNEL_MAX_SUSPEND_COUNT_ASSERT
603 CYG_ASSERT( CYGNUM_KERNEL_MAX_SUSPEND_COUNT_ASSERT > suspend_count,
604 "suspend_count overflow" );
605 #endif
606
607 // If running, remove from run qs
608 if( state == RUNNING )
609 Cyg_Scheduler::scheduler.rem_thread(this);
610
611 // Set the state
612 state |= SUSPENDED;
613
614 // Unlock the scheduler and maybe switch threads
615 Cyg_Scheduler::unlock();
616
617 CYG_REPORT_RETURN();
618 }
619
620 // -------------------------------------------------------------------------
621 // Resume thread. Decrement suspend count and reschedule if it
622 // is zero.
623
624 void
625 Cyg_Thread::resume()
626 {
627 CYG_REPORT_FUNCTION();
628
629 CYG_INSTRUMENT_THREAD(RESUME,this,Cyg_Scheduler::current_thread);
630
631 // Prevent preemption
632 Cyg_Scheduler::lock();
633
634 // If we are about to zero the count, clear the state bit and
635 // reschedule the thread if possible.
636
637 if( suspend_count == 1 )
638 {
639 suspend_count = 0;
640
641 CYG_ASSERT( (state & SUSPENDED) != 0, "SUSPENDED bit not set" );
642
643 // Set the state
644 state &= ~SUSPENDED;
645
646 // Return thread to scheduler if runnable
647 if( state == RUNNING )
648 Cyg_Scheduler::scheduler.add_thread(this);
649 }
650 else
651 if( suspend_count > 0 )
652 suspend_count--;
653 // else ignore attempt to resume
654
655 // Unlock the scheduler and maybe switch threads
656 Cyg_Scheduler::unlock();
657 CYG_REPORT_RETURN();
658 }
659
660 // -------------------------------------------------------------------------
661 // Forced Resume thread. Zero suspend count and reschedule...
662
663 void
664 Cyg_Thread::force_resume()
665 {
666 CYG_REPORT_FUNCTION();
667
668 CYG_INSTRUMENT_THREAD(RESUME,this,Cyg_Scheduler::current_thread);
669
670 // Prevent preemption
671 Cyg_Scheduler::lock();
672
673 // If we are about to zero the count, clear the state bit and
674 // reschedule the thread if possible.
675
676 if ( 0 < suspend_count ) {
677 suspend_count = 0;
678
679 CYG_ASSERT( (state & SUSPENDED) != 0, "SUSPENDED bit not set" );
680
681 // Set the state
682 state &= ~SUSPENDED;
683
684 // Return thread to scheduler if runnable
685 if( state == RUNNING )
686 Cyg_Scheduler::scheduler.add_thread(this);
687 }
688
689 // Unlock the scheduler and maybe switch threads
690 Cyg_Scheduler::unlock();
691 CYG_REPORT_RETURN();
692 }
693
694 // -------------------------------------------------------------------------
695 // Force thread to wake up from a sleep with a wake_reason of
696 // BREAK. It is the responsibility of the woken thread to detect
697 // the release() and do the right thing.
698
699 void
700 Cyg_Thread::release()
701 {
702 CYG_REPORT_FUNCTION();
703 // Prevent preemption
704 Cyg_Scheduler::lock();
705
706 // If the thread is in any of the sleep states, set the
707 // wake reason and wake it up.
708
709 switch( sleep_reason )
710 {
711
712 case NONE:
713 // The thread is not sleeping for any reason, do nothing.
714 // drop through...
715
716 case DESTRUCT:
717 case BREAK:
718 case EXIT:
719 case DONE:
720 // Do nothing in any of these cases. They are here to
721 // keep the compiler happy.
722
723 Cyg_Scheduler::unlock();
724 CYG_REPORT_RETURN();
725 return;
726
727 case WAIT:
728 // The thread was waiting for some sync object to do
729 // something.
730 // drop through...
731
732 case TIMEOUT:
733 // The thread was waiting on a sync object with a timeout.
734 // drop through...
735
736 case DELAY:
737 // The thread was simply delaying, unless it has been
738 // woken up for some other reason, wake it now.
739 sleep_reason = NONE;
740 wake_reason = BREAK;
741 break;
742 }
743
744 wake();
745
746 // Allow preemption
747 Cyg_Scheduler::unlock();
748
749 CYG_REPORT_RETURN();
750 }
751
752 // -------------------------------------------------------------------------
753 // Exit thread. This puts the thread into EXITED state.
754
755 void
756 Cyg_Thread::exit()
757 {
758 // The thread should never return from this function.
759
760 Cyg_Thread *self = Cyg_Thread::self();
761
762 Cyg_Scheduler::lock();
763
764 // clear the timer; if there was none, no worries.
765 clear_timer();
766
767 self->state = EXITED;
768
769 Cyg_Scheduler::scheduler.rem_thread(self);
770
771 // Un-nest any scheduler locks we have until we
772 // suspend.
773 for( ;; ) Cyg_Scheduler::unlock();
774 }
775
776 // -------------------------------------------------------------------------
777 // Kill thread. Force the thread into EXITED state externally, or
778 // make it wake up and call exit().
779
780 void
781 Cyg_Thread::kill()
782 {
783 CYG_REPORT_FUNCTION();
784 // If this is called by the current thread on itself,
785 // just call exit(), which is what he should have done
786 // in the first place.
787 if( this == Cyg_Scheduler::get_current_thread() )
788 exit();
789
790 // Prevent preemption
791 Cyg_Scheduler::lock();
792
793 // We are killing someone else. Find out what state he is
794 // in and force him to wakeup and call exit().
795
796 force_resume(); // this is necessary for when
797 // he is asleep AND suspended.
798 #ifdef CYGFUN_KERNEL_THREADS_TIMER
799 timer.disable(); // and make sure the timer
800 // does not persist.
801 #endif
802
803 switch( sleep_reason )
804 {
805
806 case NONE:
807 // The thread is not sleeping for any reason, it must be
808 // on a run queue.
809 // We can safely deschedule and set its state.
810 if( state == RUNNING ) Cyg_Scheduler::scheduler.rem_thread(this);
811 state = EXITED;
812 break;
813
814 case DESTRUCT:
815 case BREAK:
816 case EXIT:
817 case DONE:
818 // Do nothing in any of these cases. They are here to
819 // keep the compiler happy.
820
821 Cyg_Scheduler::unlock();
822 CYG_REPORT_RETURN();
823 return;
824
825 case WAIT:
826 // The thread was waiting for some sync object to do
827 // something.
828 // drop through...
829
830 case TIMEOUT:
831 // The thread was waiting on a sync object with a timeout.
832 // drop through...
833
834 case DELAY:
835 // The thread was simply delaying, unless it has been
836 // woken up for some other reason, wake it now.
837 sleep_reason = NONE;
838 wake_reason = EXIT;
839 break;
840 }
841
842 wake();
843
844 // Allow preemption
845 Cyg_Scheduler::unlock();
846 CYG_REPORT_RETURN();
847 }
848
849 // -------------------------------------------------------------------------
850 // Set thread priority
851
852 #ifdef CYGIMP_THREAD_PRIORITY
853
854 void
855 Cyg_Thread::set_priority( cyg_priority new_priority )
856 {
857 CYG_REPORT_FUNCTION();
858
859 // CYG_ASSERT( new_priority >= CYG_THREAD_MAX_PRIORITY, "Priority out of range");
860 // CYG_ASSERT( new_priority <= CYG_THREAD_MIN_PRIORITY, "Priority out of range");
861
862 CYG_INSTRUMENT_THREAD(PRIORITY,this,priority);
863
864 // Prevent preemption
865 Cyg_Scheduler::lock();
866
867 Cyg_ThreadQueue *queue = NULL;
868
869 // If running, remove from run qs
870 if( state == RUNNING )
871 Cyg_Scheduler::scheduler.rem_thread(this);
872 else if( state & SLEEPING )
873 {
874 // Remove thread from current queue.
875 queue = get_current_queue();
876 // if indeed we are on a queue
877 if ( NULL != queue ) {
878 CYG_CHECK_DATA_PTR(queue, "Bad queue pointer");
879 remove();
880 }
881 }
882
883 Cyg_Scheduler::scheduler.deregister_thread(this);
884
885 #if CYG_SCHED_UNIQUE_PRIORITIES
886
887 // Check that there are no other threads at this priority.
888 // If so, leave is as it is.
889
890 CYG_ASSERT( Cyg_Scheduler::scheduler.unique(new_priority), "Priority not unique");
891
892 if( Cyg_Scheduler::scheduler.unique(new_priority) )
893 priority = new_priority;
894
895 #else // !CYG_SCHED_UNIQUE_PRIORITIES
896
897 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE
898
899 // When we have priority inheritance, we must update the original
900 // priority and not the inherited one. If the new priority is
901 // better than the current inherited one, then use that
902 // immediately. We remain in inherited state to avoid problems
903 // with multiple mutex inheritances.
904
905 if( priority_inherited )
906 {
907 original_priority = new_priority;
908 if( priority > new_priority ) priority = new_priority;
909 }
910 else priority = new_priority;
911
912 #else
913
914 priority = new_priority;
915
916 #endif
917
918 #endif // CYG_SCHED_UNIQUE_PRIORITIES
919
920 Cyg_Scheduler::scheduler.register_thread(this);
921
922 // Return thread to scheduler if runnable
923 if( state == RUNNING )
924 Cyg_Scheduler::scheduler.add_thread(this);
925 else if ( state & SLEEPING )
926 {
927 // return to current queue
928 // if indeed we are on a queue
929 if ( NULL != queue ) {
930 CYG_CHECK_DATA_PTR(queue, "Bad queue pointer");
931 queue->enqueue(this);
932 }
933 }
934
935 // If the current thread is being reprioritized, set the
936 // reschedule flag to ensure that it gets rescheduled if
937 // necessary. (Strictly we only need to do this if the new
938 // priority is less than that of some other runnable thread, in
939 // practice checking that is as expensive as what the scheduler
940 // will do anyway).
941
942 if( this == Cyg_Scheduler::get_current_thread() )
943 Cyg_Scheduler::need_reschedule = true;
944
945 // Unlock the scheduler and maybe switch threads
946 Cyg_Scheduler::unlock();
947 CYG_REPORT_RETURN();
948 }
949
950 #endif
951
952
953 // -------------------------------------------------------------------------
954 // Thread delay function
955
956 void
957 Cyg_Thread::delay( cyg_tick_count delay)
958 {
959 CYG_REPORT_FUNCTION();
960
961 #if defined(CYGFUN_KERNEL_THREADS_TIMER) && defined(CYGVAR_KERNEL_COUNTERS_CLOCK)
962
963 CYG_INSTRUMENT_THREAD(DELAY,this,delay);
964
965 // Prevent preemption
966 Cyg_Scheduler::lock();
967
968 sleep();
969
970 set_timer( Cyg_Clock::real_time_clock->current_value()+delay, DELAY );
971
972 // Unlock the scheduler and maybe switch threads
973 Cyg_Scheduler::unlock();
974
975 // Clear the timeout. It is irrelevant whether the alarm has
976 // actually gone off or not.
977 clear_timer();
978
979 // and deal with anything else we must do when we return
980 switch( wake_reason ) {
981 case DESTRUCT:
982 case EXIT:
983 exit();
984 break;
985
986 default:
987 break;
988 }
989 #endif
990 CYG_REPORT_RETURN();
991 }
992
993 // -------------------------------------------------------------------------
994 //
995
996 #ifdef CYGPKG_KERNEL_EXCEPTIONS
997
998 void
999 Cyg_Thread::deliver_exception(
1000 cyg_code exception_number, // exception being raised
1001 CYG_ADDRWORD exception_info // exception specific info
1002 )
1003 {
1004 if( this == Cyg_Scheduler::get_current_thread() )
1005 {
1006 // Delivering to current thread, probably as a result
1007 // of a real hardware exception. Simply invoke the appropriate
1008 // handler.
1009
1010 exception_control.deliver_exception( exception_number, exception_info );
1011 }
1012 #ifdef CYGIMP_EXCEPTION_ASYNC
1013 else
1014 {
1015 // Delivering to another thread, probably as a result of one thread
1016 // invoking this function on another thread. Adjust the other thread's
1017 // state to make it execute the exception routine when it next runs.
1018
1019 // At present there is an unresolved problem here. We do not know what
1020 // state the destination thread is in. It may not be a suitable point at
1021 // which to invoke an exception routine. In most cases the exception
1022 // routine will be run in the scheduler thread switch code, where the world is
1023 // in an inconsistent state. We really need to run the routine at the
1024 // end of unlock_inner(). However this would add extra code to the scheduler,
1025 // and require a way of storing pending exceptions. So for now this option is
1026 // disabled and not yet implemented, it may never be.
1027
1028 }
1029 #endif
1030 }
1031
1032 #endif
1033
1034 // -------------------------------------------------------------------------
1035 // Per-thread data support
1036
1037 #ifdef CYGVAR_KERNEL_THREADS_DATA
1038
1039 // Set the data map bits for each free slot in the data array.
1040 cyg_ucount32 Cyg_Thread::thread_data_map = (~CYGNUM_KERNEL_THREADS_DATA_ALL) &
1041 ((1<<CYGNUM_KERNEL_THREADS_DATA_MAX)-1);
1042
1043 cyg_ucount32
1044 Cyg_Thread::new_data_index()
1045 {
1046 Cyg_Scheduler::lock();
1047
1048 cyg_ucount32 index;
1049
1050 CYG_ASSERT( thread_data_map != 0 , "No more thread data indexes");
1051
1052 // find ls set bit
1053 HAL_LSBIT_INDEX( index, thread_data_map );
1054
1055 // clear the bit
1056 thread_data_map &= ~(1<<index);
1057
1058 Cyg_Scheduler::unlock();
1059
1060 return index;
1061 }
1062
1063 void Cyg_Thread::free_data_index( cyg_ucount32 index )
1064 {
1065 Cyg_Scheduler::lock();
1066
1067 thread_data_map |= (1<<index);
1068
1069 Cyg_Scheduler::unlock();
1070 }
1071
1072
1073 #endif
1074
1075 // =========================================================================
1076 // Cyg_ThreadTimer member functions
1077
1078 // -------------------------------------------------------------------------
1079 // Timer alarm function. Inspect the sleep_reason and if necessary wake
1080 // up the thread with an appropriate wake_reason.
1081
1082 #ifdef CYGFUN_KERNEL_THREADS_TIMER
1083
1084 void
1085 Cyg_ThreadTimer::alarm(
1086 Cyg_Alarm *alarm,
1087 CYG_ADDRWORD data
1088 )
1089 {
1090 CYG_REPORT_FUNCTION();
1091
1092 Cyg_ThreadTimer *self = (Cyg_ThreadTimer *)data;
1093 Cyg_Thread *thread = self->thread;
1094
1095 CYG_INSTRUMENT_THREAD(ALARM, 0, 0);
1096
1097 Cyg_Scheduler::lock();
1098
1099 Cyg_Thread::cyg_reason sleep_reason = thread->get_sleep_reason();
1100
1101 switch( sleep_reason ) {
1102
1103 case Cyg_Thread::DESTRUCT:
1104 case Cyg_Thread::BREAK:
1105 case Cyg_Thread::EXIT:
1106 case Cyg_Thread::NONE:
1107 case Cyg_Thread::WAIT:
1108 case Cyg_Thread::DONE:
1109 // Do nothing in any of these cases. Most are here to
1110 // keep the compiler happy.
1111 Cyg_Scheduler::unlock();
1112 CYG_REPORT_RETURN();
1113 return;
1114
1115 case Cyg_Thread::DELAY:
1116 // The thread was simply delaying, unless it has been
1117 // woken up for some other reason, wake it now.
1118 thread->set_wake_reason(Cyg_Thread::DONE);
1119 break;
1120
1121 case Cyg_Thread::TIMEOUT:
1122 // The thread has timed out, set the wake reason to
1123 // TIMEOUT and restart.
1124 thread->set_wake_reason(Cyg_Thread::TIMEOUT);
1125 break;
1126 }
1127
1128 thread->wake();
1129
1130 Cyg_Scheduler::unlock();
1131 CYG_REPORT_RETURN();
1132 }
1133
1134 #endif
1135
1136 // =========================================================================
1137 // The Idle thread
1138 // The idle thread is implemented as a single instance of the
1139 // Cyg_IdleThread class. This is so that it can be initialized before
1140 // main in a static constructor.
1141
1142 // -------------------------------------------------------------------------
1143 // Data definitions
1144
1145 // stack
1146
1147 #ifdef CYG_HAL_MIPS
1148 extern char idle_thread_stack[CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE];
1149 #else
1150 char idle_thread_stack[CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE];
1151 #endif
1152
1153 // Loop counter for debugging/housekeeping
1154 cyg_uint32 idle_thread_loops = 1;
1155
1156 // -------------------------------------------------------------------------
1157 // Idle thread code.
1158
1159 void
1160 idle_thread_main( CYG_ADDRESS data )
1161 {
1162 CYG_REPORT_FUNCTION();
1163
1164 for(;;)
1165 {
1166 idle_thread_loops++;
1167
1168 HAL_IDLE_THREAD_ACTION(idle_thread_loops);
1169
1170 #if 0
1171 // For testing, it is useful to be able to fake
1172 // clock interrupts in the idle thread.
1173
1174 Cyg_Clock::real_time_clock->tick();
1175 #endif
1176 #ifdef CYGIMP_IDLE_THREAD_YIELD
1177 // In single priority and non-preemptive systems,
1178 // the idle thread should yield repeatedly to
1179 // other threads.
1180 Cyg_Thread::yield();
1181 #endif
1182 }
1183 }
1184
1185 // -------------------------------------------------------------------------
1186 // Idle thread class
1187
1188 class Cyg_IdleThread : public Cyg_Thread
1189 {
1190 public:
1191 Cyg_IdleThread(
1192 cyg_thread_entry *entry, // entry point function
1193 CYG_ADDRWORD entry_data, // entry data
1194 cyg_ucount32 stack_size = 0, // stack size, 0 = use default
1195 CYG_ADDRESS stack_base = 0 // stack base, NULL = allocate
1196 );
1197
1198 };
1199
1200 // -------------------------------------------------------------------------
1201 // Idle threads constructor
1202
1203 Cyg_IdleThread::Cyg_IdleThread(
1204 cyg_thread_entry *entry, // entry point function
1205 CYG_ADDRWORD entry_data, // entry data
1206 cyg_ucount32 stack_size, // stack size, 0 = use default
1207 CYG_ADDRESS stack_base // stack base, NULL = allocate
1208 )
1209 : Cyg_Thread( CYG_THREAD_MIN_PRIORITY,
1210 entry,
1211 entry_data,
1212 "Idle Thread",
1213 stack_base,
1214 stack_size)
1215 {
1216 CYG_REPORT_FUNCTION();
1217
1218 resume();
1219 CYG_REPORT_RETURN();
1220 }
1221
1222 // -------------------------------------------------------------------------
1223 // Instantiate the idle thread
1224
1225 Cyg_IdleThread idle_thread CYG_INIT_PRIORITY( IDLE_THREAD ) =
1226 Cyg_IdleThread( idle_thread_main,
1227 0,
1228 CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE,
1229 CYG_ADDRESS(idle_thread_stack)
1230 );
1231
1232
1233 // -------------------------------------------------------------------------
1234 // EOF common/thread.cxx