]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/thread.c
*: fixup snmp support
[mirror_frr.git] / lib / thread.c
index bb524f0ad00b34a31b35586ec68f3e7b37df228c..a8ccb8b3d0c002393d500c9fe8e4d20dd7852483 100644 (file)
 #include "sigevent.h"
 
 #if defined HAVE_SNMP && defined SNMP_AGENTX
+
+#ifdef HAVE_POLL
+#define QUAGGA_HAVE_POLL
+#endif
+
 #include <net-snmp/net-snmp-config.h>
 #include <net-snmp/net-snmp-includes.h>
 #include <net-snmp/agent/net-snmp-agent-includes.h>
 #include <net-snmp/agent/snmp_vars.h>
 
+#ifdef HAVE_POLL
+#undef HAVE_POLL
+#endif
+#ifdef QUAGGA_HAVE_POLL
+#define HAVE_POLL
+#endif
+
 extern int agentx_enabled;
 #endif
 
@@ -264,7 +276,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;
 }
 
@@ -308,8 +320,7 @@ cpu_record_hash_print(struct hash_backet *bucket,
   struct vty *vty = args[1];
   thread_type *filter = args[2];
   struct cpu_thread_history *a = bucket->data;
-  
-  a = bucket->data;
+
   if ( !(a->types & *filter) )
        return;
   vty_out_cpu_thread_history(vty,a);
@@ -331,7 +342,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
@@ -417,8 +428,7 @@ cpu_record_hash_clear (struct hash_backet *bucket,
 {
   thread_type *filter = args;
   struct cpu_thread_history *a = bucket->data;
-  
-  a = bucket->data;
+
   if ( !(a->types & *filter) )
        return;
   
@@ -560,7 +570,7 @@ thread_master_create (void)
   rv->timer->update = rv->background->update = thread_timer_update;
 
 #if defined(HAVE_POLL)
-  rv->handler.pfdsize = 64;
+  rv->handler.pfdsize = rv->fd_limit;
   rv->handler.pfdcount = 0;
   rv->handler.pfds = (struct pollfd *) malloc (sizeof (struct pollfd) * rv->handler.pfdsize);
   memset (rv->handler.pfds, 0, sizeof (struct pollfd) * rv->handler.pfdsize);
@@ -636,7 +646,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. */
@@ -741,35 +750,21 @@ 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;
+#define debugargdef  const char *funcname, const char *schedfrom, int fromln
+#define debugargpass funcname, schedfrom, fromln
 
-  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++;
+struct timeval
+thread_timer_remain(struct thread *thread)
+{
+  quagga_get_relative(NULL);
 
-  tmp = *e;
-  *e = '\0';
-  strcpy (dest, b);
-  *e = tmp;
+  return timeval_subtract(thread->u.sands, relative_time);
 }
 
 /* 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);
 
@@ -786,7 +781,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;
 }
@@ -795,29 +792,10 @@ thread_get (struct thread_master *m, u_char type,
 
 #define fd_copy_fd_set(X) (X)
 
-static short
-realloc_pfds (struct thread_master *m, int fd)
-{
-  size_t oldpfdlen = m->handler.pfdsize * sizeof(struct pollfd);
-  void *newpfd = NULL;
-
-  m->handler.pfdsize *= 2;
-  newpfd = XREALLOC (MTYPE_THREAD, m->handler.pfds, m->handler.pfdsize * sizeof(struct pollfd));
-  if (newpfd == NULL)
-    {
-      close(fd);
-      zlog (NULL, LOG_ERR, "failed to allocate space for pollfds");
-      return 0;
-    }
-  memset((struct pollfd*)newpfd + (m->handler.pfdsize / 2), 0, oldpfdlen);
-  m->handler.pfds = (struct pollfd*)newpfd;
-  return 1;
-}
-
 /* 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;
 
@@ -845,11 +823,9 @@ generic_thread_add(struct thread_master *m, int (*func) (struct thread *),
       }
 
   /* is there enough space for a new fd? */
-  if (queuepos >= m->handler.pfdsize)
-    if (realloc_pfds(m, fd) == 0)
-      return NULL;
+  assert (queuepos < m->handler.pfdsize);
 
-  thread = thread_get (m, type, func, arg, funcname);
+  thread = thread_get (m, type, func, arg, debugargpass);
   m->handler.pfds[queuepos].fd = fd;
   m->handler.pfds[queuepos].events |= event;
   if (queuepos == m->handler.pfdcount)
@@ -914,7 +890,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;
 
@@ -927,7 +904,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;
@@ -939,7 +916,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;
@@ -956,8 +933,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;
@@ -969,7 +946,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);
@@ -986,7 +963,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;
 
@@ -996,14 +974,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;
 
@@ -1013,15 +992,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;
   
@@ -1039,19 +1018,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);
 
@@ -1059,7 +1039,7 @@ funcname_thread_add_event (struct thread_master *m,
 }
 
 static void
-thread_cancel_read_write (struct thread *thread)
+thread_cancel_read_or_write (struct thread *thread, short int state)
 {
 #if defined(HAVE_POLL)
   nfds_t i;
@@ -1067,12 +1047,17 @@ thread_cancel_read_write (struct thread *thread)
   for (i=0;i<thread->master->handler.pfdcount;++i)
     if (thread->master->handler.pfds[i].fd == thread->u.fd)
       {
+        thread->master->handler.pfds[i].events &= ~(state);
+
         /* remove thread fds from pfd list */
-        memmove(thread->master->handler.pfds+i,
-                thread->master->handler.pfds+i+1,
-                (thread->master->handler.pfdsize-i-1) * sizeof(struct pollfd));
-        i--;
-        thread->master->handler.pfdcount--;
+        if (thread->master->handler.pfds[i].events == 0)
+          {
+            memmove(thread->master->handler.pfds+i,
+                    thread->master->handler.pfds+i+1,
+                    (thread->master->handler.pfdsize-i-1) * sizeof(struct pollfd));
+            thread->master->handler.pfdcount--;
+            return;
+          }
       }
 #endif
 
@@ -1090,11 +1075,19 @@ thread_cancel (struct thread *thread)
   switch (thread->type)
     {
     case THREAD_READ:
-      thread_cancel_read_write (thread);
+#if defined (HAVE_POLL)
+      thread_cancel_read_or_write (thread, POLLIN | POLLHUP);
+#else
+      thread_cancel_read_or_write (thread, 0);
+#endif
       thread_array = thread->master->read;
       break;
     case THREAD_WRITE:
-      thread_cancel_read_write (thread);
+#if defined (HAVE_POLL)
+      thread_cancel_read_or_write (thread, POLLOUT | POLLHUP);
+#else
+      thread_cancel_read_or_write (thread, 0);
+#endif
       thread_array = thread->master->write;
       break;
     case THREAD_TIMER:
@@ -1244,9 +1237,7 @@ add_snmp_pollfds(struct thread_master *m, fd_set *snmpfds, int fdsetsize)
     {
       if (FD_ISSET(i, snmpfds))
         {
-          if (m->handler.pfdcountsnmp > m->handler.pfdsize)
-            if (realloc_pfds(m, i) < 0)
-              return;
+          assert (m->handler.pfdcountsnmp <= m->handler.pfdsize);
 
           m->handler.pfds[m->handler.pfdcountsnmp].fd = i;
           m->handler.pfds[m->handler.pfdcountsnmp].events = POLLIN;
@@ -1268,32 +1259,23 @@ check_pollfds(struct thread_master *m, fd_set *readfd, int num)
       if(m->handler.pfds[i].revents == 0)
         continue;
 
-      /* remove fd from list on POLLNVAL */
-      if (m->handler.pfds[i].revents & POLLNVAL)
-        {
-           memmove(m->handler.pfds+i,
-                   m->handler.pfds+i+1,
-                   (m->handler.pfdsize-i-1) * sizeof(struct pollfd));
-           m->handler.pfdcount--;
-           i--;
-           continue;
-        }
+      ready++;
 
       /* POLLIN / POLLOUT process event */
       if (m->handler.pfds[i].revents & POLLIN)
-        ready += thread_process_fds_helper(m, m->read[m->handler.pfds[i].fd], NULL, POLLIN, i);
+        thread_process_fds_helper(m, m->read[m->handler.pfds[i].fd], NULL, POLLIN, i);
       if (m->handler.pfds[i].revents & POLLOUT)
-        ready += thread_process_fds_helper(m, m->write[m->handler.pfds[i].fd], NULL, POLLOUT, i);
+        thread_process_fds_helper(m, m->write[m->handler.pfds[i].fd], NULL, POLLOUT, i);
 
-      /* remove fd from list on POLLHUP after other event is processed */
-      if (m->handler.pfds[i].revents & POLLHUP)
+      /* remove fd from list on POLLNVAL */
+      if (m->handler.pfds[i].revents & POLLNVAL ||
+          m->handler.pfds[i].revents & POLLHUP)
         {
            memmove(m->handler.pfds+i,
                    m->handler.pfds+i+1,
                    (m->handler.pfdsize-i-1) * sizeof(struct pollfd));
            m->handler.pfdcount--;
            i--;
-           ready++;
         }
       else
           m->handler.pfds[i].revents = 0;
@@ -1560,6 +1542,8 @@ thread_getrusage (RUSAGE_T *r)
 #endif /* HAVE_CLOCK_MONOTONIC */
 }
 
+struct thread *thread_current = NULL;
+
 /* We check thread consumed time. If the system has getrusage, we'll
    use that to get in-depth stats on the performance of the thread in addition
    to wall clock time stats from gettimeofday. */
@@ -1580,7 +1564,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);
@@ -1589,7 +1573,9 @@ thread_call (struct thread *thread)
   GETRUSAGE (&before);
   thread->real = before.real;
 
+  thread_current = thread;
   (*thread->func) (thread);
+  thread_current = NULL;
 
   GETRUSAGE (&after);
 
@@ -1628,7 +1614,7 @@ funcname_thread_execute (struct thread_master *m,
                 int (*func)(struct thread *), 
                 void *arg,
                 int val,
-               const char* funcname)
+               debugargdef)
 {
   struct thread dummy; 
 
@@ -1640,7 +1626,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;