Skip to content

Commit 5c24c79

Browse files
bjarki-andreasennashif
authored andcommitted
modem: pipe: simplify synchronization
The design of the pipe is overly complicated compared to the in-tree and planned future use of the pipe module. The pipe is currently designed to protect against multiple threads calling any API simultaineously. This is not neccesary as only one thread ever calls open/close/transmit/receive at once, while the notification APIs are potentially called by a different thread. This commit removes the synchronization of calls to the open/ close/receive/transmit APIs. It also uses a k_event for thread safe event and state handling instead of a k_mutex and k_condvar. The callback is proteced by a k_sem as it modified using the attach/release APIs, which can be called simultaneously to a thread invoking the callback. Signed-off-by: Bjarki Arge Andreasen <[email protected]>
1 parent 87e1ab8 commit 5c24c79

File tree

3 files changed

+109
-138
lines changed

3 files changed

+109
-138
lines changed

include/zephyr/modem/pipe.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,21 +61,13 @@ struct modem_pipe_api {
6161
modem_pipe_api_close close;
6262
};
6363

64-
enum modem_pipe_state {
65-
MODEM_PIPE_STATE_CLOSED = 0,
66-
MODEM_PIPE_STATE_OPEN,
67-
};
68-
6964
struct modem_pipe {
7065
void *data;
7166
struct modem_pipe_api *api;
7267
modem_pipe_api_callback callback;
7368
void *user_data;
74-
enum modem_pipe_state state;
75-
struct k_mutex lock;
76-
struct k_condvar condvar;
77-
uint8_t receive_ready_pending : 1;
78-
uint8_t transmit_idle_pending : 1;
69+
struct k_spinlock spinlock;
70+
struct k_event event;
7971
};
8072

8173
/**

subsys/modem/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ endif
4242

4343
config MODEM_PIPE
4444
bool "Modem pipe module"
45+
select EVENTS
4546

4647
config MODEM_PIPELINK
4748
bool "Modem pipelink module"

subsys/modem/modem_pipe.c

Lines changed: 106 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,74 @@
66

77
#include <zephyr/modem/pipe.h>
88

9-
#include <zephyr/logging/log.h>
10-
LOG_MODULE_REGISTER(modem_pipe, CONFIG_MODEM_MODULES_LOG_LEVEL);
9+
#define PIPE_EVENT_OPENED_BIT BIT(0)
10+
#define PIPE_EVENT_CLOSED_BIT BIT(1)
11+
#define PIPE_EVENT_RECEIVE_READY_BIT BIT(2)
12+
#define PIPE_EVENT_TRANSMIT_IDLE_BIT BIT(3)
13+
14+
static void pipe_set_callback(struct modem_pipe *pipe,
15+
modem_pipe_api_callback callback,
16+
void *user_data)
17+
{
18+
K_SPINLOCK(&pipe->spinlock) {
19+
pipe->callback = callback;
20+
pipe->user_data = user_data;
21+
}
22+
}
23+
24+
static void pipe_call_callback(struct modem_pipe *pipe, enum modem_pipe_event event)
25+
{
26+
K_SPINLOCK(&pipe->spinlock) {
27+
if (pipe->callback != NULL) {
28+
pipe->callback(pipe, event, pipe->user_data);
29+
}
30+
}
31+
}
32+
33+
static uint32_t pipe_test_events(struct modem_pipe *pipe, uint32_t events)
34+
{
35+
return k_event_test(&pipe->event, events);
36+
}
37+
38+
static uint32_t pipe_await_events(struct modem_pipe *pipe, uint32_t events)
39+
{
40+
return k_event_wait(&pipe->event, events, false, K_MSEC(10000));
41+
}
42+
43+
static void pipe_post_events(struct modem_pipe *pipe, uint32_t events)
44+
{
45+
k_event_post(&pipe->event, events);
46+
}
47+
48+
static void pipe_clear_events(struct modem_pipe *pipe, uint32_t events)
49+
{
50+
k_event_clear(&pipe->event, events);
51+
}
52+
53+
static void pipe_set_events(struct modem_pipe *pipe, uint32_t events)
54+
{
55+
k_event_set(&pipe->event, events);
56+
}
57+
58+
static int pipe_call_open(struct modem_pipe *pipe)
59+
{
60+
return pipe->api->open(pipe->data);
61+
}
62+
63+
static int pipe_call_transmit(struct modem_pipe *pipe, const uint8_t *buf, size_t size)
64+
{
65+
return pipe->api->transmit(pipe->data, buf, size);
66+
}
67+
68+
static int pipe_call_receive(struct modem_pipe *pipe, uint8_t *buf, size_t size)
69+
{
70+
return pipe->api->receive(pipe->data, buf, size);
71+
}
72+
73+
static int pipe_call_close(struct modem_pipe *pipe)
74+
{
75+
return pipe->api->close(pipe->data);
76+
}
1177

1278
void modem_pipe_init(struct modem_pipe *pipe, void *data, struct modem_pipe_api *api)
1379
{
@@ -19,216 +85,128 @@ void modem_pipe_init(struct modem_pipe *pipe, void *data, struct modem_pipe_api
1985
pipe->api = api;
2086
pipe->callback = NULL;
2187
pipe->user_data = NULL;
22-
pipe->state = MODEM_PIPE_STATE_CLOSED;
23-
pipe->receive_ready_pending = false;
24-
pipe->transmit_idle_pending = true;
25-
26-
k_mutex_init(&pipe->lock);
27-
k_condvar_init(&pipe->condvar);
88+
k_event_init(&pipe->event);
2889
}
2990

3091
int modem_pipe_open(struct modem_pipe *pipe)
3192
{
3293
int ret;
3394

34-
k_mutex_lock(&pipe->lock, K_FOREVER);
35-
if (pipe->state == MODEM_PIPE_STATE_OPEN) {
36-
k_mutex_unlock(&pipe->lock);
95+
if (pipe_test_events(pipe, PIPE_EVENT_OPENED_BIT)) {
3796
return 0;
3897
}
3998

40-
ret = pipe->api->open(pipe->data);
99+
ret = pipe_call_open(pipe);
41100
if (ret < 0) {
42-
k_mutex_unlock(&pipe->lock);
43101
return ret;
44102
}
45103

46-
if (pipe->state == MODEM_PIPE_STATE_OPEN) {
47-
k_mutex_unlock(&pipe->lock);
48-
return 0;
104+
if (!pipe_await_events(pipe, PIPE_EVENT_OPENED_BIT)) {
105+
return -EAGAIN;
49106
}
50107

51-
k_condvar_wait(&pipe->condvar, &pipe->lock, K_MSEC(10000));
52-
ret = (pipe->state == MODEM_PIPE_STATE_OPEN) ? 0 : -EAGAIN;
53-
k_mutex_unlock(&pipe->lock);
54-
return ret;
108+
return 0;
55109
}
56110

57111
int modem_pipe_open_async(struct modem_pipe *pipe)
58112
{
59-
int ret;
60-
61-
k_mutex_lock(&pipe->lock, K_FOREVER);
62-
if (pipe->state == MODEM_PIPE_STATE_OPEN) {
63-
if (pipe->callback != NULL) {
64-
pipe->callback(pipe, MODEM_PIPE_EVENT_OPENED, pipe->user_data);
65-
}
66-
67-
k_mutex_unlock(&pipe->lock);
113+
if (pipe_test_events(pipe, PIPE_EVENT_OPENED_BIT)) {
114+
pipe_call_callback(pipe, MODEM_PIPE_EVENT_OPENED);
68115
return 0;
69116
}
70117

71-
ret = pipe->api->open(pipe->data);
72-
k_mutex_unlock(&pipe->lock);
73-
return ret;
118+
return pipe_call_open(pipe);
74119
}
75120

76121
void modem_pipe_attach(struct modem_pipe *pipe, modem_pipe_api_callback callback, void *user_data)
77122
{
78-
k_mutex_lock(&pipe->lock, K_FOREVER);
79-
pipe->callback = callback;
80-
pipe->user_data = user_data;
123+
pipe_set_callback(pipe, callback, user_data);
81124

82-
if (pipe->receive_ready_pending && (pipe->callback != NULL)) {
83-
pipe->callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY, pipe->user_data);
125+
if (pipe_test_events(pipe, PIPE_EVENT_RECEIVE_READY_BIT)) {
126+
pipe_call_callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY);
84127
}
85128

86-
if (pipe->transmit_idle_pending && (pipe->callback != NULL)) {
87-
pipe->callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE, pipe->user_data);
129+
if (pipe_test_events(pipe, PIPE_EVENT_TRANSMIT_IDLE_BIT)) {
130+
pipe_call_callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE);
88131
}
89-
90-
k_mutex_unlock(&pipe->lock);
91132
}
92133

93134
int modem_pipe_transmit(struct modem_pipe *pipe, const uint8_t *buf, size_t size)
94135
{
95-
int ret;
96-
97-
k_mutex_lock(&pipe->lock, K_FOREVER);
98-
99-
if (pipe->state == MODEM_PIPE_STATE_CLOSED) {
100-
k_mutex_unlock(&pipe->lock);
136+
if (!pipe_test_events(pipe, PIPE_EVENT_OPENED_BIT)) {
101137
return -EPERM;
102138
}
103139

104-
ret = pipe->api->transmit(pipe->data, buf, size);
105-
pipe->transmit_idle_pending = false;
106-
k_mutex_unlock(&pipe->lock);
107-
return ret;
140+
pipe_clear_events(pipe, PIPE_EVENT_TRANSMIT_IDLE_BIT);
141+
return pipe_call_transmit(pipe, buf, size);
108142
}
109143

110144
int modem_pipe_receive(struct modem_pipe *pipe, uint8_t *buf, size_t size)
111145
{
112-
int ret;
113-
114-
k_mutex_lock(&pipe->lock, K_FOREVER);
115-
116-
if (pipe->state == MODEM_PIPE_STATE_CLOSED) {
117-
k_mutex_unlock(&pipe->lock);
146+
if (!pipe_test_events(pipe, PIPE_EVENT_OPENED_BIT)) {
118147
return -EPERM;
119148
}
120149

121-
ret = pipe->api->receive(pipe->data, buf, size);
122-
pipe->receive_ready_pending = false;
123-
k_mutex_unlock(&pipe->lock);
124-
return ret;
150+
pipe_clear_events(pipe, PIPE_EVENT_RECEIVE_READY_BIT);
151+
return pipe_call_receive(pipe, buf, size);
125152
}
126153

127154
void modem_pipe_release(struct modem_pipe *pipe)
128155
{
129-
k_mutex_lock(&pipe->lock, K_FOREVER);
130-
pipe->callback = NULL;
131-
pipe->user_data = NULL;
132-
k_mutex_unlock(&pipe->lock);
156+
pipe_set_callback(pipe, NULL, NULL);
133157
}
134158

135159
int modem_pipe_close(struct modem_pipe *pipe)
136160
{
137161
int ret;
138162

139-
k_mutex_lock(&pipe->lock, K_FOREVER);
140-
if (pipe->state == MODEM_PIPE_STATE_CLOSED) {
141-
k_mutex_unlock(&pipe->lock);
163+
if (pipe_test_events(pipe, PIPE_EVENT_CLOSED_BIT)) {
142164
return 0;
143165
}
144166

145-
ret = pipe->api->close(pipe->data);
167+
ret = pipe_call_close(pipe);
146168
if (ret < 0) {
147-
k_mutex_unlock(&pipe->lock);
148169
return ret;
149170
}
150171

151-
if (pipe->state == MODEM_PIPE_STATE_CLOSED) {
152-
k_mutex_unlock(&pipe->lock);
153-
return 0;
172+
if (!pipe_await_events(pipe, PIPE_EVENT_CLOSED_BIT)) {
173+
return -EAGAIN;
154174
}
155175

156-
k_condvar_wait(&pipe->condvar, &pipe->lock, K_MSEC(10000));
157-
ret = (pipe->state == MODEM_PIPE_STATE_CLOSED) ? 0 : -EAGAIN;
158-
k_mutex_unlock(&pipe->lock);
159-
return ret;
176+
return 0;
160177
}
161178

162179
int modem_pipe_close_async(struct modem_pipe *pipe)
163180
{
164-
int ret;
165-
166-
k_mutex_lock(&pipe->lock, K_FOREVER);
167-
if (pipe->state == MODEM_PIPE_STATE_CLOSED) {
168-
if (pipe->callback != NULL) {
169-
pipe->callback(pipe, MODEM_PIPE_EVENT_CLOSED, pipe->user_data);
170-
}
171-
172-
k_mutex_unlock(&pipe->lock);
181+
if (pipe_test_events(pipe, PIPE_EVENT_CLOSED_BIT)) {
182+
pipe_call_callback(pipe, MODEM_PIPE_EVENT_CLOSED);
173183
return 0;
174184
}
175185

176-
ret = pipe->api->close(pipe->data);
177-
k_mutex_unlock(&pipe->lock);
178-
return ret;
186+
return pipe_call_close(pipe);
179187
}
180188

181189
void modem_pipe_notify_opened(struct modem_pipe *pipe)
182190
{
183-
k_mutex_lock(&pipe->lock, K_FOREVER);
184-
pipe->state = MODEM_PIPE_STATE_OPEN;
185-
186-
if (pipe->callback != NULL) {
187-
pipe->callback(pipe, MODEM_PIPE_EVENT_OPENED, pipe->user_data);
188-
pipe->callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE, pipe->user_data);
189-
}
190-
191-
k_condvar_signal(&pipe->condvar);
192-
k_mutex_unlock(&pipe->lock);
191+
pipe_set_events(pipe, PIPE_EVENT_OPENED_BIT | PIPE_EVENT_TRANSMIT_IDLE_BIT);
192+
pipe_call_callback(pipe, MODEM_PIPE_EVENT_OPENED);
193+
pipe_call_callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE);
193194
}
194195

195196
void modem_pipe_notify_closed(struct modem_pipe *pipe)
196197
{
197-
k_mutex_lock(&pipe->lock, K_FOREVER);
198-
pipe->state = MODEM_PIPE_STATE_CLOSED;
199-
pipe->receive_ready_pending = false;
200-
pipe->transmit_idle_pending = true;
201-
202-
if (pipe->callback != NULL) {
203-
pipe->callback(pipe, MODEM_PIPE_EVENT_CLOSED, pipe->user_data);
204-
}
205-
206-
k_condvar_signal(&pipe->condvar);
207-
k_mutex_unlock(&pipe->lock);
198+
pipe_set_events(pipe, PIPE_EVENT_TRANSMIT_IDLE_BIT | PIPE_EVENT_CLOSED_BIT);
199+
pipe_call_callback(pipe, MODEM_PIPE_EVENT_CLOSED);
208200
}
209201

210202
void modem_pipe_notify_receive_ready(struct modem_pipe *pipe)
211203
{
212-
k_mutex_lock(&pipe->lock, K_FOREVER);
213-
214-
pipe->receive_ready_pending = true;
215-
216-
if (pipe->callback != NULL) {
217-
pipe->callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY, pipe->user_data);
218-
}
219-
220-
k_mutex_unlock(&pipe->lock);
204+
pipe_post_events(pipe, PIPE_EVENT_RECEIVE_READY_BIT);
205+
pipe_call_callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY);
221206
}
222207

223208
void modem_pipe_notify_transmit_idle(struct modem_pipe *pipe)
224209
{
225-
k_mutex_lock(&pipe->lock, K_FOREVER);
226-
227-
pipe->transmit_idle_pending = true;
228-
229-
if (pipe->callback != NULL) {
230-
pipe->callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE, pipe->user_data);
231-
}
232-
233-
k_mutex_unlock(&pipe->lock);
210+
pipe_post_events(pipe, PIPE_EVENT_TRANSMIT_IDLE_BIT);
211+
pipe_call_callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE);
234212
}

0 commit comments

Comments
 (0)