From f316a84558120969d598bdc790a72904dc72e9ca Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Wed, 30 Mar 2016 15:03:26 +0200 Subject: [PATCH] posix: use ms timeouts in run loop and also in hci.c --- platform/posix/btstack_run_loop_posix.c | 134 +++++++++--------------- src/btstack_run_loop.h | 12 +-- src/hci.c | 19 +--- src/hci.h | 12 +-- 4 files changed, 53 insertions(+), 124 deletions(-) diff --git a/platform/posix/btstack_run_loop_posix.c b/platform/posix/btstack_run_loop_posix.c index 166016579..654b8547f 100644 --- a/platform/posix/btstack_run_loop_posix.c +++ b/platform/posix/btstack_run_loop_posix.c @@ -51,17 +51,18 @@ #else #include #endif + #include #include +#include static void btstack_run_loop_posix_dump_timer(void); -static int btstack_run_loop_posix_timeval_compare(struct timeval *a, struct timeval *b); -static int btstack_run_loop_posix_timer_compare(btstack_timer_source_t *a, btstack_timer_source_t *b); // the run loop static btstack_linked_list_t data_sources; static int data_sources_modified; static btstack_linked_list_t timers; +// start time. tv_usec = 0 static struct timeval init_tv; /** @@ -88,17 +89,18 @@ static int btstack_run_loop_posix_remove_data_source(btstack_data_source_t *ds){ static void btstack_run_loop_posix_add_timer(btstack_timer_source_t *ts){ btstack_linked_item_t *it; for (it = (btstack_linked_item_t *) &timers; it->next ; it = it->next){ - if ((btstack_timer_source_t *) it->next == ts){ + btstack_timer_source_t * next = (btstack_timer_source_t *) it->next; + if (next == ts){ log_error( "btstack_run_loop_timer_add error: timer to add already in list!"); return; } - if (btstack_run_loop_posix_timer_compare( (btstack_timer_source_t *) it->next, ts) > 0) { + if (next->timeout > ts->timeout) { break; } } ts->item.next = it->next; it->next = (btstack_linked_item_t *) ts; - // log_info("Added timer %x at %u\n", (int) ts, (unsigned int) ts->timeout.tv_sec); + log_debug("Added timer %p at %u\n", ts, ts->timeout); // btstack_run_loop_posix_dump_timer(); } @@ -116,7 +118,7 @@ static void btstack_run_loop_posix_dump_timer(void){ int i = 0; for (it = (btstack_linked_item_t *) timers; it ; it = it->next){ btstack_timer_source_t *ts = (btstack_timer_source_t*) it; - log_info("timer %u, timeout %u\n", i, (unsigned int) ts->timeout.tv_sec); + log_info("timer %u, timeout %u\n", i, ts->timeout); } } @@ -128,6 +130,17 @@ static void btstack_run_loop_posix_disable_data_source_callbacks(btstack_data_so ds->flags &= ~callback_types; } +/** + * @brief Queries the current time in ms since start + */ +static uint32_t btstack_run_loop_posix_get_time_ms(void){ + struct timeval tv; + gettimeofday(&tv, NULL); + uint32_t time_ms = ((tv.tv_sec - init_tv.tv_sec) * 1000) + (tv.tv_usec / 1000); + log_info("btstack_run_loop_posix_get_time_ms: %u <- %u / %u", time_ms, (int) tv.tv_sec, (int) tv.tv_usec); + return time_ms; +} + /** * Execute run_loop */ @@ -136,16 +149,16 @@ static void btstack_run_loop_posix_execute(void) { fd_set descriptors_write; btstack_timer_source_t *ts; - struct timeval current_tv; - struct timeval next_tv; - struct timeval *timeout; btstack_linked_list_iterator_t it; - + struct timeval * timeout; + struct timeval tv; + uint32_t now_ms; + while (1) { // collect FDs FD_ZERO(&descriptors_read); FD_ZERO(&descriptors_write); - int highest_fd = 0; + int highest_fd = -1; btstack_linked_list_iterator_init(&it, &data_sources); while (btstack_linked_list_iterator_has_next(&it)){ btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it); @@ -155,65 +168,57 @@ static void btstack_run_loop_posix_execute(void) { if (ds->fd > highest_fd) { highest_fd = ds->fd; } + log_debug("btstack_run_loop_execute adding fd %u for read", ds->fd); } if (ds->flags & DATA_SOURCE_CALLBACK_WRITE){ FD_SET(ds->fd, &descriptors_write); if (ds->fd > highest_fd) { highest_fd = ds->fd; } + log_debug("btstack_run_loop_execute adding fd %u for write", ds->fd); } } // get next timeout - // pre: 0 <= tv_usec < 1000000 timeout = NULL; if (timers) { - gettimeofday(¤t_tv, NULL); ts = (btstack_timer_source_t *) timers; - next_tv.tv_usec = ts->timeout.tv_usec - current_tv.tv_usec; - next_tv.tv_sec = ts->timeout.tv_sec - current_tv.tv_sec; - while (next_tv.tv_usec < 0){ - next_tv.tv_usec += 1000000; - next_tv.tv_sec--; + timeout = &tv; + now_ms = btstack_run_loop_posix_get_time_ms(); + int delta = ts->timeout - now_ms; + if (delta < 0){ + delta = 0; } - if (next_tv.tv_sec < 0){ - next_tv.tv_sec = 0; - next_tv.tv_usec = 0; - } - timeout = &next_tv; + tv.tv_sec = delta / 1000; + tv.tv_usec = (delta - (tv.tv_sec * 1000)) * 1000; + log_debug("btstack_run_loop_execute next timeout in %u ms", delta); } // wait for ready FDs select( highest_fd+1 , &descriptors_read, &descriptors_write, NULL, timeout); - - // process data sources very carefully - // bt_control.close() triggered from a client can remove a different data source - - // log_info("btstack_run_loop_posix_execute: before ds check\n"); + data_sources_modified = 0; btstack_linked_list_iterator_init(&it, &data_sources); while (btstack_linked_list_iterator_has_next(&it) && !data_sources_modified){ btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it); - // log_info("btstack_run_loop_posix_execute: check %x with fd %u\n", (int) ds, ds->fd); + log_debug("btstack_run_loop_posix_execute: check %x with fd %u\n", (int) ds, ds->fd); if (FD_ISSET(ds->fd, &descriptors_read)) { - // log_info("btstack_run_loop_posix_execute: process read %x with fd %u\n", (int) ds, ds->fd); + log_debug("btstack_run_loop_posix_execute: process read %x with fd %u\n", (int) ds, ds->fd); ds->process(ds, DATA_SOURCE_CALLBACK_READ); } if (FD_ISSET(ds->fd, &descriptors_write)) { - // log_info("btstack_run_loop_posix_execute: process write %x with fd %u\n", (int) ds, ds->fd); + log_debug("btstack_run_loop_posix_execute: process write %x with fd %u\n", (int) ds, ds->fd); ds->process(ds, DATA_SOURCE_CALLBACK_WRITE); } } - // log_info("btstack_run_loop_posix_execute: after ds check\n"); + log_debug("btstack_run_loop_posix_execute: after ds check\n"); // process timers // pre: 0 <= tv_usec < 1000000 while (timers) { - gettimeofday(¤t_tv, NULL); ts = (btstack_timer_source_t *) timers; - if (ts->timeout.tv_sec > current_tv.tv_sec) break; - if (ts->timeout.tv_sec == current_tv.tv_sec && ts->timeout.tv_usec > current_tv.tv_usec) break; - // log_info("btstack_run_loop_posix_execute: process times %x\n", (int) ts); + if (ts->timeout > now_ms) break; + log_debug("btstack_run_loop_posix_execute: process timer %p\n", ts); // remove timer before processing it to allow handler to re-register with run loop btstack_run_loop_remove_timer(ts); @@ -224,63 +229,18 @@ static void btstack_run_loop_posix_execute(void) { // set timer static void btstack_run_loop_posix_set_timer(btstack_timer_source_t *a, uint32_t timeout_in_ms){ - gettimeofday(&a->timeout, NULL); - a->timeout.tv_sec += timeout_in_ms / 1000; - a->timeout.tv_usec += (timeout_in_ms % 1000) * 1000; - if (a->timeout.tv_usec > 1000000) { - a->timeout.tv_usec -= 1000000; - a->timeout.tv_sec++; - } -} - -// compare timers - NULL is assumed to be before the Big Bang -// pre: 0 <= tv_usec < 1000000 -static int btstack_run_loop_posix_timeval_compare(struct timeval *a, struct timeval *b){ - if (!a && !b) return 0; - if (!a) return -1; - if (!b) return 1; - - if (a->tv_sec < b->tv_sec) { - return -1; - } - if (a->tv_sec > b->tv_sec) { - return 1; - } - - if (a->tv_usec < b->tv_usec) { - return -1; - } - if (a->tv_usec > b->tv_usec) { - return 1; - } - - return 0; - -} - -// compare timers - NULL is assumed to be before the Big Bang -// pre: 0 <= tv_usec < 1000000 -static int btstack_run_loop_posix_timer_compare(btstack_timer_source_t *a, btstack_timer_source_t *b){ - if (!a && !b) return 0; - if (!a) return -1; - if (!b) return 1; - return btstack_run_loop_posix_timeval_compare(&a->timeout, &b->timeout); + uint32_t time_ms = btstack_run_loop_posix_get_time_ms(); + a->timeout = time_ms + timeout_in_ms; + log_info("btstack_run_loop_posix_set_timer to %u ms (now %u, timeout %u)", a->timeout, time_ms, timeout_in_ms); } static void btstack_run_loop_posix_init(void){ data_sources = NULL; timers = NULL; + // just assume that we started at tv_usec == 0 gettimeofday(&init_tv, NULL); -} - -/** - * @brief Queries the current time in ms since start - */ -static uint32_t btstack_run_loop_posix_get_time_ms(void){ - struct timeval current_tv; - gettimeofday(¤t_tv, NULL); - return (current_tv.tv_sec - init_tv.tv_sec) * 1000 - + (current_tv.tv_usec - init_tv.tv_usec) / 1000; + init_tv.tv_usec = 0; + log_debug("btstack_run_loop_posix_init at %u/%u", (int) init_tv.tv_sec, 0); } diff --git a/src/btstack_run_loop.h b/src/btstack_run_loop.h index 210793f9c..43dd4196f 100644 --- a/src/btstack_run_loop.h +++ b/src/btstack_run_loop.h @@ -50,10 +50,6 @@ #include -#ifdef HAVE_POSIX_TIME -#include -#endif - #if defined __cplusplus extern "C" { #endif @@ -81,12 +77,8 @@ typedef struct btstack_data_source { typedef struct btstack_timer_source { btstack_linked_item_t item; -#ifdef HAVE_POSIX_TIME - struct timeval timeout; // <-- next timeout -#endif -#if defined(HAVE_EMBEDDED_TICK) || defined(HAVE_EMBEDDED_TIME_MS) - uint32_t timeout; // timeout in system ticks (HAVE_EMBEDDED_TICK) or millis (HAVE_EMBEDDED_TIME_MS) -#endif + // timeout in system ticks (HAVE_EMBEDDED_TICK) or milliseconds (HAVE_EMBEDDED_TIME_MS) + uint32_t timeout; // will be called when timer fired void (*process)(struct btstack_timer_source *ts); void * context; diff --git a/src/hci.c b/src/hci.c index 7f07684aa..2a8787708 100644 --- a/src/hci.c +++ b/src/hci.c @@ -207,38 +207,23 @@ hci_connection_t * hci_connection_for_bd_addr_and_type(bd_addr_t addr, bd_addr_ static void hci_connection_timeout_handler(btstack_timer_source_t *timer){ hci_connection_t * connection = (hci_connection_t *) btstack_run_loop_get_timer_context(timer); -#ifdef HAVE_POSIX_TIME - struct timeval tv; - gettimeofday(&tv, NULL); - if (tv.tv_sec >= connection->timestamp.tv_sec + HCI_CONNECTION_TIMEOUT_MS/1000) { - // connections might be timed out - hci_emit_l2cap_check_timeout(connection); - } -#endif #ifdef HAVE_EMBEDDED_TICK if (btstack_run_loop_embedded_get_ticks() > connection->timestamp + btstack_run_loop_embedded_ticks_for_ms(HCI_CONNECTION_TIMEOUT_MS)){ // connections might be timed out hci_emit_l2cap_check_timeout(connection); } -#endif -#ifdef HAVE_EMBEDDED_TIME_MS +#else if (btstack_run_loop_get_time_ms() > connection->timestamp + HCI_CONNECTION_TIMEOUT_MS){ // connections might be timed out hci_emit_l2cap_check_timeout(connection); } #endif - btstack_run_loop_set_timer(timer, HCI_CONNECTION_TIMEOUT_MS); - btstack_run_loop_add_timer(timer); } static void hci_connection_timestamp(hci_connection_t *connection){ -#ifdef HAVE_POSIX_TIME - gettimeofday(&connection->timestamp, NULL); -#endif #ifdef HAVE_EMBEDDED_TICK connection->timestamp = btstack_run_loop_embedded_get_ticks(); -#endif -#ifdef HAVE_EMBEDDED_TIME_MS +#else connection->timestamp = btstack_run_loop_get_time_ms(); #endif } diff --git a/src/hci.h b/src/hci.h index fa71ea954..44a40ccb7 100644 --- a/src/hci.h +++ b/src/hci.h @@ -386,16 +386,8 @@ typedef struct { btstack_timer_source_t timeout; -#ifdef HAVE_POSIX_TIME - // timer - struct timeval timestamp; -#endif -#ifdef HAVE_EMBEDDED_TICK - uint32_t timestamp; // timestamp in system ticks -#endif -#ifdef HAVE_EMBEDDED_TIME_MS - uint32_t timestamp; // timestamp in ms -#endif + // timeout in system ticks (HAVE_EMBEDDED_TICK) or milliseconds (HAVE_EMBEDDED_TIME_MS) + uint32_t timestamp; // ACL packet recombination - PRE_BUFFER + ACL Header + ACL payload uint8_t acl_recombination_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + 4 + HCI_ACL_BUFFER_SIZE];