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 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 chosen_f_time = el->time;
58 continue;
59 }
60 }
61 }
62 }
63
64 /**
65 * Add a function for dev_nbr to the queue and reorder it
66 */
fq_add(bs_time_t time,f_index_t index,uint32_t dev_nbr)67 void fq_add(bs_time_t time, f_index_t index, uint32_t dev_nbr) {
68 fq_element_t *el = &f_queue[dev_nbr];
69 el->time = time;
70 el->f_index = index;
71 }
72
73 /**
74 * Remove an element from the queue and reorder it
75 */
fq_remove(uint32_t d)76 void fq_remove(uint32_t d){
77 f_queue[d].f_index = State_None;
78 f_queue[d].time = TIME_NEVER;
79 }
80
81 /**
82 * Call the next function in the queue
83 * Note: The function itself is left in the queue.
84 */
fq_call_next()85 void fq_call_next(){
86 fptrs[f_queue[next_d].f_index](next_d);
87 }
88
89 /**
90 * Get the time of the next element of the queue
91 */
fq_get_next_time()92 bs_time_t fq_get_next_time(){
93 return f_queue[next_d].time;
94 }
95
fq_free()96 void fq_free(){
97 if ( f_queue != NULL )
98 free(f_queue);
99 }
100