diff options
Diffstat (limited to '')
-rw-r--r-- | cpukit/ChangeLog | 14 | ||||
-rw-r--r-- | cpukit/itron/include/rtems/itron/task.h | 6 | ||||
-rw-r--r-- | cpukit/itron/src/cre_tsk.c | 20 | ||||
-rw-r--r-- | cpukit/posix/src/pthreadcreate.c | 19 | ||||
-rw-r--r-- | cpukit/rtems/src/taskcreate.c | 16 | ||||
-rw-r--r-- | cpukit/rtems/src/taskdelete.c | 6 | ||||
-rw-r--r-- | cpukit/rtems/src/timerserver.c | 55 | ||||
-rw-r--r-- | cpukit/score/src/threadclose.c | 32 | ||||
-rw-r--r-- | cpukit/score/src/threadcreateidle.c | 11 | ||||
-rw-r--r-- | cpukit/score/src/threadinitialize.c | 12 |
10 files changed, 133 insertions, 58 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog index 42eeae108e..fc2f77746b 100644 --- a/cpukit/ChangeLog +++ b/cpukit/ChangeLog @@ -1,5 +1,19 @@ 2008-02-28 Joel Sherrill <joel.sherrill@oarcorp.com> + * itron/include/rtems/itron/task.h, itron/src/cre_tsk.c, + posix/src/pthreadcreate.c, rtems/src/taskcreate.c, + rtems/src/taskdelete.c, rtems/src/timerserver.c, + score/src/threadclose.c, score/src/threadcreateidle.c, + score/src/threadinitialize.c: Switch task create and delete + operations to using API Allocator Mutex. This moves almost all uses + of the RTEMS Workspace from dispatching disabled to mutex protected + which should improve deterministic behavior. The implementation was + carefully done to allow task create and delete extensions to invoke + more services. In particular, a task delete extension should be able + to do mutex and file operations. + +2008-02-28 Joel Sherrill <joel.sherrill@oarcorp.com> + * libmisc/Makefile.am: Turn on NFS mount support when networking is enabled. diff --git a/cpukit/itron/include/rtems/itron/task.h b/cpukit/itron/include/rtems/itron/task.h index e7ad311b29..e136c5719f 100644 --- a/cpukit/itron/include/rtems/itron/task.h +++ b/cpukit/itron/include/rtems/itron/task.h @@ -3,7 +3,7 @@ */ /* - * COPYRIGHT (c) 1989-1999. + * COPYRIGHT (c) 1989-2008. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -84,7 +84,9 @@ ER _ITRON_Delete_task( Thread_Control *the_thread ); -/* XXX remove the need for this. Enable dispatch should not be hidden */ +/* + * Return a status code and enable dispatching + */ #define _ITRON_return_errorno( _errno ) \ do { \ diff --git a/cpukit/itron/src/cre_tsk.c b/cpukit/itron/src/cre_tsk.c index 5ae87c1675..6c2047303a 100644 --- a/cpukit/itron/src/cre_tsk.c +++ b/cpukit/itron/src/cre_tsk.c @@ -1,5 +1,5 @@ /* - * COPYRIGHT (c) 1989-1999. + * COPYRIGHT (c) 1989-2008. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -20,6 +20,7 @@ #include <rtems/score/wkspace.h> #include <rtems/score/apiext.h> #include <rtems/score/sysstate.h> +#include <rtems/score/apimutex.h> #include <rtems/itron/task.h> @@ -65,18 +66,19 @@ ER cre_tsk( return E_PAR; /* - * Disable dispatching. + * Lock the allocator mutex for protection */ - - _Thread_Disable_dispatch(); + _RTEMS_Lock_allocator(); /* * allocate the thread. */ the_thread = _ITRON_Task_Allocate( tskid ); - if ( !the_thread ) - _ITRON_return_errorno( _ITRON_Task_Clarify_allocation_id_error( tskid ) ); + if ( !the_thread ) { + _RTEMS_Unlock_allocator(); + return _ITRON_Task_Clarify_allocation_id_error( tskid ); + } /* * Initialize the core thread for this task. @@ -104,7 +106,8 @@ ER cre_tsk( if ( !status ) { _ITRON_Task_Free( the_thread ); - _ITRON_return_errorno( E_NOMEM ); + _RTEMS_Unlock_allocator(); + return E_NOMEM; } /* @@ -118,5 +121,6 @@ ER cre_tsk( the_thread->Start.entry_point = (Thread_Entry) pk_ctsk->task; - _ITRON_return_errorno( E_OK ); + _RTEMS_Unlock_allocator(); + return E_OK; } diff --git a/cpukit/posix/src/pthreadcreate.c b/cpukit/posix/src/pthreadcreate.c index e6bd5bc549..6eeda2da14 100644 --- a/cpukit/posix/src/pthreadcreate.c +++ b/cpukit/posix/src/pthreadcreate.c @@ -2,7 +2,7 @@ * 16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144 */ -/* COPYRIGHT (c) 1989-2007. +/* COPYRIGHT (c) 1989-2008. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -24,6 +24,7 @@ #include <rtems/posix/pthread.h> #include <rtems/posix/priority.h> #include <rtems/posix/time.h> +#include <rtems/score/apimutex.h> int pthread_create( pthread_t *thread, @@ -157,10 +158,9 @@ int pthread_create( #endif /* - * Disable dispatch for protection + * Lock the allocator mutex for protection */ - - _Thread_Disable_dispatch(); + _RTEMS_Lock_allocator(); /* * Allocate the thread control block. @@ -171,7 +171,7 @@ int pthread_create( the_thread = _POSIX_Threads_Allocate(); if ( !the_thread ) { - _Thread_Enable_dispatch(); + _RTEMS_Unlock_allocator(); return EAGAIN; } @@ -196,7 +196,7 @@ int pthread_create( if ( !status ) { _POSIX_Threads_Free( the_thread ); - _Thread_Enable_dispatch(); + _RTEMS_Unlock_allocator(); return EAGAIN; } @@ -249,7 +249,7 @@ int pthread_create( if ( !status ) { _POSIX_Threads_Free( the_thread ); - _Thread_Enable_dispatch(); + _RTEMS_Unlock_allocator(); return EINVAL; } @@ -259,7 +259,6 @@ int pthread_create( *thread = the_thread->Object.id; - _Thread_Enable_dispatch(); - - return 0; + _RTEMS_Unlock_allocator(); + return 0; } diff --git a/cpukit/rtems/src/taskcreate.c b/cpukit/rtems/src/taskcreate.c index 99e6628c92..38d924ad39 100644 --- a/cpukit/rtems/src/taskcreate.c +++ b/cpukit/rtems/src/taskcreate.c @@ -2,7 +2,7 @@ * RTEMS Task Manager * * - * COPYRIGHT (c) 1989-1999. + * COPYRIGHT (c) 1989-2008. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -31,6 +31,7 @@ #include <rtems/score/wkspace.h> #include <rtems/score/apiext.h> #include <rtems/score/sysstate.h> +#include <rtems/score/apimutex.h> /*PAGE * @@ -133,10 +134,9 @@ rtems_status_code rtems_task_create( */ /* - * Disable dispatch for protection + * Lock the allocator mutex for protection */ - - _Thread_Disable_dispatch(); + _RTEMS_Lock_allocator(); /* * Allocate the thread control block and -- if the task is global -- @@ -151,7 +151,7 @@ rtems_status_code rtems_task_create( the_thread = _RTEMS_tasks_Allocate(); if ( !the_thread ) { - _Thread_Enable_dispatch(); + _RTEMS_Unlock_allocator(); return RTEMS_TOO_MANY; } @@ -161,7 +161,7 @@ rtems_status_code rtems_task_create( if ( _Objects_MP_Is_null_global_object( the_global_object ) ) { _RTEMS_tasks_Free( the_thread ); - _Thread_Enable_dispatch(); + _RTEMS_Unlock_allocator(); return RTEMS_TOO_MANY; } } @@ -193,7 +193,7 @@ rtems_status_code rtems_task_create( _Objects_MP_Free_global_object( the_global_object ); #endif _RTEMS_tasks_Free( the_thread ); - _Thread_Enable_dispatch(); + _RTEMS_Unlock_allocator(); return RTEMS_UNSATISFIED; } @@ -224,6 +224,6 @@ rtems_status_code rtems_task_create( } #endif - _Thread_Enable_dispatch(); + _RTEMS_Unlock_allocator(); return RTEMS_SUCCESSFUL; } diff --git a/cpukit/rtems/src/taskdelete.c b/cpukit/rtems/src/taskdelete.c index 890596866b..c7b1edb60c 100644 --- a/cpukit/rtems/src/taskdelete.c +++ b/cpukit/rtems/src/taskdelete.c @@ -31,6 +31,7 @@ #include <rtems/score/wkspace.h> #include <rtems/score/apiext.h> #include <rtems/score/sysstate.h> +#include <rtems/score/apimutex.h> /*PAGE * @@ -58,6 +59,8 @@ rtems_status_code rtems_task_delete( Objects_Locations location; Objects_Information *the_information; + _RTEMS_Lock_allocator(); + the_thread = _Thread_Get( id, &location ); switch ( location ) { @@ -89,11 +92,13 @@ rtems_status_code rtems_task_delete( } #endif + _RTEMS_Unlock_allocator(); _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: + _RTEMS_Unlock_allocator(); _Thread_Dispatch(); return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; #endif @@ -102,5 +107,6 @@ rtems_status_code rtems_task_delete( break; } + _RTEMS_Unlock_allocator(); return RTEMS_INVALID_ID; } diff --git a/cpukit/rtems/src/timerserver.c b/cpukit/rtems/src/timerserver.c index ff1fc97099..00a91e8937 100644 --- a/cpukit/rtems/src/timerserver.c +++ b/cpukit/rtems/src/timerserver.c @@ -147,6 +147,8 @@ rtems_status_code rtems_timer_initiate_server( rtems_id id; rtems_status_code status; rtems_task_priority _priority; + static boolean initialized = FALSE; + boolean tmpInitialized; /* * Make sure the requested priority is valid. The if is @@ -162,15 +164,16 @@ rtems_status_code rtems_timer_initiate_server( } /* - * Just to make sure the test versus create/start operation are atomic. + * Just to make sure this is only called once. */ _Thread_Disable_dispatch(); + tmpInitialized = initialized; + initialized = TRUE; + _Thread_Enable_dispatch(); - if ( _Timer_Server ) { - _Thread_Enable_dispatch(); + if ( tmpInitialized ) return RTEMS_INCORRECT_STATE; - } /* * Create the Timer Server with the name the name of "TIME". The attribute @@ -198,26 +201,14 @@ rtems_status_code rtems_timer_initiate_server( &id /* get the id back */ ); if (status) { - _Thread_Enable_dispatch(); + initialized = FALSE; return status; } - status = rtems_task_start( - id, /* the id from create */ - (rtems_task_entry) _Timer_Server_body, /* the timer server entry point */ - 0 /* there is no argument */ - ); - if (status) { - /* - * One would expect a call to rtems_task_delete() here to clean up - * but there is actually no way (in normal circumstances) that the - * start can fail. The id and starting address are known to be - * be good. If this service fails, something is weirdly wrong on the - * target such as a stray write in an ISR or incorrect memory layout. - */ - _Thread_Enable_dispatch(); - return status; - } + /* + * Do all the data structure initialization before starting the + * Timer Server so we do not have to have a critical section. + */ /* * We work with the TCB pointer, not the ID, so we need to convert @@ -246,9 +237,27 @@ rtems_status_code rtems_timer_initiate_server( _Watchdog_Initialize( &_Timer_Server->Timer, _Thread_Delay_ended, id, NULL ); _Watchdog_Initialize( &_Timer_Seconds_timer, _Thread_Delay_ended, id, NULL ); + /* + * Start the timer server + */ - _Thread_Enable_dispatch(); - return RTEMS_SUCCESSFUL; + status = rtems_task_start( + id, /* the id from create */ + (rtems_task_entry) _Timer_Server_body, /* the timer server entry point */ + 0 /* there is no argument */ + ); + if (status) { + /* + * One would expect a call to rtems_task_delete() here to clean up + * but there is actually no way (in normal circumstances) that the + * start can fail. The id and starting address are known to be + * be good. If this service fails, something is weirdly wrong on the + * target such as a stray write in an ISR or incorrect memory layout. + */ + initialized = FALSE; + } + + return status; } /*PAGE diff --git a/cpukit/score/src/threadclose.c b/cpukit/score/src/threadclose.c index e506b2666d..f8231a1192 100644 --- a/cpukit/score/src/threadclose.c +++ b/cpukit/score/src/threadclose.c @@ -2,7 +2,7 @@ * Thread Handler * * - * COPYRIGHT (c) 1989-1999. + * COPYRIGHT (c) 1989-2008. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -45,10 +45,30 @@ void _Thread_Close( Thread_Control *the_thread ) { + /* + * We assume the Allocator Mutex is locked when we get here. + * This provides sufficient protection to let the user extensions + * run but as soon as we get back, we will make the thread + * disappear and set a transient state on it. So we temporarily + * unnest dispatching. + */ + _Thread_Unnest_dispatch(); + _User_extensions_Thread_delete( the_thread ); + _Thread_Disable_dispatch(); + + /* + * Now we are in a dispatching critical section again and we + * can take the thread OUT of the published set. It is invalid + * to use this thread's Id after this call. + */ _Objects_Close( information, &the_thread->Object ); + /* + * By setting the transient state, the thread will not be considered + * for scheduling when we remove any blocking states. + */ _Thread_Set_state( the_thread, STATES_TRANSIENT ); if ( !_Thread_queue_Extract_with_proxy( the_thread ) ) { @@ -56,6 +76,9 @@ void _Thread_Close( (void) _Watchdog_Remove( &the_thread->Timer ); } + /* + * The thread might have been FP. So deal with that. + */ #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) #if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE ) if ( _Thread_Is_allocated_fp( the_thread ) ) @@ -67,11 +90,14 @@ void _Thread_Close( (void) _Workspace_Free( the_thread->Start.fp_context ); #endif + /* + * Free the rest of the memory associated with this task + * and set the associated pointers to NULL for safety. + */ _Thread_Stack_Free( the_thread ); + the_thread->Start.stack = NULL; if ( the_thread->extensions ) (void) _Workspace_Free( the_thread->extensions ); - - the_thread->Start.stack = NULL; the_thread->extensions = NULL; } diff --git a/cpukit/score/src/threadcreateidle.c b/cpukit/score/src/threadcreateidle.c index 602fc7840b..3eaff869cf 100644 --- a/cpukit/score/src/threadcreateidle.c +++ b/cpukit/score/src/threadcreateidle.c @@ -2,7 +2,7 @@ * Thread Handler * * - * COPYRIGHT (c) 1989-1999. + * COPYRIGHT (c) 1989-2008. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -68,6 +68,13 @@ void _Thread_Create_idle( void ) if ( idle_task_stack_size < STACK_MINIMUM_SIZE ) idle_task_stack_size = STACK_MINIMUM_SIZE; + /* + * This is only called during initialization and we better be sure + * that when _Thread_Initialize unnests dispatch that we do not + * do anything stupid. + */ + _Thread_Disable_dispatch(); + _Thread_Initialize( &_Thread_Internal_information, _Thread_Idle, @@ -82,6 +89,8 @@ void _Thread_Create_idle( void ) (Objects_Name) _Thread_Idle_name ); + _Thread_Unnest_dispatch(); + /* * WARNING!!! This is necessary to "kick" start the system and * MUST be done before _Thread_Start is invoked. diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c index b2e09727cc..7ef9125a46 100644 --- a/cpukit/score/src/threadinitialize.c +++ b/cpukit/score/src/threadinitialize.c @@ -2,7 +2,7 @@ * Thread Handler * * - * COPYRIGHT (c) 1989-2006. + * COPYRIGHT (c) 1989-2008. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -61,6 +61,7 @@ boolean _Thread_Initialize( void *fp_area; #endif void *extensions_area; + boolean extension_status; /* * Initialize the Ada self pointer @@ -220,10 +221,15 @@ boolean _Thread_Initialize( _Objects_Open( information, &the_thread->Object, name ); /* - * Invoke create extensions + * We assume the Allocator Mutex is locked and dispatching is + * enabled when we get here. We want to be able to run the + * user extensions with dispatching enabled. The Allocator + * Mutex provides sufficient protection to let the user extensions + * run safely. */ + extension_status = _User_extensions_Thread_create( the_thread ); - if ( !_User_extensions_Thread_create( the_thread ) ) { + if ( !extension_status ) { if ( extensions_area ) (void) _Workspace_Free( extensions_area ); |