diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/command.c | 12 | ||||
-rw-r--r-- | lib/qpnexus.c | 133 | ||||
-rw-r--r-- | lib/qpnexus.h | 19 | ||||
-rw-r--r-- | lib/vty.c | 8 |
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); @@ -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); } |