aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2016-04-22 13:42:01 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2016-04-22 13:42:01 +0900
commit1b12a780548cff613e9eaa5cdef0e4a9429441cb (patch)
tree81289093481837da3064036ddc589071b6401dbf
parent5d40ffbffad4b3f102a6d4cf975d7a49a6dcdb92 (diff)
Modify chopstx_poll API
-rw-r--r--ChangeLog11
-rw-r--r--chopstx.c156
-rw-r--r--chopstx.h34
-rw-r--r--doc/chopstx-api.texi10
-rw-r--r--doc/chopstx.texi4
-rw-r--r--example-fs-bb48/sample.c20
6 files changed, 154 insertions, 81 deletions
diff --git a/ChangeLog b/ChangeLog
index e64c1c9..8cc5bc7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2016-04-22 Niibe Yutaka <gniibe@fsij.org>
+
+ * chopstx.c (chx_cond_hook): Rename from chopstx_cond_hook and make
+ it internal.
+ (chx_cond_unhook): Likewise.
+ (chx_join_hook, chx_join_unhook): New.
+ (chopstx_poll): Change API, not exposing internals of hook/unhook.
+
+ * example-fs-bb48/sample.c (main): Follow the API change of
+ chopstx_poll.
+
2016-04-21 Niibe Yutaka <gniibe@fsij.org>
* chopstx.c (chx_snooze, chx_wakeup): New.
diff --git a/chopstx.c b/chopstx.c
index dcf4c10..c8bcf77 100644
--- a/chopstx.c
+++ b/chopstx.c
@@ -915,6 +915,37 @@ chx_sched (uint32_t yield)
}
+static int
+chx_wakeup (struct chx_thread *tp)
+{
+ int yield = 0;
+
+ if (tp->flag_is_proxy)
+ {
+ struct chx_px *px = (struct chx_px *)tp;
+
+ (*px->counter_p)++;
+ tp = px->master;
+ if (tp->state == THREAD_WAIT_POLL)
+ {
+ chx_timer_dequeue (tp);
+ ((struct chx_stack_regs *)tp->tc.reg[REG_SP])->reg[REG_R0] = -1;
+ goto wakeup;
+ }
+ }
+ else
+ {
+ ((struct chx_stack_regs *)tp->tc.reg[REG_SP])->reg[REG_R0] = 0;
+ wakeup:
+ chx_ready_enqueue (tp);
+ if (tp->prio > running->prio)
+ yield = 1;
+ }
+
+ return yield;
+}
+
+
/* The RETVAL is saved into register R8. */
static void __attribute__((noreturn))
chx_exit (void *retval)
@@ -1281,35 +1312,6 @@ chopstx_cond_wait (chopstx_cond_t *cond, chopstx_mutex_t *mutex)
chopstx_mutex_lock (mutex);
}
-static int
-chx_wakeup (struct chx_thread *tp)
-{
- int yield = 0;
-
- if (tp->flag_is_proxy)
- {
- struct chx_px *px = (struct chx_px *)tp;
-
- (*px->counter_p)++;
- tp = px->master;
- if (tp->state == THREAD_WAIT_POLL)
- {
- chx_timer_dequeue (tp);
- ((struct chx_stack_regs *)tp->tc.reg[REG_SP])->reg[REG_R0] = -1;
- goto wakeup;
- }
- }
- else
- {
- ((struct chx_stack_regs *)tp->tc.reg[REG_SP])->reg[REG_R0] = 0;
- wakeup:
- chx_ready_enqueue (tp);
- if (tp->prio > running->prio)
- yield = 1;
- }
-
- return yield;
-}
/**
* chopstx_cond_signal - Wake up a thread waiting on the condition variable
@@ -1360,26 +1362,16 @@ chopstx_cond_broadcast (chopstx_cond_t *cond)
}
-/**
- * chopstx_cond_hook - Register a proxy to wait on the confition variable
- * @px: Proxy to a thread
- * @cond: Condition Variable
- * @mutex: Associated mutex
- * @func: Function to evaluate the condition
- * @arg: Argument to the @func
- *
- * If @func with @arg returns 0, register @px to wait for @cond with @mutex.
- */
-void
-chopstx_cond_hook (chopstx_px_t *px, chopstx_cond_t *cond,
- chopstx_mutex_t *mutex, int (*func) (void *), void *arg)
+static void
+chx_cond_hook (struct chx_px *px, chopstx_cond_t *cond,
+ chopstx_mutex_t *mutex, int (*check) (void *), void *arg)
{
chopstx_testcancel ();
if (mutex)
chopstx_mutex_lock (mutex);
- if ((*func) (arg) != 0)
+ if ((*check) (arg) != 0)
(*px->counter_p)++;
else
{ /* Condition doesn't met.
@@ -1396,15 +1388,8 @@ chopstx_cond_hook (chopstx_px_t *px, chopstx_cond_t *cond,
chopstx_mutex_unlock (mutex);
}
-/**
- * chopstx_cond_unhook - de-register a proxy to wait on the confition variable
- * @px: Proxy to a thread
- * @cond: Condition Variable
-
- * If @px is on @cond, dequeue it from it.
- */
-void
-chopstx_cond_unhook (chopstx_px_t *px, chopstx_cond_t *cond)
+static void
+chx_cond_unhook (struct chx_px *px, chopstx_cond_t *cond)
{
chx_cpu_sched_lock ();
if (px->parent == &cond->q)
@@ -1648,6 +1633,49 @@ chopstx_join (chopstx_t thd, void **ret)
}
+static void
+chx_join_hook (struct chx_px *px, chopstx_t thd)
+{
+ struct chx_thread *tp = (struct chx_thread *)thd;
+
+ chopstx_testcancel ();
+ chx_cpu_sched_lock ();
+
+ if (tp->flag_detached)
+ {
+ chx_cpu_sched_unlock ();
+ chx_fatal (CHOPSTX_ERR_JOIN);
+ }
+
+ if (tp->state == THREAD_EXITED)
+ (*px->counter_p)++;
+ else
+ { /* Not yet exited.
+ * Register the proxy to wait for TP's exit.
+ */
+ chx_cpu_sched_lock ();
+ px->v = (uint32_t)tp;
+ chx_spin_lock (&q_join.lock);
+ ll_prio_enqueue ((struct chx_pq *)px, &q_join.q);
+ chx_spin_unlock (&q_join.lock);
+ tp->flag_join_req = 1;
+ }
+ chx_cpu_sched_unlock ();
+}
+
+static void
+chx_join_unhook (struct chx_px *px)
+{
+ chx_cpu_sched_lock ();
+ if (px->parent == &q_join.q)
+ {
+ ll_dequeue ((struct chx_pq *)px);
+ px->parent = NULL;
+ }
+ chx_cpu_sched_unlock ();
+}
+
+
/**
* chopstx_wakeup_usec_wait - wakeup the sleeping thread for timer
* @thd: Thread to be awakened
@@ -1771,6 +1799,14 @@ chx_proxy_init (struct chx_px *px, uint32_t *cp)
}
+/**
+ * chopstx_poll - wait for condition variable or thread's exit
+ * @usec_p: Pointer to usec
+ * @n: Number of poll descriptors
+ * @VARARGS: Pointers to an object of struct chx_poll_desc
+ *
+ * Returns number of active descriptors.
+ */
int
chopstx_poll (uint32_t *usec_p, int n, ...)
{
@@ -1778,7 +1814,7 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
int i;
va_list ap;
struct chx_px px[n];
- chopstx_poll_fnc pollfnc;
+ struct chx_poll_desc *pd;
chopstx_testcancel ();
@@ -1788,8 +1824,11 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
va_start (ap, n);
for (i = 0; i < n; i++)
{
- pollfnc = va_arg (ap, chopstx_poll_fnc);
- (*pollfnc) (0, &px[i]);
+ pd = va_arg (ap, struct chx_poll_desc *);
+ if (pd->type == CHOPSTX_POLL_COND)
+ chx_cond_hook (&px[i], pd->c.cond, pd->c.mutex, pd->c.check, pd->c.arg);
+ else
+ chx_join_hook (&px[i], pd->j.thd);
}
va_end (ap);
@@ -1813,8 +1852,11 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
va_start (ap, n);
for (i = 0; i < n; i++)
{
- pollfnc = va_arg (ap, chopstx_poll_fnc);
- (*pollfnc) (1, &px[i]);
+ pd = va_arg (ap, struct chx_poll_desc *);
+ if (pd->type == CHOPSTX_POLL_COND)
+ chx_cond_unhook (&px[i], pd->c.cond);
+ else
+ chx_join_unhook (&px[i]);
}
va_end (ap);
diff --git a/chopstx.h b/chopstx.h
index cfbeae4..4b39a9c 100644
--- a/chopstx.h
+++ b/chopstx.h
@@ -135,20 +135,30 @@ void chopstx_cleanup_pop (int execute);
void chopstx_wakeup_usec_wait (chopstx_t thd);
-#define CHOPSTX_THREAD_SIZE 64
+enum {
+ CHOPSTX_POLL_COND = 0,
+ CHOPSTX_POLL_JOIN,
+};
-/* Proxy for the thread. */
-typedef struct chx_px chopstx_px_t;
+struct chx_poll_cond {
+ chopstx_cond_t *cond;
+ chopstx_mutex_t *mutex;
+ int (*check) (void *);
+ void *arg;
+};
-/* Like chopstx_cond_wait. Not to wait, but to register for notification. */
-void chopstx_cond_hook (chopstx_px_t *px, chopstx_cond_t *cond,
- chopstx_mutex_t *mutex, int (*func) (void *),
- void *arg);
-void chopstx_cond_unhook (chopstx_px_t *px, chopstx_cond_t *cond);
+struct chx_poll_join {
+ chopstx_t thd;
+};
-/* Like chopstx_join. Not to wait for the termination, but to register. */
-void chopstx_join_hook (chopstx_px_t *px, chopstx_t thd);
-void chopstx_join_unhook (chopstx_px_t *px, chopstx_t thd);
+struct chx_poll_desc {
+ int type;
+ union {
+ struct chx_poll_cond c;
+ struct chx_poll_join j;
+ };
+};
-typedef void (*chopstx_poll_fnc) (int reg_or_unreg, chopstx_px_t *px);
int chopstx_poll (uint32_t *usec_p, int n, ...);
+
+#define CHOPSTX_THREAD_SIZE 64
diff --git a/doc/chopstx-api.texi b/doc/chopstx-api.texi
index 6ccf6d8..72f2553 100644
--- a/doc/chopstx-api.texi
+++ b/doc/chopstx-api.texi
@@ -209,3 +209,13 @@ Calling chopstx_setcancelstate sets cancelability state.
Returns old state which is 0 when it was enabled.
@end deftypefun
+@subheading chopstx_poll
+@anchor{chopstx_poll}
+@deftypefun {int} {chopstx_poll} (uint32_t * @var{usec_p}, int @var{n}, @var{...})
+@var{usec_p}: Pointer to usec
+
+@var{n}: Number of poll descriptors
+
+Returns number of active descriptors.
+@end deftypefun
+
diff --git a/doc/chopstx.texi b/doc/chopstx.texi
index e1db02c..bb42256 100644
--- a/doc/chopstx.texi
+++ b/doc/chopstx.texi
@@ -11,7 +11,7 @@
This manual is for Chopstx (version @value{VERSION}).
@noindent
-Copyright @copyright{} 2013, 2015 Flying Stone Technology @*
+Copyright @copyright{} 2013, 2015, 2016 Flying Stone Technology @*
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -84,7 +84,7 @@ Indexes
@chapter Introduction
Chopstx is an RT thread library for ARM Cortex-M0 and Cortex-M3.
-Specifically, it is used for STM32F030 and STM32F103.
+Specifically, it is used for STM32F030, STM32F103, and MKL27Z.
While most RTOSes come with many features, drivers, and stacks,
Chopstx just offers a RT thread library.
diff --git a/example-fs-bb48/sample.c b/example-fs-bb48/sample.c
index e692f1f..fd71f21 100644
--- a/example-fs-bb48/sample.c
+++ b/example-fs-bb48/sample.c
@@ -152,7 +152,6 @@ static char hexchar (uint8_t x)
return '?';
}
-static struct stream *st;
static int
check_recv (void *arg)
@@ -165,18 +164,11 @@ check_recv (void *arg)
return 0;
}
-static void
-poll_for_stream (int reg_or_unreg, chopstx_px_t *px)
-{
- if (reg_or_unreg == 0)
- chopstx_cond_hook (px, &st->cnd, &st->mtx, check_recv, st);
- else
- chopstx_cond_unhook (px, &st->cnd);
-}
int
main (int argc, const char *argv[])
{
+ struct stream *st;
uint8_t count;
extern uint32_t bDeviceState;
@@ -212,6 +204,7 @@ main (int argc, const char *argv[])
{
uint8_t s[64];
+ u = 1;
if (stream_wait_connection (st) < 0)
{
chopstx_usec_wait (1000*1000);
@@ -235,10 +228,17 @@ main (int argc, const char *argv[])
{
int size;
uint32_t usec;
+ struct chx_poll_desc poll_desc;
+
+ poll_desc.type = CHOPSTX_POLL_COND;
+ poll_desc.c.cond = &st->cnd;
+ poll_desc.c.mutex = &st->mtx;
+ poll_desc.c.check = check_recv;
+ poll_desc.c.arg = st;
/* With chopstx_poll, we can do timed cond_wait */
usec = 3000000;
- if (chopstx_poll (&usec, 1, poll_for_stream))
+ if (chopstx_poll (&usec, 1, &poll_desc))
{
size = stream_recv (st, s + 4);