1 /*
2 * Copyright 2018 Oticon A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "p2G4_func_queue.h"
7 #include "bs_oswrap.h"
8 #include "bs_tracing.h"
9
10 /*
11 * Array with one element per device interface
12 * Each interface can have 1 function pending
13 */
14 static fq_element_t *f_queue = NULL;
15
16 static uint32_t next_d = 0;
17 static uint32_t n_devs = 0;
18
19 static queable_f fptrs[N_funcs];
20
fq_init(uint32_t n_dev)21 void fq_init(uint32_t n_dev){
22 f_queue = bs_calloc(n_dev, sizeof(fq_element_t));
23 n_devs = n_dev;
24
25 for (int i = 0 ; i < n_devs; i ++) {
26 f_queue[i].time = TIME_NEVER;
27 f_queue[i].f_index = State_None;
28 }
29 }
30
fq_register_func(f_index_t type,queable_f fptr)31 void fq_register_func(f_index_t type, queable_f fptr) {
32 fptrs[type] = fptr;
33 }
34
35 /**
36 * Find the next function which should be executed,
37 * Based on the following order, from left to right:
38 * time (lower first), function index (higher first), device number (lower first)
39 * TOOPT: The whole function queue is implemented in a simple/naive way,
40 * which is perfectly fine for simulations with a few devices.
41 * But, if there is many devices, this would be quite slow.
42 */
fq_find_next()43 void fq_find_next(){
44 bs_time_t chosen_f_time;
45 next_d = 0;
46 chosen_f_time = f_queue[0].time;
47
48 for (int i = 1; i < n_devs; i ++) {
49 fq_element_t *el = &f_queue[i];
50 if (el->time < chosen_f_time) {
51 next_d = i;
52 chosen_f_time = el->time;
53 continue;
54 } else if (el->time == chosen_f_time) {
55 if (el->f_index > f_queue[next_d].f_index) {
56 next_d = i;
57 continue;
58 }
59 }
60 }
61 }
62
63 /**
64 * Add a function for dev_nbr to the queue and reorder it
65 */
fq_add(bs_time_t time,f_index_t index,uint32_t dev_nbr)66 void fq_add(bs_time_t time, f_index_t index, uint32_t dev_nbr) {
67 fq_element_t *el = &f_queue[dev_nbr];
68 el->time = time;
69 el->f_index = index;
70 }
71
72 /**
73 * Remove an element from the queue and reorder it
74 */
fq_remove(uint32_t d)75 void fq_remove(uint32_t d){
76 f_queue[d].f_index = State_None;
77 f_queue[d].time = TIME_NEVER;
78 }
79
80 /**
81 * Call the next function in the queue
82 * Note: The function itself is left in the queue.
83 */
fq_call_next()84 void fq_call_next(){
85 fptrs[f_queue[next_d].f_index](next_d);
86 }
87
88 /**
89 * Get the time of the next element of the queue
90 */
fq_get_next_time()91 bs_time_t fq_get_next_time(){
92 return f_queue[next_d].time;
93 }
94
fq_free()95 void fq_free(){
96 if ( f_queue != NULL )
97 free(f_queue);
98 }
99