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,
643 // Put pointer to pthread_info into eCos thread's per-thread data.
644 nthread->thread->set_data( CYGNUM_KERNEL_THREADS_DATA_POSIX, (CYG_ADDRWORD)nthread );
646 // Set timeslice enable according to scheduling policy.
647 if( use_attr.schedpolicy == SCHED_FIFO )
648 nthread->thread->timeslice_disable();
649 else nthread->thread->timeslice_enable();
651 // set up ASR and data
652 nthread->thread->set_asr( posix_asr, (CYG_ADDRWORD)nthread, NULL, NULL );
655 *thread = nthread->id;
659 pthread_mutex.unlock();
661 // finally, set the thread going
662 nthread->thread->resume();
667 //-----------------------------------------------------------------------------
668 // Get current thread id.
670 externC pthread_t pthread_self ( void )
674 pthread_info *info = pthread_self_info();
676 CYG_CHECK_DATA_PTR(info, "Not a POSIX thread!!!");
681 //-----------------------------------------------------------------------------
682 // Compare two thread identifiers.
684 externC int pthread_equal (pthread_t thread1, pthread_t thread2)
688 return thread1 == thread2;
691 //-----------------------------------------------------------------------------
692 // Terminate current thread.
694 externC void exit(int) CYGBLD_ATTRIB_NORET;
696 externC void pthread_exit (void *retval)
700 pthread_info *self = pthread_self_info();
702 // Disable cancellation requests for this thread. If cleanup
703 // handlers exist, they will generally be issuing system calls
704 // to clean up resources. We want these system calls to run
705 // without cancelling, and we also want to prevent being
707 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
709 // Call cancellation handlers. We eat up the buffers as we go in
710 // case any of the routines calls pthread_exit() itself.
711 while( self->cancelbuffer != NULL )
713 struct pthread_cleanup_buffer *buffer = self->cancelbuffer;
715 self->cancelbuffer = buffer->prev;
717 buffer->routine(buffer->arg);
720 if( self->thread_data != NULL )
722 // Call per-thread key destructors.
723 // The specification of this is that we must continue to call the
724 // destructor functions until all the per-thread data values are NULL or
725 // we have done it PTHREAD_DESTRUCTOR_ITERATIONS times.
727 cyg_bool destructors_called;
728 int destructor_iterations = 0;
732 destructors_called = false;
734 for( cyg_ucount32 key = 0; key < PTHREAD_KEYS_MAX; key++ )
736 // Skip unallocated keys
737 if( thread_key[key/KEY_MAP_TYPE_SIZE] & 1<<(key%KEY_MAP_TYPE_SIZE) )
740 // Skip NULL destructors
741 if( key_destructor[key] == NULL ) continue;
743 // Skip NULL data values
744 if( self->thread_data[key] == NULL ) continue;
746 // If it passes all that, call the destructor.
747 // Note that NULLing the data value here is new
748 // behaviour in the 2001 POSIX standard.
750 void* value = self->thread_data[key];
751 self->thread_data[key] = NULL;
752 key_destructor[key](value);
755 // Record that we called a destructor
756 destructors_called = true;
759 // Count the iteration
760 destructor_iterations++;
762 } while( destructors_called &&
763 (destructor_iterations <= PTHREAD_DESTRUCTOR_ITERATIONS));
767 pthread_mutex.lock();
769 // Set the retval for any joiner
770 self->retval = retval;
772 // If we are already detached, go to EXITED state, otherwise
773 // go into JOIN state.
775 if ( PTHREAD_STATE_DETACHED == self->state ) {
776 self->state = PTHREAD_STATE_EXITED;
779 self->state = PTHREAD_STATE_JOIN;
780 pthreads_tobejoined++;
783 // Kick any waiting joiners
784 self->joiner->broadcast();
786 cyg_bool call_exit=false;
788 // if this is the last thread (other than threads waiting to be joined)
789 // then we need to call exit() later
790 if ( pthreads_exited + pthreads_tobejoined == pthread_count )
793 pthread_mutex.unlock();
795 // Finally, call the exit function; this will not return.
799 self->thread->exit();
801 // This loop keeps some compilers happy. pthread_exit() is marked
802 // with the noreturn attribute, and without this they generate a
803 // call to abort() here in case Cyg_Thread::exit() returns.
808 //-----------------------------------------------------------------------------
809 // Wait for the thread to terminate. If thread_return is not NULL then
810 // the retval from the thread's call to pthread_exit() is stored at
813 externC int pthread_join (pthread_t thread, void **thread_return)
819 // check for cancellation first.
820 pthread_testcancel();
822 pthread_mutex.lock();
824 // Dispose of any dead threads
827 pthread_info *self = pthread_self_info();
828 pthread_info *joinee = pthread_info_id( thread );
835 if( !err && joinee == self )
841 switch ( joinee->state )
843 case PTHREAD_STATE_RUNNING:
844 // The thread is still running, we must wait for it.
845 while( joinee->state == PTHREAD_STATE_RUNNING ) {
846 if ( !joinee->joiner->wait() )
847 // check if we were woken because we were being cancelled
848 if ( checkforcancel() ) {
849 err = EAGAIN; // value unimportant, just some error
854 // check that the thread is still joinable
855 if( joinee->state == PTHREAD_STATE_JOIN )
858 // The thread has become unjoinable while we waited, so we
859 // fall through to complain.
861 case PTHREAD_STATE_FREE:
862 case PTHREAD_STATE_DETACHED:
863 case PTHREAD_STATE_EXITED:
864 // None of these may be joined.
868 case PTHREAD_STATE_JOIN:
875 // here, we know that joinee is a thread that has exited and is
876 // ready to be joined.
879 if( thread_return != NULL )
880 *thread_return = joinee->retval;
882 // set state to exited.
883 joinee->state = PTHREAD_STATE_EXITED;
885 pthreads_tobejoined--;
887 // Dispose of any dead threads
891 pthread_mutex.unlock();
893 // check for cancellation before returning
894 pthread_testcancel();
899 //-----------------------------------------------------------------------------
900 // Set the detachstate of the thread to "detached". The thread then does not
901 // need to be joined and its resources will be freed when it exits.
903 externC int pthread_detach (pthread_t thread)
909 pthread_mutex.lock();
911 pthread_info *detachee = pthread_info_id( thread );
913 if( detachee == NULL )
914 ret = ESRCH; // No such thread
915 else if( detachee->state == PTHREAD_STATE_DETACHED )
916 ret = EINVAL; // Already detached!
919 // Set state to detached and kick any joinees to
921 detachee->state = PTHREAD_STATE_DETACHED;
922 detachee->joiner->broadcast();
925 // Dispose of any dead threads
928 pthread_mutex.unlock();
934 //-----------------------------------------------------------------------------
935 // Thread attribute handling.
937 //-----------------------------------------------------------------------------
938 // Initialize attributes object with default attributes:
939 // detachstate == PTHREAD_CREATE_JOINABLE
940 // scope == PTHREAD_SCOPE_SYSTEM
941 // inheritsched == PTHREAD_INHERIT_SCHED
942 // schedpolicy == SCHED_OTHER
943 // schedparam == unset
944 // stackaddr == unset
948 externC int pthread_attr_init (pthread_attr_t *attr)
954 attr->detachstate = PTHREAD_CREATE_JOINABLE;
955 attr->scope = PTHREAD_SCOPE_SYSTEM;
956 attr->inheritsched = PTHREAD_INHERIT_SCHED;
957 attr->schedpolicy = SCHED_OTHER;
958 attr->schedparam.sched_priority = 0;
959 attr->stackaddr_valid = 0;
960 attr->stackaddr = NULL;
961 attr->stacksize_valid = 0;
967 //-----------------------------------------------------------------------------
968 // Destroy thread attributes object
970 externC int pthread_attr_destroy (pthread_attr_t *attr)
976 // Nothing to do here...
981 //-----------------------------------------------------------------------------
982 // Set the detachstate attribute
984 externC int pthread_attr_setdetachstate (pthread_attr_t *attr,
991 if( detachstate == PTHREAD_CREATE_JOINABLE ||
992 detachstate == PTHREAD_CREATE_DETACHED )
994 attr->detachstate = detachstate;
998 PTHREAD_RETURN(EINVAL);
1001 //-----------------------------------------------------------------------------
1002 // Get the detachstate attribute
1003 externC int pthread_attr_getdetachstate (const pthread_attr_t *attr,
1008 PTHREAD_CHECK(attr);
1010 if( detachstate != NULL )
1011 *detachstate = attr->detachstate;
1016 //-----------------------------------------------------------------------------
1017 // Set scheduling contention scope
1019 externC int pthread_attr_setscope (pthread_attr_t *attr, int scope)
1023 PTHREAD_CHECK(attr);
1025 if( scope == PTHREAD_SCOPE_SYSTEM ||
1026 scope == PTHREAD_SCOPE_PROCESS )
1028 if( scope == PTHREAD_SCOPE_PROCESS )
1029 PTHREAD_RETURN(ENOTSUP);
1031 attr->scope = scope;
1036 PTHREAD_RETURN(EINVAL);
1039 //-----------------------------------------------------------------------------
1040 // Get scheduling contention scope
1042 externC int pthread_attr_getscope (const pthread_attr_t *attr, int *scope)
1046 PTHREAD_CHECK(attr);
1049 *scope = attr->scope;
1054 //-----------------------------------------------------------------------------
1055 // Set scheduling inheritance attribute
1057 externC int pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit)
1061 PTHREAD_CHECK(attr);
1063 if( inherit == PTHREAD_INHERIT_SCHED ||
1064 inherit == PTHREAD_EXPLICIT_SCHED )
1066 attr->inheritsched = inherit;
1071 PTHREAD_RETURN(EINVAL);
1074 //-----------------------------------------------------------------------------
1075 // Get scheduling inheritance attribute
1077 externC int pthread_attr_getinheritsched (const pthread_attr_t *attr,
1082 PTHREAD_CHECK(attr);
1084 if( inherit != NULL )
1085 *inherit = attr->inheritsched;
1090 //-----------------------------------------------------------------------------
1091 // Set scheduling policy
1093 externC int pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy)
1097 PTHREAD_CHECK(attr);
1099 if( policy == SCHED_OTHER ||
1100 policy == SCHED_FIFO ||
1101 policy == SCHED_RR )
1103 attr->schedpolicy = policy;
1108 PTHREAD_RETURN(EINVAL);
1111 //-----------------------------------------------------------------------------
1112 // Get scheduling policy
1114 externC int pthread_attr_getschedpolicy (const pthread_attr_t *attr,
1119 PTHREAD_CHECK(attr);
1121 if( policy != NULL )
1122 *policy = attr->schedpolicy;
1127 //-----------------------------------------------------------------------------
1128 // Set scheduling parameters
1129 externC int pthread_attr_setschedparam (pthread_attr_t *attr,
1130 const struct sched_param *param)
1134 PTHREAD_CHECK(attr);
1135 PTHREAD_CHECK(param);
1137 attr->schedparam = *param;
1142 //-----------------------------------------------------------------------------
1143 // Get scheduling parameters
1145 externC int pthread_attr_getschedparam (const pthread_attr_t *attr,
1146 struct sched_param *param)
1150 PTHREAD_CHECK(attr);
1153 *param = attr->schedparam;
1158 //-----------------------------------------------------------------------------
1159 // Set starting address of stack. Whether this is at the start or end of
1160 // the memory block allocated for the stack depends on whether the stack
1161 // grows up or down.
1163 externC int pthread_attr_setstackaddr (pthread_attr_t *attr, void *stackaddr)
1167 PTHREAD_CHECK(attr);
1169 attr->stackaddr = stackaddr;
1170 attr->stackaddr_valid = 1;
1175 //-----------------------------------------------------------------------------
1176 // Get any previously set stack address.
1178 externC int pthread_attr_getstackaddr (const pthread_attr_t *attr,
1183 PTHREAD_CHECK(attr);
1185 if( stackaddr != NULL )
1187 if( attr->stackaddr_valid )
1189 *stackaddr = attr->stackaddr;
1192 // Stack address not set, return EINVAL.
1193 else PTHREAD_RETURN(EINVAL);
1200 //-----------------------------------------------------------------------------
1201 // Set minimum creation stack size.
1203 externC int pthread_attr_setstacksize (pthread_attr_t *attr,
1208 PTHREAD_CHECK(attr);
1210 CYG_ASSERT( stacksize >= PTHREAD_STACK_MIN, "Inadequate stack size supplied");
1212 // Reject inadequate stack sizes
1213 if( stacksize < PTHREAD_STACK_MIN )
1214 PTHREAD_RETURN(EINVAL);
1216 attr->stacksize_valid = 1;
1217 attr->stacksize = stacksize;
1222 //-----------------------------------------------------------------------------
1223 // Get current minimal stack size.
1225 externC int pthread_attr_getstacksize (const pthread_attr_t *attr,
1230 PTHREAD_CHECK(attr);
1232 // Reject attempts to get a stack size when one has not been set.
1233 if( !attr->stacksize_valid )
1234 PTHREAD_RETURN(EINVAL);
1236 if( stacksize != NULL )
1237 *stacksize = attr->stacksize;
1242 //-----------------------------------------------------------------------------
1243 // Thread scheduling controls
1245 //-----------------------------------------------------------------------------
1246 // Set scheduling policy and parameters for the thread
1248 externC int pthread_setschedparam (pthread_t thread_id,
1250 const struct sched_param *param)
1254 if( policy != SCHED_OTHER &&
1255 policy != SCHED_FIFO &&
1256 policy != SCHED_RR )
1257 PTHREAD_RETURN(EINVAL);
1259 PTHREAD_CHECK(param);
1261 // The parameters seem OK, change the thread...
1263 pthread_mutex.lock();
1265 pthread_info *thread = pthread_info_id( thread_id );
1267 if( thread == NULL )
1269 pthread_mutex.unlock();
1270 PTHREAD_RETURN(ESRCH);
1273 thread->attr.schedpolicy = policy;
1274 thread->attr.schedparam = *param;
1276 if ( policy == SCHED_FIFO )
1277 thread->thread->timeslice_disable();
1278 else thread->thread->timeslice_enable();
1280 thread->thread->set_priority( PTHREAD_ECOS_PRIORITY( param->sched_priority ));
1282 pthread_mutex.unlock();
1287 //-----------------------------------------------------------------------------
1288 // Get scheduling policy and parameters for the thread
1290 externC int pthread_getschedparam (pthread_t thread_id,
1292 struct sched_param *param)
1296 pthread_mutex.lock();
1298 pthread_info *thread = pthread_info_id( thread_id );
1300 if( thread == NULL )
1302 pthread_mutex.unlock();
1303 PTHREAD_RETURN(ESRCH);
1306 if( policy != NULL )
1307 *policy = thread->attr.schedpolicy;
1310 *param = thread->attr.schedparam;
1312 pthread_mutex.unlock();
1318 //=============================================================================
1319 // Dynamic package initialization
1320 // Call init_routine just the once per control variable.
1322 externC int pthread_once (pthread_once_t *once_control,
1323 void (*init_routine) (void))
1327 PTHREAD_CHECK( once_control );
1328 PTHREAD_CHECK( init_routine );
1332 // Do a test and set on the once_control object.
1333 pthread_mutex.lock();
1335 old = *once_control;
1338 pthread_mutex.unlock();
1340 // If the once_control was zero, call the init_routine().
1341 if( !old ) init_routine();
1347 //=============================================================================
1348 //Thread specific data
1350 //-----------------------------------------------------------------------------
1351 // Create a key to identify a location in the thread specific data area.
1352 // Each thread has its own distinct thread-specific data area but all are
1353 // addressed by the same keys. The destructor function is called whenever a
1354 // thread exits and the value associated with the key is non-NULL.
1356 externC int pthread_key_create (pthread_key_t *key,
1357 void (*destructor) (void *))
1361 pthread_key_t k = -1;
1363 pthread_mutex.lock();
1365 // Find a key to allocate
1366 for( cyg_ucount32 i = 0; i < (PTHREAD_KEYS_MAX/KEY_MAP_TYPE_SIZE); i++ )
1368 if( thread_key[i] != 0 )
1370 // We have a table slot with space available
1372 // Get index of ls set bit.
1373 HAL_LSBIT_INDEX( k, thread_key[i] );
1376 thread_key[i] &= ~(1<<k);
1378 // Add index of word
1379 k += i * KEY_MAP_TYPE_SIZE;
1381 // Install destructor
1382 key_destructor[k] = destructor;
1384 // break out with key found
1391 // plant a NULL in all the valid thread data slots for this
1392 // key in case we are reusing a key we used before.
1394 for( cyg_ucount32 i = 0; i < CYGNUM_POSIX_PTHREAD_THREADS_MAX ; i++ )
1396 pthread_info *thread = thread_table[i];
1398 if( thread != NULL && thread->thread_data != NULL )
1399 thread->thread_data[k] = NULL;
1403 pthread_mutex.unlock();
1405 if( k == -1 ) PTHREAD_RETURN(EAGAIN);
1412 //-----------------------------------------------------------------------------
1415 externC int pthread_key_delete (pthread_key_t key)
1419 pthread_mutex.lock();
1421 // Set the key bit to 1 to indicate it is free.
1422 thread_key[key/KEY_MAP_TYPE_SIZE] |= 1<<(key%(KEY_MAP_TYPE_SIZE));
1424 pthread_mutex.unlock();
1429 //-----------------------------------------------------------------------------
1430 // Store the pointer value in the thread-specific data slot addressed
1433 externC int pthread_setspecific (pthread_key_t key, const void *pointer)
1437 if( thread_key[key/KEY_MAP_TYPE_SIZE] & 1<<(key%KEY_MAP_TYPE_SIZE) )
1438 PTHREAD_RETURN(EINVAL);
1440 pthread_info *self = pthread_self_info();
1442 if( self->thread_data == NULL )
1444 // Allocate the per-thread data table
1446 (void **)self->thread->increment_stack_limit(
1447 PTHREAD_KEYS_MAX * sizeof(void *) );
1449 // Clear out all entries
1450 for( int i = 0; i < PTHREAD_KEYS_MAX; i++ )
1451 self->thread_data[i] = NULL;
1454 self->thread_data[key] = (void *)pointer;
1459 //-----------------------------------------------------------------------------
1460 // Retrieve the pointer value in the thread-specific data slot addressed
1463 externC void *pthread_getspecific (pthread_key_t key)
1468 if( thread_key[key/KEY_MAP_TYPE_SIZE] & 1<<(key%KEY_MAP_TYPE_SIZE) )
1469 PTHREAD_RETURN(NULL);
1471 pthread_info *self = pthread_self_info();
1473 if( self->thread_data == NULL )
1475 else val = self->thread_data[key];
1477 PTHREAD_RETURN(val);
1480 //=============================================================================
1481 // Thread Cancellation Functions
1483 //-----------------------------------------------------------------------------
1484 // Set cancel state of current thread to ENABLE or DISABLE.
1485 // Returns old state in *oldstate.
1487 externC int pthread_setcancelstate (int state, int *oldstate)
1491 if( state != PTHREAD_CANCEL_ENABLE &&
1492 state != PTHREAD_CANCEL_DISABLE )
1493 PTHREAD_RETURN(EINVAL);
1495 pthread_mutex.lock();
1497 pthread_info *self = pthread_self_info();
1499 if( oldstate != NULL ) *oldstate = self->cancelstate;
1501 self->cancelstate = state;
1503 pthread_mutex.unlock();
1505 // Note: This function may have made it possible for a pending
1506 // cancellation to now be delivered. However the standard does not
1507 // list this function as a cancellation point, so for now we do
1508 // nothing. In future we might call pthread_testcancel() here.
1513 //-----------------------------------------------------------------------------
1514 // Set cancel type of current thread to ASYNCHRONOUS or DEFERRED.
1515 // Returns old type in *oldtype.
1517 externC int pthread_setcanceltype (int type, int *oldtype)
1521 if( type != PTHREAD_CANCEL_ASYNCHRONOUS &&
1522 type != PTHREAD_CANCEL_DEFERRED )
1523 PTHREAD_RETURN(EINVAL);
1525 pthread_mutex.lock();
1527 pthread_info *self = pthread_self_info();
1529 if( oldtype != NULL ) *oldtype = self->canceltype;
1531 self->canceltype = type;
1533 pthread_mutex.unlock();
1535 // Note: This function may have made it possible for a pending
1536 // cancellation to now be delivered. However the standard does not
1537 // list this function as a cancellation point, so for now we do
1538 // nothing. In future we might call pthread_testcancel() here.
1543 //-----------------------------------------------------------------------------
1544 // Cancel the thread.
1546 externC int pthread_cancel (pthread_t thread)
1550 pthread_mutex.lock();
1552 pthread_info *th = pthread_info_id(thread);
1556 pthread_mutex.unlock();
1557 PTHREAD_RETURN(ESRCH);
1560 th->cancelpending = true;
1562 if ( th->cancelstate == PTHREAD_CANCEL_ENABLE )
1564 if ( th->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS )
1566 // If the thread has cancellation enabled, and it is in
1567 // asynchronous mode, set the eCos thread's ASR pending to
1568 // deal with it when the thread wakes up. We also release the
1569 // thread out of any current wait to make it wake up.
1571 th->thread->set_asr_pending();
1572 th->thread->release();
1574 else if ( th->canceltype == PTHREAD_CANCEL_DEFERRED )
1576 // If the thread has cancellation enabled, and it is in
1577 // deferred mode, wake the thread up so that cancellation
1578 // points can test for cancellation.
1579 th->thread->release();
1582 CYG_FAIL("Unknown cancellation type");
1585 // Otherwise the thread has cancellation disabled, in which case
1586 // it is up to the thread to enable cancellation
1588 pthread_mutex.unlock();
1594 //-----------------------------------------------------------------------------
1595 // Test for a pending cancellation for the current thread and terminate
1596 // the thread if there is one.
1598 externC void pthread_testcancel (void)
1600 PTHREAD_ENTRY_VOID();
1602 if( checkforcancel() )
1604 // If we have cancellation enabled, and there is a cancellation
1605 // pending, then go ahead and do the deed.
1607 // Exit now with special retval. pthread_exit() calls the
1608 // cancellation handlers implicitly.
1609 pthread_exit(PTHREAD_CANCELED);
1612 PTHREAD_RETURN_VOID;
1615 //-----------------------------------------------------------------------------
1616 // These two functions actually implement the cleanup push and pop functionality.
1618 externC void pthread_cleanup_push_inner (struct pthread_cleanup_buffer *buffer,
1619 void (*routine) (void *),
1624 pthread_info *self = pthread_self_info();
1626 buffer->routine = routine;
1629 buffer->prev = self->cancelbuffer;
1631 self->cancelbuffer = buffer;
1636 externC void pthread_cleanup_pop_inner (struct pthread_cleanup_buffer *buffer,
1641 pthread_info *self = pthread_self_info();
1643 CYG_ASSERT( self->cancelbuffer == buffer, "Stacking error in cleanup buffers");
1645 if( self->cancelbuffer == buffer )
1647 // Remove the buffer from the stack
1648 self->cancelbuffer = buffer->prev;
1652 // If the top of the stack is not the buffer we expect, do not
1657 if( execute ) buffer->routine(buffer->arg);
1663 // -------------------------------------------------------------------------
1664 // eCos-specific function to measure stack usage of the supplied thread
1666 #ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT
1667 externC size_t pthread_measure_stack_usage (pthread_t thread)
1669 pthread_info *th = pthread_info_id(thread);
1674 return (size_t)th->thread->measure_stack_usage();
1678 // -------------------------------------------------------------------------