Skip to content

Commit 3da90f9

Browse files
Nicolas Pitrekartben
authored andcommitted
kernel/pipe: add missing calls to z_reschedule()
We are waking up threads but failed to let them run if they are higher priority. Add missing calls to z_reschedule(). Also wake up all pending writers as we don't know how many there might be. It is more efficient to wake them all when the ring buffer is full before reading from it rather than waking them one by one whenever there is more room in it. Thanks to Peter Mitsis for noticing those issues. Signed-off-by: Nicolas Pitre <[email protected]>
1 parent 99c2057 commit 3da90f9

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

kernel/pipe.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ static inline bool pipe_empty(struct k_pipe *pipe)
3535
}
3636

3737
static int wait_for(_wait_q_t *waitq, struct k_pipe *pipe, k_spinlock_key_t *key,
38-
k_timepoint_t time_limit)
38+
k_timepoint_t time_limit, bool *need_resched)
3939
{
4040
k_timeout_t timeout = sys_timepoint_timeout(time_limit);
4141
int rc;
@@ -45,6 +45,7 @@ static int wait_for(_wait_q_t *waitq, struct k_pipe *pipe, k_spinlock_key_t *key
4545
}
4646

4747
pipe->waiting++;
48+
*need_resched = false;
4849
SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(k_pipe, read, pipe, timeout);
4950
rc = z_pend_curr(&pipe->lock, *key, waitq, timeout);
5051
*key = k_spin_lock(&pipe->lock);
@@ -85,7 +86,7 @@ struct pipe_buf_spec {
8586
size_t used;
8687
};
8788

88-
static size_t copy_to_pending_readers(struct k_pipe *pipe,
89+
static size_t copy_to_pending_readers(struct k_pipe *pipe, bool *need_resched,
8990
const uint8_t *data, size_t len)
9091
{
9192
struct k_thread *reader;
@@ -132,6 +133,7 @@ static size_t copy_to_pending_readers(struct k_pipe *pipe,
132133
/* rest of thread wake-up outside the scheduler lock */
133134
z_thread_return_value_set_with_data(reader, 0, NULL);
134135
z_ready_thread(reader);
136+
*need_resched = true;
135137
}
136138
} while (reader != NULL && written < len);
137139

@@ -144,6 +146,7 @@ int z_impl_k_pipe_write(struct k_pipe *pipe, const uint8_t *data, size_t len, k_
144146
size_t written = 0;
145147
k_timepoint_t end = sys_timepoint_calc(timeout);
146148
k_spinlock_key_t key = k_spin_lock(&pipe->lock);
149+
bool need_resched = false;
147150

148151
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_pipe, write, pipe, data, len, timeout);
149152

@@ -160,7 +163,8 @@ int z_impl_k_pipe_write(struct k_pipe *pipe, const uint8_t *data, size_t len, k_
160163

161164
if (pipe_empty(pipe)) {
162165
if (pipe->waiting != 0) {
163-
written += copy_to_pending_readers(pipe, &data[written],
166+
written += copy_to_pending_readers(pipe, &need_resched,
167+
&data[written],
164168
len - written);
165169
if (written >= len) {
166170
rc = written;
@@ -179,7 +183,7 @@ int z_impl_k_pipe_write(struct k_pipe *pipe, const uint8_t *data, size_t len, k_
179183
break;
180184
}
181185

182-
rc = wait_for(&pipe->space, pipe, &key, end);
186+
rc = wait_for(&pipe->space, pipe, &key, end, &need_resched);
183187
if (rc != 0) {
184188
if (rc == -EAGAIN) {
185189
rc = written ? written : -EAGAIN;
@@ -189,7 +193,11 @@ int z_impl_k_pipe_write(struct k_pipe *pipe, const uint8_t *data, size_t len, k_
189193
}
190194
exit:
191195
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_pipe, write, pipe, rc);
192-
k_spin_unlock(&pipe->lock, key);
196+
if (need_resched) {
197+
z_reschedule(&pipe->lock, key);
198+
} else {
199+
k_spin_unlock(&pipe->lock, key);
200+
}
193201
return rc;
194202
}
195203

@@ -199,6 +207,7 @@ int z_impl_k_pipe_read(struct k_pipe *pipe, uint8_t *data, size_t len, k_timeout
199207
int rc;
200208
k_timepoint_t end = sys_timepoint_calc(timeout);
201209
k_spinlock_key_t key = k_spin_lock(&pipe->lock);
210+
bool need_resched = false;
202211

203212
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_pipe, read, pipe, data, len, timeout);
204213

@@ -209,7 +218,8 @@ int z_impl_k_pipe_read(struct k_pipe *pipe, uint8_t *data, size_t len, k_timeout
209218

210219
for (;;) {
211220
if (pipe_full(pipe)) {
212-
z_sched_wake(&pipe->space, 0, NULL);
221+
/* One or more pending writers may exist. */
222+
need_resched = z_sched_wake_all(&pipe->space, 0, NULL);
213223
}
214224

215225
buf.used += ring_buf_get(&pipe->buf, &data[buf.used], len - buf.used);
@@ -226,7 +236,7 @@ int z_impl_k_pipe_read(struct k_pipe *pipe, uint8_t *data, size_t len, k_timeout
226236
/* provide our "direct copy" info to potential writers */
227237
_current->base.swap_data = &buf;
228238

229-
rc = wait_for(&pipe->data, pipe, &key, end);
239+
rc = wait_for(&pipe->data, pipe, &key, end, &need_resched);
230240
if (rc != 0) {
231241
if (rc == -EAGAIN) {
232242
rc = buf.used ? buf.used : -EAGAIN;
@@ -236,7 +246,11 @@ int z_impl_k_pipe_read(struct k_pipe *pipe, uint8_t *data, size_t len, k_timeout
236246
}
237247
exit:
238248
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_pipe, read, pipe, rc);
239-
k_spin_unlock(&pipe->lock, key);
249+
if (need_resched) {
250+
z_reschedule(&pipe->lock, key);
251+
} else {
252+
k_spin_unlock(&pipe->lock, key);
253+
}
240254
return rc;
241255
}
242256

0 commit comments

Comments
 (0)