diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2016-04-22 13:42:01 +0900 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2016-04-22 13:42:01 +0900 |
commit | 1b12a780548cff613e9eaa5cdef0e4a9429441cb (patch) | |
tree | 81289093481837da3064036ddc589071b6401dbf | |
parent | 5d40ffbffad4b3f102a6d4cf975d7a49a6dcdb92 (diff) |
Modify chopstx_poll API
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | chopstx.c | 156 | ||||
-rw-r--r-- | chopstx.h | 34 | ||||
-rw-r--r-- | doc/chopstx-api.texi | 10 | ||||
-rw-r--r-- | doc/chopstx.texi | 4 | ||||
-rw-r--r-- | example-fs-bb48/sample.c | 20 |
6 files changed, 154 insertions, 81 deletions
@@ -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. @@ -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); @@ -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); |