Modify chopstx_poll API
This commit is contained in:
11
ChangeLog
11
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>
|
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
156
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. */
|
/* 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);
|
||||||
|
|
||||||
|
|||||||
34
chopstx.h
34
chopstx.h
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user