Modify chopstx_poll API

This commit is contained in:
NIIBE Yutaka
2016-04-22 13:42:01 +09:00
parent 5d40ffbffa
commit 1b12a78054
6 changed files with 154 additions and 81 deletions

View File

@@ -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> 2016-04-21 Niibe Yutaka <gniibe@fsij.org>
* chopstx.c (chx_snooze, chx_wakeup): New. * chopstx.c (chx_snooze, chx_wakeup): New.

156
chopstx.c
View File

@@ -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. */ /* The RETVAL is saved into register R8. */
static void __attribute__((noreturn)) static void __attribute__((noreturn))
chx_exit (void *retval) chx_exit (void *retval)
@@ -1281,35 +1312,6 @@ chopstx_cond_wait (chopstx_cond_t *cond, chopstx_mutex_t *mutex)
chopstx_mutex_lock (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 * chopstx_cond_signal - Wake up a thread waiting on the condition variable
@@ -1360,26 +1362,16 @@ chopstx_cond_broadcast (chopstx_cond_t *cond)
} }
/** static void
* chopstx_cond_hook - Register a proxy to wait on the confition variable chx_cond_hook (struct chx_px *px, chopstx_cond_t *cond,
* @px: Proxy to a thread chopstx_mutex_t *mutex, int (*check) (void *), void *arg)
* @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)
{ {
chopstx_testcancel (); chopstx_testcancel ();
if (mutex) if (mutex)
chopstx_mutex_lock (mutex); chopstx_mutex_lock (mutex);
if ((*func) (arg) != 0) if ((*check) (arg) != 0)
(*px->counter_p)++; (*px->counter_p)++;
else else
{ /* Condition doesn't met. { /* Condition doesn't met.
@@ -1396,15 +1388,8 @@ chopstx_cond_hook (chopstx_px_t *px, chopstx_cond_t *cond,
chopstx_mutex_unlock (mutex); chopstx_mutex_unlock (mutex);
} }
/** static void
* chopstx_cond_unhook - de-register a proxy to wait on the confition variable chx_cond_unhook (struct chx_px *px, chopstx_cond_t *cond)
* @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)
{ {
chx_cpu_sched_lock (); chx_cpu_sched_lock ();
if (px->parent == &cond->q) 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 * chopstx_wakeup_usec_wait - wakeup the sleeping thread for timer
* @thd: Thread to be awakened * @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 int
chopstx_poll (uint32_t *usec_p, int n, ...) chopstx_poll (uint32_t *usec_p, int n, ...)
{ {
@@ -1778,7 +1814,7 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
int i; int i;
va_list ap; va_list ap;
struct chx_px px[n]; struct chx_px px[n];
chopstx_poll_fnc pollfnc; struct chx_poll_desc *pd;
chopstx_testcancel (); chopstx_testcancel ();
@@ -1788,8 +1824,11 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
va_start (ap, n); va_start (ap, n);
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
pollfnc = va_arg (ap, chopstx_poll_fnc); pd = va_arg (ap, struct chx_poll_desc *);
(*pollfnc) (0, &px[i]); 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); va_end (ap);
@@ -1813,8 +1852,11 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
va_start (ap, n); va_start (ap, n);
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
pollfnc = va_arg (ap, chopstx_poll_fnc); pd = va_arg (ap, struct chx_poll_desc *);
(*pollfnc) (1, &px[i]); if (pd->type == CHOPSTX_POLL_COND)
chx_cond_unhook (&px[i], pd->c.cond);
else
chx_join_unhook (&px[i]);
} }
va_end (ap); va_end (ap);

View File

@@ -135,20 +135,30 @@ void chopstx_cleanup_pop (int execute);
void chopstx_wakeup_usec_wait (chopstx_t thd); 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. */ struct chx_poll_cond {
typedef struct chx_px chopstx_px_t; 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. */ struct chx_poll_join {
void chopstx_cond_hook (chopstx_px_t *px, chopstx_cond_t *cond, chopstx_t thd;
chopstx_mutex_t *mutex, int (*func) (void *), };
void *arg);
void chopstx_cond_unhook (chopstx_px_t *px, chopstx_cond_t *cond);
/* Like chopstx_join. Not to wait for the termination, but to register. */ struct chx_poll_desc {
void chopstx_join_hook (chopstx_px_t *px, chopstx_t thd); int type;
void chopstx_join_unhook (chopstx_px_t *px, chopstx_t thd); 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, ...); int chopstx_poll (uint32_t *usec_p, int n, ...);
#define CHOPSTX_THREAD_SIZE 64

View File

@@ -209,3 +209,13 @@ Calling chopstx_setcancelstate sets cancelability state.
Returns old state which is 0 when it was enabled. Returns old state which is 0 when it was enabled.
@end deftypefun @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

View File

@@ -11,7 +11,7 @@
This manual is for Chopstx (version @value{VERSION}). This manual is for Chopstx (version @value{VERSION}).
@noindent @noindent
Copyright @copyright{} 2013, 2015 Flying Stone Technology @* Copyright @copyright{} 2013, 2015, 2016 Flying Stone Technology @*
@quotation @quotation
Permission is granted to copy, distribute and/or modify this document Permission is granted to copy, distribute and/or modify this document
@@ -84,7 +84,7 @@ Indexes
@chapter Introduction @chapter Introduction
Chopstx is an RT thread library for ARM Cortex-M0 and Cortex-M3. 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, While most RTOSes come with many features, drivers, and stacks,
Chopstx just offers a RT thread library. Chopstx just offers a RT thread library.

View File

@@ -152,7 +152,6 @@ static char hexchar (uint8_t x)
return '?'; return '?';
} }
static struct stream *st;
static int static int
check_recv (void *arg) check_recv (void *arg)
@@ -165,18 +164,11 @@ check_recv (void *arg)
return 0; 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 int
main (int argc, const char *argv[]) main (int argc, const char *argv[])
{ {
struct stream *st;
uint8_t count; uint8_t count;
extern uint32_t bDeviceState; extern uint32_t bDeviceState;
@@ -212,6 +204,7 @@ main (int argc, const char *argv[])
{ {
uint8_t s[64]; uint8_t s[64];
u = 1;
if (stream_wait_connection (st) < 0) if (stream_wait_connection (st) < 0)
{ {
chopstx_usec_wait (1000*1000); chopstx_usec_wait (1000*1000);
@@ -235,10 +228,17 @@ main (int argc, const char *argv[])
{ {
int size; int size;
uint32_t usec; 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 */ /* With chopstx_poll, we can do timed cond_wait */
usec = 3000000; usec = 3000000;
if (chopstx_poll (&usec, 1, poll_for_stream)) if (chopstx_poll (&usec, 1, &poll_desc))
{ {
size = stream_recv (st, s + 4); size = stream_recv (st, s + 4);