int add_timer_file(tymer_t *db, FILE *fp) { int ret = -1; char *line; timer_data_t data; while((line = read_line(fp))){ if(read_timer_line(&data, line)){ if(!is_countdn){ int i; for(i = 0; i < 3 && strcmp(line, timer_at_end[i]); i++); if(i < 3){ set_timer_at_end(i); update_timer_at_end(db); } } free(line); continue; } if(find_timer(db, &data) < 0){ add_timer(db, &data); ret = 0; } free(line); } return ret; }
static int pthread_timer_set_rate(int handle, unsigned int rate) { struct pthread_timer *timer; if (!(timer = find_timer(handle, 0))) { errno = EINVAL; return -1; } if (rate > MAX_RATE) { ast_log(LOG_ERROR, "res_timing_pthread only supports timers at a " "max rate of %d / sec\n", MAX_RATE); errno = EINVAL; return -1; } ao2_lock(timer); if ((timer->rate = rate)) { timer->interval = roundf(1000.0 / ((float) rate)); timer->start = ast_tvnow(); timer->state = TIMER_STATE_TICKING; } else { timer->interval = 0; timer->start = ast_tv(0, 0); timer->state = TIMER_STATE_IDLE; } timer->tick_count = 0; ao2_unlock(timer); ao2_ref(timer, -1); return 0; }
static int pthread_timer_disable_continuous(int handle) { struct pthread_timer *timer; if (!(timer = find_timer(handle, 0))) { errno = EINVAL; return -1; } ao2_lock(timer); if (timer->continuous) { timer->continuous = 0; if (read_pipe(timer, 1) != 0) { /* Let the errno from read_pipe propagate up */ ao2_unlock(timer); ao2_ref(timer, -1); return -1; } } ao2_unlock(timer); ao2_ref(timer, -1); return 0; }
static void pthread_timer_close(int handle) { struct pthread_timer *timer; if (!(timer = find_timer(handle, 1))) { return; } ao2_ref(timer, -1); }
/* Remove timer from the timer chain. */ STATICFNDEF void remove_timer(TID tid) { GT_TIMER *tprev, *tp, *tpp; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; if (tp = find_timer(tid, &tprev)) { if (tprev) tprev->next = tp->next; else timeroot = tp->next; if (tp->safe) safe_timer_cnt--; tp->next = (GT_TIMER *)timefree; /* place element on free queue */ timefree = tp; num_timers_free++; assert(0 < num_timers_free); /* assert that no duplicate timer entry with the same "tid" exists in the timer chain */ assert((NULL == find_timer(tid, &tpp))); } }
static void pthread_timer_ack(int handle, unsigned int quantity) { struct pthread_timer *timer; ast_assert(quantity > 0); if (!(timer = find_timer(handle, 0))) { return; } ao2_lock(timer); read_pipe(timer, quantity); ao2_unlock(timer); ao2_ref(timer, -1); }
// Add a callback timer to the list. bool set_timer( swTimer_t* t, int tag, int ticks, timerCallback callback, bool fPeriodic ) { if ( callback == NULL ) { return false; } // dont add if callback appears in the list if ( find_timer( callback, tag ) != NULL ) { return false; } t->callback = callback; t->tag = tag; t->timeout = ticks; t->fperiodic = fPeriodic; t->timeoutReload = ticks; return add_timer( t ); }
static enum ast_timer_event pthread_timer_get_event(int handle) { struct pthread_timer *timer; enum ast_timer_event res = AST_TIMING_EVENT_EXPIRED; if (!(timer = find_timer(handle, 0))) { return res; } ao2_lock(timer); if (timer->continuous && timer->pending_ticks == 1) { res = AST_TIMING_EVENT_CONTINUOUS; } ao2_unlock(timer); ao2_ref(timer, -1); return res; }
int del_timer_file(tymer_t *db, FILE *fp) { int ret = -1, i; char *line; timer_data_t data; while((line = read_line(fp))){ if(read_timer_line(&data, line)){ free(line); continue; } if((i = find_timer(db, &data)) >= 0 && !del_timer(db, i)) ret = 0; free(line); } return ret; }
/* * Return true if packet has been acknowledged (its timer is not running) */ bool packetACKd(struct packet* pckt) { bool retval = false; pthread_mutex_lock(&timers_mutex); // find timer struct packet_timer* timer; if((timer = find_timer(timer_list, pckt->header.ackno)) != NULL) { if(timer->running == false && timer->time_sent != -1) retval = true; } else { printf("Cannot check if packet %d is ACK'd\n",pckt->header.seqno); exit(-1); } pthread_mutex_unlock(&timers_mutex); return retval; }
static int pthread_timer_disable_continuous(int handle) { struct pthread_timer *timer; if (!(timer = find_timer(handle, 0))) { errno = EINVAL; return -1; } ao2_lock(timer); if (timer->continuous) { timer->continuous = 0; read_pipe(timer, 1); } ao2_unlock(timer); ao2_ref(timer, -1); return 0; }
int main(int argc, char *argv[]) { int ret = 1, istty, i, idx; char *msg = NULL, *timer = NULL, *at_end = NULL, *halfway = NULL; dldev_t dev; tymer_t db; u8 *data; u16 len; /* for data security */ /* umask(S_IRWXG | S_IRWXO); */ istty = isatty(0); i = strlen(argv[0]) - 1; for(; i >= 0 && argv[0][i] != '/'; i--); i++; if(strstr(argv[0] + i, "interval")){ set_timer(POR_INTERVAL); is_countdn = 0; } while((i = getopt(argc, argv, "hd:")) != -1){ switch(i){ case 'd': dev_file = optarg; break; case 'h': default: usage(); break; } } argc -= optind; argv += optind; #ifdef USB_USBHID dev.usb.file = dev_file; #endif BEGIN_OPT() OPT("msg", msg) OPT("timer", timer) OPT("at_end", at_end) OPT("halfway", halfway) END_OPT() /* allows the user to change only at_end in interval timer */ if(istty && ((!msg || !timer) && (is_countdn || !at_end))) usage(); if(open_dev(&dev)){ ERROR("open_dev"); goto exit; } if(start_session(&dev)){ ERROR("read_app_info"); goto exit; } /******************************************************************************/ #ifdef DEBUG for(i = 0; i < NUM_APPS; i++){ if(!dev.app[i].acd.app_idx) continue; printf("%2d: %d%d%d%d%d%d%d%d %02x %02x %04x %04x %04x %04x %04x %04x %s\n", i, dev.app[i].acd.app_idx, dev.app[i].acd.code_loc, dev.app[i].acd.db_loc, dev.app[i].acd.code_invalid, dev.app[i].acd.db_modified, dev.app[i].acd.db_invalid, dev.app[i].acd.passwd_req, dev.app[i].acd.mode_name, dev.app[i].acb.app_type, dev.app[i].acb.app_inst, dev.app[i].acb.asd_addr, dev.app[i].acb.add_addr, dev.app[i].acb.state_mgr_addr, dev.app[i].acb.refresh_addr, dev.app[i].acb.banner_addr, dev.app[i].acb.code_addr, dev.app[i].banner ); } #endif /******************************************************************************/ if((idx = find_app(&dev, uapp_name)) < 0){ ERROR("%s application not found", uapp_name); goto end; } if(dump_add(&dev, idx, &data, &len)){ ERROR("dump_add"); goto end; } read_timer(&db, data); free(data); if(!istty) add_timer_file(&db, stdin); if(msg && timer){ char buf[BUFSIZ]; timer_data_t rec; sprintf(buf, "%s\t%s\t%s%s", msg, timer, (at_end ? at_end : "stop"), (halfway && strcmp(halfway, "no") ? "\thalfway" : "")); if(read_timer_line(&rec, buf)) fprintf(stderr, "add_%s: format error!\n", lapp_name); else if(find_timer(&db, &rec) < 0) add_timer(&db, &rec); } if(!is_countdn && at_end){ int i; for(i = 0; i < 3 && strcmp(at_end, timer_at_end[i]); i++); if(i < 3){ set_timer_at_end(i); update_timer_at_end(&db); } } create_timer(&db, &data, &len); if(load_add(&dev, idx, data)){ ERROR("load_add"); goto end; } free(data); print_timer(&db, stdout); free_timer(&db); /******************************************************************************/ end: if(end_session(&dev)){ ERROR("end_session"); goto exit; } ret = 0; exit: close_dev(&dev); exit(ret); }
/* Add timer to timer chain. Allocate a new link for a timer. Convert time to expiration into absolute time. * Insert new link into chain in timer order. * Arguments: tid - timer id * time_to_expir - elapsed time to expiration * handler - pointer to handler routine * hdata_len - length of data to follow * hdata - data to pass to timer rtn if any */ STATICFNDEF void add_timer(ABS_TIME *atp, TID tid, int4 time_to_expir, void (*handler)(), int4 hdata_len, void *hdata) { GT_TIMER *tp, *tpp, *ntp, *lastntp; int4 cmp, i; st_timer_alloc *new_alloc; boolean_t safe_to_add = FALSE; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; /* assert that no timer entry with the same "tid" exists in the timer chain */ assert(NULL == find_timer(tid, &tpp)); /* obtain a new timer block */ ntp = (GT_TIMER *)timefree; lastntp = NULL; for ( ; NULL != ntp; ) { /* we expect all callers of timer functions to not require more than 8 bytes of data; any violations * of this assumption need to be caught---hence the assert below */ assert(GT_TIMER_INIT_DATA_LEN == ntp->hd_len_max); assert(ntp->hd_len_max >= hdata_len); if (ntp->hd_len_max >= hdata_len) /* found one that can hold our data */ { /* dequeue block */ if (NULL == lastntp) /* first one on queue */ timefree = ntp->next; /* dequeue 1st element */ else /* is not 1st on queue -- use simple dequeue */ lastntp->next = ntp->next; assert(0 < num_timers_free); num_timers_free--; break; } lastntp = ntp; /* still looking, try next block */ ntp = ntp->next; } /* if didn't find one, fail if dbg; else malloc a new one */ if (NULL == ntp) { assert(FALSE); /* if dbg, we should have enough already */ ntp = (GT_TIMER *)malloc(timeblk_hdrlen + hdata_len); /* if we are in a timer, malloc may error out */ new_alloc = (st_timer_alloc *)malloc(SIZEOF(st_timer_alloc)); /* insert in front of the list */ new_alloc->addr = ntp; new_alloc->next = (st_timer_alloc *)timer_allocs; timer_allocs = new_alloc; ntp->hd_len_max = hdata_len; } ntp->tid = tid; ntp->handler = handler; ntp->safe = FALSE; if (NULL == handler) { ntp->safe = TRUE; safe_timer_cnt++; assert(0 < safe_timer_cnt); } else { for (i = 0; NULL != safe_handlers[i]; i++) if (safe_handlers[i] == handler) { ntp->safe = TRUE; /* known to just set flags, etc. */ safe_timer_cnt++; break; } } if (ntp->safe || (wcs_clean_dbsync_fptr == handler) || (wcs_stale_fptr == handler)) safe_to_add = TRUE; if ((INTRPT_OK_TO_INTERRUPT != intrpt_ok_state) && !safe_to_add) GTMASSERT; if (process_exiting && !safe_to_add) GTMASSERT; ntp->hd_len = hdata_len; if (0 < hdata_len) memcpy(ntp->hd_data, hdata, hdata_len); add_int_to_abs_time(atp, time_to_expir, &ntp->expir_time); ntp->start_time.at_sec = atp->at_sec; ntp->start_time.at_usec = atp->at_usec; tp = (GT_TIMER *)timeroot; tpp = NULL; while (tp) { cmp = abs_time_comp(&tp->expir_time, &ntp->expir_time); if (cmp >= 0) break; tpp = tp; tp = tp->next; } ntp->next = tp; if (NULL == tpp) timeroot = ntp; else tpp->next = ntp; return; }
/* Timer handler. This is the main handler routine that is being called by the kernel upon receipt * of timer signal. It dispatches to the user handler routine, and removes first timer in a timer * queue. If the queue is not empty, it starts the first timer in the queue. The why parameter is a * no-op in our case, but is required to maintain compatibility with the system type of __sighandler_t, * which is (void*)(int). */ STATICFNDEF void timer_handler(int why) { int4 cmp; GT_TIMER *tpop, *tpop_prev = NULL; ABS_TIME at; sigset_t savemask; int save_errno, timer_defer_cnt, offset; TID *deferred_tid; boolean_t tid_found; char *save_util_outptr; va_list save_last_va_list_ptr; boolean_t util_copy_saved = FALSE; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; # ifdef DEBUG if (IS_GTM_IMAGE) { tpop = find_timer((TID)heartbeat_timer_ptr, &tpop); assert(process_exiting || (((NULL != tpop) && heartbeat_started) || ((NULL == tpop) && !heartbeat_started))); } # endif if (0 < timer_stack_count) return; timer_stack_count++; deferred_timers_check_needed = FALSE; save_errno = errno; timer_active = FALSE; /* timer has popped; system timer not active anymore */ sys_get_curr_time(&at); tpop = (GT_TIMER *)timeroot; timer_defer_cnt = 0; /* reset the deferred timer count, since we are in timer_handler */ SAVE_UTIL_OUT_BUFFER(save_util_outptr, save_last_va_list_ptr, util_copy_saved); while (tpop) /* fire all handlers that expired */ { cmp = abs_time_comp(&at, (ABS_TIME *)&tpop->expir_time); if (cmp < 0) break; /* A timer might pop while we are in the non-zero intrpt_ok_state zone, which could cause collisions. Instead, * we will defer timer events and drive them once the deferral is removed, unless the timer is safe. */ if ((INTRPT_OK_TO_INTERRUPT == intrpt_ok_state) && (FALSE == process_exiting) || tpop->safe) { if (NULL != tpop_prev) tpop_prev->next = tpop->next; else timeroot = tpop->next; if (tpop->safe) { safe_timer_cnt--; assert(0 <= safe_timer_cnt); } if (NULL != tpop->handler) /* if there is a handler, call it */ { # ifdef DEBUG if (gtm_white_box_test_case_enabled && (WBTEST_DEFERRED_TIMERS == gtm_white_box_test_case_number) && ((void *)tpop->handler != (void*)heartbeat_timer_ptr)) { DBGFPF((stderr, "TIMER_HANDLER: handled a timer\n")); timer_pop_cnt++; } # endif timer_in_handler = TRUE; (*tpop->handler)(tpop->tid, tpop->hd_len, tpop->hd_data); timer_in_handler = FALSE; if (!tpop->safe) /* if safe, avoid a system call */ sys_get_curr_time(&at); /* refresh current time if called a handler */ } tpop->next = (GT_TIMER *)timefree; /* put timer block on the free chain */ timefree = tpop; if (NULL != tpop_prev) tpop = tpop_prev->next; else tpop = (GT_TIMER *)timeroot; num_timers_free++; assert(0 < num_timers_free); } else { timer_defer_cnt++; # ifdef DEBUG if (gtm_white_box_test_case_enabled && (WBTEST_DEFERRED_TIMERS == gtm_white_box_test_case_number)) { if (!deferred_tids) { deferred_tids = (TID *)malloc(SIZEOF(TID) * 2); *deferred_tids = tpop->tid; *(deferred_tids + 1) = -1; DBGFPF((stderr, "TIMER_HANDLER: deferred a timer\n")); } else { tid_found = FALSE; deferred_tid = deferred_tids; while (-1 != *deferred_tid) { if (*deferred_tid == tpop->tid) { tid_found = TRUE; break; } deferred_tid++; } if (!tid_found) { offset = deferred_tid - deferred_tids; deferred_tid = (TID *)malloc((offset + 2) * SIZEOF(TID)); memcpy(deferred_tid, deferred_tids, offset * SIZEOF(TID)); free(deferred_tids); deferred_tids = deferred_tid; *(deferred_tids + offset++) = tpop->tid; *(deferred_tids + offset) = -1; DBGFPF((stderr, "TIMER_HANDLER: deferred a timer\n")); } } } # endif tpop_prev = tpop; tpop = tpop->next; if (0 == safe_timer_cnt) /* no more safe timers left, so quit */ break; } } RESTORE_UTIL_OUT_BUFFER(save_util_outptr, save_last_va_list_ptr, util_copy_saved); if (((FALSE == process_exiting) && (INTRPT_OK_TO_INTERRUPT == intrpt_ok_state)) || (0 < safe_timer_cnt)) start_first_timer(&at); else if ((NULL != timeroot) || (0 < timer_defer_cnt)) deferred_timers_check_needed = TRUE; errno = save_errno; /* restore mainline errno */ timer_stack_count--; }