Skip to content

Commit 7b5b5e5

Browse files
protobitssjanc
authored andcommitted
nuttx: fix callout mechanism
SIGEV_THREAD on NuttX currently has a limitation where the thread is not really a child of original process so it is not possible to interact with the open POSIX queue. This is addressed by having a specific thread wait for a condition variable which is triggered from the handler.
1 parent f25b1de commit 7b5b5e5

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

porting/npl/nuttx/src/os_callout.c

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,52 @@
2828

2929
#include "nimble/nimble_npl.h"
3030

31-
static void
32-
ble_npl_callout_timer_cb(union sigval sv)
31+
#ifndef CONFIG_NIMBLE_CALLOUT_THREAD_STACKSIZE
32+
#define CONFIG_NIMBLE_CALLOUT_THREAD_STACKSIZE 1024
33+
#endif
34+
35+
struct ble_npl_callout *pending_callout = NULL;
36+
37+
bool thread_started = false;
38+
pthread_t callout_thread;
39+
pthread_mutex_t callout_mutex = PTHREAD_MUTEX_INITIALIZER;
40+
pthread_cond_t callout_cond = PTHREAD_COND_INITIALIZER;
41+
42+
static pthread_addr_t
43+
callout_handler(pthread_addr_t arg)
3344
{
34-
struct ble_npl_callout *c = (struct ble_npl_callout *)sv.sival_ptr;
35-
assert(c);
45+
struct ble_npl_callout *c;
46+
47+
pthread_mutex_lock(&callout_mutex);
48+
while (!pending_callout) {
49+
pthread_cond_wait(&callout_cond, &callout_mutex);
50+
}
51+
52+
c = pending_callout;
53+
pending_callout = NULL;
54+
pthread_mutex_unlock(&callout_mutex);
55+
56+
/* Invoke callback */
3657

3758
if (c->c_evq) {
3859
ble_npl_eventq_put(c->c_evq, &c->c_ev);
3960
} else {
4061
c->c_ev.ev_cb(&c->c_ev);
4162
}
63+
64+
return NULL;
65+
}
66+
67+
static void
68+
ble_npl_callout_timer_cb(union sigval sv)
69+
{
70+
struct ble_npl_callout *c = (struct ble_npl_callout *)sv.sival_ptr;
71+
assert(c);
72+
73+
pthread_mutex_lock(&callout_mutex);
74+
pending_callout = c;
75+
pthread_cond_signal(&callout_cond);
76+
pthread_mutex_unlock(&callout_mutex);
4277
}
4378

4479
void
@@ -49,6 +84,14 @@ ble_npl_callout_init(struct ble_npl_callout *c,
4984
{
5085
struct sigevent event;
5186

87+
if (!thread_started) {
88+
pthread_attr_t attr;
89+
pthread_attr_init(&attr);
90+
pthread_attr_setstacksize(&attr, CONFIG_NIMBLE_CALLOUT_THREAD_STACKSIZE);
91+
pthread_create(&callout_thread, &attr, callout_handler, NULL);
92+
thread_started = true;
93+
}
94+
5295
/* Initialize the callout. */
5396
memset(c, 0, sizeof(*c));
5497
c->c_ev.ev_cb = ev_cb;

porting/npl/nuttx/src/os_eventq.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,18 @@ ble_npl_eventq_inited(const struct ble_npl_eventq *evq)
7373
void
7474
ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
7575
{
76+
int ret;
77+
7678
if (ev->ev_queued)
7779
{
7880
return;
7981
}
8082

8183
ev->ev_queued = 1;
82-
mq_send(evq->mq, (const char*)&ev, sizeof(ev), 0);
84+
ret = mq_send(evq->mq, (const char*)&ev, sizeof(ev), 0);
85+
86+
DEBUGASSERT(ret == 0);
87+
UNUSED(ret);
8388
}
8489

8590
struct ble_npl_event *

porting/npl/nuttx/src/os_task.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,22 @@ ble_npl_task_init(struct ble_npl_task *t, const char *name, ble_npl_task_func_t
6060
if (err) return err;
6161
err = pthread_attr_getschedparam (&t->attr, &t->param);
6262
if (err) return err;
63+
#if CONFIG_RR_INTERVAL > 0
6364
err = pthread_attr_setschedpolicy(&t->attr, SCHED_RR);
6465
if (err) return err;
66+
#endif
6567
t->param.sched_priority = prio;
6668
err = pthread_attr_setschedparam (&t->attr, &t->param);
6769
if (err) return err;
6870

6971
t->name = name;
7072
err = pthread_create(&t->handle, &t->attr, func, arg);
7173

74+
if (err == ENOMEM)
75+
{
76+
err = OS_ENOMEM;
77+
}
78+
7279
return err;
7380
}
7481

0 commit comments

Comments
 (0)