summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/memory.c7
-rw-r--r--lib/privs.c5
-rw-r--r--lib/privs.h2
-rw-r--r--lib/qlib_init.c6
-rw-r--r--lib/qpnexus.c26
-rw-r--r--lib/qpnexus.h2
-rw-r--r--lib/thread.c33
-rw-r--r--lib/thread.h4
8 files changed, 73 insertions, 12 deletions
diff --git a/lib/memory.c b/lib/memory.c
index 36599f18..9bb49d18 100644
--- a/lib/memory.c
+++ b/lib/memory.c
@@ -524,7 +524,12 @@ void
memory_finish (void)
{
if (memory_mutex)
- memory_mutex = qpt_mutex_destroy(memory_mutex, 1);
+ {
+ /* avoid re-entrancy with memory disposal */
+ qpt_mutex_t* mx = memory_mutex;
+ memory_mutex = NULL;
+ qpt_mutex_destroy(mx, 1);
+ }
}
void
diff --git a/lib/privs.c b/lib/privs.c
index 9d8cf79c..cd0f94ec 100644
--- a/lib/privs.c
+++ b/lib/privs.c
@@ -677,9 +677,10 @@ zprivs_init_r()
}
void
-zprivs_destroy_r(void)
+zprivs_finish(void)
{
- mx = qpt_mutex_destroy(mx, 1);
+ if (mx)
+ mx = qpt_mutex_destroy(mx, 1);
}
void
diff --git a/lib/privs.h b/lib/privs.h
index 9c789d16..45c5f49a 100644
--- a/lib/privs.h
+++ b/lib/privs.h
@@ -83,7 +83,7 @@ struct zprivs_ids_t
/* initialise zebra privileges */
extern void zprivs_init_r (void);
extern void zprivs_init (struct zebra_privs_t *zprivs);
-extern void zprivs_destroy_r (void);
+extern void zprivs_finish (void);
/* drop all and terminate privileges */
extern void zprivs_terminate (struct zebra_privs_t *);
diff --git a/lib/qlib_init.c b/lib/qlib_init.c
index 8f46c610..e6bce633 100644
--- a/lib/qlib_init.c
+++ b/lib/qlib_init.c
@@ -23,6 +23,8 @@
#include "zassert.h"
#include "memory.h"
#include "qpthreads.h"
+#include "thread.h"
+#include "privs.h"
/*==============================================================================
* Quagga Library Initialise/Closedown
@@ -71,12 +73,16 @@ qlib_init_second_stage(int pthreads)
{
qpt_set_qpthreads_enabled(pthreads);
memory_init_r();
+ thread_init_r();
+ zprivs_init_r();
}
void
qexit(int exit_code)
{
+ zprivs_finish();
+ thread_finish();
memory_finish();
exit (exit_code);
}
diff --git a/lib/qpnexus.c b/lib/qpnexus.c
index 5a5c5417..fa500e36 100644
--- a/lib/qpnexus.c
+++ b/lib/qpnexus.c
@@ -84,13 +84,18 @@ qpn_init_bgp(qpn_nexus qpn)
return qpn;
}
-/* free timers, selection, message queue and nexus */
-static void
+/* free timers, selection, message queue and nexus
+ * return NULL
+ */
+qpn_nexus
qpn_free(qpn_nexus qpn)
{
qps_file qf;
qtimer qtr;
+ if (qpn == NULL)
+ return NULL;
+
/* timers and the pile */
if (qpn->pile != NULL)
{
@@ -112,6 +117,8 @@ qpn_free(qpn_nexus qpn)
/* TODO: free qtn->queue */
XFREE(MTYPE_QPN_NEXUS, qpn) ;
+
+ return NULL;
}
/* If not main thread create new qpthread.
@@ -127,7 +134,7 @@ qpn_exec(qpn_nexus qpn)
else
{
/* create a qpthread and run the state machine in it */
- qpn->thread_id = qpt_thread_create(qpn->start, qpn, NULL) ;
+ qpt_thread_create(qpn->start, qpn, NULL) ;
}
}
@@ -173,8 +180,6 @@ qpn_start_main(void* arg)
}
}
- qpn_free(qpn);
-
return NULL;
}
@@ -224,7 +229,14 @@ qpn_start_bgp(void* arg)
mqueue_done_waiting(qpn->queue, qpn->mts);
}
- qpn_free(qpn);
-
return NULL;
}
+
+/* Ask the thread to terminate itself quickly and cleanly */
+void
+qpn_terminate(qpn_nexus qpn)
+{
+ qpn->terminate = 1;
+ /* wake up any pselect */
+ qpt_thread_signal(qpn->thread_id, SIGMQUEUE);
+}
diff --git a/lib/qpnexus.h b/lib/qpnexus.h
index bda5234f..7436c55d 100644
--- a/lib/qpnexus.h
+++ b/lib/qpnexus.h
@@ -93,5 +93,7 @@ extern qpn_nexus qpn_init_new(qpn_nexus qtn);
extern qpn_nexus qpn_init_main(qpn_nexus qtn);
extern qpn_nexus qpn_init_bgp(qpn_nexus qtn);
extern void qpn_exec(qpn_nexus qtn);
+extern void qpn_terminate(qpn_nexus qpn);
+extern qpn_nexus qpn_free(qpn_nexus qpn);
#endif /* _ZEBRA_QPNEXUS_H */
diff --git a/lib/thread.c b/lib/thread.c
index 9fa1fd9f..b58a2c73 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -40,6 +40,10 @@ static struct timeval relative_time_base;
/* init flag */
static unsigned short timers_inited;
+/* cpu stats needs to be qpthread safe. */
+static qpt_mutex_t* thread_mutex = NULL;
+#define LOCK qpt_mutex_lock(thread_mutex);
+#define UNLOCK qpt_mutex_unlock(thread_mutex);
static struct hash *cpu_record = NULL;
/* TODO: remove this */
@@ -323,15 +327,19 @@ cpu_record_print(struct vty *vty, thread_type filter)
vty_out(vty, " Avg uSec Max uSecs");
#endif
vty_out(vty, " Type Thread%s", VTY_NEWLINE);
+
+ LOCK
hash_iterate(cpu_record,
(void(*)(struct hash_backet*,void*))cpu_record_hash_print,
args);
if (tmp.total_calls > 0)
vty_out_cpu_thread_history(vty, &tmp);
+
+ UNLOCK
}
-DEFUN(show_thread_cpu,
+DEFUN_CALL(show_thread_cpu,
show_thread_cpu_cmd,
"show thread cpu [FILTER]",
SHOW_STR
@@ -529,12 +537,14 @@ thread_master_free (struct thread_master *m)
XFREE (MTYPE_THREAD_MASTER, m);
+ LOCK
if (cpu_record)
{
hash_clean (cpu_record, cpu_record_hash_free);
hash_free (cpu_record);
cpu_record = NULL;
}
+ UNLOCK
}
/* Thread list is empty or not. */
@@ -1088,8 +1098,10 @@ thread_call (struct thread *thread)
tmp.func = thread->func;
tmp.funcname = thread->funcname;
+ LOCK
thread->hist = hash_get (cpu_record, &tmp,
(void * (*) (void *))cpu_record_hash_alloc);
+ UNLOCK
}
GETRUSAGE (&thread->ru);
@@ -1099,6 +1111,8 @@ thread_call (struct thread *thread)
GETRUSAGE (&ru);
realtime = thread_consumed_time (&ru, &thread->ru, &cputime);
+
+ LOCK
thread->hist->real.total += realtime;
if (thread->hist->real.max < realtime)
thread->hist->real.max = realtime;
@@ -1110,6 +1124,7 @@ thread_call (struct thread *thread)
++(thread->hist->total_calls);
thread->hist->types |= (1 << thread->add_type);
+ UNLOCK
#ifdef CONSUMED_TIME_CHECK
if (realtime > CONSUMED_TIME_CHECK)
@@ -1154,4 +1169,20 @@ funcname_thread_execute (struct thread_master *m,
return NULL;
}
+
+/* Second state initialisation if qpthreaded */
+void
+thread_init_r (void)
+{
+ thread_mutex = qpt_mutex_init(thread_mutex, qpt_mutex_quagga);
+}
+
+/* Finished with module */
+void
+thread_finish (void)
+{
+ if (thread_mutex)
+ thread_mutex = qpt_mutex_destroy(thread_mutex, 1);
+}
+
#undef USE_MQUEUE
diff --git a/lib/thread.h b/lib/thread.h
index b52bc541..43d4d12f 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -22,6 +22,8 @@
#ifndef _ZEBRA_THREAD_H
#define _ZEBRA_THREAD_H
+#include <sys/resource.h>
+
struct rusage_t
{
#ifdef HAVE_RUSAGE
@@ -163,6 +165,8 @@ enum quagga_clkid {
/* Prototypes. */
extern struct thread_master *thread_master_create (void);
extern void thread_master_free (struct thread_master *);
+extern void thread_init_r (void);
+extern void thread_finish (void);
extern struct thread *funcname_thread_add_read (struct thread_master *,
int (*)(struct thread *),