Diff for /embedaddon/quagga/lib/thread.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2012/10/09 09:22:28 version 1.1.1.3, 2013/07/21 23:54:39
Line 29 Line 29
 #include "hash.h"  #include "hash.h"
 #include "command.h"  #include "command.h"
 #include "sigevent.h"  #include "sigevent.h"
   
   #if defined HAVE_SNMP && defined SNMP_AGENTX
   #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>
   
   extern int agentx_enabled;
   #endif
   
   #if defined(__APPLE__)
   #include <mach/mach.h>
   #include <mach/mach_time.h>
   #endif
   
   
 /* Recent absolute time of day */  /* Recent absolute time of day */
 struct timeval recent_time;  struct timeval recent_time;
Line 93  timeval_elapsed (struct timeval a, struct timeval b) Line 108  timeval_elapsed (struct timeval a, struct timeval b)
           + (a.tv_usec - b.tv_usec));            + (a.tv_usec - b.tv_usec));
 }  }
   
#ifndef HAVE_CLOCK_MONOTONIC#if !defined(HAVE_CLOCK_MONOTONIC) && !defined(__APPLE__)
 static void  static void
 quagga_gettimeofday_relative_adjust (void)  quagga_gettimeofday_relative_adjust (void)
 {  {
Line 112  quagga_gettimeofday_relative_adjust (void) Line 127  quagga_gettimeofday_relative_adjust (void)
     }      }
   last_recent_time = recent_time;    last_recent_time = recent_time;
 }  }
#endif /* !HAVE_CLOCK_MONOTONIC */#endif /* !HAVE_CLOCK_MONOTONIC && !__APPLE__ */
   
 /* gettimeofday wrapper, to keep recent_time updated */  /* gettimeofday wrapper, to keep recent_time updated */
 static int  static int
Line 152  quagga_get_relative (struct timeval *tv) Line 167  quagga_get_relative (struct timeval *tv)
         relative_time.tv_usec = tp.tv_nsec / 1000;          relative_time.tv_usec = tp.tv_nsec / 1000;
       }        }
   }    }
#else /* !HAVE_CLOCK_MONOTONIC */#elif defined(__APPLE__)
   {
     uint64_t ticks;
     uint64_t useconds;
     static mach_timebase_info_data_t timebase_info;
 
     ticks = mach_absolute_time();
     if (timebase_info.denom == 0)
       mach_timebase_info(&timebase_info);
 
     useconds = ticks * timebase_info.numer / timebase_info.denom / 1000;
     relative_time.tv_sec = useconds / 1000000;
     relative_time.tv_usec = useconds % 1000000;
 
     return 0;
   }
 #else /* !HAVE_CLOCK_MONOTONIC && !__APPLE__ */
   if (!(ret = quagga_gettimeofday (&recent_time)))    if (!(ret = quagga_gettimeofday (&recent_time)))
     quagga_gettimeofday_relative_adjust();      quagga_gettimeofday_relative_adjust();
 #endif /* HAVE_CLOCK_MONOTONIC */  #endif /* HAVE_CLOCK_MONOTONIC */
Line 235  cpu_record_hash_alloc (struct cpu_thread_history *a) Line 266  cpu_record_hash_alloc (struct cpu_thread_history *a)
   struct cpu_thread_history *new;    struct cpu_thread_history *new;
   new = XCALLOC (MTYPE_THREAD_STATS, sizeof (struct cpu_thread_history));    new = XCALLOC (MTYPE_THREAD_STATS, sizeof (struct cpu_thread_history));
   new->func = a->func;    new->func = a->func;
  new->funcname = XSTRDUP(MTYPE_THREAD_FUNCNAME, a->funcname);  strcpy(new->funcname, a->funcname);
   return new;    return new;
 }  }
   
Line 244  cpu_record_hash_free (void *a) Line 275  cpu_record_hash_free (void *a)
 {  {
   struct cpu_thread_history *hist = a;    struct cpu_thread_history *hist = a;
     
   XFREE (MTYPE_THREAD_FUNCNAME, hist->funcname);  
   XFREE (MTYPE_THREAD_STATS, hist);    XFREE (MTYPE_THREAD_STATS, hist);
 }  }
   
Line 303  cpu_record_print(struct vty *vty, thread_type filter) Line 333  cpu_record_print(struct vty *vty, thread_type filter)
   void *args[3] = {&tmp, vty, &filter};    void *args[3] = {&tmp, vty, &filter};
   
   memset(&tmp, 0, sizeof tmp);    memset(&tmp, 0, sizeof tmp);
  tmp.funcname = (char *)"TOTAL";  strcpy(tmp.funcname, "TOTAL");
   tmp.types = filter;    tmp.types = filter;
   
 #ifdef HAVE_RUSAGE  #ifdef HAVE_RUSAGE
Line 577  thread_list_free (struct thread_master *m, struct thre Line 607  thread_list_free (struct thread_master *m, struct thre
   for (t = list->head; t; t = next)    for (t = list->head; t; t = next)
     {      {
       next = t->next;        next = t->next;
       if (t->funcname)  
         XFREE (MTYPE_THREAD_FUNCNAME, t->funcname);  
       XFREE (MTYPE_THREAD, t);        XFREE (MTYPE_THREAD, t);
       list->count--;        list->count--;
       m->alloc--;        m->alloc--;
Line 636  thread_timer_remain_second (struct thread *thread) Line 664  thread_timer_remain_second (struct thread *thread)
 }  }
   
 /* Trim blankspace and "()"s */  /* Trim blankspace and "()"s */
static char *void
strip_funcname (const char *funcname) strip_funcname (char *dest, const char *funcname)
 {  {
  char buff[100];  char buff[FUNCNAME_LEN];
  char tmp, *ret, *e, *b = buff;  char tmp, *e, *b = buff;
   
   strncpy(buff, funcname, sizeof(buff));    strncpy(buff, funcname, sizeof(buff));
   buff[ sizeof(buff) -1] = '\0';    buff[ sizeof(buff) -1] = '\0';
Line 656  strip_funcname (const char *funcname)  Line 684  strip_funcname (const char *funcname) 
   
   tmp = *e;    tmp = *e;
   *e = '\0';    *e = '\0';
  ret  = XSTRDUP (MTYPE_THREAD_FUNCNAME, b);  strcpy (dest, b);
   *e = tmp;    *e = tmp;
   
   return ret;  
 }  }
   
 /* Get new thread.  */  /* Get new thread.  */
Line 667  static struct thread * Line 693  static struct thread *
 thread_get (struct thread_master *m, u_char type,  thread_get (struct thread_master *m, u_char type,
             int (*func) (struct thread *), void *arg, const char* funcname)              int (*func) (struct thread *), void *arg, const char* funcname)
 {  {
  struct thread *thread;  struct thread *thread = thread_trim_head (&m->unuse);
   
  if (!thread_empty (&m->unuse))  if (! thread)
     {      {
       thread = thread_trim_head (&m->unuse);  
       if (thread->funcname)  
         XFREE(MTYPE_THREAD_FUNCNAME, thread->funcname);  
     }  
   else  
     {  
       thread = XCALLOC (MTYPE_THREAD, sizeof (struct thread));        thread = XCALLOC (MTYPE_THREAD, sizeof (struct thread));
       m->alloc++;        m->alloc++;
     }      }
Line 686  thread_get (struct thread_master *m, u_char type, Line 706  thread_get (struct thread_master *m, u_char type,
   thread->func = func;    thread->func = func;
   thread->arg = arg;    thread->arg = arg;
       
  thread->funcname = strip_funcname(funcname);  strip_funcname (thread->funcname, funcname);
   
   return thread;    return thread;
 }  }
Line 916  thread_cancel_event (struct thread_master *m, void *ar Line 936  thread_cancel_event (struct thread_master *m, void *ar
           thread_add_unuse (m, t);            thread_add_unuse (m, t);
         }          }
     }      }
   
     /* thread can be on the ready list too */
     thread = m->ready.head;
     while (thread)
       {
         struct thread *t;
   
         t = thread;
         thread = t->next;
   
         if (t->arg == arg)
           {
             ret++;
             thread_list_delete (&m->ready, t);
             t->type = THREAD_UNUSED;
             thread_add_unuse (m, t);
           }
       }
   return ret;    return ret;
 }  }
   
Line 936  thread_run (struct thread_master *m, struct thread *th Line 974  thread_run (struct thread_master *m, struct thread *th
 {  {
   *fetch = *thread;    *fetch = *thread;
   thread->type = THREAD_UNUSED;    thread->type = THREAD_UNUSED;
   thread->funcname = NULL;  /* thread_call will free fetch's copied pointer */  
   thread_add_unuse (m, thread);    thread_add_unuse (m, thread);
   return fetch;    return fetch;
 }  }
Line 1024  thread_fetch (struct thread_master *m, struct thread * Line 1061  thread_fetch (struct thread_master *m, struct thread *
   while (1)    while (1)
     {      {
       int num = 0;        int num = 0;
   #if defined HAVE_SNMP && defined SNMP_AGENTX
         struct timeval snmp_timer_wait;
         int snmpblock = 0;
         int fdsetsize;
   #endif
               
       /* Signals pre-empt everything */        /* Signals pre-empt everything */
       quagga_sigevent_process ();        quagga_sigevent_process ();
Line 1059  thread_fetch (struct thread_master *m, struct thread * Line 1101  thread_fetch (struct thread_master *m, struct thread *
             timer_wait = timer_wait_bg;              timer_wait = timer_wait_bg;
         }          }
               
   #if defined HAVE_SNMP && defined SNMP_AGENTX
         /* When SNMP is enabled, we may have to select() on additional
            FD. snmp_select_info() will add them to `readfd'. The trick
            with this function is its last argument. We need to set it to
            0 if timer_wait is not NULL and we need to use the provided
            new timer only if it is still set to 0. */
         if (agentx_enabled)
           {
             fdsetsize = FD_SETSIZE;
             snmpblock = 1;
             if (timer_wait)
               {
                 snmpblock = 0;
                 memcpy(&snmp_timer_wait, timer_wait, sizeof(struct timeval));
               }
             snmp_select_info(&fdsetsize, &readfd, &snmp_timer_wait, &snmpblock);
             if (snmpblock == 0)
               timer_wait = &snmp_timer_wait;
           }
   #endif
       num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);        num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
               
       /* Signals should get quick treatment */        /* Signals should get quick treatment */
Line 1070  thread_fetch (struct thread_master *m, struct thread * Line 1132  thread_fetch (struct thread_master *m, struct thread *
             return NULL;              return NULL;
         }          }
   
   #if defined HAVE_SNMP && defined SNMP_AGENTX
         if (agentx_enabled)
           {
             if (num > 0)
               snmp_read(&readfd);
             else if (num == 0)
               {
                 snmp_timeout();
                 run_alarms();
               }
             netsnmp_check_outstanding_agent_requests();
           }
   #endif
   
       /* Check foreground timers.  Historically, they have had higher        /* Check foreground timers.  Historically, they have had higher
          priority than I/O threads, so let's push them onto the ready           priority than I/O threads, so let's push them onto the ready
          list in front of the I/O threads. */           list in front of the I/O threads. */
Line 1128  int Line 1204  int
 thread_should_yield (struct thread *thread)  thread_should_yield (struct thread *thread)
 {  {
   quagga_get_relative (NULL);    quagga_get_relative (NULL);
  return (timeval_elapsed(relative_time, thread->ru.real) >  return (timeval_elapsed(relative_time, thread->real) >
           THREAD_YIELD_TIME_SLOT);            THREAD_YIELD_TIME_SLOT);
 }  }
   
Line 1157  void Line 1233  void
 thread_call (struct thread *thread)  thread_call (struct thread *thread)
 {  {
   unsigned long realtime, cputime;    unsigned long realtime, cputime;
  RUSAGE_T ru;  RUSAGE_T before, after;
   
  /* Cache a pointer to the relevant cpu history thread, if the thread   /* Cache a pointer to the relevant cpu history thread, if the thread
   * does not have it yet.    * does not have it yet.
Line 1170  thread_call (struct thread *thread) Line 1246  thread_call (struct thread *thread)
       struct cpu_thread_history tmp;        struct cpu_thread_history tmp;
               
       tmp.func = thread->func;        tmp.func = thread->func;
      tmp.funcname = thread->funcname;      strcpy(tmp.funcname, thread->funcname);
               
       thread->hist = hash_get (cpu_record, &tmp,         thread->hist = hash_get (cpu_record, &tmp, 
                     (void * (*) (void *))cpu_record_hash_alloc);                      (void * (*) (void *))cpu_record_hash_alloc);
     }      }
   
  GETRUSAGE (&thread->ru);  GETRUSAGE (&before);
   thread->real = before.real;
   
   (*thread->func) (thread);    (*thread->func) (thread);
   
  GETRUSAGE (&ru);  GETRUSAGE (&after);
   
  realtime = thread_consumed_time (&ru, &thread->ru, &cputime);  realtime = thread_consumed_time (&after, &before, &cputime);
   thread->hist->real.total += realtime;    thread->hist->real.total += realtime;
   if (thread->hist->real.max < realtime)    if (thread->hist->real.max < realtime)
     thread->hist->real.max = realtime;      thread->hist->real.max = realtime;
Line 1209  thread_call (struct thread *thread) Line 1286  thread_call (struct thread *thread)
                  realtime/1000, cputime/1000);                   realtime/1000, cputime/1000);
     }      }
 #endif /* CONSUMED_TIME_CHECK */  #endif /* CONSUMED_TIME_CHECK */
   
   XFREE (MTYPE_THREAD_FUNCNAME, thread->funcname);  
 }  }
   
 /* Execute thread */  /* Execute thread */
Line 1231  funcname_thread_execute (struct thread_master *m, Line 1306  funcname_thread_execute (struct thread_master *m,
   dummy.func = func;    dummy.func = func;
   dummy.arg = arg;    dummy.arg = arg;
   dummy.u.val = val;    dummy.u.val = val;
  dummy.funcname = strip_funcname (funcname);  strip_funcname (dummy.funcname, funcname);
   thread_call (&dummy);    thread_call (&dummy);
   
   XFREE (MTYPE_THREAD_FUNCNAME, dummy.funcname);  
   
   return NULL;    return NULL;
 }  }

Removed from v.1.1.1.2  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>