# HG changeset patch # User nickg # Date 1039717894 0 # Node ID a65a4055f146f09ce088f7a1b39f4befe2a8f43c # Parent a6cede66ea36db3179aac50e41d605e897df211f * src/common/kapi.cxx: * include/kapi.h: Added function cyg_thread_get_next(), cyg_thread_find() and cyg_thread_get_info() to allow the current set of threads to be enumerated, and per-thread information to be retrieved safely. * doc/kernel.sgml: Documented new KAPI calls. * src/common/thread.cxx: Zero unique_id in thread destructor so that a stale thread pointer can be checked for validity. * include/instrmnt.h: Added cyg_instrument_state() to report the current state of an instrumentation flag. Moved ifdef for CYGDBG_KERNEL_INSTRUMENT_MSGS out of within FLAGS ifdef. We can have messages without flags. * src/instrmnt/meminst.cxx: Added cyg_instrument_state() to report the current state of an instrumentation flag. Modified cyg_instrument_msg() in line with header and table changes. * host/instr/dump_instr.c: * host/instr/instrument.sh: * include/instrument_desc.h: Added a final NULL element to the generated table in instrument_desc.h to mark its end. Otherwise code that does not have access to the table definition cannot find its end. Also added ifdefs to allow instrument_desc.h to be used to acquire the structure definition and table pointer. diff --git a/packages/kernel/current/ChangeLog b/packages/kernel/current/ChangeLog --- a/packages/kernel/current/ChangeLog +++ b/packages/kernel/current/ChangeLog @@ -1,3 +1,37 @@ +2002-12-12 Nick Garnett + + * src/common/kapi.cxx: + * include/kapi.h: + Added function cyg_thread_get_next(), cyg_thread_find() and + cyg_thread_get_info() to allow the current set of threads to be + enumerated, and per-thread information to be retrieved safely. + + * doc/kernel.sgml: Documented new KAPI calls. + + * src/common/thread.cxx: Zero unique_id in thread destructor so + that a stale thread pointer can be checked for validity. + + * include/instrmnt.h: + Added cyg_instrument_state() to report the current state of an + instrumentation flag. + Moved ifdef for CYGDBG_KERNEL_INSTRUMENT_MSGS out of within FLAGS + ifdef. We can have messages without flags. + + * src/instrmnt/meminst.cxx: + Added cyg_instrument_state() to report the current state of an + instrumentation flag. + Modified cyg_instrument_msg() in line with header and table + changes. + + * host/instr/dump_instr.c: + * host/instr/instrument.sh: + * include/instrument_desc.h: + Added a final NULL element to the generated table in + instrument_desc.h to mark its end. Otherwise code that does not + have access to the table definition cannot find its end. Also + added ifdefs to allow instrument_desc.h to be used to acquire the + structure definition and table pointer. + 2002-12-03 Gary Thomas * tests/tm_basic.cxx: Add tests of 'flag' synchronizers. diff --git a/packages/kernel/current/doc/kernel.sgml b/packages/kernel/current/doc/kernel.sgml --- a/packages/kernel/current/doc/kernel.sgml +++ b/packages/kernel/current/doc/kernel.sgml @@ -1276,6 +1276,9 @@ be achieved when programming in C++ is l cyg_thread_get_stack_base cyg_thread_get_stack_size cyg_thread_measure_stack_usage + cyg_thread_get_next + cyg_thread_get_info + cyg_thread_find Get basic thread information @@ -1304,6 +1307,21 @@ be achieved when programming in C++ is l cyg_uint32 cyg_thread_measure_stack_usage cyg_handle_t thread + + cyg_bool cyg_thread_get_next + cyg_handle_t *thread + cyg_uint16 *id + + + cyg_bool cyg_thread_get_info + cyg_handle_t thread + cyg_uint16 id + cyg_thread_info *info + + + cyg_handle_t cyg_thread_find + cyg_uint16 id + @@ -1344,6 +1362,31 @@ run the specified thread has not yet bee point in the function call graph. Never the less the value returned can give some useful indication of the thread's stack requirements. + +cyg_thread_get_next is used to enumerate all the +current threads in the system. It should be called intially with the +locations pointed to by thread and +id set to zero. On return these will be set to +the handle and ID of the first thread. On subsequent calls, these +parameters should be left set to the values returned by the previous +call. The handle and ID of the next thread in the system will be +installed each time, until a false return value +indicates the end of the list. + + +cyg_thread_get_info fills in the +cyg_thread_info structure with information about the +thread described by the thread and +id arguments. The information returned includes +the thread's handle and id, its state and name, priorities and stack +parameters. If the thread does not exist the function returns +false. + + +cyg_thread_find returns a handle for the thread +whose ID is id. If no such thread exists, a +zero handle is returned. + Valid contexts @@ -1359,6 +1402,38 @@ stack usage involves looping over at lea so this should normally only be done from thread context. + + Examples + +A simple example of the use of the +cyg_thread_get_next and +cyg_thread_get_info follows: + + + +#include <cyg/kernel/kapi.h> +#include <stdio.h> + +void show_threads(void) +{ + cyg_handle_t thread = 0; + cyg_uint16 id = 0; + + while( cyg_thread_get_next( &thread, &id ) ) + { + cyg_thread_info info; + + if( !cyg_thread_get_info( thread, id, &info ) ) + break; + + printf("ID: %04x name: %10s pri: %d\n", + info.id, info.name?info.name:"----", info.set_pri ); + } +} + + + + diff --git a/packages/kernel/current/host/instr/dump_instr.c b/packages/kernel/current/host/instr/dump_instr.c --- a/packages/kernel/current/host/instr/dump_instr.c +++ b/packages/kernel/current/host/instr/dump_instr.c @@ -21,6 +21,7 @@ struct Instrument_Record // ------------------------------------------------------------------------- #ifdef CYGDBG_KERNEL_INSTRUMENT_MSGS +#define CYGDBG_KERNEL_INSTRUMENT_MSGS_DEFINE_TABLE #include #define NELEM(x) (sizeof(x)/sizeof*(x)) externC char * cyg_instrument_msg(CYG_WORD16 type) { @@ -30,7 +31,7 @@ externC char * cyg_instrument_msg(CYG_WO CYG_WORD cl, event; record = instrument_desc; - end_record = &instrument_desc[NELEM(instrument_desc)]; + end_record = &instrument_desc[NELEM(instrument_desc)-1]; cl = type & 0xff00; event = type & 0x00ff; diff --git a/packages/kernel/current/host/instr/instrument.sh b/packages/kernel/current/host/instr/instrument.sh --- a/packages/kernel/current/host/instr/instrument.sh +++ b/packages/kernel/current/host/instr/instrument.sh @@ -8,11 +8,16 @@ echo " char * msg; echo " CYG_WORD num; " echo "}; " echo +echo "#ifdef CYGDBG_KERNEL_INSTRUMENT_MSGS_DEFINE_TABLE " echo struct instrument_desc_s instrument_desc[] = { grep -e \#define.CYG_INSTRUMENT_EVENT -e \#define.CYG_INSTRUMENT_CLASS $1 | grep -v MAX | cut -d " " -f 2- | cut -d "_" -f 4- | sort | awk '{ print("{\""$1"\", " $2 "},") }' +echo { 0, 0 } echo }\; +echo "#else /* CYGDBG_KERNEL_INSTRUMENT_MSGS_DEFINE_TABLE */ " +echo "extern struct instrument_desc_s instrument_desc[]; " +echo "#endif /* CYGDBG_KERNEL_INSTRUMENT_MSGS_DEFINE_TABLE */ " echo echo "/* EOF instrument_desc.h */" diff --git a/packages/kernel/current/include/instrmnt.h b/packages/kernel/current/include/instrmnt.h --- a/packages/kernel/current/include/instrmnt.h +++ b/packages/kernel/current/include/instrmnt.h @@ -82,10 +82,13 @@ externC void cyg_instrument_enable( cyg_ externC void cyg_instrument_disable( cyg_uint32 cl, cyg_uint32 event ); +externC cyg_bool cyg_instrument_state( cyg_uint32 cl, cyg_uint32 event ); + +#endif + #ifdef CYGDBG_KERNEL_INSTRUMENT_MSGS externC char * cyg_instrument_msg(CYG_WORD16 type); #endif -#endif // ------------------------------------------------------------------------- // Instrumentation macros diff --git a/packages/kernel/current/include/instrument_desc.h b/packages/kernel/current/include/instrument_desc.h --- a/packages/kernel/current/include/instrument_desc.h +++ b/packages/kernel/current/include/instrument_desc.h @@ -7,6 +7,7 @@ struct instrument_desc_s { CYG_WORD num; }; +#ifdef CYGDBG_KERNEL_INSTRUMENT_MSGS_DEFINE_TABLE struct instrument_desc_s instrument_desc[] = { {"ALARM", 0x0900}, {"ALARM_ADD", 1}, @@ -133,6 +134,10 @@ struct instrument_desc_s instrument_desc {"USER_7", 7}, {"USER_8", 8}, {"USER_9", 9}, +{ 0, 0 } }; +#else /* CYGDBG_KERNEL_INSTRUMENT_MSGS_DEFINE_TABLE */ +extern struct instrument_desc_s instrument_desc[]; +#endif /* CYGDBG_KERNEL_INSTRUMENT_MSGS_DEFINE_TABLE */ /* EOF instrument_desc.h */ diff --git a/packages/kernel/current/include/kapi.h b/packages/kernel/current/include/kapi.h --- a/packages/kernel/current/include/kapi.h +++ b/packages/kernel/current/include/kapi.h @@ -12,6 +12,7 @@ // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 2002 Bart Veer +// Copyright (C) 2002 Nick Garnett // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. // // eCos is free software; you can redistribute it and/or modify it under @@ -207,6 +208,30 @@ cyg_uint32 cyg_thread_measure_stack_usag #endif /*---------------------------------------------------------------------------*/ +/* Thread enumeration and information */ + +typedef struct +{ + cyg_handle_t handle; + cyg_uint16 id; + cyg_uint32 state; + char *name; + cyg_priority_t set_pri; + cyg_priority_t cur_pri; + cyg_addrword_t stack_base; + cyg_uint32 stack_size; + cyg_uint32 stack_used; +} cyg_thread_info; + +cyg_bool_t cyg_thread_get_next( cyg_handle_t *thread, cyg_uint16 *id ); + +cyg_bool_t cyg_thread_get_info( cyg_handle_t thread, + cyg_uint16 id, + cyg_thread_info *info ); + +cyg_handle_t cyg_thread_find( cyg_uint16 id ); + +/*---------------------------------------------------------------------------*/ /* Per-thread Data */ #ifdef CYGVAR_KERNEL_THREADS_DATA diff --git a/packages/kernel/current/src/common/kapi.cxx b/packages/kernel/current/src/common/kapi.cxx --- a/packages/kernel/current/src/common/kapi.cxx +++ b/packages/kernel/current/src/common/kapi.cxx @@ -9,6 +9,7 @@ // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2002 Nick Garnett // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -309,6 +310,101 @@ externC cyg_uint32 cyg_thread_measure_st #endif /*---------------------------------------------------------------------------*/ +/* Thread enumeration and information */ + +#ifdef CYGVAR_KERNEL_THREADS_LIST + +cyg_bool_t cyg_thread_get_next( cyg_handle_t *current, cyg_uint16 *id ) +{ + cyg_bool_t result = true; + + Cyg_Scheduler::lock(); + + Cyg_Thread *thread = (Cyg_Thread *)*current; + + if( *current == 0 ) + { + thread = Cyg_Thread::get_list_head(); + *current = (cyg_handle_t)thread; + *id = thread->get_unique_id(); + } + else if( (thread->get_unique_id() == *id) && + (thread = thread->get_list_next()) != NULL ) + { + *current = (cyg_handle_t)thread; + *id = thread->get_unique_id(); + } + else + { + *current = 0; + *id = 0; + result = false; + } + + Cyg_Scheduler::unlock(); + + return result; +} + +cyg_handle_t cyg_thread_find( cyg_uint16 id ) +{ + Cyg_Scheduler::lock(); + + Cyg_Thread *thread = Cyg_Thread::get_list_head(); + + while( thread != NULL ) + { + if( thread->get_unique_id() == id ) + break; + + thread = thread->get_list_next(); + } + + Cyg_Scheduler::unlock(); + + return (cyg_handle_t)thread; +} + +#endif + +cyg_bool_t cyg_thread_get_info( cyg_handle_t threadh, + cyg_uint16 id, + cyg_thread_info *info ) +{ + cyg_bool_t result = true; + Cyg_Thread *thread = (Cyg_Thread *)threadh; + + Cyg_Scheduler::lock(); + + if( thread->get_unique_id() == id && info != NULL ) + { + info->handle = threadh; + info->id = id; + info->state = thread->get_state(); +#ifdef CYGVAR_KERNEL_THREADS_NAME + info->name = thread->get_name(); +#else + info->name = NULL; +#endif + info->set_pri = thread->get_priority(); + info->cur_pri = thread->get_current_priority(); + info->stack_base = thread->get_stack_base(); + info->stack_size = thread->get_stack_size(); + +#ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT + info->stack_used = thread->measure_stack_usage(); +#else + info->stack_used = 0; +#endif + } + else result = false; + + Cyg_Scheduler::unlock(); + + return result; +} + +/*---------------------------------------------------------------------------*/ /* Per-thread data */ #ifdef CYGVAR_KERNEL_THREADS_DATA diff --git a/packages/kernel/current/src/common/thread.cxx b/packages/kernel/current/src/common/thread.cxx --- a/packages/kernel/current/src/common/thread.cxx +++ b/packages/kernel/current/src/common/thread.cxx @@ -295,6 +295,9 @@ Cyg_Thread::~Cyg_Thread() remove_from_list(); #endif + // Zero the unique_id to render this thread inconsistent. + unique_id = 0; + CYG_REPORT_RETURN(); } diff --git a/packages/kernel/current/src/instrmnt/meminst.cxx b/packages/kernel/current/src/instrmnt/meminst.cxx --- a/packages/kernel/current/src/instrmnt/meminst.cxx +++ b/packages/kernel/current/src/instrmnt/meminst.cxx @@ -214,11 +214,17 @@ externC void cyg_instrument_disable( cyg } +externC cyg_bool cyg_instrument_state( cyg_uint32 cl, cyg_uint32 event) +{ + return (instrument_flags[cl>>8] & (1< #define NELEM(x) (sizeof(x)/sizeof*(x)) externC char * cyg_instrument_msg(CYG_WORD16 type) { @@ -228,7 +234,7 @@ externC char * cyg_instrument_msg(CYG_WO CYG_WORD cl, event; record = instrument_desc; - end_record = &instrument_desc[NELEM(instrument_desc)]; + end_record = &instrument_desc[NELEM(instrument_desc)-1]; cl = type & 0xff00; event = type & 0x00ff;