Close #2423. --- cpukit/libcsupport/src/sync.c | 6 ++- cpukit/libmisc/capture/capture-cli.c | 27 ++++++------ cpukit/libmisc/capture/capture.c | 15 ++++--- cpukit/libmisc/cpuuse/cpuusagereset.c | 8 ++-- cpukit/libmisc/cpuuse/cpuusagetop.c | 49 ++++------------------ cpukit/libmisc/stackchk/check.c | 46 ++++++++++---------- cpukit/rtems/Makefile.am | 1 + cpukit/rtems/include/rtems/rtems/tasks.h | 32 ++++++++++++++ cpukit/rtems/src/taskiterate.c | 31 ++++++++++++++ cpukit/score/Makefile.am | 1 + cpukit/score/include/rtems/score/thread.h | 10 +---- cpukit/score/include/rtems/score/threadimpl.h | 7 ++++ cpukit/score/src/iterateoverthreads.c | 45 ++++++++------------ cpukit/score/src/threaditerate.c | 60 +++++++++++++++++++++++++++ testsuites/sptests/sp41/init.c | 35 ++++++++++++---- testsuites/sptests/sp41/sp41.scn | 9 ++-- 16 files changed, 245 insertions(+), 137 deletions(-) create mode 100644 cpukit/rtems/src/taskiterate.c create mode 100644 cpukit/score/src/threaditerate.c
diff --git a/cpukit/libcsupport/src/sync.c b/cpukit/libcsupport/src/sync.c index 214e42c..1786b59 100644 --- a/cpukit/libcsupport/src/sync.c +++ b/cpukit/libcsupport/src/sync.c @@ -47,7 +47,7 @@ static void sync_wrapper(FILE *f) } /* iterate over all FILE *'s for this thread */ -static void sync_per_thread(Thread_Control *t) +static bool sync_per_thread(Thread_Control *t, void *arg) { struct _reent *current_reent; struct _reent *this_reent; @@ -64,6 +64,8 @@ static void sync_per_thread(Thread_Control *t) _fwalk (t->libc_reent, sync_wrapper); executing->libc_reent = current_reent; } + + return false; } /* @@ -95,5 +97,5 @@ void sync(void) /* * Now walk all the per-thread reentrancy structures. */ - rtems_iterate_over_all_threads(sync_per_thread); + rtems_task_iterate(sync_per_thread, NULL); } diff --git a/cpukit/libmisc/capture/capture-cli.c b/cpukit/libmisc/capture/capture-cli.c index 05c922b..d489d9f 100644 --- a/cpukit/libmisc/capture/capture-cli.c +++ b/cpukit/libmisc/capture/capture-cli.c @@ -42,11 +42,6 @@ #define RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS (20) /* - * Counter used to count the number of active tasks. - */ -static int rtems_capture_cli_task_count = 0; - -/* * The user capture timestamper. */ static rtems_capture_timestamp capture_timestamp; @@ -197,8 +192,8 @@ rtems_capture_cli_disable (int argc RC_UNUSED, fprintf (stdout, "capture engine disabled.\n"); } -static void -rtems_capture_cli_print_task (rtems_tcb *tcb) +static bool +rtems_capture_cli_print_task (rtems_tcb *tcb, void *arg) { rtems_task_priority ceiling = rtems_capture_watch_get_ceiling (); rtems_task_priority floor = rtems_capture_watch_get_floor (); @@ -242,6 +237,7 @@ rtems_capture_cli_print_task (rtems_tcb *tcb) rtems_capture_watch_global_on () ? 'g' : '-'); } fprintf (stdout, "\n"); + return false; } /* @@ -251,10 +247,12 @@ rtems_capture_cli_print_task (rtems_tcb *tcb) * number of tasks. */ -static void -rtems_capture_cli_count_tasks (rtems_tcb *tcb) +static bool +rtems_capture_cli_count_tasks (rtems_tcb *tcb, void *arg) { - rtems_capture_cli_task_count++; + uint32_t *task_count = arg; + ++(*task_count); + return false; } @@ -271,16 +269,17 @@ rtems_capture_cli_task_list (int argc RC_UNUSED, bool verbose RC_UNUSED) { rtems_capture_time uptime; + uint32_t task_count; rtems_capture_get_time (&uptime); - rtems_capture_cli_task_count = 0; - rtems_iterate_over_all_threads (rtems_capture_cli_count_tasks); + task_count = 0; + rtems_task_iterate (rtems_capture_cli_count_tasks, &task_count); fprintf (stdout, "uptime: "); rtems_capture_print_timestamp (uptime); - fprintf (stdout, "\ntotal %i\n", rtems_capture_cli_task_count); - rtems_iterate_over_all_threads (rtems_capture_cli_print_task); + fprintf (stdout, "\ntotal %" PRIu32 "\n", task_count); + rtems_task_iterate (rtems_capture_cli_print_task, NULL); } /* diff --git a/cpukit/libmisc/capture/capture.c b/cpukit/libmisc/capture/capture.c index 69015c8..41f25aa 100644 --- a/cpukit/libmisc/capture/capture.c +++ b/cpukit/libmisc/capture/capture.c @@ -279,8 +279,8 @@ rtems_capture_find_control (rtems_name name, rtems_id id) * This function checks if a new control structure matches * the given task and sets the control if it does. */ -static void -rtems_capture_initialize_control (rtems_tcb *tcb) +static bool +rtems_capture_initialize_control (rtems_tcb *tcb, void *arg) { if (tcb->Capture.control == NULL) { @@ -305,6 +305,8 @@ rtems_capture_initialize_control (rtems_tcb *tcb) } } } + + return false; } static rtems_capture_control* @@ -342,7 +344,7 @@ rtems_capture_create_control (rtems_name name, rtems_id id) control->next = capture_controls; capture_controls = control; - rtems_iterate_over_all_threads (rtems_capture_initialize_control); + _Thread_Iterate (rtems_capture_initialize_control, NULL); rtems_interrupt_lock_release (&capture_lock_global, &lock_context); } @@ -749,10 +751,11 @@ rtems_capture_set_monitor (bool enable) /* * This function clears the capture trace flag in the tcb. */ -static void -rtems_capture_flush_tcb (rtems_tcb *tcb) +static bool +rtems_capture_flush_tcb (rtems_tcb *tcb, void *arg) { tcb->Capture.flags &= ~RTEMS_CAPTURE_TRACED; + return false; } /* @@ -776,7 +779,7 @@ rtems_capture_flush (bool prime) return RTEMS_UNSATISFIED; } - rtems_iterate_over_all_threads (rtems_capture_flush_tcb); + _Thread_Iterate (rtems_capture_flush_tcb, NULL); if (prime) capture_flags_global &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW); diff --git a/cpukit/libmisc/cpuuse/cpuusagereset.c b/cpukit/libmisc/cpuuse/cpuusagereset.c index f6cf7dd..507044a 100644 --- a/cpukit/libmisc/cpuuse/cpuusagereset.c +++ b/cpukit/libmisc/cpuuse/cpuusagereset.c @@ -26,8 +26,9 @@ #include "cpuuseimpl.h" -static void CPU_usage_Per_thread_handler( - Thread_Control *the_thread +static bool CPU_usage_Per_thread_handler( + Thread_Control *the_thread, + void *arg ) { const Scheduler_Control *scheduler; @@ -42,6 +43,7 @@ static void CPU_usage_Per_thread_handler( _Scheduler_Release_critical( scheduler, &scheduler_lock_context ); _Thread_State_release( the_thread, &state_lock_context ); + return false; } /* @@ -61,5 +63,5 @@ void rtems_cpu_usage_reset( void ) cpu->cpu_usage_timestamp = CPU_usage_Uptime_at_last_reset; } - rtems_iterate_over_all_threads(CPU_usage_Per_thread_handler); + rtems_task_iterate(CPU_usage_Per_thread_handler, NULL); } diff --git a/cpukit/libmisc/cpuuse/cpuusagetop.c b/cpukit/libmisc/cpuuse/cpuusagetop.c index 38d5ca4..9afa4e2 100644 --- a/cpukit/libmisc/cpuuse/cpuusagetop.c +++ b/cpukit/libmisc/cpuuse/cpuusagetop.c @@ -85,43 +85,6 @@ typedef struct #define RTEMS_TOP_SORT_CURRENT (4) #define RTEMS_TOP_SORT_MAX (4) -/* - * Private version of the iterator with an arg. This will be moved - * to the public version in 5.0. - */ - -typedef void (*rtems_per_thread_routine_2)( Thread_Control *, void* ); - -void rtems_iterate_over_all_threads_2(rtems_per_thread_routine_2 routine, - void* arg); - -void rtems_iterate_over_all_threads_2(rtems_per_thread_routine_2 routine, - void* arg) -{ - uint32_t i; - uint32_t api_index; - Thread_Control *the_thread; - Objects_Information *information; - - if ( !routine ) - return; - - for ( api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++ ) { - #if !defined(RTEMS_POSIX_API) || defined(RTEMS_DEBUG) - if ( !_Objects_Information_table[ api_index ] ) - continue; - #endif - information = _Objects_Information_table[ api_index ][ 1 ]; - if ( information ) { - for ( i=1 ; i <= information->maximum ; i++ ) { - the_thread = (Thread_Control *)information->local_table[ i ]; - if ( the_thread ) - (*routine)(the_thread, arg); - } - } - } -} - static inline bool equal_to_uint32_t( uint32_t * lhs, uint32_t * rhs ) { if ( *lhs == *rhs ) @@ -190,17 +153,19 @@ print_time(rtems_cpu_usage_data* data, /* * Count the number of tasks. */ -static void +static bool task_counter(Thread_Control *thrad, void* arg) { rtems_cpu_usage_data* data = (rtems_cpu_usage_data*) arg; ++data->task_count; + + return false; } /* * Create the sorted table with the current and total usage. */ -static void +static bool task_usage(Thread_Control* thread, void* arg) { rtems_cpu_usage_data* data = (rtems_cpu_usage_data*) arg; @@ -287,6 +252,8 @@ task_usage(Thread_Control* thread, void* arg) data->current_usage[j] = current; break; } + + return false; } /* @@ -322,7 +289,7 @@ rtems_cpuusage_top_thread (rtems_task_argument arg) Timestamp_Control load; data->task_count = 0; - rtems_iterate_over_all_threads_2(task_counter, data); + _Thread_Iterate(task_counter, data); tasks_size = sizeof(Thread_Control*) * (data->task_count + 1); usage_size = sizeof(Timestamp_Control) * (data->task_count + 1); @@ -353,7 +320,7 @@ rtems_cpuusage_top_thread (rtems_task_argument arg) _Timestamp_Subtract(&data->last_uptime, &data->uptime, &data->period); data->last_uptime = data->uptime; - rtems_iterate_over_all_threads_2(task_usage, data); + _Thread_Iterate(task_usage, data); if (data->task_count > data->task_size) { diff --git a/cpukit/libmisc/stackchk/check.c b/cpukit/libmisc/stackchk/check.c index ae4ae79..4c48c5b 100644 --- a/cpukit/libmisc/stackchk/check.c +++ b/cpukit/libmisc/stackchk/check.c @@ -352,23 +352,20 @@ static inline void *Stack_check_find_high_water_mark( * * Try to print out how much stack was actually used by the task. */ -static const rtems_printer* printer; - -static void Stack_check_Dump_threads_usage( - Thread_Control *the_thread +static bool Stack_check_Dump_threads_usage( + Thread_Control *the_thread, + void *arg ) { - uint32_t size, used; - void *low; - void *high_water_mark; - void *current; - Stack_Control *stack; - char name[5]; + uint32_t size, used; + void *low; + void *high_water_mark; + void *current; + Stack_Control *stack; + char name[5]; + const rtems_printer *printer; - /* - * The pointer passed in for the_thread is guaranteed to be non-NULL from - * rtems_iterate_over_all_threads() so no need to check it here. - */ + printer = arg; /* * Obtain interrupt stack information @@ -376,7 +373,7 @@ static void Stack_check_Dump_threads_usage( #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) if (the_thread == (Thread_Control *) -1) { if (!Stack_check_Interrupt_stack.area) - return; + return false; stack = &Stack_check_Interrupt_stack; the_thread = 0; current = 0; @@ -430,7 +427,7 @@ static void Stack_check_Dump_threads_usage( rtems_printf( printer, "%8" PRId32 "\n", used ); } - + return false; } /* @@ -453,25 +450,26 @@ static void Stack_check_Dump_threads_usage( */ void rtems_stack_checker_report_usage_with_plugin( - const rtems_printer* printer_ + const rtems_printer* printer ) { - if ( printer != NULL || ! rtems_print_printer_valid ( printer_ ) ) - return; - - printer = printer_; - rtems_printf( printer, "Stack usage by thread\n"); rtems_printf( printer, " ID NAME LOW HIGH CURRENT AVAILABLE USED\n" ); /* iterate over all threads and dump the usage */ - rtems_iterate_over_all_threads( Stack_check_Dump_threads_usage ); + rtems_task_iterate( + Stack_check_Dump_threads_usage, + RTEMS_DECONST( rtems_printer *, printer ) + ); #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) /* dump interrupt stack info if any */ - Stack_check_Dump_threads_usage((Thread_Control *) -1); + Stack_check_Dump_threads_usage( + (Thread_Control *) -1, + RTEMS_DECONST( rtems_printer *, printer ) + ); #endif printer = NULL; diff --git a/cpukit/rtems/Makefile.am b/cpukit/rtems/Makefile.am index 4be4266..6ecff9e 100644 --- a/cpukit/rtems/Makefile.am +++ b/cpukit/rtems/Makefile.am @@ -93,6 +93,7 @@ librtems_a_SOURCES += src/taskgetscheduler.c librtems_a_SOURCES += src/taskident.c librtems_a_SOURCES += src/taskinitusers.c librtems_a_SOURCES += src/taskissuspended.c +librtems_a_SOURCES += src/taskiterate.c librtems_a_SOURCES += src/taskmode.c librtems_a_SOURCES += src/taskrestart.c librtems_a_SOURCES += src/taskresume.c diff --git a/cpukit/rtems/include/rtems/rtems/tasks.h b/cpukit/rtems/include/rtems/rtems/tasks.h index 0eaaeca..180e50e 100644 --- a/cpukit/rtems/include/rtems/rtems/tasks.h +++ b/cpukit/rtems/include/rtems/rtems/tasks.h @@ -513,6 +513,38 @@ rtems_status_code rtems_task_set_scheduler( rtems_id rtems_task_self(void); /** + * @brief Task visitor. + * + * @param[in] tcb The task control block. + * @param[in] arg The visitor argument. + * + * @retval true Stop the iteration. + * @retval false Otherwise. + * + * @see rtems_task_iterate(). + */ +typedef bool ( *rtems_task_visitor )( rtems_tcb *tcb, void *arg ); + +/** + * @brief Iterates over all tasks in the system. + * + * This operation covers all tasks of all APIs. + * + * Must be called from task context. This operation obtains and releases the + * objects allocator lock. The task visitor is called while owning the objects + * allocator lock. It is possible to perform blocking operations in the task + * visitor, however, take care that no deadlocks via the object allocator lock + * can occur. + * + * @param[in] visitor The task visitor. + * @param[in] arg The visitor argument. + */ +void rtems_task_iterate( + rtems_task_visitor visitor, + void *arg +); + +/** * @brief Identifies a scheduler by its name. * * The scheduler name is determined by the scheduler configuration. diff --git a/cpukit/rtems/src/taskiterate.c b/cpukit/rtems/src/taskiterate.c new file mode 100644 index 0000000..853551b --- /dev/null +++ b/cpukit/rtems/src/taskiterate.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rt...@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/rtems/tasks.h> +#include <rtems/score/threadimpl.h> +#include <rtems/score/objectimpl.h> + +void rtems_task_iterate( + rtems_task_visitor visitor, + void *arg +) +{ + _Objects_Allocator_lock(); + _Thread_Iterate( visitor, arg ); + _Objects_Allocator_unlock(); +} diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index 528c3fe..58f9e65 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -307,6 +307,7 @@ libscore_a_SOURCES += src/threadentryadaptornumeric.c libscore_a_SOURCES += src/threadentryadaptorpointer.c libscore_a_SOURCES += src/threadgetcputimeused.c libscore_a_SOURCES += src/threadglobalconstruction.c +libscore_a_SOURCES += src/threaditerate.c libscore_a_SOURCES += src/threadscheduler.c libscore_a_SOURCES += src/threadtimeout.c libscore_a_SOURCES += src/threadwaitgetid.c diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index e98059e..ff7f13b 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -839,18 +839,12 @@ void *_Thread_Idle_body( ); #endif -/** This defines the type for a method which operates on a single thread. - */ typedef void (*rtems_per_thread_routine)( Thread_Control * ); -/** - * @brief Iterates over all threads. - * This routine iterates over all threads regardless of API and - * invokes the specified routine. - */ +/* Use rtems_task_iterate() instead */ void rtems_iterate_over_all_threads( rtems_per_thread_routine routine -); +) RTEMS_DEPRECATED; /** * @brief Thread control add-on. diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index f96c4b0..5425978 100644 --- a/cpukit/score/include/rtems/score/threadimpl.h +++ b/cpukit/score/include/rtems/score/threadimpl.h @@ -82,6 +82,13 @@ extern Thread_Control *_Thread_Allocated_fp; RTEMS_CONTAINER_OF( node, Thread_Control, Scheduler.Help_node ) #endif +typedef bool ( *Thread_Visitor )( Thread_Control *the_thread, void *arg ); + +void _Thread_Iterate( + Thread_Visitor visitor, + void *arg +); + void _Thread_Initialize_information( Thread_Information *information, Objects_APIs the_api, diff --git a/cpukit/score/src/iterateoverthreads.c b/cpukit/score/src/iterateoverthreads.c index 8933352..e829fc9 100644 --- a/cpukit/score/src/iterateoverthreads.c +++ b/cpukit/score/src/iterateoverthreads.c @@ -18,37 +18,28 @@ #include "config.h" #endif -#include <rtems/score/thread.h> -#include <rtems/score/objectimpl.h> +#include <rtems/score/threadimpl.h> -void rtems_iterate_over_all_threads(rtems_per_thread_routine routine) -{ - uint32_t i; - uint32_t api_index; - Thread_Control *the_thread; - Objects_Information *information; - - if ( !routine ) - return; +typedef struct { + rtems_per_thread_routine routine; +} routine_arg; - for ( api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++ ) { - #if !defined(RTEMS_POSIX_API) || defined(RTEMS_DEBUG) - if ( !_Objects_Information_table[ api_index ] ) - continue; - #endif - - information = _Objects_Information_table[ api_index ][ 1 ]; - if ( !information ) - continue; +static bool routine_adaptor( rtems_tcb *tcb, void *arg ) +{ + routine_arg *ra; - for ( i=1 ; i <= information->maximum ; i++ ) { - the_thread = (Thread_Control *)information->local_table[ i ]; + ra = arg; + ( *ra->routine )( tcb ); + return false; +} - if ( !the_thread ) - continue; +void rtems_iterate_over_all_threads( rtems_per_thread_routine routine ) +{ + routine_arg arg = { + .routine = routine + }; - (*routine)(the_thread); - } + if ( routine != NULL ) { + _Thread_Iterate( routine_adaptor, &arg ); } - } diff --git a/cpukit/score/src/threaditerate.c b/cpukit/score/src/threaditerate.c new file mode 100644 index 0000000..0f9a1be --- /dev/null +++ b/cpukit/score/src/threaditerate.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rt...@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/score/threadimpl.h> + +void _Thread_Iterate( + Thread_Visitor visitor, + void *arg +) +{ + int api_index; + + for ( api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; ++api_index ) { + const Objects_Information *information; + Objects_Maximum i; + +#if !defined(RTEMS_POSIX_API) + if ( _Objects_Information_table[ api_index ] == NULL ) { + continue; + } +#endif + + information = _Objects_Information_table[ api_index ][ 1 ]; + + if ( information == NULL ) { + continue; + } + + for ( i = 1 ; i <= information->maximum ; ++i ) { + Thread_Control *the_thread; + + the_thread = (Thread_Control *) information->local_table[ i ]; + + if ( the_thread != NULL ) { + bool done; + + done = (* visitor )( the_thread, arg ); + + if ( done ) { + return; + } + } + } + } +} diff --git a/testsuites/sptests/sp41/init.c b/testsuites/sptests/sp41/init.c index c484608..04b855b 100644 --- a/testsuites/sptests/sp41/init.c +++ b/testsuites/sptests/sp41/init.c @@ -11,27 +11,31 @@ #include "config.h" #endif +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #include <tmacros.h> #include <rtems/score/objectimpl.h> const char rtems_test_name[] = "SP 41"; -/* forward declarations to avoid warnings */ -rtems_task Init(rtems_task_argument argument); -void iterator(Thread_Control *thread); +static bool visitor( Thread_Control *thread, void *arg ) +{ + int *counter = arg; + ++( *counter ); + return false; +} -void iterator( - Thread_Control *thread -) +static void iterator( Thread_Control *thread ) { } -rtems_task Init( +static rtems_task Init( rtems_task_argument ignored ) { void *tmp; + int counter; TEST_BEGIN(); @@ -39,9 +43,22 @@ rtems_task Init( tmp = _Objects_Information_table[ OBJECTS_CLASSIC_API ][ 1 ]; _Objects_Information_table[ OBJECTS_CLASSIC_API ][ 1 ] = NULL; - puts( "Init - rtems_iterate_over_all_threads" ); - rtems_iterate_over_all_threads(iterator); + puts( "Init - rtems_task_iterate - NULL table" ); + counter = 0; + rtems_task_iterate( visitor, &counter ); _Objects_Information_table[ OBJECTS_CLASSIC_API ][ 1 ] = tmp; + rtems_test_assert( counter == 1 ); + + puts( "Init - rtems_task_iterate - normal" ); + counter = 0; + rtems_task_iterate( visitor, &counter ); + rtems_test_assert( counter == 2 ); + + puts( "Init - rtems_iterate_over_all_threads - NULL" ); + rtems_iterate_over_all_threads( NULL ); + + puts( "Init - rtems_iterate_over_all_threads - iterator" ); + rtems_iterate_over_all_threads( iterator ); TEST_END(); rtems_test_exit(0); diff --git a/testsuites/sptests/sp41/sp41.scn b/testsuites/sptests/sp41/sp41.scn index 02933ae..9a43b0a 100644 --- a/testsuites/sptests/sp41/sp41.scn +++ b/testsuites/sptests/sp41/sp41.scn @@ -1,4 +1,7 @@ -*** TEST 41 *** +*** BEGIN OF TEST SP 41 *** Init - overwrite internal value to trip case -Init - rtems_iterate_over_all_threads -*** END OF TEST 41 *** +Init - rtems_task_iterate - NULL table +Init - rtems_task_iterate - normal +Init - rtems_iterate_over_all_threads - NULL +Init - rtems_iterate_over_all_threads - iterator +*** END OF TEST SP 41 *** -- 1.8.4.5 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel