summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/command.c12
-rw-r--r--lib/qpnexus.c133
-rw-r--r--lib/qpnexus.h19
-rw-r--r--lib/vty.c8
4 files changed, 73 insertions, 99 deletions
diff --git a/lib/command.c b/lib/command.c
index c3c9145d..574e45bf 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -1992,7 +1992,7 @@ node_parent ( enum node_type node )
/* Execute command by argument vline vector. */
static int
cmd_execute_command_real (vector vline, struct vty *vty,
- struct cmd_element **cmd, qpn_nexus bgp_nexus)
+ struct cmd_element **cmd, qpn_nexus dest_nexus)
{
unsigned int i;
unsigned int index;
@@ -2111,7 +2111,7 @@ cmd_execute_command_real (vector vline, struct vty *vty,
if (qpthreads_enabled && !(matched_element->attr & CMD_ATTR_CALL))
{
/* Don't do it now, but send to bgp qpthread */
- cq_enqueue(matched_element, vty, argc, argv, bgp_nexus);
+ cq_enqueue(matched_element, vty, argc, argv, dest_nexus);
return CMD_QUEUED;
}
else
@@ -2122,7 +2122,7 @@ cmd_execute_command_real (vector vline, struct vty *vty,
int
cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd,
- qpn_nexus bgp_nexus, int vtysh) {
+ qpn_nexus dest_nexus, int vtysh) {
int ret, saved_ret, tried = 0;
enum node_type onode, try_node;
@@ -2143,7 +2143,7 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd,
vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
}
- ret = cmd_execute_command_real (shifted_vline, vty, cmd, bgp_nexus);
+ ret = cmd_execute_command_real (shifted_vline, vty, cmd, dest_nexus);
vector_free(shifted_vline);
vty_set_node(vty, onode);
@@ -2151,7 +2151,7 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd,
}
- saved_ret = ret = cmd_execute_command_real (vline, vty, cmd, bgp_nexus);
+ saved_ret = ret = cmd_execute_command_real (vline, vty, cmd, dest_nexus);
if (vtysh)
return saved_ret;
@@ -2162,7 +2162,7 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd,
{
try_node = node_parent(try_node);
vty_set_node(vty, try_node);
- ret = cmd_execute_command_real (vline, vty, cmd, bgp_nexus);
+ ret = cmd_execute_command_real (vline, vty, cmd, dest_nexus);
tried = 1;
if (ret == CMD_SUCCESS || ret == CMD_WARNING)
{
diff --git a/lib/qpnexus.c b/lib/qpnexus.c
index 5ecb97cf..98bd767c 100644
--- a/lib/qpnexus.c
+++ b/lib/qpnexus.c
@@ -28,12 +28,8 @@
/* prototypes */
static void* qpn_start(void* arg);
-static void* qpn_start_bgp(void* arg);
static void qpn_in_thread_init(qpn_nexus qpn);
-/* Master of the threads. */
-extern struct thread_master *master;
-
/*==============================================================================
* Quagga Nexus Interface -- qpn_xxxx
*
@@ -50,54 +46,17 @@ extern struct thread_master *master;
* Returns the qpn_nexus.
*/
qpn_nexus
-qpn_init_new(qpn_nexus qpn)
+qpn_init_new(qpn_nexus qpn, int main_thread)
{
if (qpn == NULL)
qpn = XCALLOC(MTYPE_QPN_NEXUS, sizeof(struct qpn_nexus)) ;
else
memset(qpn, 0, sizeof(struct qpn_nexus)) ;
- return qpn;
-}
-
-/* Initialize main qpthread */
-qpn_nexus
-qpn_init_main(qpn_nexus qpn)
-{
- qpn = qpn_init_new(qpn);
- qpn->selection = qps_selection_init_new(qpn->selection);
- qpn->pile = qtimer_pile_init_new(qpn->pile);
- qpn->queue = mqueue_init_new(qpn->queue, mqt_signal_unicast);
- qpn->main_thread = 1;
- qpn->start = qpn_start;
-
- return qpn;
-}
-
-/* Initialize bgp engine's qpthread */
-qpn_nexus
-qpn_init_bgp(qpn_nexus qpn)
-{
- qpn = qpn_init_new(qpn);
- qpn->queue = mqueue_init_new(qpn->queue, mqt_signal_unicast);
- qpn->start = qpn_start_bgp;
-
- return qpn;
-}
-
-/* Initialize Routing engine's qpthread
- *
- * Although not expected to do I/O we still use qps_selection (pselect) as
- * the mechanism to wait for either a timeout or a signal from the message
- * queue.
-*/
-qpn_nexus
-qpn_init_routing(qpn_nexus qpn)
-{
- qpn = qpn_init_new(qpn);
qpn->selection = qps_selection_init_new(qpn->selection);
qpn->pile = qtimer_pile_init_new(qpn->pile);
qpn->queue = mqueue_init_new(qpn->queue, mqt_signal_unicast);
+ qpn->main_thread = main_thread;
qpn->start = qpn_start;
return qpn;
@@ -155,9 +114,30 @@ qpn_exec(qpn_nexus qpn)
}
}
-/* Thread routine, complete init, then run finite state machine
- * using mqueue, qps_selection and qtimer
-*/
+/*==============================================================================
+ * Pthread routine
+ *
+ * Processes:
+ *
+ * 1) Main thread only -- signals.
+ *
+ * 2) Pending work -- local queue.
+ *
+ * 3) messages coming from other pthreads -- mqueue_queue.
+ *
+ * 4) I/O -- qpselect
+ *
+ * This deals with all active sockets for read/write/connect/accept.
+ *
+ * Each time a socket is readable, one message is read and dispatched.
+ * The pselect timeout is set to be when the next timer is due.
+ *
+ * 5) Timers -- qtimers
+ *
+ * 6) Legacy threads. To deal with legacy timer mechanism.
+ *
+ *
+ */
static void*
qpn_start(void* arg)
{
@@ -165,6 +145,7 @@ qpn_start(void* arg)
mqueue_block mqb;
int actions;
qtime_mono_t now;
+ struct thread thread;
/* now in our thread, complete initialisation */
qpn_in_thread_init(qpn);
@@ -176,13 +157,8 @@ qpn_start(void* arg)
if (qpn->main_thread)
quagga_sigevent_process ();
- /* process timers */
- now = qt_get_monotonic();
- while (qtimer_pile_dispatch_next(qpn->pile, now))
- {
- }
-
- /* drain the message queue, will be waiting when it's empty */
+ /* drain the message queue, will be in waiting for signal state
+ * when it's empty */
for (;;)
{
mqb = mqueue_dequeue(qpn->queue, 1, qpn->mts) ;
@@ -193,6 +169,7 @@ qpn_start(void* arg)
}
/* block for some input, output, signal or timeout */
+ now = qt_get_monotonic();
actions = qps_pselect(qpn->selection,
qtimer_pile_top_time(qpn->pile, now + QTIME(MAX_PSELECT_TIMOUT)) );
@@ -201,43 +178,27 @@ qpn_start(void* arg)
actions = qps_dispatch_next(qpn->selection) ;
mqueue_done_waiting(qpn->queue, qpn->mts);
- }
- return NULL;
-}
-
-/* Bgp engine's qpthread, complete init, then run finite state machine
- * using legacy threads
-*/
-static void*
-qpn_start_bgp(void* arg)
-{
- qpn_nexus qpn = arg;
- struct thread thread;
- mqueue_block mqb;
-
- /* now in our thread, complete initialisation */
- qpn_in_thread_init(qpn);
-
- while (!qpn->terminate)
- {
- /* drain the message queue, will be waiting when it's empty */
- for (;;)
+ /* process timers */
+ now = qt_get_monotonic();
+ while (qtimer_pile_dispatch_next(qpn->pile, now))
{
- mqb = mqueue_dequeue(qpn->queue, 1, qpn->mts) ;
- if (mqb == NULL)
- break;
-
- mqb_dispatch(mqb, mqb_action);
}
- /* TODO: use qpselect stuff */
- if (thread_fetch (master, &thread))
- thread_call (&thread);
-
- mqueue_done_waiting(qpn->queue, qpn->mts);
+ /* legacy threads */
+ /* TODO: legacy threads must not pselect. How is the pselect above
+ * to know when to timeout for legacy timers? */
+ if (qpn->master != NULL)
+ {
+ if (thread_fetch (qpn->master, &thread))
+ thread_call (&thread);
+ }
}
+ /* last bit of code to run in this thread */
+ if (qpn->in_thread_final)
+ qpn->in_thread_final();
+
return NULL;
}
@@ -281,6 +242,10 @@ qpn_in_thread_init(qpn_nexus qpn)
qpn->mts = mqueue_thread_signal_init(qpn->mts, qpn->thread_id, SIGMQUEUE);
if (qpn->selection != NULL)
qps_set_signal(qpn->selection, SIGMQUEUE, newmask);
+
+ /* custom in-thread initialization */
+ if (qpn->in_thread_init != NULL)
+ qpn->in_thread_init();
}
/* Ask the thread to terminate itself quickly and cleanly */
diff --git a/lib/qpnexus.h b/lib/qpnexus.h
index 69fe8044..c717ed23 100644
--- a/lib/qpnexus.h
+++ b/lib/qpnexus.h
@@ -80,19 +80,28 @@ struct qpn_nexus
mqueue_queue queue;
mqueue_thread_signal mts;
- /* qpthread routine */
+ /* legacy threads */
+ struct thread_master *master;
+
+ /* qpthread routine, can override */
void* (*start)(void*);
+ /* in-thread initialize, can override. Called within the thread
+ * after all other initializion just before thread loop */
+ void (*in_thread_init)(void);
+
+ /* in-thread finalize, can override. Called within thread
+ * just before thread dies. Nexus components all exist but
+ * thread loop is no longer executed */
+ void (*in_thread_final)(void);
+
};
/*==============================================================================
* Functions
*/
-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 qpn_nexus qpn_init_routing(qpn_nexus qtn);
+extern qpn_nexus qpn_init_new(qpn_nexus qtn, int main_thread);
extern void qpn_exec(qpn_nexus qtn);
extern void qpn_terminate(qpn_nexus qpn);
extern qpn_nexus qpn_free(qpn_nexus qpn);
diff --git a/lib/vty.c b/lib/vty.c
index 27bab60a..4797f923 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -141,7 +141,7 @@ char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;
/* Master of the threads. */
static struct thread_master *master = NULL;
static qpn_nexus cli_nexus = NULL;
-static qpn_nexus bgp_nexus = NULL;
+static qpn_nexus routing_nexus = NULL;
/* VTY standard output function. vty == NULL or VTY_SHELL => stdout */
int
@@ -553,7 +553,7 @@ vty_command (struct vty *vty, char *buf)
#endif /* CONSUMED_TIME_CHECK */
UNLOCK
- ret = cmd_execute_command (vline, vty, NULL, bgp_nexus, 0);
+ ret = cmd_execute_command (vline, vty, NULL, routing_nexus, 0);
LOCK
/* Get the name of the protocol if any */
@@ -3644,10 +3644,10 @@ vty_set_lines(struct vty *vty, int lines)
/* qpthreads: Install vty's own commands like `who' command. */
void
-vty_init_r (qpn_nexus cli_n, qpn_nexus bgp_n)
+vty_init_r (qpn_nexus cli_n, qpn_nexus routing_n)
{
cli_nexus = cli_n;
- bgp_nexus = bgp_n;
+ routing_nexus = routing_n;
qpt_mutex_init(&vty_mutex, qpt_mutex_recursive);
}