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 long | unsigned 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 void | thread_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 |
void | thread_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; |