#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
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;
}
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);
void *args[3] = {&tmp, vty, &filter};
memset(&tmp, 0, sizeof tmp);
- strcpy(tmp.funcname, "TOTAL");
+ tmp.funcname = "TOTAL";
tmp.types = filter;
#ifdef HAVE_RUSAGE
{
thread_type *filter = args;
struct cpu_thread_history *a = bucket->data;
-
- a = bucket->data;
+
if ( !(a->types & *filter) )
return;
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);
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. */
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);
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;
}
#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;
}
/* 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)
/* 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;
#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;
}
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;
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;
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);
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;
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;
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;
}
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);
}
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;
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
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:
{
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;
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;
#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. */
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);
GETRUSAGE (&before);
thread->real = before.real;
+ thread_current = thread;
(*thread->func) (thread);
+ thread_current = NULL;
GETRUSAGE (&after);
int (*func)(struct thread *),
void *arg,
int val,
- const char* funcname)
+ debugargdef)
{
struct thread dummy;
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;