This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Kernel KAPI and instrumentation mods


Just tidying up some changes from my source tree. There are two things
here:

1. Some new functions for the KAPI to give access to the thread list.

2. Some minor updates to the instrumentation code.



Index: ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/ChangeLog,v
retrieving revision 1.84
diff -u -5 -r1.84 ChangeLog
--- ChangeLog	3 Dec 2002 14:25:22 -0000	1.84
+++ ChangeLog	12 Dec 2002 18:28:26 -0000
@@ -1,5 +1,39 @@
+2002-12-12  Nick Garnett  <nickg@ecoscentric.com>
+
+	* 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  <gthomas@ecoscentric.com>
 
 	* tests/tm_basic.cxx: Add tests of 'flag' synchronizers.
 
 2002-10-28  Andrew Lunn  <andrew.lunn@ascom.ch>
Index: doc/kernel.sgml
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/doc/kernel.sgml,v
retrieving revision 1.4
diff -u -5 -r1.4 kernel.sgml
--- doc/kernel.sgml	1 Oct 2002 19:10:21 -0000	1.4
+++ doc/kernel.sgml	12 Dec 2002 18:28:49 -0000
@@ -1274,10 +1274,13 @@
       <refname>cyg_thread_self</refname>
       <refname>cyg_thread_idle_thread</refname>
       <refname>cyg_thread_get_stack_base</refname>
       <refname>cyg_thread_get_stack_size</refname>
       <refname>cyg_thread_measure_stack_usage</refname>
+      <refname>cyg_thread_get_next</refname>
+      <refname>cyg_thread_get_info</refname>
+      <refname>cyg_thread_find</refname>
       <refpurpose>Get basic thread information</refpurpose>
     </refnamediv>
 
     <refsynopsisdiv>
       <funcsynopsis>
@@ -1302,10 +1305,25 @@
         </funcprototype>
         <funcprototype>
           <funcdef>cyg_uint32 <function>cyg_thread_measure_stack_usage</function></funcdef>
           <paramdef>cyg_handle_t <parameter>thread</parameter></paramdef>
         </funcprototype>        
+        <funcprototype>
+          <funcdef>cyg_bool <function>cyg_thread_get_next</function></funcdef>
+          <paramdef>cyg_handle_t *<parameter>thread</parameter></paramdef>
+          <paramdef>cyg_uint16 *<parameter>id</parameter></paramdef>
+        </funcprototype>        
+        <funcprototype>
+          <funcdef>cyg_bool <function>cyg_thread_get_info</function></funcdef>
+          <paramdef>cyg_handle_t <parameter>thread</parameter></paramdef>
+          <paramdef>cyg_uint16 <parameter>id</parameter></paramdef>
+          <paramdef>cyg_thread_info *<parameter>info</parameter></paramdef>
+        </funcprototype>        
+        <funcprototype>
+          <funcdef>cyg_handle_t <function>cyg_thread_find</function></funcdef>
+          <paramdef>cyg_uint16 <parameter>id</parameter></paramdef>
+        </funcprototype>        
       </funcsynopsis>
     </refsynopsisdiv>
 
     <refsect1 id="kernel-thread-info-description"><title>Description</title>
       <para>
@@ -1342,10 +1360,35 @@
 true upper bound, for example it is possible that in the current test
 run the specified thread has not yet been interrupted at the deepest
 point in the function call graph. Never the less the value returned
 can give some useful indication of the thread's stack requirements.
       </para>
+      <para>
+<function>cyg_thread_get_next</function> is used to enumerate all the
+current threads in the system. It should be called intially with the
+locations pointed to by <parameter>thread</parameter> and
+<parameter>id</parameter> 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 <literal>false</literal> return value
+indicates the end of the list.
+      </para>
+      <para>
+<function>cyg_thread_get_info</function> fills in the
+<type>cyg_thread_info</type> structure with information about the
+thread described by the <parameter>thread</parameter> and
+<parameter>id</parameter> 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
+<literal>false</literal>.
+    </para>
+    <para>
+<function>cyg_thread_find</function> returns a handle for the thread
+whose ID is <parameter>id</parameter>. If no such thread exists, a
+zero handle is returned.
+    </para>
     </refsect1>
 
     <refsect1 id="kernel-thread-info-context"><title>Valid contexts</title>
       <para>
 <function>cyg_thread_self</function> may only be called from thread
@@ -1357,10 +1400,42 @@
 any time after the specified thread has been created, but measuring
 stack usage involves looping over at least part of the thread's stack
 so this should normally only be done from thread context.
       </para>
     </refsect1>
+
+    <refsect1 id="kernel-thread-info-examples"><title>Examples</title>
+      <para>
+A simple example of the use of the
+<function>cyg_thread_get_next</function> and
+<function>cyg_thread_get_info</function> follows:      
+      </para>
+      <programlisting width=72>
+
+#include &lt;cyg/kernel/kapi.h&gt;
+#include &lt;stdio.h&gt;
+
+void show_threads(void)
+{
+    cyg_handle_t thread = 0;
+    cyg_uint16 id = 0;
+
+    while( cyg_thread_get_next( &amp;thread, &amp;id ) )
+    {
+        cyg_thread_info info;
+
+        if( !cyg_thread_get_info( thread, id, &amp;info ) )
+            break;
+
+        printf("ID: %04x name: %10s pri: %d\n",
+                info.id, info.name?info.name:"----", info.set_pri );
+    }
+}
+
+      </programlisting>
+    </refsect1>
+
   </refentry>
 
 <!-- }}} -->
 <!-- {{{ Thread control                 -->
 
Index: host/instr/dump_instr.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/host/instr/dump_instr.c,v
retrieving revision 1.2
diff -u -5 -r1.2 dump_instr.c
--- host/instr/dump_instr.c	2 Oct 2001 18:28:29 -0000	1.2
+++ host/instr/dump_instr.c	12 Dec 2002 18:28:49 -0000
@@ -19,20 +19,21 @@
 };
 
 // -------------------------------------------------------------------------
 
 #ifdef CYGDBG_KERNEL_INSTRUMENT_MSGS
+#define CYGDBG_KERNEL_INSTRUMENT_MSGS_DEFINE_TABLE
 #include <cyg/kernel/instrument_desc.h>
 #define NELEM(x) (sizeof(x)/sizeof*(x))
 externC char * cyg_instrument_msg(CYG_WORD16 type) {
 
   struct instrument_desc_s *record;
   struct instrument_desc_s *end_record;
   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;
 
   while ((record != end_record) && (record->num != cl)) {
     record++;
Index: host/instr/instrument.sh
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/host/instr/instrument.sh,v
retrieving revision 1.1
diff -u -5 -r1.1 instrument.sh
--- host/instr/instrument.sh	12 Sep 2001 00:59:24 -0000	1.1
+++ host/instr/instrument.sh	12 Dec 2002 18:28:49 -0000
@@ -6,13 +6,18 @@
 echo "struct instrument_desc_s {                                "
 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 */"
 
Index: include/instrmnt.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/include/instrmnt.h,v
retrieving revision 1.10
diff -u -5 -r1.10 instrmnt.h
--- include/instrmnt.h	23 May 2002 23:06:46 -0000	1.10
+++ include/instrmnt.h	12 Dec 2002 18:28:51 -0000
@@ -80,14 +80,17 @@
 
 externC void cyg_instrument_enable( cyg_uint32 cl, cyg_uint32 event );
 
 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
 
 #ifdef CYGPKG_KERNEL_INSTRUMENT
Index: include/instrument_desc.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/include/instrument_desc.h,v
retrieving revision 1.1
diff -u -5 -r1.1 instrument_desc.h
--- include/instrument_desc.h	12 Sep 2001 00:59:24 -0000	1.1
+++ include/instrument_desc.h	12 Dec 2002 18:28:51 -0000
@@ -5,10 +5,11 @@
 struct instrument_desc_s {                                
     char *   msg;                                         
     CYG_WORD num;                                         
 };                                                        
 
+#ifdef CYGDBG_KERNEL_INSTRUMENT_MSGS_DEFINE_TABLE         
 struct instrument_desc_s instrument_desc[] = {
 {"ALARM",   0x0900},
 {"ALARM_ADD",   1},
 {"ALARM_CALL",   3},
 {"ALARM_INIT",   4},
@@ -131,8 +132,12 @@
 {"USER_5",   5},
 {"USER_6",   6},
 {"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 */
Index: include/kapi.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/include/kapi.h,v
retrieving revision 1.17
diff -u -5 -r1.17 kapi.h
--- include/kapi.h	5 Aug 2002 21:53:26 -0000	1.17
+++ include/kapi.h	12 Dec 2002 18:28:52 -0000
@@ -10,10 +10,11 @@
 //==========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // 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
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
@@ -204,10 +205,34 @@
 
 #ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT
 cyg_uint32 cyg_thread_measure_stack_usage(cyg_handle_t thread);
 #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
 
Index: src/common/kapi.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/src/common/kapi.cxx,v
retrieving revision 1.19
diff -u -5 -r1.19 kapi.cxx
--- src/common/kapi.cxx	23 May 2002 23:06:52 -0000	1.19
+++ src/common/kapi.cxx	12 Dec 2002 18:28:55 -0000
@@ -7,10 +7,11 @@
 //==========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // 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
 // Software Foundation; either version 2 or (at your option) any later version.
 //
@@ -305,10 +306,105 @@
 externC cyg_uint32 cyg_thread_measure_stack_usage(cyg_handle_t thread)
 {
     return ((Cyg_Thread *)thread)->measure_stack_usage();
 }
 #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
Index: src/common/thread.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/src/common/thread.cxx,v
retrieving revision 1.18
diff -u -5 -r1.18 thread.cxx
--- src/common/thread.cxx	23 May 2002 23:06:53 -0000	1.18
+++ src/common/thread.cxx	12 Dec 2002 18:28:58 -0000
@@ -293,10 +293,13 @@
 #ifdef CYGVAR_KERNEL_THREADS_LIST
     // Remove thread from housekeeping list.
     remove_from_list();
 #endif 
     
+    // Zero the unique_id to render this thread inconsistent.
+    unique_id = 0;
+    
     CYG_REPORT_RETURN();
 }
 
 // -------------------------------------------------------------------------
 // Thread consistency checker.
Index: src/instrmnt/meminst.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/src/instrmnt/meminst.cxx,v
retrieving revision 1.9
diff -u -5 -r1.9 meminst.cxx
--- src/instrmnt/meminst.cxx	23 May 2002 23:06:53 -0000	1.9
+++ src/instrmnt/meminst.cxx	12 Dec 2002 18:28:58 -0000
@@ -212,25 +212,31 @@
     else
         instrument_flags[cl>>8] = 0;
 
 }
 
+externC cyg_bool cyg_instrument_state( cyg_uint32 cl, cyg_uint32 event)
+{
+    return (instrument_flags[cl>>8] & (1<<event)) != 0;
+}
+
 #endif
 
 // -------------------------------------------------------------------------
 
 #ifdef CYGDBG_KERNEL_INSTRUMENT_MSGS
+#define CYGDBG_KERNEL_INSTRUMENT_MSGS_DEFINE_TABLE
 #include <cyg/kernel/instrument_desc.h>
 #define NELEM(x) (sizeof(x)/sizeof*(x))
 externC char * cyg_instrument_msg(CYG_WORD16 type) {
 
   struct instrument_desc_s *record;
   struct instrument_desc_s *end_record;
   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;
 
   while ((record != end_record) && (record->num != cl)) {
     record++;


-- 
Nick Garnett - eCos Kernel Architect
http://www.eCosCentric.com/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]