diff options
Diffstat (limited to 'src/vlib/node_funcs.h')
-rw-r--r-- | src/vlib/node_funcs.h | 114 |
1 files changed, 71 insertions, 43 deletions
diff --git a/src/vlib/node_funcs.h b/src/vlib/node_funcs.h index 4c7020d6a42..ffa17ba7bb1 100644 --- a/src/vlib/node_funcs.h +++ b/src/vlib/node_funcs.h @@ -187,10 +187,7 @@ vlib_node_set_state (vlib_main_t * vm, u32 node_index, vlib_process_t *p = vec_elt (nm->processes, n->runtime_index); r = &p->node_runtime; - /* When disabling make sure flags are cleared. */ - p->flags &= ~(VLIB_PROCESS_RESUME_PENDING - | VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK - | VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT); + p->event_resume_pending = 0; } else r = vec_elt_at_index (nm->nodes_by_type[n->type], n->runtime_index); @@ -599,7 +596,7 @@ vlib_process_suspend (vlib_main_t * vm, f64 dt) if (vlib_process_suspend_time_is_zero (dt)) return VLIB_PROCESS_RESUME_LONGJMP_RESUME; - p->flags |= VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK; + p->state = VLIB_PROCESS_STATE_SUSPENDED; r = clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND); if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND) { @@ -614,6 +611,38 @@ vlib_process_suspend (vlib_main_t * vm, f64 dt) return r; } +/** Suspend a vlib cooperative multi-tasking thread and put it at the end of + * resume queue + @param vm - vlib_main_t * + @returns VLIB_PROCESS_RESUME_LONGJMP_RESUME, routinely ignored +*/ + +always_inline uword +vlib_process_yield (vlib_main_t *vm) +{ + uword r; + vlib_node_main_t *nm = &vm->node_main; + vlib_process_t *p = vec_elt (nm->processes, nm->current_process_index); + + p->state = VLIB_PROCESS_STATE_YIELD; + r = clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND); + if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND) + { + vlib_process_restore_t r = { + .reason = VLIB_PROCESS_RESTORE_REASON_YIELD, + .runtime_index = nm->current_process_index, + }; + p->resume_clock_interval = 0; + vec_add1 (nm->process_restore_next, r); + vlib_process_start_switch_stack (vm, 0); + clib_longjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_SUSPEND); + } + else + vlib_process_finish_switch_stack (vm); + + return r; +} + always_inline void vlib_process_free_event_type (vlib_process_t * p, uword t, uword is_one_time_event) @@ -773,11 +802,12 @@ vlib_process_wait_for_event (vlib_main_t * vm) p = vec_elt (nm->processes, nm->current_process_index); if (clib_bitmap_is_zero (p->non_empty_event_type_bitmap)) { - p->flags |= VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT; + p->state = VLIB_PROCESS_STATE_WAIT_FOR_EVENT; r = clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND); if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND) { + p->resume_clock_interval = 0; vlib_process_start_switch_stack (vm, 0); clib_longjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_SUSPEND); @@ -802,11 +832,12 @@ vlib_process_wait_for_one_time_event (vlib_main_t * vm, ASSERT (!pool_is_free_index (p->event_type_pool, with_type_index)); while (!clib_bitmap_get (p->non_empty_event_type_bitmap, with_type_index)) { - p->flags |= VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT; + p->state = VLIB_PROCESS_STATE_WAIT_FOR_ONE_TIME_EVENT; r = clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND); if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND) { + p->resume_clock_interval = 0; vlib_process_start_switch_stack (vm, 0); clib_longjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_SUSPEND); @@ -831,11 +862,12 @@ vlib_process_wait_for_event_with_type (vlib_main_t * vm, h = hash_get (p->event_type_index_by_type_opaque, with_type_opaque); while (!h || !clib_bitmap_get (p->non_empty_event_type_bitmap, h[0])) { - p->flags |= VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT; + p->state = VLIB_PROCESS_STATE_WAIT_FOR_EVENT; r = clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND); if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND) { + p->resume_clock_interval = 0; vlib_process_start_switch_stack (vm, 0); clib_longjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_SUSPEND); @@ -875,8 +907,7 @@ vlib_process_wait_for_event_or_clock (vlib_main_t * vm, f64 dt) wakeup_time = vlib_time_now (vm) + dt; /* Suspend waiting for both clock and event to occur. */ - p->flags |= (VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT - | VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK); + p->state = VLIB_PROCESS_STATE_WAIT_FOR_EVENT_OR_CLOCK; r = clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND); if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND) @@ -938,7 +969,7 @@ vlib_process_signal_event_helper (vlib_node_main_t * nm, uword t, uword n_data_elts, uword n_data_elt_bytes) { - uword p_flags, add_to_pending, delete_from_wheel; + uword add_to_pending = 0, delete_from_wheel = 0; u8 *data_to_be_written_by_caller; vec_attr_t va = { .elt_sz = n_data_elt_bytes }; @@ -970,47 +1001,44 @@ vlib_process_signal_event_helper (vlib_node_main_t * nm, p->non_empty_event_type_bitmap = clib_bitmap_ori (p->non_empty_event_type_bitmap, t); - p_flags = p->flags; + switch (p->state) + { + case VLIB_PROCESS_STATE_WAIT_FOR_EVENT: + add_to_pending = 1; + break; - /* Event was already signalled? */ - add_to_pending = (p_flags & VLIB_PROCESS_RESUME_PENDING) == 0; + case VLIB_PROCESS_STATE_WAIT_FOR_EVENT_OR_CLOCK: + add_to_pending = 1; + delete_from_wheel = 1; + break; - /* Process will resume when suspend time elapses? */ - delete_from_wheel = 0; - if (p_flags & VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK) - { - /* Waiting for both event and clock? */ - if (p_flags & VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT) - { - if (!TW (tw_timer_handle_is_free) - ((TWT (tw_timer_wheel) *) nm->timing_wheel, - p->stop_timer_handle)) - delete_from_wheel = 1; - else - /* timer just popped so process should already be on the list */ - add_to_pending = 0; - } - else - /* Waiting only for clock. Event will be queue and may be - handled when timer expires. */ - add_to_pending = 0; + default: + break; } + if (TW (tw_timer_handle_is_free) ((TWT (tw_timer_wheel) *) nm->timing_wheel, + p->stop_timer_handle)) + delete_from_wheel = 0; + /* Never add current process to pending vector since current process is already running. */ add_to_pending &= nm->current_process_index != n->runtime_index; - if (add_to_pending) + if (add_to_pending && p->event_resume_pending == 0) { - u32 x = vlib_timing_wheel_data_set_suspended_process (n->runtime_index); - p->flags = p_flags | VLIB_PROCESS_RESUME_PENDING; - vec_add1 (nm->data_from_advancing_timing_wheel, x); - if (delete_from_wheel) - { - TW (tw_timer_stop) - ((TWT (tw_timer_wheel) *) nm->timing_wheel, p->stop_timer_handle); - p->stop_timer_handle = ~0; - } + vlib_process_restore_t restore = { + .runtime_index = n->runtime_index, + .reason = VLIB_PROCESS_RESTORE_REASON_EVENT, + }; + p->event_resume_pending = 1; + vec_add1 (nm->process_restore_current, restore); + } + + if (delete_from_wheel) + { + TW (tw_timer_stop) + ((TWT (tw_timer_wheel) *) nm->timing_wheel, p->stop_timer_handle); + p->stop_timer_handle = ~0; } return data_to_be_written_by_caller; |