diff options
Diffstat (limited to 'lib/vty_io_basic.c')
-rw-r--r-- | lib/vty_io_basic.c | 543 |
1 files changed, 235 insertions, 308 deletions
diff --git a/lib/vty_io_basic.c b/lib/vty_io_basic.c index 85ea2587..3239c893 100644 --- a/lib/vty_io_basic.c +++ b/lib/vty_io_basic.c @@ -34,7 +34,7 @@ * */ -/*============================================================================== +/*------------------------------------------------------------------------------ * Try to open the given file for the given type of I/O. * * vfd_io_write => create if does not exist (mode 0600) @@ -80,7 +80,7 @@ uty_vfd_file_open(const char* name, vfd_io_type_t io_type) if ((io_type & vfd_io_blocking) == 0) oflag |= O_NONBLOCK ; - return open(name, oflag, S_IRUSR | S_IWUSR) ; + return open(name, oflag, S_IRUSR | S_IWUSR) ; /* TODO umask etc ? */ } ; /*============================================================================== @@ -90,25 +90,8 @@ uty_vfd_file_open(const char* name, vfd_io_type_t io_type) * and an old thread environment are encapsulated here. */ -struct vio_io_set_args /* to CLI thread */ -{ - bool active ; /* set when queued, cleared when dequeued */ - bool close ; /* close and free the vio_vfd and mqb */ - - bool readable ; /* set when read state to be changed */ - on_off_b read_on ; /* what to change read to */ - vty_timer_time read_timeout ; - /* what to set the timeout to, if any */ - - bool writable ; /* set when write state to be changed */ - on_off_b write_on ; /* what to change write to */ - vty_timer_time write_timeout ; - /* what to set the timeout to, if any */ -} ; -MQB_ARGS_SIZE_OK(vio_io_set_args) ; - -static void vio_vfd_mqb_dispatch(vio_vfd vfd) ; -static struct vio_io_set_args* vio_vfd_mqb_args(vio_vfd vfd) ; +static void vio_vfd_mqb_kick(vio_vfd vfd) ; +static void vio_vfd_mqb_free(vio_vfd vfd) ; /*============================================================================== * File Descriptor handling @@ -130,24 +113,30 @@ static void vio_vfd_qps_write_action(qps_file qf, void* file_info) ; static int vio_vfd_thread_read_action(struct thread *thread) ; static int vio_vfd_thread_write_action(struct thread *thread) ; -static void vio_timer_squelch(vio_timer_t* timer) ; +static void vio_timer_squelch(vio_timer timer) ; Inline void vio_vfd_do_read_action(vio_vfd vfd) { - if (vfd->active) + if (vfd->read_action != NULL) vfd->read_action(vfd, vfd->action_info) ; } Inline void vio_vfd_do_write_action(vio_vfd vfd) { - if (vfd->active) + if (vfd->write_action != NULL) vfd->write_action(vfd, vfd->action_info) ; } ; /*------------------------------------------------------------------------------ * Create a new vfd structure. + * + * Note that sets the same action info for read, write, read timeout and + * write timeout. + * + * Sets the blocking_vf state, which will disallow any attempt to set read/write + * ready/timeout -- but enable open/close when not in cli thread. */ extern vio_vfd vio_vfd_new(int fd, vfd_type_t type, vfd_io_type_t io_type, void* action_info) @@ -158,45 +147,59 @@ vio_vfd_new(int fd, vfd_type_t type, vfd_io_type_t io_type, void* action_info) /* Has set: * - * active -- false ! + * fd -- X -- see below + * active -- X -- see below + * + * type -- X -- see below + * io_type -- X -- see below + * + * blocking_vf -- X -- see below + * + * action_info -- NULL -- set below if !blocking_vf * * read_action -- NULL * write_action -- NULL * - * f.qf -- NULL + * read_timer -- NULL -- set below if !blocking_vf + * write_timer -- NULL -- set below if !blocking_vf + * + * f.qf -- NULL -- set below if !blocking_vf + * * f.thread.read -- NULL * f.thread.write -- NULL * - * mqb -- NULL + * queued -- false + * + * read_req -- all zeros -- none set + * write_req -- all zeros -- none set + * + * mqb -- NULL -- none, yet */ + confirm(VIO_TIMER_INIT_ZERO) ; - vio_vfd_set_fd(vfd, fd, type, io_type) ; + vfd->fd = fd ; + vfd->type = type ; + vfd->io_type = io_type ; - vio_timer_init(&vfd->read_timer, NULL, NULL) ; - vio_timer_init(&vfd->write_timer, NULL, NULL) ; + vfd->blocking_vf = (io_type & vfd_io_blocking) != 0 ; - vio_vfd_set_action_info(vfd, action_info) ; + if (!vfd->blocking_vf) + { + VTY_ASSERT_CLI_THREAD() ; - return vfd ; -} ; + if (vty_nexus) + { + vfd->f.qf = qps_file_init_new(NULL, NULL) ; + qps_add_file(vty_cli_nexus->selection, vfd->f.qf, vfd->fd, vfd) ; + } ; -/*------------------------------------------------------------------------------ - * If vfd was not fully set up when created, set it up now. - * - * To close an active vfd, use vio_vfd_close() ! - * - * NB: for use when vfd has been created, but the fd was not known at that - * time -- ie the vfd is NOT active. - */ -extern void -vio_vfd_set_fd(vio_vfd vfd, int fd, vfd_type_t type, vfd_io_type_t io_type) -{ - assert(!vfd->active) ; + vfd->read_timer = vio_timer_init_new(NULL, NULL, NULL) ; + vfd->write_timer = vio_timer_init_new(NULL, NULL, NULL) ; - vfd->fd = fd ; - vfd->active = (fd >= 0) ; - vfd->type = type ; - vfd->io_type = io_type ; + vio_vfd_set_action_info(vfd, action_info) ; + } ; + + return vfd ; } ; /*------------------------------------------------------------------------------ @@ -223,7 +226,7 @@ vio_vfd_set_write_action(vio_vfd vfd, vio_vfd_action* action) extern void vio_vfd_set_read_timeout_action(vio_vfd vfd, vio_timer_action* action) { - vio_timer_set_action(&vfd->read_timer, action) ; + vio_timer_set_action(vfd->read_timer, action) ; } ; /*------------------------------------------------------------------------------ @@ -232,7 +235,7 @@ vio_vfd_set_read_timeout_action(vio_vfd vfd, vio_timer_action* action) extern void vio_vfd_set_write_timeout_action(vio_vfd vfd, vio_timer_action* action) { - vio_timer_set_action(&vfd->write_timer, action) ; + vio_timer_set_action(vfd->write_timer, action) ; } ; /*------------------------------------------------------------------------------ @@ -242,8 +245,8 @@ extern void vio_vfd_set_action_info(vio_vfd vfd, void* action_info) { vfd->action_info = action_info ; - vio_timer_set_info(&vfd->read_timer, action_info) ; - vio_timer_set_info(&vfd->write_timer, action_info) ; + vio_timer_set_info(vfd->read_timer, action_info) ; + vio_timer_set_info(vfd->write_timer, action_info) ; } ; #if 0 @@ -278,6 +281,8 @@ vio_vfd_kick_write_action(vio_vfd vfd) * In any case, turns off any read ready and read ready timeout. * * Returns original vfd, or NULL if it has been closed. + * + * NB: if this is not a "blocking_vf", then MUST be in the cli thread. */ extern vio_vfd vio_vfd_read_close(vio_vfd vfd) @@ -287,47 +292,60 @@ vio_vfd_read_close(vio_vfd vfd) if (vfd == NULL) return NULL ; - if (vfd->fd >= 0) - { - assert(vfd->active) ; + if (!vfd->blocking_vf) + VTY_ASSERT_CLI_THREAD() ; - if (vfd->io_type & vfd_io_read) + if ((vfd->io_type & vfd_io_read) != 0) + { + if ((vfd->io_type & vfd_io_write) != 0) { - if (vfd->io_type & vfd_io_write) + /* read & write, so really half-close if can */ + if (vfd->fd >= 0) { - /* read & write, so really half-close if can */ if (vfd->type == vfd_socket) shutdown(vfd->fd, SHUT_RD) ; /* ignore errors TODO */ vio_vfd_set_read(vfd, off, 0) ; - vfd->io_type ^= vfd_io_read ; /* now write only ! */ - } - else - { - /* read only, so fully close */ - vfd = vio_vfd_close(vfd) ; + vfd->io_type ^= vfd_io_read ; /* now write only ! */ } ; + } + else + { + /* read only, so fully close */ + vfd = vio_vfd_close(vfd) ; } ; - } - else - assert(!vfd->active) ; + } ; return vfd ; } ; /*------------------------------------------------------------------------------ - * If there is an fd, close it. + * Close the given vfd (if any). * - * Stops any read/write waiting and releases all memory, including the vfd - * itself if required.. + * If there is an fd, close it. Stops any read/write waiting and releases all + * memory. + * + * NB: if this is not a "blocking_vf", then MUST be in the cli thread. + * Inter alia, this guarantees that cannot be in the middle of a read/write + * ready/timeout operation -- so the file can be closed down, and + * any pending ready/timeout will be swept away. */ -static void -vio_vfd_do_close(vio_vfd vfd, free_keep_b free) +extern vio_vfd +vio_vfd_close(vio_vfd vfd) { + VTY_ASSERT_LOCKED() ; + if (vfd == NULL) - return ; + return NULL ; - VTY_ASSERT_LOCKED() ; - VTY_ASSERT_CLI_THREAD() ; + if (!vfd->blocking_vf) + VTY_ASSERT_CLI_THREAD() ; + + /* Close the underlying fd, if any */ + + if (vfd->fd >= 0) + close(vfd->fd) ; /* ignores errors TODO */ + + /* Clear out the vfd then free it */ if (vty_nexus) { @@ -337,11 +355,7 @@ vio_vfd_do_close(vio_vfd vfd, free_keep_b free) vfd->f.qf = qps_file_free(vfd->f.qf) ; } ; - if (vfd->mqb != NULL) - { - mqb_free(vfd->mqb) ; - vfd->mqb = NULL ; - } ; + vio_vfd_mqb_free(vfd) ; } else { @@ -362,85 +376,10 @@ vio_vfd_do_close(vio_vfd vfd, free_keep_b free) assert(vfd->mqb == NULL) ; } ; - if (vfd->fd >= 0) - close(vfd->fd) ; /* ignores errors TODO */ - - vio_timer_reset(&vfd->read_timer) ; - vio_timer_reset(&vfd->write_timer) ; - - if (free == free_it) - XFREE(MTYPE_VTY, vfd) ; -} ; - -/*------------------------------------------------------------------------------ - * Close the given vfd (if any). - * - * If there is an fd, close it. Stops any read/write waiting and releases all - * memory. - * - * NB: this can done from any thread, but if not done from the CLI thread, - * and there is a qf, a message must be sent to the CLI thread to actually - * implement: which passes the vio_vfd to the CLI thread for later - * close and destruction. - * - * The actual close has to be delayed, so that cannot open another fd - * and bang into a still active qps_file ! - * - * The message looks after freeing the vio_vfd, the qps_file and the mqb. - */ -extern vio_vfd -vio_vfd_close(vio_vfd vfd) -{ - VTY_ASSERT_LOCKED() ; + vfd->read_timer = vio_timer_reset(vfd->read_timer, free_it) ; + vfd->write_timer = vio_timer_reset(vfd->write_timer, free_it) ; - if (vfd == NULL) - return NULL ; - - if (vfd->fd < 0) - { - /* closing an inactive vio_vfd -- make sure all is quiet */ - assert(!vfd->active) ; - if (vty_nexus) - { - assert(vfd->f.qf == NULL) ; - } - else - { - assert(vfd->f.thread.read == NULL) ; - assert(vfd->f.thread.write == NULL) ; - } ; - assert(vfd->mqb == NULL) ; - } - else - { - /* closing an active vio_vfd */ - if (vty_is_cli_thread()) - { - /* In cli thread, so close directly */ - vio_vfd_do_close(vfd, free_it) ; - } - else - { - /* Rats... have to send message to cli thread to close */ - struct vio_io_set_args* args = vio_vfd_mqb_args(vfd) ; - - args->close = true ; - - /* in case something goes ready before the close message - * is processed, squelch. - */ - vfd->active = false ; - vfd->read_action = NULL ; - vfd->write_action = NULL ; - vfd->action_info = NULL ; - - vio_timer_squelch(&vfd->read_timer) ; - vio_timer_squelch(&vfd->write_timer) ; - - assert(vfd == mqb_get_arg0(vfd->mqb)) ; - vio_vfd_mqb_dispatch(vfd) ; - } ; - } ; + XFREE(MTYPE_VTY, vfd) ; return NULL ; } ; @@ -448,48 +387,39 @@ vio_vfd_close(vio_vfd vfd) /*------------------------------------------------------------------------------ * Set or unset read ready state on given vio_vfd (if any) if it is active. * + * Do nothing if vfd NULL, fd < 0 or not a read type of fd. + * * If setting read_on, starts any read timeout timer (or stops it if 0). * If setting read off, stops any read timeout timer. * * NB: this can done from any thread, but if not done from the CLI thread, * a message must be sent to the CLI thread to actually implement. + * + * NB: must NOT be a "blocking_vf" !! */ extern on_off_b vio_vfd_set_read(vio_vfd vfd, on_off_b on, vty_timer_time timeout) { - struct vio_io_set_args* args ; - VTY_ASSERT_LOCKED() ; - if ((vfd == NULL) || (!vfd->active)) + if ((vfd == NULL) || (vfd->fd < 0) || ((vfd->io_type & vfd_io_read) == 0)) return off ; + assert(!vfd->blocking_vf) ; + if (vty_is_cli_thread()) { /* In the cli thread (effectively) so do things directly. */ - if (vfd->mqb != NULL) - { - /* discard/override any pending message setting */ - args = mqb_get_args(vfd->mqb) ; - args->readable = false ; - } ; + vfd->read_req.set = false ; /* doing or overriding request */ if (on) { assert(vfd->read_action != NULL) ; if (vty_nexus) - { - if (vfd->f.qf == NULL) - { - vfd->f.qf = qps_file_init_new(NULL, NULL); - qps_add_file(vty_cli_nexus->selection, vfd->f.qf, - vfd->fd, vfd) ; - } ; qps_enable_mode(vfd->f.qf, qps_read_mnum, vio_vfd_qps_read_action) ; - } else { if (vfd->f.thread.read == NULL) @@ -497,34 +427,31 @@ vio_vfd_set_read(vio_vfd vfd, on_off_b on, vty_timer_time timeout) vio_vfd_thread_read_action, vfd, vfd->fd) ; } ; - vio_timer_set(&vfd->read_timer, timeout) ; + vio_timer_set(vfd->read_timer, timeout) ; } else { if (vty_nexus) - { - if (vfd->f.qf != NULL) - qps_disable_modes(vfd->f.qf, qps_read_mbit) ; - } + qps_disable_modes(vfd->f.qf, qps_read_mbit) ; else { if (vfd->f.thread.read != NULL) thread_cancel (vfd->f.thread.read) ; } ; - vio_timer_unset(&vfd->read_timer) ; + vio_timer_unset(vfd->read_timer) ; } ; } else { /* In other threads, must send message to cli thread */ + vfd->read_req.set = true ; + vfd->read_req.on = on ; + vfd->read_req.timeout = timeout ; + + vio_timer_squelch(vfd->read_timer) ; - args = vio_vfd_mqb_args(vfd) ; - args->readable = true ; - args->read_on = on ; - args->read_timeout = timeout ; - vio_timer_squelch(&vfd->read_timer) ; - vio_vfd_mqb_dispatch(vfd) ; + vio_vfd_mqb_kick(vfd) ; } ; return on ; @@ -533,48 +460,39 @@ vio_vfd_set_read(vio_vfd vfd, on_off_b on, vty_timer_time timeout) /*------------------------------------------------------------------------------ * Set or unset write ready state on given vio_vfd (if any) if it is active. * + * Do nothing if vfd NULL, fd < 0 or not a write type of fd. + * * If setting write_on, starts any write timeout timer. * If setting write off, stops any write timeout timer. * * NB: this can done from any thread, but if not done from the CLI thread, * a message must be sent to the CLI thread to actually implement. + * + * NB: must NOT be a "blocking_vf" !! */ extern on_off_b vio_vfd_set_write(vio_vfd vfd, on_off_b on, vty_timer_time timeout) { - struct vio_io_set_args* args ; - VTY_ASSERT_LOCKED() ; - if ((vfd == NULL) || (!vfd->active)) + if ((vfd == NULL) || (vfd->fd < 0) || ((vfd->io_type & vfd_io_write) == 0)) return off ; + assert(!vfd->blocking_vf) ; + if (vty_is_cli_thread()) { /* In the cli thread (effectively) so do things directly. */ - if (vfd->mqb != NULL) - { - /* discard/override any pending message setting */ - args = mqb_get_args(vfd->mqb) ; - args->writable = false ; - } ; + vfd->write_req.set = false ; /* doing or overriding request */ if (on) { assert(vfd->write_action != NULL) ; if (vty_nexus) - { - if (vfd->f.qf == NULL) - { - vfd->f.qf = qps_file_init_new(NULL, NULL); - qps_add_file(vty_cli_nexus->selection, vfd->f.qf, - vfd->fd, vfd) ; - } ; - qps_enable_mode(vfd->f.qf, qps_write_mnum, + qps_enable_mode(vfd->f.qf, qps_write_mnum, vio_vfd_qps_write_action) ; - } else { if (vfd->f.thread.write == NULL) @@ -582,34 +500,31 @@ vio_vfd_set_write(vio_vfd vfd, on_off_b on, vty_timer_time timeout) vio_vfd_thread_write_action, vfd, vfd->fd) ; } ; - vio_timer_set(&vfd->write_timer, timeout) ; + vio_timer_set(vfd->write_timer, timeout) ; } else { if (vty_nexus) - { - if (vfd->f.qf != NULL) - qps_disable_modes(vfd->f.qf, qps_write_mbit) ; - } + qps_disable_modes(vfd->f.qf, qps_write_mbit) ; else { if (vfd->f.thread.write != NULL) thread_cancel (vfd->f.thread.write) ; } ; - vio_timer_unset(&vfd->write_timer) ; + vio_timer_unset(vfd->write_timer) ; } ; } else { /* In other threads, must send message to cli thread */ + vfd->write_req.set = true ; + vfd->write_req.on = on ; + vfd->write_req.timeout = timeout ; + + vio_timer_squelch(vfd->write_timer) ; - args = vio_vfd_mqb_args(vfd) ; - args->writable = true ; - args->write_on = on ; - args->write_timeout = timeout ; - vio_timer_squelch(&vfd->write_timer) ; - vio_vfd_mqb_dispatch(vfd) ; + vio_vfd_mqb_kick(vfd) ; } ; return on ; @@ -619,24 +534,21 @@ vio_vfd_set_write(vio_vfd vfd, on_off_b on, vty_timer_time timeout) * Callback -- qnexus: ready to read * * Clears read ready state and unsets any read timer. - * - * NB: if !vfd->active, then has been closed in another thread, but close - * message is yet to be procesed. */ static void vio_vfd_qps_read_action(qps_file qf, void* file_info) { vio_vfd vfd ; - VTY_ASSERT_CLI_THREAD() ; VTY_LOCK() ; + VTY_ASSERT_CLI_THREAD() ; vfd = file_info ; assert((vfd->fd == qf->fd) && (vfd->f.qf == qf)) ; qps_disable_modes(vfd->f.qf, qps_read_mbit) ; - vio_timer_unset(&vfd->read_timer) ; + vio_timer_unset(vfd->read_timer) ; vio_vfd_do_read_action(vfd) ; @@ -656,15 +568,15 @@ vio_vfd_thread_read_action(struct thread *thread) { vio_vfd vfd ; - VTY_ASSERT_CLI_THREAD() ; VTY_LOCK() ; + VTY_ASSERT_CLI_THREAD() ; vfd = THREAD_ARG(thread); assert(vfd->fd == THREAD_FD(thread)) ; vfd->f.thread.read = NULL ; /* implicitly */ - vio_timer_unset(&vfd->read_timer) ; + vio_timer_unset(vfd->read_timer) ; vio_vfd_do_read_action(vfd) ; @@ -685,13 +597,13 @@ vio_vfd_qps_write_action(qps_file qf, void* file_info) { vio_vfd vfd = file_info ; - VTY_ASSERT_CLI_THREAD() ; VTY_LOCK() ; + VTY_ASSERT_CLI_THREAD() ; assert((vfd->fd == qf->fd) && (vfd->f.qf == qf)) ; qps_disable_modes(vfd->f.qf, qps_write_mbit) ; - vio_timer_unset(&vfd->write_timer) ; + vio_timer_unset(vfd->write_timer) ; vio_vfd_do_write_action(vfd) ; @@ -711,11 +623,11 @@ vio_vfd_thread_write_action(struct thread *thread) { vio_vfd vfd = THREAD_ARG (thread); - VTY_ASSERT_CLI_THREAD() ; VTY_LOCK() ; + VTY_ASSERT_CLI_THREAD() ; assert(vfd->fd == THREAD_FD(thread)) ; - vio_timer_unset(&vfd->write_timer) ; + vio_timer_unset(vfd->write_timer) ; vfd->f.thread.write = NULL ; /* implicitly */ @@ -740,37 +652,42 @@ vio_vfd_thread_write_action(struct thread *thread) * which it will do when it is dequeued and actioned. */ -static void vio_vfd_set_action(mqueue_block mqb, mqb_flag_t flag) ; +static void vio_vfd_mqb_action(mqueue_block mqb, mqb_flag_t flag) ; /*------------------------------------------------------------------------------ - * Get mqb for the given vfd -- make one if required. + * Dispatch mqb, if not already active */ -static struct vio_io_set_args* -vio_vfd_mqb_args(vio_vfd vfd) +static void +vio_vfd_mqb_kick(vio_vfd vfd) { VTY_ASSERT_LOCKED() ; - if (vfd->mqb == NULL) - vfd->mqb = mqb_init_new(NULL, vio_vfd_set_action, vfd) ; + if (!vfd->queued) + { + vfd->queued = true ; + + if (vfd->mqb == NULL) + vfd->mqb = mqb_init_new(NULL, vio_vfd_mqb_action, vfd) ; - return mqb_get_args(vfd->mqb) ; + mqueue_enqueue(vty_cli_nexus->queue, vfd->mqb, mqb_priority) ; + } ; } ; /*------------------------------------------------------------------------------ - * Dispatch mqb, if not already active + * Free mqb, if exists. */ static void -vio_vfd_mqb_dispatch(vio_vfd vfd) +vio_vfd_mqb_free(vio_vfd vfd) { - struct vio_io_set_args* args = mqb_get_args(vfd->mqb) ; - VTY_ASSERT_LOCKED() ; - if (!args->active) - { - args->active = true ; - mqueue_enqueue(vty_cli_nexus->queue, vfd->mqb, mqb_ordinary) ; - } ; + if (vfd->queued) + mqb_set_arg0(vfd->mqb, NULL) ; /* mqb will suicide */ + else + mqb_free(vfd->mqb) ; /* kill now (if any) */ + + vfd->queued = false ; + vfd->mqb = NULL ; } ; /*------------------------------------------------------------------------------ @@ -783,36 +700,33 @@ vio_vfd_mqb_dispatch(vio_vfd vfd) * If the mqb is being revoked */ static void -vio_vfd_set_action(mqueue_block mqb, mqb_flag_t flag) +vio_vfd_mqb_action(mqueue_block mqb, mqb_flag_t flag) { - struct vio_io_set_args* args ; - vio_vfd vfd ; + vio_vfd vfd ; - VTY_ASSERT_CLI_THREAD() ; VTY_LOCK() ; + VTY_ASSERT_CLI_THREAD() ; - args = mqb_get_args(mqb) ; vfd = mqb_get_arg0(mqb) ; - args->active = false ; + if (vfd != NULL) + { + assert(mqb == vfd->mqb) ; + vfd->queued = false ; + } ; - if ((flag != mqb_destroy) && (!args->close)) + if ((flag != mqb_destroy) && (vfd != NULL)) { - if (args->readable) - vio_vfd_set_read(vfd, args->read_on, args->read_timeout) ; - if (args->writable) - vio_vfd_set_write(vfd, args->write_on, args->write_timeout) ; + if (vfd->read_req.set) + vio_vfd_set_read(vfd, vfd->read_req.on, vfd->read_req.timeout) ; + if (vfd->write_req.set) + vio_vfd_set_write(vfd, vfd->write_req.on, vfd->write_req.timeout) ; } else { - /* Revoke and/or close. - * - * If close can free the vfd. - * - * If just revoke (should not happen), then cannot free the vfd, because - * somewhere there can be a dangling reference. - */ - vio_vfd_do_close(vfd, args->close) ; /* frees the mqb */ + mqb_free(mqb) ; /* Suicide */ + if (vfd != NULL) + vfd->mqb = NULL ; /* make sure vfd knows */ } ; VTY_UNLOCK() ; @@ -839,8 +753,7 @@ vio_listener_new(int fd, vio_vfd_accept* accept_action) { vio_listener listener ; - VTY_ASSERT_LOCKED() ; - VTY_ASSERT_CLI_THREAD() ; + VTY_ASSERT_CLI_THREAD_LOCKED() ; listener = XCALLOC(MTYPE_VTY, sizeof(struct vio_listener)) ; /* sets the next pointer to NULL */ @@ -864,8 +777,7 @@ vio_listener_new(int fd, vio_vfd_accept* accept_action) extern void vio_listener_close(vio_listener listener) { - VTY_ASSERT_LOCKED() ; - VTY_ASSERT_CLI_THREAD() ; + VTY_ASSERT_CLI_THREAD_LOCKED() ; vio_vfd_close(listener->vfd) ; XFREE(MTYPE_VTY, listener) ; @@ -881,8 +793,7 @@ vio_accept(vio_vfd vfd, void* info) { vio_listener listener ; - VTY_ASSERT_LOCKED() ; - VTY_ASSERT_CLI_THREAD() ; + VTY_ASSERT_CLI_THREAD_LOCKED() ; listener = info ; assert(vfd == listener->vfd) ; @@ -896,7 +807,7 @@ vio_accept(vio_vfd vfd, void* info) * Timer Handling * * Provides timer primitives that work either in qnexus environment or in - * a thread environment. + * a thread environment. Timer times are seconds. * * The main difference is that thread environment timers are 'one-shot', set up * for one timing run and then destroyed. @@ -906,14 +817,17 @@ static void vio_timer_qtr_action(qtimer qtr, void* timer_info, qtime_t when) ; static int vio_timer_thread_action(struct thread *thread) ; /*------------------------------------------------------------------------------ - * Initialise vio_timer structure. Assumes is all new. - * - * This assumes the vio_timer structure is embedded in another structure. + * Allocate and/or initialise vio_timer structure. */ -extern void -vio_timer_init(vio_timer_t* timer, vio_timer_action* action, void* action_info) +extern vio_timer +vio_timer_init_new(vio_timer timer, vio_timer_action* action, void* action_info) { - memset(timer, 0, sizeof(vio_timer_t)) ; + if (timer == NULL) + timer = XCALLOC(MTYPE_VTY, sizeof(vio_timer_t)) ; + else + memset(timer, 0, sizeof(vio_timer_t)) ; + + confirm(VIO_TIMER_INIT_ZERO) ; /* active -- 0, false * squelch -- 0, false @@ -922,74 +836,88 @@ vio_timer_init(vio_timer_t* timer, vio_timer_action* action, void* action_info) timer->action = action ; timer->action_info = action_info ; + + return timer ; } ; /*------------------------------------------------------------------------------ * Set the action field for the given timer. */ extern void -vio_timer_set_action(vio_timer_t* timer, vio_timer_action* action) +vio_timer_set_action(vio_timer timer, vio_timer_action* action) { - timer->action = action ; + if (timer != NULL) + timer->action = action ; } ; /*------------------------------------------------------------------------------ * Set the info field for the given timer. */ extern void -vio_timer_set_info(vio_timer_t* timer, void* action_info) +vio_timer_set_info(vio_timer timer, void* action_info) { - timer->action_info = action_info ; + if (timer != NULL) + timer->action_info = action_info ; } ; /*------------------------------------------------------------------------------ - * Kill vio_timer -- used when closing . + * Squelch the given timer -- if it goes off, do not call the action routine, + * and leave the rimer inactive. + * + * Used when doing read/write ready from not-cli thread. */ static void -vio_timer_squelch(vio_timer_t* timer) +vio_timer_squelch(vio_timer timer) { VTY_ASSERT_LOCKED() ; - timer->squelch = true ; + if (timer != NULL) + timer->squelch = true ; } ; /*------------------------------------------------------------------------------ * Reset vio_timer structure. Stops any timer and releases all memory. - * - * This assumes the vio_timer structure is embedded in another structure. */ -extern void -vio_timer_reset(vio_timer_t* timer) +extern vio_timer +vio_timer_reset(vio_timer timer, free_keep_b free_structure) { VTY_ASSERT_LOCKED() ; - VTY_ASSERT_CLI_THREAD() ; - if (timer->t.anon != NULL) + if (timer != NULL) { - if (vty_nexus) - qtimer_free(timer->t.qtr) ; - else - thread_cancel(timer->t.thread) ; + VTY_ASSERT_CLI_THREAD() ; + + if (timer->t.anon != NULL) + { + if (vty_nexus) + qtimer_free(timer->t.qtr) ; + else + thread_cancel(timer->t.thread) ; - timer->t.anon = NULL ; + timer->t.anon = NULL ; + } ; + + timer->active = false ; + timer->squelch = false ; + + if (free_structure) + XFREE(MTYPE_VTY, timer) ; /* sets timer = NULL */ } ; - timer->active = false ; - timer->squelch = false ; + return timer ; } ; /*------------------------------------------------------------------------------ - * Set vio_timer going, with the given time. + * Set vio_timer going, with the given time (in seconds). * * If timer is running, set to new time. * * If the time == 0, stop any current timer, do not restart. */ extern void -vio_timer_set(vio_timer_t* timer, vty_timer_time time) +vio_timer_set(vio_timer timer, vty_timer_time time) { - VTY_ASSERT_LOCKED() ; - VTY_ASSERT_CLI_THREAD() ; + VTY_ASSERT_CLI_THREAD_LOCKED() ; if (time == 0) { @@ -1022,10 +950,9 @@ vio_timer_set(vio_timer_t* timer, vty_timer_time time) * Stop vio_timer, if any. */ extern void -vio_timer_unset(vio_timer_t* timer) +vio_timer_unset(vio_timer timer) { - VTY_ASSERT_LOCKED() ; - VTY_ASSERT_CLI_THREAD() ; + VTY_ASSERT_CLI_THREAD_LOCKED() ; if (timer->active) { @@ -1053,11 +980,11 @@ vio_timer_unset(vio_timer_t* timer) static void vio_timer_qtr_action(qtimer qtr, void* timer_info, qtime_t when) { - vio_timer_t* timer ; + vio_timer timer ; vty_timer_time time ; - VTY_ASSERT_CLI_THREAD() ; VTY_LOCK() ; + VTY_ASSERT_CLI_THREAD() ; timer = timer_info ; @@ -1084,11 +1011,11 @@ vio_timer_qtr_action(qtimer qtr, void* timer_info, qtime_t when) static int vio_timer_thread_action(struct thread *thread) { - vio_timer_t* timer ; + vio_timer timer ; vty_timer_time time ; - VTY_ASSERT_CLI_THREAD() ; VTY_LOCK() ; + VTY_ASSERT_CLI_THREAD() ; timer = THREAD_ARG(thread) ; timer->t.thread = NULL ; /* implicitly */ |