1 //==========================================================================
5 // POSIX pthreads implementation
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, jlarmour
46 // Purpose: POSIX pthread implementation
47 // Description: This file contains the implementation of the POSIX pthread
52 //####DESCRIPTIONEND####
54 //==========================================================================
56 #include <pkgconf/hal.h>
57 #include <pkgconf/kernel.h>
58 #include <pkgconf/posix.h>
59 #include <pkgconf/isoinfra.h>
60 #include <pkgconf/libc_startup.h>
62 #include <cyg/kernel/ktypes.h> // base kernel types
63 #include <cyg/infra/cyg_trac.h> // tracing macros
64 #include <cyg/infra/cyg_ass.h> // assertion macros
66 #include "pprivate.h" // POSIX private header
68 #include <stdlib.h> // malloc(), free()
70 #include <cyg/kernel/sched.hxx> // scheduler definitions
71 #include <cyg/kernel/thread.hxx> // thread definitions
72 #include <cyg/kernel/clock.hxx> // clock definitions
74 #include <cyg/kernel/sched.inl> // scheduler inlines
76 //-----------------------------------------------------------------------------
77 // First check that the configuration contains the elements we need
80 #error POSIX pthread need eCos kernel
83 #ifndef CYGSEM_KERNEL_SCHED_MLQUEUE
84 #error POSIX pthreads need MLQ scheduler
87 #ifndef CYGSEM_KERNEL_SCHED_TIMESLICE
88 #error POSIX pthreads need timeslicing
91 #ifndef CYGVAR_KERNEL_THREADS_DATA
92 #error POSIX pthreads need per-thread data
95 //=============================================================================
96 // Internal data structures
98 // Mutex for controlling access to shared data structures
99 Cyg_Mutex pthread_mutex CYGBLD_POSIX_INIT;
101 // Array of pthread control structures. A pthread_t object is
102 // "just" an index into this array.
103 static pthread_info *thread_table[CYGNUM_POSIX_PTHREAD_THREADS_MAX];
105 // Count of number of threads in table.
106 static int pthread_count = 0;
108 // Count of number of threads that have exited and not been reaped.
109 static int pthreads_exited;
111 // Count of number of threads that are waiting to be joined
112 static int pthreads_tobejoined;
114 // Per-thread key allocation. This key map has a 1 bit set for each
115 // key that is free, zero if it is allocated.
116 #define KEY_MAP_TYPE cyg_uint32
117 #define KEY_MAP_TYPE_SIZE (sizeof(KEY_MAP_TYPE)*8) // in BITS!
118 static KEY_MAP_TYPE thread_key[PTHREAD_KEYS_MAX/KEY_MAP_TYPE_SIZE];
119 static void (*key_destructor[PTHREAD_KEYS_MAX]) (void *);
121 // Index of next pthread_info to allocate from thread_table array.
122 static int thread_info_next = 0;
124 // This is used to make pthread_t values unique even when reusing
125 // a table slot. This allows CYGNUM_POSIX_PTHREAD_THREADS_MAX to range
127 #define THREAD_ID_COOKIE_INC 0x00000400
128 #define THREAD_ID_COOKIE_MASK (THREAD_ID_COOKIE_INC-1)
129 static pthread_t thread_id_cookie = THREAD_ID_COOKIE_INC;
131 //-----------------------------------------------------------------------------
134 #define MAIN_DEFAULT_STACK_SIZE \
135 (CYGNUM_LIBC_MAIN_DEFAULT_STACK_SIZE < PTHREAD_STACK_MIN \
136 ? PTHREAD_STACK_MIN : CYGNUM_LIBC_MAIN_DEFAULT_STACK_SIZE)
138 static char main_stack[MAIN_DEFAULT_STACK_SIZE];
140 // Thread ID of main thread.
141 static pthread_t main_thread;
143 //=============================================================================
144 // Exported variables
146 int pthread_canceled_dummy_var; // pointed to by PTHREAD_CANCELED
148 //=============================================================================
149 // Internal functions
151 //-----------------------------------------------------------------------------
152 // Private version of pthread_self() that returns a pointer to our internal
153 // control structure.
155 pthread_info *pthread_self_info(void)
157 Cyg_Thread *thread = Cyg_Thread::self();
159 CYG_CHECK_DATA_PTR(thread, "Illegal current thread");
161 pthread_info *info = (pthread_info *)thread->get_data(CYGNUM_KERNEL_THREADS_DATA_POSIX);
163 // This assertion mustn't be enabled because sometimes we can legitimately
164 // carefully call this as long as we realise the value can be NULL.
165 // e.g. consider the use of this when inheriting sigmasks when in the
166 // context of creating the main() thread.
167 // CYG_CHECK_DATA_PTR(info, "Not a POSIX thread!!!");
172 externC pthread_info *pthread_info_id( pthread_t id )
174 pthread_t index = id & THREAD_ID_COOKIE_MASK;
176 pthread_info *info = thread_table[index];
178 // Check for a valid entry
182 // Check that this is a valid entry
183 if ( info->state == PTHREAD_STATE_FREE ||
184 info->state == PTHREAD_STATE_EXITED )
187 // Check that the entry matches the id
188 if( info->id != id ) return NULL;
190 // Return the pointer
194 //-----------------------------------------------------------------------------
195 // new operator to allow us to invoke the Cyg_Thread constructor on the
196 // pthread_info.thread_obj array.
198 inline void *operator new(size_t size, cyg_uint8 *ptr) { return (void *)ptr; };
200 //-----------------------------------------------------------------------------
201 // Optional memory allocation functions for pthread stacks.
202 // If there is an implementation of malloc() available, define pthread_malloc()
203 // and pthread_free() to use it. Otherwise define them to do nothing.
204 // In the future we may want to add configuration here to permit thread stacks
205 // to be allocated in a nominated memory pool separate from the standard malloc()
206 // pool. Hence the (currently redundant) encapsulation of these functions.
208 #if CYGINT_ISO_MALLOC
210 static __inline__ CYG_ADDRWORD pthread_malloc( CYG_ADDRWORD size )
212 return (CYG_ADDRWORD)malloc( size );
215 static __inline__ void pthread_free( CYG_ADDRWORD m )
220 #define PTHREAD_MALLOC
224 #define pthread_malloc(_x_) (0)
226 #define pthread_free(_x_)
230 //-----------------------------------------------------------------------------
231 // pthread entry function.
232 // does some housekeeping and then calls the user's start routine.
234 static void pthread_entry(CYG_ADDRWORD data)
236 pthread_info *self = (pthread_info *)data;
238 void *retval = self->start_routine(self->start_arg);
240 pthread_exit( retval );
243 //-----------------------------------------------------------------------------
244 // Main entry function.
245 // This is set as the start_routine of the main thread. It invokes main()
246 // and if it returns, shuts down the system.
248 externC void cyg_libc_invoke_main( void );
250 static void *call_main( void * )
252 cyg_libc_invoke_main();
253 return NULL; // placate compiler
256 //-----------------------------------------------------------------------------
257 // Check whether there is a cancel pending and if so, whether
258 // cancellations are enabled. We do it in this order to reduce the
259 // number of tests in the common case - when no cancellations are
261 // We make this inline so it can be called directly below for speed
263 static __inline__ int
264 checkforcancel( void )
266 pthread_info *self = pthread_self_info();
269 self->cancelpending &&
270 self->cancelstate == PTHREAD_CANCEL_ENABLE )
277 //-----------------------------------------------------------------------------
279 // This is installed as the ASR for all POSIX threads.
281 static void posix_asr( CYG_ADDRWORD data )
283 pthread_info *self = (pthread_info *)data;
285 #ifdef CYGPKG_POSIX_TIMERS
286 // Call into timer subsystem to deliver any pending
287 // timer expirations.
288 cyg_posix_timer_asr(self);
291 #ifdef CYGPKG_POSIX_SIGNALS
292 // Call signal subsystem to deliver any signals
293 cyg_posix_signal_asr(self);
296 // Check for cancellation
297 if( self->cancelpending &&
298 self->cancelstate == PTHREAD_CANCEL_ENABLE &&
299 self->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS )
301 // If we have a pending cancellation, cancellations are
302 // enabled and we are in asynchronous mode, then we can do the
303 // cancellation processing. Since pthread_exit() does
304 // everything we need to do, we just call that here.
306 pthread_exit(PTHREAD_CANCELED);
310 //-----------------------------------------------------------------------------
311 // The (Grim) Reaper.
312 // This function is called to tidy up and dispose of any threads that have
313 // exited. This work must be done from a thread other than the one exiting.
314 // Note: this function _must_ be called with pthread_mutex locked.
316 static void pthread_reap()
320 // Loop over the thread table looking for exited threads. The
321 // pthreads_exited counter springs us out of this once we have
322 // found them all (and keeps us out if there are none to do).
324 for( i = 0; pthreads_exited && i < CYGNUM_POSIX_PTHREAD_THREADS_MAX ; i++ )
326 pthread_info *thread = thread_table[i];
328 if( thread != NULL && thread->state == PTHREAD_STATE_EXITED )
330 // The thread has exited, so it is a candidate for being
331 // reaped. We have to make sure that the eCos thread has
332 // also reached EXITED state before we can tidy it up.
334 while( thread->thread->get_state() != Cyg_Thread::EXITED )
336 // The eCos thread has not yet exited. This is
337 // probably because its priority is too low to allow
338 // it to complete. We fix this here by raising its
339 // priority to equal ours and then yielding. This
340 // should eventually get it into exited state.
342 Cyg_Thread *self = Cyg_Thread::self();
344 // Set thread's priority to our current dispatching priority.
345 thread->thread->set_priority( self->get_current_priority() );
350 // and keep looping until he exits.
353 // At this point we have a thread that we can reap.
355 // destroy the eCos thread
356 thread->thread->~Cyg_Thread();
358 // destroy the joiner condvar
359 thread->joiner->~Cyg_Condition_Variable();
361 #ifdef CYGPKG_POSIX_SIGNALS
362 // Destroy signal handling fields
363 cyg_posix_thread_sigdestroy( thread );
366 // Free the stack if we allocated it
367 if( thread->freestack )
368 pthread_free( thread->stackmem );
370 // Finally, set the thread table entry to NULL so that it
372 thread_table[i] = NULL;
380 //=============================================================================
381 // Functions exported to rest of POSIX subsystem.
383 //-----------------------------------------------------------------------------
384 // Create the main() thread.
386 externC void cyg_posix_pthread_start( void )
389 // Initialize the per-thread data key map.
391 for( cyg_ucount32 i = 0; i < (PTHREAD_KEYS_MAX/KEY_MAP_TYPE_SIZE); i++ )
396 // Create the main thread
398 struct sched_param schedparam;
400 schedparam.sched_priority = CYGNUM_POSIX_MAIN_DEFAULT_PRIORITY;
402 pthread_attr_init( &attr );
403 pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );
404 pthread_attr_setstackaddr( &attr, &main_stack[sizeof(main_stack)] );
405 pthread_attr_setstacksize( &attr, sizeof(main_stack) );
406 pthread_attr_setschedpolicy( &attr, SCHED_RR );
407 pthread_attr_setschedparam( &attr, &schedparam );
409 pthread_create( &main_thread, &attr, call_main, NULL );
412 #ifdef CYGPKG_POSIX_SIGNALS
413 //-----------------------------------------------------------------------------
414 // Look for a thread that can accept delivery of any of the signals in
415 // the mask and release it from any wait it is in. Since this may be
416 // called from a DSR, it cannot use any locks internally - any locking
417 // should be done before the call.
419 externC void cyg_posix_pthread_release_thread( sigset_t *mask )
422 int count = pthread_count;
424 // Loop over the thread table looking for a thread that has a
425 // signal mask that does not mask all the signals in mask.
426 // FIXME: find a more efficient way of doing this.
428 for( i = 0; count > 0 && i < CYGNUM_POSIX_PTHREAD_THREADS_MAX ; i++ )
430 pthread_info *thread = thread_table[i];
432 if( (thread != NULL) &&
433 (thread->state <= PTHREAD_STATE_RUNNING) &&
434 ((*mask & ~thread->sigmask) != 0) )
436 // This thread can service at least one of the signals in
437 // *mask. Knock it out of its wait and make its ASR pending.
439 thread->thread->set_asr_pending();
440 thread->thread->release();
444 // Decrement count for each valid thread we find.
445 if( thread != NULL && thread->state != PTHREAD_STATE_FREE )
451 //=============================================================================
452 // General thread operations
454 //-----------------------------------------------------------------------------
455 // Thread creation and management.
458 externC int pthread_create ( pthread_t *thread,
459 const pthread_attr_t *attr,
460 void *(*start_routine) (void *),
465 PTHREAD_CHECK(thread);
466 PTHREAD_CHECK(start_routine);
468 pthread_info *self = pthread_self_info();
470 pthread_attr_t use_attr;
472 // Set use_attr to the set of attributes we are going to
473 // actually use. Either those passed in, or the default set.
476 pthread_attr_init( &use_attr );
477 else use_attr = *attr;
479 // Adjust the attributes to cope with the setting of inheritsched.
481 if( use_attr.inheritsched == PTHREAD_INHERIT_SCHED )
483 CYG_ASSERT( NULL != self,
484 "Attempt to inherit sched policy from non-POSIX thread" );
485 #ifdef CYGDBG_USE_ASSERTS
488 for (i=(sizeof(thread_table)/sizeof(*thread_table))-1; i>=0; i--) {
489 if (thread_table[i] == self)
492 CYG_ASSERT( i>=0, "Current pthread not found in table" );
494 use_attr.schedpolicy = self->attr.schedpolicy;
495 use_attr.schedparam = self->attr.schedparam;
498 CYG_ADDRWORD stackbase, stacksize;
499 cyg_bool freestack = false;
500 CYG_ADDRWORD stackmem = 0;
502 // If the stack size is not valid, we can assume that it is at
503 // least PTHREAD_STACK_MIN bytes.
505 if( use_attr.stacksize_valid )
506 stacksize = use_attr.stacksize;
507 else stacksize = PTHREAD_STACK_MIN;
509 if( use_attr.stackaddr_valid )
511 // Set up stack base and size from supplied arguments.
513 // Calculate stack base from address and size.
514 // FIXME: Falling stack assumed in pthread_create().
515 stackmem = stackbase = (CYG_ADDRWORD)use_attr.stackaddr-stacksize;
519 #ifdef PTHREAD_MALLOC
521 stackmem = stackbase = pthread_malloc( stacksize );
524 PTHREAD_RETURN( EAGAIN );
528 PTHREAD_RETURN(EINVAL);
533 // Get sole access to data structures
535 pthread_mutex.lock();
537 // Dispose of any dead threads
540 // Find a free slot in the thread table
542 pthread_info *nthread;
543 int thread_next = thread_info_next;
545 while( thread_table[thread_next] != NULL )
548 if( thread_next >= CYGNUM_POSIX_PTHREAD_THREADS_MAX )
551 // check for wrap, and return error if no slots left
552 if( thread_next == thread_info_next )
554 pthread_mutex.unlock();
556 pthread_free( stackmem );
557 PTHREAD_RETURN(ENOMEM);
561 nthread = (pthread_info *)stackbase;
563 stackbase += sizeof(pthread_info);
564 stacksize -= sizeof(pthread_info);
566 thread_table[thread_next] = nthread;
568 // Set new next index
569 thread_info_next = thread_next;
572 thread_id_cookie += THREAD_ID_COOKIE_INC;
574 // Initialize the table entry
575 nthread->state = use_attr.detachstate == PTHREAD_CREATE_JOINABLE ?
576 PTHREAD_STATE_RUNNING : PTHREAD_STATE_DETACHED;
577 nthread->id = thread_next+thread_id_cookie;
578 nthread->attr = use_attr;
580 nthread->start_routine = start_routine;
581 nthread->start_arg = arg;
583 nthread->freestack = freestack;
584 nthread->stackmem = stackmem;
586 nthread->cancelstate = PTHREAD_CANCEL_ENABLE;
587 nthread->canceltype = PTHREAD_CANCEL_DEFERRED;
588 nthread->cancelbuffer = NULL;
589 nthread->cancelpending = false;
591 nthread->thread_data = NULL;
593 #ifdef CYGVAR_KERNEL_THREADS_NAME
594 // generate a name for this thread
596 char *name = nthread->name;
597 static char *name_template = "pthread.00000000";
598 pthread_t id = nthread->id;
600 for( int i = 0; name_template[i]; i++ ) name[i] = name_template[i];
602 // dump the id, in hex into the name.
603 for( int i = 15; i >= 8; i-- )
605 name[i] = "0123456789ABCDEF"[id&0xF];
611 // Initialize the joiner condition variable
613 nthread->joiner = new(nthread->joiner_obj) Cyg_Condition_Variable( pthread_mutex );
615 #ifdef CYGPKG_POSIX_SIGNALS
616 // Initialize signal specific fields.
618 CYG_CHECK_DATA_PTR( self,
619 "Attempt to inherit signal mask from bogus pthread" );
620 #ifdef CYGDBG_USE_ASSERTS
623 for (i=(sizeof(thread_table)/sizeof(*thread_table))-1; i>=0; i--) {
624 if (thread_table[i] == self)
627 CYG_ASSERT( i>=0, "Current pthread not found in table" );
630 cyg_posix_thread_siginit( nthread, self );
633 // create the underlying eCos thread
635 nthread->thread = new(&nthread->thread_obj[0])
636 Cyg_Thread ( PTHREAD_ECOS_PRIORITY(use_attr.schedparam.sched_priority),
638 (CYG_ADDRWORD)nthread,
639 #ifdef CYGVAR_KERNEL_THREADS_NAME
647 // Put pointer to pthread_info into eCos thread's per-thread data.
648 nthread->thread->set_data( CYGNUM_KERNEL_THREADS_DATA_POSIX, (CYG_ADDRWORD)nthread );
650 // Set timeslice enable according to scheduling policy.
651 if( use_attr.schedpolicy == SCHED_FIFO )
652 nthread->thread->timeslice_disable();
653 else nthread->thread->timeslice_enable();
655 // set up ASR and data
656 nthread->thread->set_asr( posix_asr, (CYG_ADDRWORD)nthread, NULL, NULL );
659 *thread = nthread->id;
663 pthread_mutex.unlock();
665 // finally, set the thread going
666 nthread->thread->resume();
671 //-----------------------------------------------------------------------------
672 // Get current thread id.
674 externC pthread_t pthread_self ( void )
678 pthread_info *info = pthread_self_info();
680 CYG_CHECK_DATA_PTR(info, "Not a POSIX thread!!!");
685 //-----------------------------------------------------------------------------
686 // Compare two thread identifiers.
688 externC int pthread_equal (pthread_t thread1, pthread_t thread2)
692 return thread1 == thread2;
695 //-----------------------------------------------------------------------------
696 // Terminate current thread.
698 externC void exit(int) CYGBLD_ATTRIB_NORET;
700 externC void pthread_exit (void *retval)
704 pthread_info *self = pthread_self_info();
706 // Disable cancellation requests for this thread. If cleanup
707 // handlers exist, they will generally be issuing system calls
708 // to clean up resources. We want these system calls to run
709 // without cancelling, and we also want to prevent being
711 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
713 // Call cancellation handlers. We eat up the buffers as we go in
714 // case any of the routines calls pthread_exit() itself.
715 while( self->cancelbuffer != NULL )
717 struct pthread_cleanup_buffer *buffer = self->cancelbuffer;
719 self->cancelbuffer = buffer->prev;
721 buffer->routine(buffer->arg);
724 if( self->thread_data != NULL )
726 // Call per-thread key destructors.
727 // The specification of this is that we must continue to call the
728 // destructor functions until all the per-thread data values are NULL or
729 // we have done it PTHREAD_DESTRUCTOR_ITERATIONS times.
731 cyg_bool destructors_called;
732 int destructor_iterations = 0;
736 destructors_called = false;
738 for( cyg_ucount32 key = 0; key < PTHREAD_KEYS_MAX; key++ )
740 // Skip unallocated keys
741 if( thread_key[key/KEY_MAP_TYPE_SIZE] & 1<<(key%KEY_MAP_TYPE_SIZE) )
744 // Skip NULL destructors
745 if( key_destructor[key] == NULL ) continue;
747 // Skip NULL data values
748 if( self->thread_data[key] == NULL ) continue;
750 // If it passes all that, call the destructor.
751 // Note that NULLing the data value here is new
752 // behaviour in the 2001 POSIX standard.
754 void* value = self->thread_data[key];
755 self->thread_data[key] = NULL;
756 key_destructor[key](value);
759 // Record that we called a destructor
760 destructors_called = true;
763 // Count the iteration
764 destructor_iterations++;
766 } while( destructors_called &&
767 (destructor_iterations <= PTHREAD_DESTRUCTOR_ITERATIONS));
771 pthread_mutex.lock();
773 // Set the retval for any joiner
774 self->retval = retval;
776 // If we are already detached, go to EXITED state, otherwise
777 // go into JOIN state.
779 if ( PTHREAD_STATE_DETACHED == self->state ) {
780 self->state = PTHREAD_STATE_EXITED;
783 self->state = PTHREAD_STATE_JOIN;
784 pthreads_tobejoined++;
787 // Kick any waiting joiners
788 self->joiner->broadcast();
790 cyg_bool call_exit=false;
792 // if this is the last thread (other than threads waiting to be joined)
793 // then we need to call exit() later
794 if ( pthreads_exited + pthreads_tobejoined == pthread_count )
797 pthread_mutex.unlock();
799 // Finally, call the exit function; this will not return.
803 self->thread->exit();
805 // This loop keeps some compilers happy. pthread_exit() is marked
806 // with the noreturn attribute, and without this they generate a
807 // call to abort() here in case Cyg_Thread::exit() returns.
812 //-----------------------------------------------------------------------------
813 // Wait for the thread to terminate. If thread_return is not NULL then
814 // the retval from the thread's call to pthread_exit() is stored at
817 externC int pthread_join (pthread_t thread, void **thread_return)
823 // check for cancellation first.
824 pthread_testcancel();
826 pthread_mutex.lock();
828 // Dispose of any dead threads
831 pthread_info *self = pthread_self_info();
832 pthread_info *joinee = pthread_info_id( thread );
839 if( !err && joinee == self )
845 switch ( joinee->state )
847 case PTHREAD_STATE_RUNNING:
848 // The thread is still running, we must wait for it.
849 while( joinee->state == PTHREAD_STATE_RUNNING ) {
850 if ( !joinee->joiner->wait() )
851 // check if we were woken because we were being cancelled
852 if ( checkforcancel() ) {
853 err = EAGAIN; // value unimportant, just some error
858 // check that the thread is still joinable
859 if( joinee->state == PTHREAD_STATE_JOIN )
862 // The thread has become unjoinable while we waited, so we
863 // fall through to complain.
865 case PTHREAD_STATE_FREE:
866 case PTHREAD_STATE_DETACHED:
867 case PTHREAD_STATE_EXITED:
868 // None of these may be joined.
872 case PTHREAD_STATE_JOIN:
879 // here, we know that joinee is a thread that has exited and is
880 // ready to be joined.
883 if( thread_return != NULL )
884 *thread_return = joinee->retval;
886 // set state to exited.
887 joinee->state = PTHREAD_STATE_EXITED;
889 pthreads_tobejoined--;
891 // Dispose of any dead threads
895 pthread_mutex.unlock();
897 // check for cancellation before returning
898 pthread_testcancel();
903 //-----------------------------------------------------------------------------
904 // Set the detachstate of the thread to "detached". The thread then does not
905 // need to be joined and its resources will be freed when it exits.
907 externC int pthread_detach (pthread_t thread)
913 pthread_mutex.lock();
915 pthread_info *detachee = pthread_info_id( thread );
917 if( detachee == NULL )
918 ret = ESRCH; // No such thread
919 else if( detachee->state == PTHREAD_STATE_DETACHED )
920 ret = EINVAL; // Already detached!
923 // Set state to detached and kick any joinees to
925 detachee->state = PTHREAD_STATE_DETACHED;
926 detachee->joiner->broadcast();
929 // Dispose of any dead threads
932 pthread_mutex.unlock();
938 //-----------------------------------------------------------------------------
939 // Thread attribute handling.
941 //-----------------------------------------------------------------------------
942 // Initialize attributes object with default attributes:
943 // detachstate == PTHREAD_CREATE_JOINABLE
944 // scope == PTHREAD_SCOPE_SYSTEM
945 // inheritsched == PTHREAD_INHERIT_SCHED
946 // schedpolicy == SCHED_OTHER
947 // schedparam == unset
948 // stackaddr == unset
952 externC int pthread_attr_init (pthread_attr_t *attr)
958 attr->detachstate = PTHREAD_CREATE_JOINABLE;
959 attr->scope = PTHREAD_SCOPE_SYSTEM;
960 attr->inheritsched = PTHREAD_INHERIT_SCHED;
961 attr->schedpolicy = SCHED_OTHER;
962 attr->schedparam.sched_priority = 0;
963 attr->stackaddr_valid = 0;
964 attr->stackaddr = NULL;
965 attr->stacksize_valid = 0;
971 //-----------------------------------------------------------------------------
972 // Destroy thread attributes object
974 externC int pthread_attr_destroy (pthread_attr_t *attr)
980 // Nothing to do here...
985 //-----------------------------------------------------------------------------
986 // Set the detachstate attribute
988 externC int pthread_attr_setdetachstate (pthread_attr_t *attr,
995 if( detachstate == PTHREAD_CREATE_JOINABLE ||
996 detachstate == PTHREAD_CREATE_DETACHED )
998 attr->detachstate = detachstate;
1002 PTHREAD_RETURN(EINVAL);
1005 //-----------------------------------------------------------------------------
1006 // Get the detachstate attribute
1007 externC int pthread_attr_getdetachstate (const pthread_attr_t *attr,
1012 PTHREAD_CHECK(attr);
1014 if( detachstate != NULL )
1015 *detachstate = attr->detachstate;
1020 //-----------------------------------------------------------------------------
1021 // Set scheduling contention scope
1023 externC int pthread_attr_setscope (pthread_attr_t *attr, int scope)
1027 PTHREAD_CHECK(attr);
1029 if( scope == PTHREAD_SCOPE_SYSTEM ||
1030 scope == PTHREAD_SCOPE_PROCESS )
1032 if( scope == PTHREAD_SCOPE_PROCESS )
1033 PTHREAD_RETURN(ENOTSUP);
1035 attr->scope = scope;
1040 PTHREAD_RETURN(EINVAL);
1043 //-----------------------------------------------------------------------------
1044 // Get scheduling contention scope
1046 externC int pthread_attr_getscope (const pthread_attr_t *attr, int *scope)
1050 PTHREAD_CHECK(attr);
1053 *scope = attr->scope;
1058 //-----------------------------------------------------------------------------
1059 // Set scheduling inheritance attribute
1061 externC int pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit)
1065 PTHREAD_CHECK(attr);
1067 if( inherit == PTHREAD_INHERIT_SCHED ||
1068 inherit == PTHREAD_EXPLICIT_SCHED )
1070 attr->inheritsched = inherit;
1075 PTHREAD_RETURN(EINVAL);
1078 //-----------------------------------------------------------------------------
1079 // Get scheduling inheritance attribute
1081 externC int pthread_attr_getinheritsched (const pthread_attr_t *attr,
1086 PTHREAD_CHECK(attr);
1088 if( inherit != NULL )
1089 *inherit = attr->inheritsched;
1094 //-----------------------------------------------------------------------------
1095 // Set scheduling policy
1097 externC int pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy)
1101 PTHREAD_CHECK(attr);
1103 if( policy == SCHED_OTHER ||
1104 policy == SCHED_FIFO ||
1105 policy == SCHED_RR )
1107 attr->schedpolicy = policy;
1112 PTHREAD_RETURN(EINVAL);
1115 //-----------------------------------------------------------------------------
1116 // Get scheduling policy
1118 externC int pthread_attr_getschedpolicy (const pthread_attr_t *attr,
1123 PTHREAD_CHECK(attr);
1125 if( policy != NULL )
1126 *policy = attr->schedpolicy;
1131 //-----------------------------------------------------------------------------
1132 // Set scheduling parameters
1133 externC int pthread_attr_setschedparam (pthread_attr_t *attr,
1134 const struct sched_param *param)
1138 PTHREAD_CHECK(attr);
1139 PTHREAD_CHECK(param);
1141 attr->schedparam = *param;
1146 //-----------------------------------------------------------------------------
1147 // Get scheduling parameters
1149 externC int pthread_attr_getschedparam (const pthread_attr_t *attr,
1150 struct sched_param *param)
1154 PTHREAD_CHECK(attr);
1157 *param = attr->schedparam;
1162 //-----------------------------------------------------------------------------
1163 // Set starting address of stack. Whether this is at the start or end of
1164 // the memory block allocated for the stack depends on whether the stack
1165 // grows up or down.
1167 externC int pthread_attr_setstackaddr (pthread_attr_t *attr, void *stackaddr)
1171 PTHREAD_CHECK(attr);
1173 attr->stackaddr = stackaddr;
1174 attr->stackaddr_valid = 1;
1179 //-----------------------------------------------------------------------------
1180 // Get any previously set stack address.
1182 externC int pthread_attr_getstackaddr (const pthread_attr_t *attr,
1187 PTHREAD_CHECK(attr);
1189 if( stackaddr != NULL )
1191 if( attr->stackaddr_valid )
1193 *stackaddr = attr->stackaddr;
1196 // Stack address not set, return EINVAL.
1197 else PTHREAD_RETURN(EINVAL);
1204 //-----------------------------------------------------------------------------
1205 // Set minimum creation stack size.
1207 externC int pthread_attr_setstacksize (pthread_attr_t *attr,
1212 PTHREAD_CHECK(attr);
1214 CYG_ASSERT( stacksize >= PTHREAD_STACK_MIN, "Inadequate stack size supplied");
1216 // Reject inadequate stack sizes
1217 if( stacksize < PTHREAD_STACK_MIN )
1218 PTHREAD_RETURN(EINVAL);
1220 attr->stacksize_valid = 1;
1221 attr->stacksize = stacksize;
1226 //-----------------------------------------------------------------------------
1227 // Get current minimal stack size.
1229 externC int pthread_attr_getstacksize (const pthread_attr_t *attr,
1234 PTHREAD_CHECK(attr);
1236 // Reject attempts to get a stack size when one has not been set.
1237 if( !attr->stacksize_valid )
1238 PTHREAD_RETURN(EINVAL);
1240 if( stacksize != NULL )
1241 *stacksize = attr->stacksize;
1246 //-----------------------------------------------------------------------------
1247 // Thread scheduling controls
1249 //-----------------------------------------------------------------------------
1250 // Set scheduling policy and parameters for the thread
1252 externC int pthread_setschedparam (pthread_t thread_id,
1254 const struct sched_param *param)
1258 if( policy != SCHED_OTHER &&
1259 policy != SCHED_FIFO &&
1260 policy != SCHED_RR )
1261 PTHREAD_RETURN(EINVAL);
1263 PTHREAD_CHECK(param);
1265 // The parameters seem OK, change the thread...
1267 pthread_mutex.lock();
1269 pthread_info *thread = pthread_info_id( thread_id );
1271 if( thread == NULL )
1273 pthread_mutex.unlock();
1274 PTHREAD_RETURN(ESRCH);
1277 thread->attr.schedpolicy = policy;
1278 thread->attr.schedparam = *param;
1280 if ( policy == SCHED_FIFO )
1281 thread->thread->timeslice_disable();
1282 else thread->thread->timeslice_enable();
1284 thread->thread->set_priority( PTHREAD_ECOS_PRIORITY( param->sched_priority ));
1286 pthread_mutex.unlock();
1291 //-----------------------------------------------------------------------------
1292 // Get scheduling policy and parameters for the thread
1294 externC int pthread_getschedparam (pthread_t thread_id,
1296 struct sched_param *param)
1300 pthread_mutex.lock();
1302 pthread_info *thread = pthread_info_id( thread_id );
1304 if( thread == NULL )
1306 pthread_mutex.unlock();
1307 PTHREAD_RETURN(ESRCH);
1310 if( policy != NULL )
1311 *policy = thread->attr.schedpolicy;
1314 *param = thread->attr.schedparam;
1316 pthread_mutex.unlock();
1322 //=============================================================================
1323 // Dynamic package initialization
1324 // Call init_routine just the once per control variable.
1326 externC int pthread_once (pthread_once_t *once_control,
1327 void (*init_routine) (void))
1331 PTHREAD_CHECK( once_control );
1332 PTHREAD_CHECK( init_routine );
1336 // Do a test and set on the once_control object.
1337 pthread_mutex.lock();
1339 old = *once_control;
1342 pthread_mutex.unlock();
1344 // If the once_control was zero, call the init_routine().
1345 if( !old ) init_routine();
1351 //=============================================================================
1352 //Thread specific data
1354 //-----------------------------------------------------------------------------
1355 // Create a key to identify a location in the thread specific data area.
1356 // Each thread has its own distinct thread-specific data area but all are
1357 // addressed by the same keys. The destructor function is called whenever a
1358 // thread exits and the value associated with the key is non-NULL.
1360 externC int pthread_key_create (pthread_key_t *key,
1361 void (*destructor) (void *))
1365 pthread_key_t k = -1;
1367 pthread_mutex.lock();
1369 // Find a key to allocate
1370 for( cyg_ucount32 i = 0; i < (PTHREAD_KEYS_MAX/KEY_MAP_TYPE_SIZE); i++ )
1372 if( thread_key[i] != 0 )
1374 // We have a table slot with space available
1376 // Get index of ls set bit.
1377 HAL_LSBIT_INDEX( k, thread_key[i] );
1380 thread_key[i] &= ~(1<<k);
1382 // Add index of word
1383 k += i * KEY_MAP_TYPE_SIZE;
1385 // Install destructor
1386 key_destructor[k] = destructor;
1388 // break out with key found
1395 // plant a NULL in all the valid thread data slots for this
1396 // key in case we are reusing a key we used before.
1398 for( cyg_ucount32 i = 0; i < CYGNUM_POSIX_PTHREAD_THREADS_MAX ; i++ )
1400 pthread_info *thread = thread_table[i];
1402 if( thread != NULL && thread->thread_data != NULL )
1403 thread->thread_data[k] = NULL;
1407 pthread_mutex.unlock();
1409 if( k == -1 ) PTHREAD_RETURN(EAGAIN);
1416 //-----------------------------------------------------------------------------
1419 externC int pthread_key_delete (pthread_key_t key)
1423 pthread_mutex.lock();
1425 // Set the key bit to 1 to indicate it is free.
1426 thread_key[key/KEY_MAP_TYPE_SIZE] |= 1<<(key%(KEY_MAP_TYPE_SIZE));
1428 pthread_mutex.unlock();
1433 //-----------------------------------------------------------------------------
1434 // Store the pointer value in the thread-specific data slot addressed
1437 externC int pthread_setspecific (pthread_key_t key, const void *pointer)
1441 if( thread_key[key/KEY_MAP_TYPE_SIZE] & 1<<(key%KEY_MAP_TYPE_SIZE) )
1442 PTHREAD_RETURN(EINVAL);
1444 pthread_info *self = pthread_self_info();
1446 if( self->thread_data == NULL )
1448 // Allocate the per-thread data table
1450 (void **)self->thread->increment_stack_limit(
1451 PTHREAD_KEYS_MAX * sizeof(void *) );
1453 // Clear out all entries
1454 for( int i = 0; i < PTHREAD_KEYS_MAX; i++ )
1455 self->thread_data[i] = NULL;
1458 self->thread_data[key] = (void *)pointer;
1463 //-----------------------------------------------------------------------------
1464 // Retrieve the pointer value in the thread-specific data slot addressed
1467 externC void *pthread_getspecific (pthread_key_t key)
1472 if( thread_key[key/KEY_MAP_TYPE_SIZE] & 1<<(key%KEY_MAP_TYPE_SIZE) )
1473 PTHREAD_RETURN(NULL);
1475 pthread_info *self = pthread_self_info();
1477 if( self->thread_data == NULL )
1479 else val = self->thread_data[key];
1481 PTHREAD_RETURN(val);
1484 //=============================================================================
1485 // Thread Cancellation Functions
1487 //-----------------------------------------------------------------------------
1488 // Set cancel state of current thread to ENABLE or DISABLE.
1489 // Returns old state in *oldstate.
1491 externC int pthread_setcancelstate (int state, int *oldstate)
1495 if( state != PTHREAD_CANCEL_ENABLE &&
1496 state != PTHREAD_CANCEL_DISABLE )
1497 PTHREAD_RETURN(EINVAL);
1499 pthread_mutex.lock();
1501 pthread_info *self = pthread_self_info();
1503 if( oldstate != NULL ) *oldstate = self->cancelstate;
1505 self->cancelstate = state;
1507 pthread_mutex.unlock();
1509 // Note: This function may have made it possible for a pending
1510 // cancellation to now be delivered. However the standard does not
1511 // list this function as a cancellation point, so for now we do
1512 // nothing. In future we might call pthread_testcancel() here.
1517 //-----------------------------------------------------------------------------
1518 // Set cancel type of current thread to ASYNCHRONOUS or DEFERRED.
1519 // Returns old type in *oldtype.
1521 externC int pthread_setcanceltype (int type, int *oldtype)
1525 if( type != PTHREAD_CANCEL_ASYNCHRONOUS &&
1526 type != PTHREAD_CANCEL_DEFERRED )
1527 PTHREAD_RETURN(EINVAL);
1529 pthread_mutex.lock();
1531 pthread_info *self = pthread_self_info();
1533 if( oldtype != NULL ) *oldtype = self->canceltype;
1535 self->canceltype = type;
1537 pthread_mutex.unlock();
1539 // Note: This function may have made it possible for a pending
1540 // cancellation to now be delivered. However the standard does not
1541 // list this function as a cancellation point, so for now we do
1542 // nothing. In future we might call pthread_testcancel() here.
1547 //-----------------------------------------------------------------------------
1548 // Cancel the thread.
1550 externC int pthread_cancel (pthread_t thread)
1554 pthread_mutex.lock();
1556 pthread_info *th = pthread_info_id(thread);
1560 pthread_mutex.unlock();
1561 PTHREAD_RETURN(ESRCH);
1564 th->cancelpending = true;
1566 if ( th->cancelstate == PTHREAD_CANCEL_ENABLE )
1568 if ( th->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS )
1570 // If the thread has cancellation enabled, and it is in
1571 // asynchronous mode, set the eCos thread's ASR pending to
1572 // deal with it when the thread wakes up. We also release the
1573 // thread out of any current wait to make it wake up.
1575 th->thread->set_asr_pending();
1576 th->thread->release();
1578 else if ( th->canceltype == PTHREAD_CANCEL_DEFERRED )
1580 // If the thread has cancellation enabled, and it is in
1581 // deferred mode, wake the thread up so that cancellation
1582 // points can test for cancellation.
1583 th->thread->release();
1586 CYG_FAIL("Unknown cancellation type");
1589 // Otherwise the thread has cancellation disabled, in which case
1590 // it is up to the thread to enable cancellation
1592 pthread_mutex.unlock();
1598 //-----------------------------------------------------------------------------
1599 // Test for a pending cancellation for the current thread and terminate
1600 // the thread if there is one.
1602 externC void pthread_testcancel (void)
1604 PTHREAD_ENTRY_VOID();
1606 if( checkforcancel() )
1608 // If we have cancellation enabled, and there is a cancellation
1609 // pending, then go ahead and do the deed.
1611 // Exit now with special retval. pthread_exit() calls the
1612 // cancellation handlers implicitly.
1613 pthread_exit(PTHREAD_CANCELED);
1616 PTHREAD_RETURN_VOID;
1619 //-----------------------------------------------------------------------------
1620 // These two functions actually implement the cleanup push and pop functionality.
1622 externC void pthread_cleanup_push_inner (struct pthread_cleanup_buffer *buffer,
1623 void (*routine) (void *),
1628 pthread_info *self = pthread_self_info();
1630 buffer->routine = routine;
1633 buffer->prev = self->cancelbuffer;
1635 self->cancelbuffer = buffer;
1640 externC void pthread_cleanup_pop_inner (struct pthread_cleanup_buffer *buffer,
1645 pthread_info *self = pthread_self_info();
1647 CYG_ASSERT( self->cancelbuffer == buffer, "Stacking error in cleanup buffers");
1649 if( self->cancelbuffer == buffer )
1651 // Remove the buffer from the stack
1652 self->cancelbuffer = buffer->prev;
1656 // If the top of the stack is not the buffer we expect, do not
1661 if( execute ) buffer->routine(buffer->arg);
1667 // -------------------------------------------------------------------------
1668 // eCos-specific function to measure stack usage of the supplied thread
1670 #ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT
1671 externC size_t pthread_measure_stack_usage (pthread_t thread)
1673 pthread_info *th = pthread_info_id(thread);
1678 return (size_t)th->thread->measure_stack_usage();
1682 // -------------------------------------------------------------------------