]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: unstupidify thread debug information
authorDavid Lamparter <equinox@opensourcerouting.org>
Mon, 18 Nov 2013 22:04:27 +0000 (23:04 +0100)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 30 May 2016 00:08:52 +0000 (20:08 -0400)
the library's thread scheduling functions keep track of the thread
function's name, so far so good.  However, copying the compiler-provided
constant into a buffer inside the thread structure is plain useless.
Also, strip_funcname() was trying to support something that never
happens.

Instead, let's use some bytes here to track where threads are scheduled
from.  Another commit will print that information on crashes.

Ripping out useless stuff:  -64 bytes in the thread structure
Re-add as const ptr:         +8 bytes
Extra debug info:           +12 bytes

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
(cherry picked from commit 3493b7731b750cbc62f00be94b624a08ccccf0b2)

lib/thread.c
lib/thread.h

index ca54a445630fbf69f8ebfaf765b20857fde90996..b666219cebb08b2a5dd8289a22f13d0f3b93d76f 100644 (file)
@@ -264,7 +264,7 @@ cpu_record_hash_alloc (struct cpu_thread_history *a)
   struct cpu_thread_history *new;
   new = XCALLOC (MTYPE_THREAD_STATS, sizeof (struct cpu_thread_history));
   new->func = a->func;
-  strcpy(new->funcname, a->funcname);
+  new->funcname = a->funcname;
   return new;
 }
 
@@ -330,7 +330,7 @@ cpu_record_print(struct vty *vty, thread_type filter)
   void *args[3] = {&tmp, vty, &filter};
 
   memset(&tmp, 0, sizeof tmp);
-  strcpy(tmp.funcname, "TOTAL");
+  tmp.funcname = "TOTAL";
   tmp.types = filter;
 
 #ifdef HAVE_RUSAGE
@@ -634,7 +634,6 @@ thread_add_unuse (struct thread_master *m, struct thread *thread)
   assert (thread->prev == NULL);
   assert (thread->type == THREAD_UNUSED);
   thread_list_add (&m->unuse, thread);
-  /* XXX: Should we deallocate funcname here? */
 }
 
 /* Free all unused thread. */
@@ -739,30 +738,8 @@ thread_timer_remain_second (struct thread *thread)
     return 0;
 }
 
-/* Trim blankspace and "()"s */
-static void
-strip_funcname (char *dest, const char *funcname)
-{
-  char buff[FUNCNAME_LEN];
-  char tmp, *e, *b = buff;
-
-  strncpy(buff, funcname, sizeof(buff));
-  buff[ sizeof(buff) -1] = '\0';
-  e = buff +strlen(buff) -1;
-
-  /* Wont work for funcname ==  "Word (explanation)"  */
-
-  while (*b == ' ' || *b == '(')
-    ++b;
-  while (*e == ' ' || *e == ')')
-    --e;
-  e++;
-
-  tmp = *e;
-  *e = '\0';
-  strcpy (dest, b);
-  *e = tmp;
-}
+#define debugargdef  const char *funcname, const char *schedfrom, int fromln
+#define debugargpass funcname, schedfrom, fromln
 
 struct timeval
 thread_timer_remain(struct thread *thread)
@@ -775,7 +752,7 @@ thread_timer_remain(struct thread *thread)
 /* Get new thread.  */
 static struct thread *
 thread_get (struct thread_master *m, u_char type,
-           int (*func) (struct thread *), void *arg, const char* funcname)
+           int (*func) (struct thread *), void *arg, debugargdef)
 {
   struct thread *thread = thread_trim_head (&m->unuse);
 
@@ -792,7 +769,9 @@ thread_get (struct thread_master *m, u_char type,
   thread->index = -1;
   thread->yield = THREAD_YIELD_TIME_SLOT; /* default */
 
-  strip_funcname (thread->funcname, funcname);
+  thread->funcname = funcname;
+  thread->schedfrom = schedfrom;
+  thread->schedfrom_line = fromln;
 
   return thread;
 }
@@ -804,7 +783,7 @@ thread_get (struct thread_master *m, u_char type,
 /* generic add thread function */
 static struct thread *
 generic_thread_add(struct thread_master *m, int (*func) (struct thread *),
-                  void *arg, int fd, const char* funcname, int dir)
+                  void *arg, int fd, int dir, debugargdef)
 {
   struct thread *thread;
 
@@ -834,7 +813,7 @@ generic_thread_add(struct thread_master *m, int (*func) (struct thread *),
   /* is there enough space for a new fd? */
   assert (queuepos < m->handler.pfdsize);
 
-  thread = thread_get (m, type, func, arg, funcname);
+  thread = thread_get (m, type, func, arg, funcname, debugargpass);
   m->handler.pfds[queuepos].fd = fd;
   m->handler.pfds[queuepos].events |= event;
   if (queuepos == m->handler.pfdcount)
@@ -899,7 +878,8 @@ fd_clear_read_write (struct thread *thread)
 /* Add new read thread. */
 struct thread *
 funcname_thread_add_read_write (int dir, struct thread_master *m,
-                               int (*func) (struct thread *), void *arg, int fd, const char* funcname)
+                               int (*func) (struct thread *), void *arg, int fd,
+                               debugargdef)
 {
   struct thread *thread = NULL;
 
@@ -912,7 +892,7 @@ funcname_thread_add_read_write (int dir, struct thread_master *m,
 #endif
 
 #if defined (HAVE_POLL)
-  thread = generic_thread_add(m, func, arg, fd, funcname, dir);
+  thread = generic_thread_add(m, func, arg, fd, dir, debugargpass);
 
   if (thread == NULL)
     return NULL;
@@ -924,7 +904,7 @@ funcname_thread_add_read_write (int dir, struct thread_master *m,
     }
 
   FD_SET (fd, fdset);
-  thread = thread_get (m, dir, func, arg, funcname);
+  thread = thread_get (m, dir, func, arg, debugargpass);
 #endif
 
   thread->u.fd = fd;
@@ -941,8 +921,8 @@ funcname_thread_add_timer_timeval (struct thread_master *m,
                                    int (*func) (struct thread *), 
                                   int type,
                                   void *arg, 
-                                  struct timeval *time_relative, 
-                                  const char* funcname)
+                                  struct timeval *time_relative,
+                                 debugargdef)
 {
   struct thread *thread;
   struct pqueue *queue;
@@ -954,7 +934,7 @@ funcname_thread_add_timer_timeval (struct thread_master *m,
   assert (time_relative);
   
   queue = ((type == THREAD_TIMER) ? m->timer : m->background);
-  thread = thread_get (m, type, func, arg, funcname);
+  thread = thread_get (m, type, func, arg, debugargpass);
 
   /* Do we need jitter here? */
   quagga_get_relative (NULL);
@@ -971,7 +951,8 @@ funcname_thread_add_timer_timeval (struct thread_master *m,
 struct thread *
 funcname_thread_add_timer (struct thread_master *m,
                           int (*func) (struct thread *), 
-                          void *arg, long timer, const char* funcname)
+                          void *arg, long timer,
+                          debugargdef)
 {
   struct timeval trel;
 
@@ -981,14 +962,15 @@ funcname_thread_add_timer (struct thread_master *m,
   trel.tv_usec = 0;
 
   return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, 
-                                            &trel, funcname);
+                                            &trel, debugargpass);
 }
 
 /* Add timer event thread with "millisecond" resolution */
 struct thread *
 funcname_thread_add_timer_msec (struct thread_master *m,
                                 int (*func) (struct thread *), 
-                                void *arg, long timer, const char* funcname)
+                                void *arg, long timer,
+                               debugargdef)
 {
   struct timeval trel;
 
@@ -998,15 +980,15 @@ funcname_thread_add_timer_msec (struct thread_master *m,
   trel.tv_usec = 1000*(timer % 1000);
 
   return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, 
-                                            arg, &trel, funcname);
+                                            arg, &trel, debugargpass);
 }
 
 /* Add a background thread, with an optional millisec delay */
 struct thread *
 funcname_thread_add_background (struct thread_master *m,
                                 int (*func) (struct thread *),
-                                void *arg, long delay, 
-                                const char *funcname)
+                                void *arg, long delay,
+                               debugargdef)
 {
   struct timeval trel;
   
@@ -1024,19 +1006,20 @@ funcname_thread_add_background (struct thread_master *m,
     }
 
   return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND,
-                                            arg, &trel, funcname);
+                                            arg, &trel, debugargpass);
 }
 
 /* Add simple event thread. */
 struct thread *
 funcname_thread_add_event (struct thread_master *m,
-                 int (*func) (struct thread *), void *arg, int val, const char* funcname)
+                 int (*func) (struct thread *), void *arg, int val,
+                 debugargdef)
 {
   struct thread *thread;
 
   assert (m != NULL);
 
-  thread = thread_get (m, THREAD_EVENT, func, arg, funcname);
+  thread = thread_get (m, THREAD_EVENT, func, arg, debugargpass);
   thread->u.val = val;
   thread_list_add (&m->event, thread);
 
@@ -1563,7 +1546,7 @@ thread_call (struct thread *thread)
       struct cpu_thread_history tmp;
       
       tmp.func = thread->func;
-      strcpy(tmp.funcname, thread->funcname);
+      tmp.funcname = thread->funcname;
       
       thread->hist = hash_get (cpu_record, &tmp, 
                     (void * (*) (void *))cpu_record_hash_alloc);
@@ -1611,7 +1594,7 @@ funcname_thread_execute (struct thread_master *m,
                 int (*func)(struct thread *), 
                 void *arg,
                 int val,
-               const char* funcname)
+               debugargdef)
 {
   struct thread dummy; 
 
@@ -1623,7 +1606,11 @@ funcname_thread_execute (struct thread_master *m,
   dummy.func = func;
   dummy.arg = arg;
   dummy.u.val = val;
-  strip_funcname (dummy.funcname, funcname);
+
+  dummy.funcname = funcname;
+  dummy.schedfrom = schedfrom;
+  dummy.schedfrom_line = fromln;
+
   thread_call (&dummy);
 
   return NULL;
index 853ef3fb78345ac0bf31b6c87abfed3a18f2a4de..66dd9cf7889a0e2dea7d7406f6b7241053e392d7 100644 (file)
@@ -89,9 +89,6 @@ struct thread_master
 
 typedef unsigned char thread_type;
 
-/* ISO C99 maximum function name length is 63 */
-#define FUNCNAME_LEN   64
-
 /* Thread itself. */
 struct thread
 {
@@ -111,7 +108,9 @@ struct thread
   struct timeval real;
   struct cpu_thread_history *hist; /* cache pointer to cpu_history */
   unsigned long yield; /* yield time in us */
-  char funcname[FUNCNAME_LEN];
+  const char *funcname;
+  const char *schedfrom;
+  int schedfrom_line;
 };
 
 struct cpu_thread_history 
@@ -126,7 +125,7 @@ struct cpu_thread_history
   struct time_stats cpu;
 #endif
   thread_type types;
-  char funcname[FUNCNAME_LEN];
+  const char *funcname;
 };
 
 /* Clocks supported by Quagga */
@@ -194,15 +193,17 @@ enum quagga_clkid {
 #define THREAD_WRITE_OFF(thread)  THREAD_OFF(thread)
 #define THREAD_TIMER_OFF(thread)  THREAD_OFF(thread)
 
-#define thread_add_read(m,f,a,v) funcname_thread_add_read_write(THREAD_READ,m,f,a,v,#f)
-#define thread_add_write(m,f,a,v) funcname_thread_add_read_write(THREAD_WRITE,m,f,a,v,#f)
-#define thread_add_timer(m,f,a,v) funcname_thread_add_timer(m,f,a,v,#f)
-#define thread_add_timer_msec(m,f,a,v) funcname_thread_add_timer_msec(m,f,a,v,#f)
-#define thread_add_event(m,f,a,v) funcname_thread_add_event(m,f,a,v,#f)
-#define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f)
+#define debugargdef  const char *funcname, const char *schedfrom, int fromln
+
+#define thread_add_read(m,f,a,v) funcname_thread_add_read_write(THREAD_READ,m,f,a,v,#f,__FILE__,__LINE__)
+#define thread_add_write(m,f,a,v) funcname_thread_add_read_write(THREAD_WRITE,m,f,a,v,#f,__FILE__,__LINE__)
+#define thread_add_timer(m,f,a,v) funcname_thread_add_timer(m,f,a,v,#f,__FILE__,__LINE__)
+#define thread_add_timer_msec(m,f,a,v) funcname_thread_add_timer_msec(m,f,a,v,#f,__FILE__,__LINE__)
+#define thread_add_event(m,f,a,v) funcname_thread_add_event(m,f,a,v,#f,__FILE__,__LINE__)
+#define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__)
 
 /* The 4th arg to thread_add_background is the # of milliseconds to delay. */
-#define thread_add_background(m,f,a,v) funcname_thread_add_background(m,f,a,v,#f)
+#define thread_add_background(m,f,a,v) funcname_thread_add_background(m,f,a,v,#f,__FILE__,__LINE__)
 
 /* Prototypes. */
 extern struct thread_master *thread_master_create (void);
@@ -211,24 +212,26 @@ extern void thread_master_free_unused(struct thread_master *);
 
 extern struct thread *funcname_thread_add_read_write (int dir, struct thread_master *,
                                                int (*)(struct thread *),
-                                               void *, int, const char*);
+                                               void *, int, debugargdef);
 extern struct thread *funcname_thread_add_timer (struct thread_master *,
                                                 int (*)(struct thread *),
-                                                void *, long, const char*);
+                                                void *, long, debugargdef);
 extern struct thread *funcname_thread_add_timer_msec (struct thread_master *,
                                                      int (*)(struct thread *),
-                                                     void *, long, const char*);
+                                                     void *, long, debugargdef);
 extern struct thread *funcname_thread_add_event (struct thread_master *,
                                                 int (*)(struct thread *),
-                                                void *, int, const char*);
+                                                void *, int, debugargdef);
 extern struct thread *funcname_thread_add_background (struct thread_master *,
                                                int (*func)(struct thread *),
                                               void *arg,
                                               long milliseconds_to_delay,
-                                              const char *funcname);
+                                              debugargdef);
 extern struct thread *funcname_thread_execute (struct thread_master *,
                                                int (*)(struct thread *),
-                                               void *, int, const char *);
+                                               void *, int, debugargdef);
+#undef debugargdef
+
 extern void thread_cancel (struct thread *);
 extern unsigned int thread_cancel_event (struct thread_master *, void *);
 extern struct thread *thread_fetch (struct thread_master *, struct thread *);