OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [kernel/] [current/] [src/] [common/] [thread.cxx] - Blame information for rev 851

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.