-
Notifications
You must be signed in to change notification settings - Fork 39
Expand file tree
/
Copy pathpeer_id.c
More file actions
171 lines (140 loc) · 3.92 KB
/
peer_id.c
File metadata and controls
171 lines (140 loc) · 3.92 KB
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
* Copyright (c) 2015-2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include <nrf_error.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include <zephyr/sys/atomic.h>
#if !defined(CONFIG_UNITY)
#include <nrfx.h>
#endif
#include <bm/bluetooth/peer_manager/peer_manager_types.h>
#include <modules/peer_id.h>
struct peer_id_flags {
/** Bitmap designating which peer IDs are in use. */
ATOMIC_DEFINE(used_peer_ids, PM_PEER_ID_N_AVAILABLE_IDS);
/** Bitmap designating which peer IDs are marked for deletion. */
ATOMIC_DEFINE(deleted_peer_ids, PM_PEER_ID_N_AVAILABLE_IDS);
};
static struct peer_id_flags peer_id_flags = {{0}, {0}};
static void internal_state_reset(struct peer_id_flags *pi_flags)
{
memset(pi_flags, 0, sizeof(struct peer_id_flags));
}
void peer_id_init(void)
{
internal_state_reset(&peer_id_flags);
}
static uint32_t find_and_set_flag(atomic_t *pi_flags, uint32_t flag_count)
{
for (uint32_t i = 0; i < ATOMIC_BITMAP_SIZE(flag_count); i++) {
uint32_t word = atomic_get(&pi_flags[i]);
uint32_t inverted = ~word;
while (inverted) {
/* Find lowest zero bit */
#if defined(CONFIG_UNITY)
uint32_t first_zero = __builtin_ctz(inverted);
#else
uint32_t first_zero = NRF_CTZ(inverted);
#endif
uint32_t first_zero_global = first_zero + (i * 32);
if (first_zero_global >= flag_count) {
break;
}
if (!atomic_test_and_set_bit(pi_flags, first_zero_global)) {
return first_zero_global;
}
inverted &= ~(1u << first_zero);
}
}
return flag_count;
}
static uint16_t claim(uint16_t peer_id, atomic_t *pi_flags)
{
uint16_t allocated_peer_id = PM_PEER_ID_INVALID;
if (peer_id == PM_PEER_ID_INVALID) {
allocated_peer_id =
find_and_set_flag(pi_flags, PM_PEER_ID_N_AVAILABLE_IDS);
if (allocated_peer_id == PM_PEER_ID_N_AVAILABLE_IDS) {
allocated_peer_id = PM_PEER_ID_INVALID;
}
} else if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) {
bool lock_success = !atomic_test_and_set_bit(pi_flags, peer_id);
allocated_peer_id = lock_success ? peer_id : PM_PEER_ID_INVALID;
}
return allocated_peer_id;
}
static void release(uint16_t peer_id, atomic_t *pi_flags)
{
if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) {
atomic_clear_bit(pi_flags, peer_id);
}
}
uint16_t peer_id_allocate(uint16_t peer_id)
{
return claim(peer_id, peer_id_flags.used_peer_ids);
}
bool peer_id_delete(uint16_t peer_id)
{
uint16_t deleted_peer_id;
if (peer_id == PM_PEER_ID_INVALID) {
return false;
}
deleted_peer_id = claim(peer_id, peer_id_flags.deleted_peer_ids);
return (deleted_peer_id == peer_id);
}
void peer_id_free(uint16_t peer_id)
{
release(peer_id, peer_id_flags.used_peer_ids);
release(peer_id, peer_id_flags.deleted_peer_ids);
}
bool peer_id_is_allocated(uint16_t peer_id)
{
if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) {
return atomic_test_bit(peer_id_flags.used_peer_ids, peer_id);
}
return false;
}
bool peer_id_is_deleted(uint16_t peer_id)
{
if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) {
return atomic_test_bit(peer_id_flags.deleted_peer_ids, peer_id);
}
return false;
}
uint16_t next_id_get(uint16_t prev_peer_id, atomic_t *pi_flags)
{
uint16_t i = (prev_peer_id == PM_PEER_ID_INVALID) ? 0 : (prev_peer_id + 1);
for (; i < PM_PEER_ID_N_AVAILABLE_IDS; i++) {
if (atomic_test_bit(pi_flags, i)) {
return i;
}
}
return PM_PEER_ID_INVALID;
}
uint16_t peer_id_get_next_used(uint16_t peer_id)
{
peer_id = next_id_get(peer_id, peer_id_flags.used_peer_ids);
while (peer_id != PM_PEER_ID_INVALID) {
if (!peer_id_is_deleted(peer_id)) {
return peer_id;
}
peer_id = next_id_get(peer_id, peer_id_flags.used_peer_ids);
}
return peer_id;
}
uint16_t peer_id_get_next_deleted(uint16_t prev_peer_id)
{
return next_id_get(prev_peer_id, peer_id_flags.deleted_peer_ids);
}
uint32_t peer_id_n_ids(void)
{
uint32_t n_ids = 0;
for (uint16_t i = 0; i < PM_PEER_ID_N_AVAILABLE_IDS; i++) {
n_ids += atomic_test_bit(peer_id_flags.used_peer_ids, i);
}
return n_ids;
}