xref: /btstack/platform/posix/btstack_run_loop_posix.c (revision ff3cc4a5378c2f681cc9b75cf54d154a12a3051e)
1b7d596c1SMatthias Ringwald /*
2b7d596c1SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3b7d596c1SMatthias Ringwald  *
4b7d596c1SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5b7d596c1SMatthias Ringwald  * modification, are permitted provided that the following conditions
6b7d596c1SMatthias Ringwald  * are met:
7b7d596c1SMatthias Ringwald  *
8b7d596c1SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9b7d596c1SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10b7d596c1SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11b7d596c1SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12b7d596c1SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13b7d596c1SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14b7d596c1SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15b7d596c1SMatthias Ringwald  *    from this software without specific prior written permission.
16b7d596c1SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17b7d596c1SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18b7d596c1SMatthias Ringwald  *    monetary gain.
19b7d596c1SMatthias Ringwald  *
20b7d596c1SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21b7d596c1SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22b7d596c1SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23b7d596c1SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24b7d596c1SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25b7d596c1SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26b7d596c1SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27b7d596c1SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28b7d596c1SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29b7d596c1SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30b7d596c1SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b7d596c1SMatthias Ringwald  * SUCH DAMAGE.
32b7d596c1SMatthias Ringwald  *
33b7d596c1SMatthias Ringwald  * Please inquire about commercial licensing options at
34b7d596c1SMatthias Ringwald  * [email protected]
35b7d596c1SMatthias Ringwald  *
36b7d596c1SMatthias Ringwald  */
37b7d596c1SMatthias Ringwald 
38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_run_loop_posix.c"
39ab2c6ae4SMatthias Ringwald 
40b7d596c1SMatthias Ringwald /*
414ab92137SMatthias Ringwald  *  btstack_run_loop.c
42b7d596c1SMatthias Ringwald  *
43b7d596c1SMatthias Ringwald  *  Created by Matthias Ringwald on 6/6/09.
44b7d596c1SMatthias Ringwald  */
45b7d596c1SMatthias Ringwald 
4692b78dd7SMatthias Ringwald // enable POSIX functions (needed for -std=c99)
4792b78dd7SMatthias Ringwald #define _POSIX_C_SOURCE 200809
4892b78dd7SMatthias Ringwald 
498f2a52f4SMatthias Ringwald #include "btstack_run_loop_posix.h"
50b6fc147fSMatthias Ringwald 
51b6fc147fSMatthias Ringwald #include "btstack_run_loop.h"
52b6fc147fSMatthias Ringwald #include "btstack_util.h"
53b7d596c1SMatthias Ringwald #include "btstack_linked_list.h"
54b7d596c1SMatthias Ringwald #include "btstack_debug.h"
55b7d596c1SMatthias Ringwald 
56b7d596c1SMatthias Ringwald #include <stdio.h>
57b7d596c1SMatthias Ringwald #include <stdlib.h>
58b6fc147fSMatthias Ringwald #include <sys/select.h>
59f316a845SMatthias Ringwald #include <sys/time.h>
6092b78dd7SMatthias Ringwald #include <time.h>
6192b78dd7SMatthias Ringwald #include <unistd.h>
62b7d596c1SMatthias Ringwald 
63528a4a3bSMatthias Ringwald static void btstack_run_loop_posix_dump_timer(void);
64b7d596c1SMatthias Ringwald 
65b7d596c1SMatthias Ringwald // the run loop
668f2a52f4SMatthias Ringwald static btstack_linked_list_t data_sources;
67b7d596c1SMatthias Ringwald static int data_sources_modified;
688f2a52f4SMatthias Ringwald static btstack_linked_list_t timers;
6992b78dd7SMatthias Ringwald 
7092b78dd7SMatthias Ringwald // start time. tv_usec/tv_nsec = 0
7192b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK
7292b78dd7SMatthias Ringwald // use monotonic clock if available
7392b78dd7SMatthias Ringwald static struct timespec init_ts;
7492b78dd7SMatthias Ringwald #else
7592b78dd7SMatthias Ringwald // fallback to gettimeofday
76b7d596c1SMatthias Ringwald static struct timeval init_tv;
7792b78dd7SMatthias Ringwald #endif
78b7d596c1SMatthias Ringwald 
79b7d596c1SMatthias Ringwald /**
80b7d596c1SMatthias Ringwald  * Add data_source to run_loop
81b7d596c1SMatthias Ringwald  */
82ec820d77SMatthias Ringwald static void btstack_run_loop_posix_add_data_source(btstack_data_source_t *ds){
83b7d596c1SMatthias Ringwald     data_sources_modified = 1;
84398a95ecSMatthias Ringwald     // log_info("btstack_run_loop_posix_add_data_source %x with fd %u\n", (int) ds, ds->source.fd);
85b7d596c1SMatthias Ringwald     btstack_linked_list_add(&data_sources, (btstack_linked_item_t *) ds);
86b7d596c1SMatthias Ringwald }
87b7d596c1SMatthias Ringwald 
88b7d596c1SMatthias Ringwald /**
89b7d596c1SMatthias Ringwald  * Remove data_source from run loop
90b7d596c1SMatthias Ringwald  */
91d58a1b5fSMatthias Ringwald static bool btstack_run_loop_posix_remove_data_source(btstack_data_source_t *ds){
92b7d596c1SMatthias Ringwald     data_sources_modified = 1;
93bd539f2bSMatthias Ringwald     log_debug("btstack_run_loop_posix_remove_data_source %p\n", ds);
94b7d596c1SMatthias Ringwald     return btstack_linked_list_remove(&data_sources, (btstack_linked_item_t *) ds);
95b7d596c1SMatthias Ringwald }
96b7d596c1SMatthias Ringwald 
97b7d596c1SMatthias Ringwald /**
98b7d596c1SMatthias Ringwald  * Add timer to run_loop (keep list sorted)
99b7d596c1SMatthias Ringwald  */
100ec820d77SMatthias Ringwald static void btstack_run_loop_posix_add_timer(btstack_timer_source_t *ts){
101b7d596c1SMatthias Ringwald     btstack_linked_item_t *it;
102b7d596c1SMatthias Ringwald     for (it = (btstack_linked_item_t *) &timers; it->next ; it = it->next){
103f316a845SMatthias Ringwald         btstack_timer_source_t * next = (btstack_timer_source_t *) it->next;
104160fcf34SMatthias Ringwald         btstack_assert(next != ts);
105b6fc147fSMatthias Ringwald         // exit if new timeout before list timeout
106b6fc147fSMatthias Ringwald         int32_t delta = btstack_time_delta(ts->timeout, next->timeout);
107b6fc147fSMatthias Ringwald         if (delta < 0) break;
108b7d596c1SMatthias Ringwald     }
109b7d596c1SMatthias Ringwald     ts->item.next = it->next;
110b7d596c1SMatthias Ringwald     it->next = (btstack_linked_item_t *) ts;
111f316a845SMatthias Ringwald     log_debug("Added timer %p at %u\n", ts, ts->timeout);
112528a4a3bSMatthias Ringwald     // btstack_run_loop_posix_dump_timer();
113b7d596c1SMatthias Ringwald }
114b7d596c1SMatthias Ringwald 
115b7d596c1SMatthias Ringwald /**
116b7d596c1SMatthias Ringwald  * Remove timer from run loop
117b7d596c1SMatthias Ringwald  */
118d58a1b5fSMatthias Ringwald static bool btstack_run_loop_posix_remove_timer(btstack_timer_source_t *ts){
119b7d596c1SMatthias Ringwald     // log_info("Removed timer %x at %u\n", (int) ts, (unsigned int) ts->timeout.tv_sec);
120528a4a3bSMatthias Ringwald     // btstack_run_loop_posix_dump_timer();
121b7d596c1SMatthias Ringwald     return btstack_linked_list_remove(&timers, (btstack_linked_item_t *) ts);
122b7d596c1SMatthias Ringwald }
123b7d596c1SMatthias Ringwald 
124528a4a3bSMatthias Ringwald static void btstack_run_loop_posix_dump_timer(void){
125b7d596c1SMatthias Ringwald     btstack_linked_item_t *it;
126b7d596c1SMatthias Ringwald     int i = 0;
127b7d596c1SMatthias Ringwald     for (it = (btstack_linked_item_t *) timers; it ; it = it->next){
128ec820d77SMatthias Ringwald         btstack_timer_source_t *ts = (btstack_timer_source_t*) it;
129bd539f2bSMatthias Ringwald         log_info("timer %u (%p): timeout %u\n", i, ts, ts->timeout);
130b7d596c1SMatthias Ringwald     }
131b7d596c1SMatthias Ringwald }
132b7d596c1SMatthias Ringwald 
1339120e843SMatthias Ringwald static void btstack_run_loop_posix_enable_data_source_callbacks(btstack_data_source_t * ds, uint16_t callback_types){
1349120e843SMatthias Ringwald     ds->flags |= callback_types;
1359120e843SMatthias Ringwald }
1369120e843SMatthias Ringwald 
1379120e843SMatthias Ringwald static void btstack_run_loop_posix_disable_data_source_callbacks(btstack_data_source_t * ds, uint16_t callback_types){
1389120e843SMatthias Ringwald     ds->flags &= ~callback_types;
1399120e843SMatthias Ringwald }
1409120e843SMatthias Ringwald 
14192b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK
14292b78dd7SMatthias Ringwald /**
14392b78dd7SMatthias Ringwald  * @brief Returns the timespec which represents the time(stop - start). It might be negative
14492b78dd7SMatthias Ringwald  */
14592b78dd7SMatthias Ringwald static void timespec_diff(struct timespec *start, struct timespec *stop, struct timespec *result){
14692b78dd7SMatthias Ringwald     result->tv_sec = stop->tv_sec - start->tv_sec;
14792b78dd7SMatthias Ringwald     if ((stop->tv_nsec - start->tv_nsec) < 0) {
14892b78dd7SMatthias Ringwald         result->tv_sec = stop->tv_sec - start->tv_sec - 1;
14992b78dd7SMatthias Ringwald         result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000;
15092b78dd7SMatthias Ringwald     } else {
15192b78dd7SMatthias Ringwald         result->tv_sec = stop->tv_sec - start->tv_sec;
15292b78dd7SMatthias Ringwald         result->tv_nsec = stop->tv_nsec - start->tv_nsec;
15392b78dd7SMatthias Ringwald     }
15492b78dd7SMatthias Ringwald }
15592b78dd7SMatthias Ringwald 
15692b78dd7SMatthias Ringwald /**
15792b78dd7SMatthias Ringwald  * @brief Convert timespec to miliseconds, might overflow
15892b78dd7SMatthias Ringwald  */
15992b78dd7SMatthias Ringwald static uint64_t timespec_to_milliseconds(struct timespec *a){
16092b78dd7SMatthias Ringwald     uint64_t ret = 0;
16192b78dd7SMatthias Ringwald     uint64_t sec_val = (uint64_t)(a->tv_sec);
16292b78dd7SMatthias Ringwald     uint64_t nsec_val = (uint64_t)(a->tv_nsec);
16392b78dd7SMatthias Ringwald     ret = (sec_val*1000) + (nsec_val/1000000);
16492b78dd7SMatthias Ringwald     return ret;
16592b78dd7SMatthias Ringwald }
16692b78dd7SMatthias Ringwald 
16792b78dd7SMatthias Ringwald /**
16892b78dd7SMatthias Ringwald  * @brief Returns the milisecond value of (stop - start). Might overflow
16992b78dd7SMatthias Ringwald  */
17092b78dd7SMatthias Ringwald static uint64_t timespec_diff_milis(struct timespec* start, struct timespec* stop){
17192b78dd7SMatthias Ringwald     struct timespec diff_ts;
17292b78dd7SMatthias Ringwald     timespec_diff(start, stop, &diff_ts);
17392b78dd7SMatthias Ringwald     return timespec_to_milliseconds(&diff_ts);
17492b78dd7SMatthias Ringwald }
17592b78dd7SMatthias Ringwald #endif
17692b78dd7SMatthias Ringwald 
177b7d596c1SMatthias Ringwald /**
178f316a845SMatthias Ringwald  * @brief Queries the current time in ms since start
179f316a845SMatthias Ringwald  */
180f316a845SMatthias Ringwald static uint32_t btstack_run_loop_posix_get_time_ms(void){
18192b78dd7SMatthias Ringwald     uint32_t time_ms;
18292b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK
18392b78dd7SMatthias Ringwald     struct timespec now_ts;
18492b78dd7SMatthias Ringwald     clock_gettime(CLOCK_MONOTONIC, &now_ts);
18592b78dd7SMatthias Ringwald     time_ms = (uint32_t) timespec_diff_milis(&init_ts, &now_ts);
18692b78dd7SMatthias Ringwald #else
187f316a845SMatthias Ringwald     struct timeval tv;
188f316a845SMatthias Ringwald     gettimeofday(&tv, NULL);
18992b78dd7SMatthias Ringwald     time_ms = (uint32_t) ((tv.tv_sec  - init_tv.tv_sec) * 1000) + (tv.tv_usec / 1000);
19092b78dd7SMatthias Ringwald #endif
191f316a845SMatthias Ringwald     return time_ms;
192f316a845SMatthias Ringwald }
193f316a845SMatthias Ringwald 
194f316a845SMatthias Ringwald /**
195b7d596c1SMatthias Ringwald  * Execute run_loop
196b7d596c1SMatthias Ringwald  */
197528a4a3bSMatthias Ringwald static void btstack_run_loop_posix_execute(void) {
1989120e843SMatthias Ringwald     fd_set descriptors_read;
1999120e843SMatthias Ringwald     fd_set descriptors_write;
200b7d596c1SMatthias Ringwald 
201ec820d77SMatthias Ringwald     btstack_timer_source_t       *ts;
202b7d596c1SMatthias Ringwald     btstack_linked_list_iterator_t it;
203f316a845SMatthias Ringwald     struct timeval * timeout;
204f316a845SMatthias Ringwald     struct timeval tv;
205f316a845SMatthias Ringwald     uint32_t now_ms;
206b7d596c1SMatthias Ringwald 
20792b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK
20892b78dd7SMatthias Ringwald     log_info("POSIX run loop with monotonic clock");
20992b78dd7SMatthias Ringwald #else
21092b78dd7SMatthias Ringwald     log_info("POSIX run loop using ettimeofday fallback.");
21192b78dd7SMatthias Ringwald #endif
21292b78dd7SMatthias Ringwald 
213*ff3cc4a5SMatthias Ringwald     while (true) {
214b7d596c1SMatthias Ringwald         // collect FDs
2159120e843SMatthias Ringwald         FD_ZERO(&descriptors_read);
2169120e843SMatthias Ringwald         FD_ZERO(&descriptors_write);
217f316a845SMatthias Ringwald         int highest_fd = -1;
218b7d596c1SMatthias Ringwald         btstack_linked_list_iterator_init(&it, &data_sources);
219b7d596c1SMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&it)){
220ec820d77SMatthias Ringwald             btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it);
221398a95ecSMatthias Ringwald             if (ds->source.fd < 0) continue;
2229120e843SMatthias Ringwald             if (ds->flags & DATA_SOURCE_CALLBACK_READ){
223398a95ecSMatthias Ringwald                 FD_SET(ds->source.fd, &descriptors_read);
224398a95ecSMatthias Ringwald                 if (ds->source.fd > highest_fd) {
225398a95ecSMatthias Ringwald                     highest_fd = ds->source.fd;
2269120e843SMatthias Ringwald                 }
227398a95ecSMatthias Ringwald                 log_debug("btstack_run_loop_execute adding fd %u for read", ds->source.fd);
2289120e843SMatthias Ringwald             }
2299120e843SMatthias Ringwald             if (ds->flags & DATA_SOURCE_CALLBACK_WRITE){
230398a95ecSMatthias Ringwald                 FD_SET(ds->source.fd, &descriptors_write);
231398a95ecSMatthias Ringwald                 if (ds->source.fd > highest_fd) {
232398a95ecSMatthias Ringwald                     highest_fd = ds->source.fd;
233b7d596c1SMatthias Ringwald                 }
234398a95ecSMatthias Ringwald                 log_debug("btstack_run_loop_execute adding fd %u for write", ds->source.fd);
235b7d596c1SMatthias Ringwald             }
236b7d596c1SMatthias Ringwald         }
237b7d596c1SMatthias Ringwald 
238b7d596c1SMatthias Ringwald         // get next timeout
239b7d596c1SMatthias Ringwald         timeout = NULL;
240b7d596c1SMatthias Ringwald         if (timers) {
241ec820d77SMatthias Ringwald             ts = (btstack_timer_source_t *) timers;
242f316a845SMatthias Ringwald             timeout = &tv;
243b6fc147fSMatthias Ringwald             uint32_t list_timeout  = ts->timeout;
244f316a845SMatthias Ringwald             now_ms = btstack_run_loop_posix_get_time_ms();
245b6fc147fSMatthias Ringwald             int32_t delta = btstack_time_delta(list_timeout, now_ms);
246f316a845SMatthias Ringwald             if (delta < 0){
247f316a845SMatthias Ringwald                 delta = 0;
248b7d596c1SMatthias Ringwald             }
249f316a845SMatthias Ringwald             tv.tv_sec  = delta / 1000;
2507c959318SMatthias Ringwald             tv.tv_usec = (int) (delta - (tv.tv_sec * 1000)) * 1000;
251f316a845SMatthias Ringwald             log_debug("btstack_run_loop_execute next timeout in %u ms", delta);
252b7d596c1SMatthias Ringwald         }
253b7d596c1SMatthias Ringwald 
254b7d596c1SMatthias Ringwald         // wait for ready FDs
2559120e843SMatthias Ringwald         select( highest_fd+1 , &descriptors_read, &descriptors_write, NULL, timeout);
256b7d596c1SMatthias Ringwald 
25788e0b3b2SMatthias Ringwald 
258b7d596c1SMatthias Ringwald         data_sources_modified = 0;
259b7d596c1SMatthias Ringwald         btstack_linked_list_iterator_init(&it, &data_sources);
260b7d596c1SMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&it) && !data_sources_modified){
261ec820d77SMatthias Ringwald             btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it);
262398a95ecSMatthias Ringwald             log_debug("btstack_run_loop_posix_execute: check ds %p with fd %u\n", ds, ds->source.fd);
263398a95ecSMatthias Ringwald             if (FD_ISSET(ds->source.fd, &descriptors_read)) {
264398a95ecSMatthias Ringwald                 log_debug("btstack_run_loop_posix_execute: process read ds %p with fd %u\n", ds, ds->source.fd);
2657cd5ef95SMatthias Ringwald                 ds->process(ds, DATA_SOURCE_CALLBACK_READ);
266b7d596c1SMatthias Ringwald             }
2674b7565a2SMatthias Ringwald             if (data_sources_modified) break;
268398a95ecSMatthias Ringwald             if (FD_ISSET(ds->source.fd, &descriptors_write)) {
269398a95ecSMatthias Ringwald                 log_debug("btstack_run_loop_posix_execute: process write ds %p with fd %u\n", ds, ds->source.fd);
2709120e843SMatthias Ringwald                 ds->process(ds, DATA_SOURCE_CALLBACK_WRITE);
2719120e843SMatthias Ringwald             }
272b7d596c1SMatthias Ringwald         }
273f316a845SMatthias Ringwald         log_debug("btstack_run_loop_posix_execute: after ds check\n");
274b7d596c1SMatthias Ringwald 
275b7d596c1SMatthias Ringwald         // process timers
27688e0b3b2SMatthias Ringwald         now_ms = btstack_run_loop_posix_get_time_ms();
277b7d596c1SMatthias Ringwald         while (timers) {
278ec820d77SMatthias Ringwald             ts = (btstack_timer_source_t *) timers;
279b6fc147fSMatthias Ringwald             int32_t delta = btstack_time_delta(ts->timeout, now_ms);
280b6fc147fSMatthias Ringwald             if (delta > 0) break;
281f316a845SMatthias Ringwald             log_debug("btstack_run_loop_posix_execute: process timer %p\n", ts);
282b7d596c1SMatthias Ringwald 
283b7d596c1SMatthias Ringwald             // remove timer before processing it to allow handler to re-register with run loop
284b7832c7fSMatthias Ringwald             btstack_run_loop_posix_remove_timer(ts);
285b7d596c1SMatthias Ringwald             ts->process(ts);
286b7d596c1SMatthias Ringwald         }
287b7d596c1SMatthias Ringwald     }
288b7d596c1SMatthias Ringwald }
289b7d596c1SMatthias Ringwald 
290b7d596c1SMatthias Ringwald // set timer
291ec820d77SMatthias Ringwald static void btstack_run_loop_posix_set_timer(btstack_timer_source_t *a, uint32_t timeout_in_ms){
292f316a845SMatthias Ringwald     uint32_t time_ms = btstack_run_loop_posix_get_time_ms();
293f316a845SMatthias Ringwald     a->timeout = time_ms + timeout_in_ms;
294615ae444SMatthias Ringwald     log_debug("btstack_run_loop_posix_set_timer to %u ms (now %u, timeout %u)", a->timeout, time_ms, timeout_in_ms);
295b7d596c1SMatthias Ringwald }
296b7d596c1SMatthias Ringwald 
297528a4a3bSMatthias Ringwald static void btstack_run_loop_posix_init(void){
298b7d596c1SMatthias Ringwald     data_sources = NULL;
299b7d596c1SMatthias Ringwald     timers = NULL;
30092b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK
30192b78dd7SMatthias Ringwald     clock_gettime(CLOCK_MONOTONIC, &init_ts);
30292b78dd7SMatthias Ringwald     init_ts.tv_nsec = 0;
30392b78dd7SMatthias Ringwald #else
304f316a845SMatthias Ringwald     // just assume that we started at tv_usec == 0
305b7d596c1SMatthias Ringwald     gettimeofday(&init_tv, NULL);
306f316a845SMatthias Ringwald     init_tv.tv_usec = 0;
30792b78dd7SMatthias Ringwald #endif
308b7d596c1SMatthias Ringwald }
309b7d596c1SMatthias Ringwald 
310b7d596c1SMatthias Ringwald 
311528a4a3bSMatthias Ringwald static const btstack_run_loop_t btstack_run_loop_posix = {
312528a4a3bSMatthias Ringwald     &btstack_run_loop_posix_init,
313528a4a3bSMatthias Ringwald     &btstack_run_loop_posix_add_data_source,
314528a4a3bSMatthias Ringwald     &btstack_run_loop_posix_remove_data_source,
3159120e843SMatthias Ringwald     &btstack_run_loop_posix_enable_data_source_callbacks,
3169120e843SMatthias Ringwald     &btstack_run_loop_posix_disable_data_source_callbacks,
317528a4a3bSMatthias Ringwald     &btstack_run_loop_posix_set_timer,
318528a4a3bSMatthias Ringwald     &btstack_run_loop_posix_add_timer,
319528a4a3bSMatthias Ringwald     &btstack_run_loop_posix_remove_timer,
320528a4a3bSMatthias Ringwald     &btstack_run_loop_posix_execute,
321528a4a3bSMatthias Ringwald     &btstack_run_loop_posix_dump_timer,
322528a4a3bSMatthias Ringwald     &btstack_run_loop_posix_get_time_ms,
323b7d596c1SMatthias Ringwald };
324b7d596c1SMatthias Ringwald 
325b7d596c1SMatthias Ringwald /**
326528a4a3bSMatthias Ringwald  * Provide btstack_run_loop_posix instance
327b7d596c1SMatthias Ringwald  */
328528a4a3bSMatthias Ringwald const btstack_run_loop_t * btstack_run_loop_posix_get_instance(void){
329528a4a3bSMatthias Ringwald     return &btstack_run_loop_posix;
330b7d596c1SMatthias Ringwald }
331b7d596c1SMatthias Ringwald 
332