/* timeout tick task - calls event handlers when they expire * Event handlers may alter expiration, callback and data during operation. */ static void timeout_tick(void) { unsigned long tick = current_tick; struct timeout **p = tmo_list; struct timeout *curr; for(curr = *p; curr != NULL; curr = *(++p)) { int ticks; if(TIME_BEFORE(tick, curr->expires)) continue; /* this event has expired - call callback */ ticks = curr->callback(curr); if(ticks > 0) { curr->expires = tick + ticks; /* reload */ } else { timeout_cancel(curr); /* cancel */ } } }
bool recycle_con(g2_connection_t *w_entry, some_fd epoll_fd, int keep_it) { struct epoll_event tmp_eevent; if(!keep_it) { /* * make sure the timeouts can not fire again, * so they do not undo the epoll_ctl */ timeout_cancel(&w_entry->active_to); timeout_cancel(&w_entry->aux_to); } tmp_eevent.events = 0; tmp_eevent.data.u64 = 0; /* remove from EPoll */ if(my_epoll_ctl(epoll_fd, EPOLL_CTL_DEL, w_entry->com_socket, &tmp_eevent)) { if(ENOENT != s_errno) logg_serrno(LOGF_ERR, "removing bad socket from EPoll"); } if(!keep_it) { int ret_val; /* free the fd */ do { ret_val = my_epoll_closesocket(w_entry->com_socket); } while(ret_val && EINTR == s_errno); if(ret_val) logg_serrno(LOGF_DEBUG, "closing bad socket"); w_entry->com_socket = -1; /* free associated rescources and remove from conreg */ g2_con_clear(w_entry); atomic_dec(&server.status.act_connection_sum); /* return datastructure to FreeCons */ g2_con_ret_free(w_entry); } else mutex_unlock(&w_entry->lock); logg_develd_old("%s\n", (keep_it) ? "connection removed" : "connection recyled"); return true; }
void teardown_con(g2_connection_t *w_entry, some_fd epoll_fd) { struct epoll_event tmp_eevent; int ret_val; /* remove from conreg */ g2_conreg_remove(w_entry); /* * make sure the timeouts can not fire again, * so they do not undo the epoll_ctl */ /* * we would need to cancel both timeouts, but we may hold the timeout lock * we simply assume that it is not the aux_to */ timeout_cancel(&w_entry->aux_to); tmp_eevent.events = 0; tmp_eevent.data.u64 = 0; /* remove from EPoll */ if(my_epoll_ctl(epoll_fd, EPOLL_CTL_DEL, w_entry->com_socket, &tmp_eevent)) { if(ENOENT != s_errno) logg_serrno(LOGF_ERR, "removing bad socket from EPoll"); } /* free the fd */ do { ret_val = my_epoll_closesocket(w_entry->com_socket); } while(ret_val && EINTR == s_errno); if(ret_val) logg_serrno(LOGF_DEBUG, "closing bad socket"); w_entry->com_socket = -1; /* after the fs is free we can take another one */ atomic_dec(&server.status.act_connection_sum); /* to avoid deadlocks with timer, defer final free */ hzp_deferfree(&w_entry->hzp, w_entry, (void (*)(void *))g2_con_free_glob); }
/* cancels all currently active kinetic scrolling */ static void kinetic_force_stop(void) { timeout_cancel(&kinetic_tmo); kinetic_stats_reset(); }
static void statemachine(enum state_event ev) { static enum { st_off, st_power, st_ezport_running, st_erasing, st_programming, st_app_running, } state = st_off; static size_t program_address; static struct timeout_ctx t; if (state == st_off && ev == ev_button) { state = st_power; signal_leds(RESULT_UNKNOWN); enable_power(); timeout_add(&t, 10, timeout, NULL); } else if (state == st_power && ev == ev_reset) { state = st_ezport_running; timeout_cancel(&t); enable_spi(); check_status(); } else if (state == st_ezport_running && ev == ev_cmd_done) { /* Is chip bricked? */ if (ezport_status.fs && ezport_status.bedis) goto error; state = st_erasing; bulk_erase(); /* Datasheet 6.4.1.2 */ timeout_add(&t, 300, timeout, NULL); } else if (state == st_erasing && ev == ev_cmd_done) { /* if still running, check again */ if (ezport_status.wip) { check_status(); return; } timeout_cancel(&t); program_address = 0; state = st_programming; goto program; } else if (state == st_programming && ev == ev_cmd_done) { /* if still running, check again */ if (ezport_status.wip) { check_status(); return; } timeout_cancel(&t); /* repeat if not done */ if (program_address < (size_t)&_binary_payload_bin_size) { program: program_address = program_sector(program_address); /* Datasheet 6.4.1.2 */ timeout_add(&t, 200, timeout, NULL); return; } state = st_app_running; reset_target(); timeout_add(&t, 1000, timeout, NULL); } else if (state == st_app_running && ev == ev_led) { /** * We reset the target here, but because there is a * cap on the reset line, we never see that reset * "edge" (actually an exponential slope). * * Instead, we wait for the LED to blink. */ state = st_off; timeout_cancel(&t); signal_leds(RESULT_SUCCESS); disable_power(); } else { error: /* invalid transition */ state = st_off; timeout_cancel(&t); signal_leds(RESULT_FAIL); disable_power(); } }