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

version 1.1.1.3, 2013/07/21 23:54:39 version 1.1.1.4, 2016/11/02 10:09:11
Line 27 Line 27
 #include "memory.h"  #include "memory.h"
 #include "log.h"  #include "log.h"
 #include "hash.h"  #include "hash.h"
   #include "pqueue.h"
 #include "command.h"  #include "command.h"
 #include "sigevent.h"  #include "sigevent.h"
   
Line 44  extern int agentx_enabled; Line 45  extern int agentx_enabled;
 #include <mach/mach_time.h>  #include <mach/mach_time.h>
 #endif  #endif
   
 /* Recent absolute time of day */  /* Recent absolute time of day */
 struct timeval recent_time;  struct timeval recent_time;
 static struct timeval last_recent_time;  static struct timeval last_recent_time;
Line 53  static struct timeval relative_time; Line 54  static struct timeval relative_time;
 static struct timeval relative_time_base;  static struct timeval relative_time_base;
 /* init flag */  /* init flag */
 static unsigned short timers_inited;  static unsigned short timers_inited;
 static struct hash *cpu_record = NULL;  static struct hash *cpu_record = NULL;
 /* Struct timeval's tv_usec one second value.  */  /* Struct timeval's tv_usec one second value.  */
 #define TIMER_SECOND_MICRO 1000000L  #define TIMER_SECOND_MICRO 1000000L
   
Line 101  timeval_cmp (struct timeval a, struct timeval b) Line 102  timeval_cmp (struct timeval a, struct timeval b)
           ? a.tv_usec - b.tv_usec : a.tv_sec - b.tv_sec);            ? a.tv_usec - b.tv_usec : a.tv_sec - b.tv_sec);
 }  }
   
static unsigned longunsigned long
 timeval_elapsed (struct timeval a, struct timeval b)  timeval_elapsed (struct timeval a, struct timeval b)
 {  {
   return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO)    return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO)
           + (a.tv_usec - b.tv_usec));            + (a.tv_usec - b.tv_usec));
 }  }
 #if !defined(HAVE_CLOCK_MONOTONIC) && !defined(__APPLE__)  #if !defined(HAVE_CLOCK_MONOTONIC) && !defined(__APPLE__)
 static void  static void
 quagga_gettimeofday_relative_adjust (void)  quagga_gettimeofday_relative_adjust (void)
Line 246  recent_relative_time (void) Line 247  recent_relative_time (void)
 {  {
   return relative_time;    return relative_time;
 }  }
 static unsigned int  static unsigned int
 cpu_record_hash_key (struct cpu_thread_history *a)  cpu_record_hash_key (struct cpu_thread_history *a)
 {  {
Line 266  cpu_record_hash_alloc (struct cpu_thread_history *a) Line 267  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;
  strcpy(new->funcname, a->funcname);  new->funcname = a->funcname;
   return new;    return new;
 }  }
   
Line 333  cpu_record_print(struct vty *vty, thread_type filter) Line 334  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);
  strcpy(tmp.funcname, "TOTAL");  tmp.funcname = "TOTAL";
   tmp.types = filter;    tmp.types = filter;
   
 #ifdef HAVE_RUSAGE  #ifdef HAVE_RUSAGE
Line 495  DEFUN(clear_thread_cpu, Line 496  DEFUN(clear_thread_cpu,
   cpu_record_clear (filter);    cpu_record_clear (filter);
   return CMD_SUCCESS;    return CMD_SUCCESS;
 }  }
/* List allocation and head/tail print out. */static int
static voidthread_timer_cmp(void *a, void *b)
thread_list_debug (struct thread_list *list) 
 {  {
  printf ("count [%d] head [%p] tail [%p]\n",  struct thread *thread_a = a;
          list->count, list->head, list->tail);  struct thread *thread_b = b;
 
   long cmp = timeval_cmp(thread_a->u.sands, thread_b->u.sands);
 
   if (cmp < 0)
     return -1;
   if (cmp > 0)
     return 1;
   return 0;
 }  }
   
/* Debug print for thread_master. */static void
static void  __attribute__ ((unused))thread_timer_update(void *node, int actual_position)
thread_master_debug (struct thread_master *m) 
 {  {
  printf ("-----------\n");  struct thread *thread = node;
  printf ("readlist  : ");
  thread_list_debug (&m->read);  thread->index = actual_position;
  printf ("writelist : "); 
  thread_list_debug (&m->write); 
  printf ("timerlist : "); 
  thread_list_debug (&m->timer); 
  printf ("eventlist : "); 
  thread_list_debug (&m->event); 
  printf ("unuselist : "); 
  thread_list_debug (&m->unuse); 
  printf ("bgndlist : "); 
  thread_list_debug (&m->background); 
  printf ("total alloc: [%ld]\n", m->alloc); 
  printf ("-----------\n"); 
 }  }
 /* Allocate new thread master.  */  /* Allocate new thread master.  */
 struct thread_master *  struct thread_master *
 thread_master_create ()  thread_master_create ()
 {  {
     struct thread_master *rv;
   
   if (cpu_record == NULL)     if (cpu_record == NULL) 
     cpu_record       cpu_record 
      = hash_create_size (1011, (unsigned int (*) (void *))cpu_record_hash_key,       = hash_create ((unsigned int (*) (void *))cpu_record_hash_key,
                          (int (*) (const void *, const void *))cpu_record_hash_cmp);                     (int (*) (const void *, const void *))cpu_record_hash_cmp);
    
  return (struct thread_master *) XCALLOC (MTYPE_THREAD_MASTER,  rv = XCALLOC (MTYPE_THREAD_MASTER, sizeof (struct thread_master));
                                           sizeof (struct thread_master));
   /* Initialize the timer queues */
   rv->timer = pqueue_create();
   rv->background = pqueue_create();
   rv->timer->cmp = rv->background->cmp = thread_timer_cmp;
   rv->timer->update = rv->background->update = thread_timer_update;
 
   return rv;
 }  }
   
 /* Add a new thread to the list.  */  /* Add a new thread to the list.  */
Line 552  thread_list_add (struct thread_list *list, struct thre Line 556  thread_list_add (struct thread_list *list, struct thre
   list->count++;    list->count++;
 }  }
   
 /* Add a new thread just before the point.  */  
 static void  
 thread_list_add_before (struct thread_list *list,   
                         struct thread *point,   
                         struct thread *thread)  
 {  
   thread->next = point;  
   thread->prev = point->prev;  
   if (point->prev)  
     point->prev->next = thread;  
   else  
     list->head = thread;  
   point->prev = thread;  
   list->count++;  
 }  
   
 /* Delete a thread from the list. */  /* Delete a thread from the list. */
 static struct thread *  static struct thread *
 thread_list_delete (struct thread_list *list, struct thread *thread)  thread_list_delete (struct thread_list *list, struct thread *thread)
Line 594  thread_add_unuse (struct thread_master *m, struct thre Line 582  thread_add_unuse (struct thread_master *m, struct thre
   assert (thread->prev == NULL);    assert (thread->prev == NULL);
   assert (thread->type == THREAD_UNUSED);    assert (thread->type == THREAD_UNUSED);
   thread_list_add (&m->unuse, thread);    thread_list_add (&m->unuse, thread);
   /* XXX: Should we deallocate funcname here? */  
 }  }
   
 /* Free all unused thread. */  /* Free all unused thread. */
Line 613  thread_list_free (struct thread_master *m, struct thre Line 600  thread_list_free (struct thread_master *m, struct thre
     }      }
 }  }
   
   static void
   thread_queue_free (struct thread_master *m, struct pqueue *queue)
   {
     int i;
   
     for (i = 0; i < queue->size; i++)
       XFREE(MTYPE_THREAD, queue->array[i]);
   
     m->alloc -= queue->size;
     pqueue_delete(queue);
   }
   
 /* Stop thread scheduler. */  /* Stop thread scheduler. */
 void  void
 thread_master_free (struct thread_master *m)  thread_master_free (struct thread_master *m)
 {  {
   thread_list_free (m, &m->read);    thread_list_free (m, &m->read);
   thread_list_free (m, &m->write);    thread_list_free (m, &m->write);
  thread_list_free (m, &m->timer);  thread_queue_free (m, m->timer);
   thread_list_free (m, &m->event);    thread_list_free (m, &m->event);
   thread_list_free (m, &m->ready);    thread_list_free (m, &m->ready);
   thread_list_free (m, &m->unuse);    thread_list_free (m, &m->unuse);
  thread_list_free (m, &m->background);  thread_queue_free (m, m->background);
       
   XFREE (MTYPE_THREAD_MASTER, m);    XFREE (MTYPE_THREAD_MASTER, m);
   
Line 663  thread_timer_remain_second (struct thread *thread) Line 662  thread_timer_remain_second (struct thread *thread)
     return 0;      return 0;
 }  }
   
/* Trim blankspace and "()"s */struct timeval
voidthread_timer_remain(struct thread *thread)
strip_funcname (char *dest, const char *funcname) 
 {  {
  char buff[FUNCNAME_LEN];  quagga_get_relative(NULL);
  char tmp, *e, *b = buff; 
   
  strncpy(buff, funcname, sizeof(buff));  return timeval_subtract(thread->u.sands, relative_time);
  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
   
 /* Get new thread.  */  /* Get new thread.  */
 static struct thread *  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, debugargdef)
 {  {
   struct thread *thread = thread_trim_head (&m->unuse);    struct thread *thread = thread_trim_head (&m->unuse);
   
Line 705  thread_get (struct thread_master *m, u_char type, Line 690  thread_get (struct thread_master *m, u_char type,
   thread->master = m;    thread->master = m;
   thread->func = func;    thread->func = func;
   thread->arg = arg;    thread->arg = arg;
    thread->index = -1;
  strip_funcname (thread->funcname, funcname); 
   
     thread->funcname = funcname;
     thread->schedfrom = schedfrom;
     thread->schedfrom_line = fromln;
   
   return thread;    return thread;
 }  }
   
 /* Add new read thread. */  /* Add new read thread. */
 struct thread *  struct thread *
 funcname_thread_add_read (struct thread_master *m,   funcname_thread_add_read (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;    struct thread *thread;
   
Line 726  funcname_thread_add_read (struct thread_master *m,  Line 715  funcname_thread_add_read (struct thread_master *m, 
       return NULL;        return NULL;
     }      }
   
  thread = thread_get (m, THREAD_READ, func, arg, funcname);  thread = thread_get (m, THREAD_READ, func, arg, debugargpass);
   FD_SET (fd, &m->readfd);    FD_SET (fd, &m->readfd);
   thread->u.fd = fd;    thread->u.fd = fd;
   thread_list_add (&m->read, thread);    thread_list_add (&m->read, thread);
Line 737  funcname_thread_add_read (struct thread_master *m,  Line 726  funcname_thread_add_read (struct thread_master *m, 
 /* Add new write thread. */  /* Add new write thread. */
 struct thread *  struct thread *
 funcname_thread_add_write (struct thread_master *m,  funcname_thread_add_write (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;    struct thread *thread;
   
Line 749  funcname_thread_add_write (struct thread_master *m, Line 739  funcname_thread_add_write (struct thread_master *m,
       return NULL;        return NULL;
     }      }
   
  thread = thread_get (m, THREAD_WRITE, func, arg, funcname);  thread = thread_get (m, THREAD_WRITE, func, arg, debugargpass);
   FD_SET (fd, &m->writefd);    FD_SET (fd, &m->writefd);
   thread->u.fd = fd;    thread->u.fd = fd;
   thread_list_add (&m->write, thread);    thread_list_add (&m->write, thread);
Line 762  funcname_thread_add_timer_timeval (struct thread_maste Line 752  funcname_thread_add_timer_timeval (struct thread_maste
                                    int (*func) (struct thread *),                                      int (*func) (struct thread *), 
                                   int type,                                    int type,
                                   void *arg,                                     void *arg, 
                                  struct timeval *time_relative,                                   struct timeval *time_relative,
                                  const char* funcname)                                  debugargdef)
 {  {
   struct thread *thread;    struct thread *thread;
  struct thread_list *list;  struct pqueue *queue;
   struct timeval alarm_time;    struct timeval alarm_time;
   struct thread *tt;  
   
   assert (m != NULL);    assert (m != NULL);
   
   assert (type == THREAD_TIMER || type == THREAD_BACKGROUND);    assert (type == THREAD_TIMER || type == THREAD_BACKGROUND);
   assert (time_relative);    assert (time_relative);
       
  list = ((type == THREAD_TIMER) ? &m->timer : &m->background);  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? */    /* Do we need jitter here? */
   quagga_get_relative (NULL);    quagga_get_relative (NULL);
Line 784  funcname_thread_add_timer_timeval (struct thread_maste Line 773  funcname_thread_add_timer_timeval (struct thread_maste
   alarm_time.tv_usec = relative_time.tv_usec + time_relative->tv_usec;    alarm_time.tv_usec = relative_time.tv_usec + time_relative->tv_usec;
   thread->u.sands = timeval_adjust(alarm_time);    thread->u.sands = timeval_adjust(alarm_time);
   
  /* Sort by timeval. */  pqueue_enqueue(thread, queue);
  for (tt = list->head; tt; tt = tt->next) 
    if (timeval_cmp (thread->u.sands, tt->u.sands) <= 0) 
      break; 
 
  if (tt) 
    thread_list_add_before (list, tt, thread); 
  else 
    thread_list_add (list, thread); 
 
   return thread;    return thread;
 }  }
   
Line 802  funcname_thread_add_timer_timeval (struct thread_maste Line 782  funcname_thread_add_timer_timeval (struct thread_maste
 struct thread *  struct thread *
 funcname_thread_add_timer (struct thread_master *m,  funcname_thread_add_timer (struct thread_master *m,
                            int (*func) (struct thread *),                              int (*func) (struct thread *), 
                           void *arg, long timer, const char* funcname)                           void *arg, long timer,
                            debugargdef)
 {  {
   struct timeval trel;    struct timeval trel;
   
Line 812  funcname_thread_add_timer (struct thread_master *m, Line 793  funcname_thread_add_timer (struct thread_master *m,
   trel.tv_usec = 0;    trel.tv_usec = 0;
   
   return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg,     return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, 
                                            &trel, funcname);                                            &trel, debugargpass);
 }  }
   
 /* Add timer event thread with "millisecond" resolution */  /* Add timer event thread with "millisecond" resolution */
 struct thread *  struct thread *
 funcname_thread_add_timer_msec (struct thread_master *m,  funcname_thread_add_timer_msec (struct thread_master *m,
                                 int (*func) (struct thread *),                                   int (*func) (struct thread *), 
                                void *arg, long timer, const char* funcname)                                void *arg, long timer,
                                 debugargdef)
 {  {
   struct timeval trel;    struct timeval trel;
   
Line 829  funcname_thread_add_timer_msec (struct thread_master * Line 811  funcname_thread_add_timer_msec (struct thread_master *
   trel.tv_usec = 1000*(timer % 1000);    trel.tv_usec = 1000*(timer % 1000);
   
   return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER,     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 */  /* Add a background thread, with an optional millisec delay */
 struct thread *  struct thread *
 funcname_thread_add_background (struct thread_master *m,  funcname_thread_add_background (struct thread_master *m,
                                 int (*func) (struct thread *),                                  int (*func) (struct thread *),
                                void *arg, long delay,                                 void *arg, long delay,
                                const char *funcname)                                debugargdef)
 {  {
   struct timeval trel;    struct timeval trel;
       
Line 855  funcname_thread_add_background (struct thread_master * Line 837  funcname_thread_add_background (struct thread_master *
     }      }
   
   return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND,    return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND,
                                            arg, &trel, funcname);                                            arg, &trel, debugargpass);
 }  }
   
 /* Add simple event thread. */  /* Add simple event thread. */
 struct thread *  struct thread *
 funcname_thread_add_event (struct thread_master *m,  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;    struct thread *thread;
   
   assert (m != NULL);    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->u.val = val;
   thread_list_add (&m->event, thread);    thread_list_add (&m->event, thread);
   
Line 878  funcname_thread_add_event (struct thread_master *m, Line 861  funcname_thread_add_event (struct thread_master *m,
 void  void
 thread_cancel (struct thread *thread)  thread_cancel (struct thread *thread)
 {  {
  struct thread_list *list;  struct thread_list *list = NULL;
   struct pqueue *queue = NULL;
       
   switch (thread->type)    switch (thread->type)
     {      {
Line 893  thread_cancel (struct thread *thread) Line 877  thread_cancel (struct thread *thread)
       list = &thread->master->write;        list = &thread->master->write;
       break;        break;
     case THREAD_TIMER:      case THREAD_TIMER:
      list = &thread->master->timer;      queue = thread->master->timer;
       break;        break;
     case THREAD_EVENT:      case THREAD_EVENT:
       list = &thread->master->event;        list = &thread->master->event;
Line 902  thread_cancel (struct thread *thread) Line 886  thread_cancel (struct thread *thread)
       list = &thread->master->ready;        list = &thread->master->ready;
       break;        break;
     case THREAD_BACKGROUND:      case THREAD_BACKGROUND:
      list = &thread->master->background;      queue = thread->master->background;
       break;        break;
     default:      default:
       return;        return;
       break;        break;
     }      }
  thread_list_delete (list, thread);
   if (queue)
     {
       assert(thread->index >= 0);
       assert(thread == queue->array[thread->index]);
       pqueue_remove_at(thread->index, queue);
     }
   else if (list)
     {
       thread_list_delete (list, thread);
     }
   else
     {
       assert(!"Thread should be either in queue or list!");
     }
 
   thread->type = THREAD_UNUSED;    thread->type = THREAD_UNUSED;
   thread_add_unuse (thread->master, thread);    thread_add_unuse (thread->master, thread);
 }  }
Line 958  thread_cancel_event (struct thread_master *m, void *ar Line 957  thread_cancel_event (struct thread_master *m, void *ar
 }  }
   
 static struct timeval *  static struct timeval *
thread_timer_wait (struct thread_list *tlist, struct timeval *timer_val)thread_timer_wait (struct pqueue *queue, struct timeval *timer_val)
 {  {
  if (!thread_empty (tlist))  if (queue->size)
     {      {
      *timer_val = timeval_subtract (tlist->head->u.sands, relative_time);      struct thread *next_timer = queue->array[0];
       *timer_val = timeval_subtract (next_timer->u.sands, relative_time);
       return timer_val;        return timer_val;
     }      }
   return NULL;    return NULL;
Line 1006  thread_process_fd (struct thread_list *list, fd_set *f Line 1006  thread_process_fd (struct thread_list *list, fd_set *f
   
 /* Add all timers that have popped to the ready list. */  /* Add all timers that have popped to the ready list. */
 static unsigned int  static unsigned int
thread_timer_process (struct thread_list *list, struct timeval *timenow)thread_timer_process (struct pqueue *queue, struct timeval *timenow)
 {  {
   struct thread *thread;    struct thread *thread;
   struct thread *next;  
   unsigned int ready = 0;    unsigned int ready = 0;
       
  for (thread = list->head; thread; thread = next)  while (queue->size)
     {      {
      next = thread->next;      thread = queue->array[0];
       if (timeval_cmp (*timenow, thread->u.sands) < 0)        if (timeval_cmp (*timenow, thread->u.sands) < 0)
         return ready;          return ready;
      thread_list_delete (list, thread);      pqueue_dequeue(queue);
       thread->type = THREAD_READY;        thread->type = THREAD_READY;
       thread_list_add (&thread->master->ready, thread);        thread_list_add (&thread->master->ready, thread);
       ready++;        ready++;
Line 1093  thread_fetch (struct thread_master *m, struct thread * Line 1092  thread_fetch (struct thread_master *m, struct thread *
       if (m->ready.count == 0)        if (m->ready.count == 0)
         {          {
           quagga_get_relative (NULL);            quagga_get_relative (NULL);
          timer_wait = thread_timer_wait (&m->timer, &timer_val);          timer_wait = thread_timer_wait (m->timer, &timer_val);
          timer_wait_bg = thread_timer_wait (&m->background, &timer_val_bg);          timer_wait_bg = thread_timer_wait (m->background, &timer_val_bg);
                       
           if (timer_wait_bg &&            if (timer_wait_bg &&
               (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0)))                (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0)))
Line 1150  thread_fetch (struct thread_master *m, struct thread * Line 1149  thread_fetch (struct thread_master *m, struct thread *
          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. */
       quagga_get_relative (NULL);        quagga_get_relative (NULL);
      thread_timer_process (&m->timer, &relative_time);      thread_timer_process (m->timer, &relative_time);
               
       /* Got IO, process it */        /* Got IO, process it */
       if (num > 0)        if (num > 0)
Line 1171  thread_fetch (struct thread_master *m, struct thread * Line 1170  thread_fetch (struct thread_master *m, struct thread *
 #endif  #endif
   
       /* Background timer/events, lowest priority */        /* Background timer/events, lowest priority */
      thread_timer_process (&m->background, &relative_time);      thread_timer_process (m->background, &relative_time);
               
       if ((thread = thread_trim_head (&m->ready)) != NULL)        if ((thread = thread_trim_head (&m->ready)) != NULL)
         return thread_run (m, thread, fetch);          return thread_run (m, thread, fetch);
Line 1226  thread_getrusage (RUSAGE_T *r) Line 1225  thread_getrusage (RUSAGE_T *r)
 #endif /* HAVE_CLOCK_MONOTONIC */  #endif /* HAVE_CLOCK_MONOTONIC */
 }  }
   
   struct thread *thread_current = NULL;
   
 /* We check thread consumed time. If the system has getrusage, we'll  /* 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     use that to get in-depth stats on the performance of the thread in addition
    to wall clock time stats from gettimeofday. */     to wall clock time stats from gettimeofday. */
Line 1246  thread_call (struct thread *thread) Line 1247  thread_call (struct thread *thread)
       struct cpu_thread_history tmp;        struct cpu_thread_history tmp;
               
       tmp.func = thread->func;        tmp.func = thread->func;
      strcpy(tmp.funcname, thread->funcname);      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);
Line 1255  thread_call (struct thread *thread) Line 1256  thread_call (struct thread *thread)
   GETRUSAGE (&before);    GETRUSAGE (&before);
   thread->real = before.real;    thread->real = before.real;
   
     thread_current = thread;
   (*thread->func) (thread);    (*thread->func) (thread);
     thread_current = NULL;
   
   GETRUSAGE (&after);    GETRUSAGE (&after);
   
Line 1294  funcname_thread_execute (struct thread_master *m, Line 1297  funcname_thread_execute (struct thread_master *m,
                 int (*func)(struct thread *),                   int (*func)(struct thread *), 
                 void *arg,                  void *arg,
                 int val,                  int val,
                const char* funcname)                debugargdef)
 {  {
   struct thread dummy;     struct thread dummy; 
   
Line 1306  funcname_thread_execute (struct thread_master *m, Line 1309  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;
  strip_funcname (dummy.funcname, funcname);
   dummy.funcname = funcname;
   dummy.schedfrom = schedfrom;
   dummy.schedfrom_line = fromln;
 
   thread_call (&dummy);    thread_call (&dummy);
   
   return NULL;    return NULL;

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


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