forked from RIOT-OS/RIOT
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcb_mux.c
124 lines (101 loc) · 2.47 KB
/
cb_mux.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
* Copyright (C) 2018 Acutam Automation, LLC
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup sys_cb_mux
* @{
*
* @file
* @brief cb_mux implementation
*
* @author Matthew Blue <matthew.blue.neuro@gmail.com>
* @}
*/
#include "cb_mux.h"
#include "utlist.h"
void cb_mux_add(cb_mux_t **head, cb_mux_t *entry)
{
LL_APPEND(*head, entry);
}
void cb_mux_del(cb_mux_t **head, cb_mux_t *entry)
{
LL_DELETE(*head, entry);
}
cb_mux_t *cb_mux_find_cbid(cb_mux_t *head, cb_mux_cbid_t cbid_val)
{
cb_mux_t *entry;
LL_SEARCH_SCALAR(head, entry, cbid, cbid_val);
return entry;
}
cb_mux_t *cb_mux_find_low(cb_mux_t *head)
{
cb_mux_t *entry;
cb_mux_t *entry_low = NULL;
cb_mux_cbid_t id = (cb_mux_cbid_t)(-1);
LL_FOREACH(head, entry) {
/* Entry does not have lower ID */
if (entry->cbid >= id) {
continue;
}
id = entry->cbid;
entry_low = entry;
}
return entry_low;
}
cb_mux_t *cb_mux_find_high(cb_mux_t *head)
{
cb_mux_t *entry;
cb_mux_t *entry_high = NULL;
cb_mux_cbid_t id = 0;
LL_FOREACH(head, entry) {
/* Entry does not have higher ID */
if (entry->cbid <= id) {
continue;
}
id = entry->cbid;
entry_high = entry;
}
return entry_high;
}
cb_mux_cbid_t cb_mux_find_free_id(cb_mux_t *head)
{
uint32_t free;
cb_mux_cbid_t block;
cb_mux_t *entry;
uint8_t num;
/* Search for free IDs in blocks of 32 IDs */
for (block = 0; block + 31 < (cb_mux_cbid_t)(-1); block += 32) {
/* Set all IDs in block to free */
free = 0;
LL_FOREACH(head, entry) {
/* cbid falls within this block */
if ((entry->cbid >= block) && (entry->cbid < block + 32)) {
/* Set cbid to taken */
free |= 1 << (entry->cbid & 0x1F);
}
}
/* At least one ID in block free */
if (~free) {
break;
}
}
/* Find which ID in block was free */
for (num = 0; num < 32; num++) {
if (~free & (1 << num)) {
return block | num;
}
}
/* No free IDs */
return (cb_mux_cbid_t)(-1);
}
void cb_mux_iter(cb_mux_t *head, cb_mux_iter_t func, void *arg)
{
cb_mux_t *entry;
LL_FOREACH(head, entry) {
func(entry, arg);
}
}