summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2016-05-13 14:22:12 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2016-05-13 14:22:12 +0900
commitdaa7aebd6f774de5079b0d3c211293db597084fc (patch)
treecc1cf2b339d128200ec7770af82f1357061acc5e
parent5fc2617ae5d16b7f6f4fb00a617d14888d6c74cc (diff)
Add READY field for chx_poll_XXX so that we can check if it's ready
-rw-r--r--ChangeLog17
-rw-r--r--chopstx.c151
-rw-r--r--chopstx.h25
-rw-r--r--example-cdc/sample.c11
-rw-r--r--example-fs-bb48/sample.c11
5 files changed, 132 insertions, 83 deletions
diff --git a/ChangeLog b/ChangeLog
index e0ea3e6..aa452dc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2016-05-13 NIIBE Yutaka <gniibe@fsij.org>
+
+ * chopstx.c (chx_sched) [__ARM_ARCH_6M__]: Fix asm.
+
+ * example-cdc/sample.c (main): Update chopstx_poll example.
+ * example-fs-bb48/sample.c (main): Ditto.
+
+ * chopstx.c (struct chx_px): Add READY_P and LOCK.
+ (chx_proxy_init): Add initialization of new members.
+ (chx_wakeup): Spinlock PX.
+ (chopstx_mutex_lock): Add protection by splinlock.
+ (chx_cond_hook, chx_join_hook): Change arguments.
+ (chx_cond_unhook, chx_join_unhook): Remove.
+ (chopstx_claim_irq): Compatible to chx_poll.
+ (chopstx_join): Fix spinlocking.
+ (chopstx_cancel): Fix spinlocking.
+
2016-05-12 NIIBE Yutaka <gniibe@fsij.org>
* example-cdc/sample.c: Update using chopstx_poll.
diff --git a/chopstx.c b/chopstx.c
index 53b1919..14d3f82 100644
--- a/chopstx.c
+++ b/chopstx.c
@@ -315,6 +315,8 @@ struct chx_px { /* inherits PQ */
uint32_t v;
struct chx_thread *master;
uint32_t *counter_p;
+ uint16_t *ready_p;
+ struct chx_spinlock lock; /* spinlock to update the COUNTER */
};
struct chx_thread { /* inherits PQ */
@@ -791,7 +793,7 @@ chx_sched (uint32_t yield)
"mov r2, r1\n\t"
"mov r3, r1\n\t"
"push {r1, r2, r3}\n\t"
- "push {%1, r1}"
+ "push {%0, r1}"
: /* no output*/
: "r" (yield)
: "r1", "r2", "r3", "memory");
@@ -876,7 +878,7 @@ chx_sched (uint32_t yield)
24: pc
28: psr
32: possibly exists for alignment
- [28 or 32] <-- pc
+ [28 or 32] <-- pc
*/
"ldr r0, [sp, #28]\n\t"
"lsl r1, r0, #23\n\t"
@@ -930,19 +932,23 @@ chx_wakeup (struct chx_thread *tp)
{
struct chx_px *px = (struct chx_px *)tp;
+ chx_spin_lock (&px->lock);
(*px->counter_p)++;
+ *px->ready_p = 1;
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;
+ chx_ready_enqueue (tp);
+ if (tp->prio > running->prio)
+ yield = 1;
}
+ chx_spin_unlock (&px->lock);
}
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;
@@ -1213,16 +1219,31 @@ chopstx_mutex_lock (chopstx_mutex_t *mutex)
while (1)
{ /* Priority inheritance. */
owner->prio = tp->prio;
- if (owner->state == THREAD_READY || owner->state == THREAD_WAIT_CND)
+ if (owner->state == THREAD_READY)
{
+ chx_spin_lock (&q_ready.lock);
ll_prio_enqueue (ll_dequeue ((struct chx_pq *)owner),
owner->parent);
+ chx_spin_unlock (&q_ready.lock);
break;
}
+ if (owner->state == THREAD_WAIT_CND)
+ {
+ struct chx_cond *cond = (struct chx_cond *)owner->parent;
+
+ chx_spin_lock (&cond->lock);
+ ll_prio_enqueue (ll_dequeue ((struct chx_pq *)owner),
+ owner->parent);
+ chx_spin_unlock (&cond->lock);
+ }
else if (owner->state == THREAD_WAIT_MTX)
{
+ struct chx_mtx *mutex = (struct chx_mtx *)owner->parent;
+
+ chx_spin_lock (&mutex->lock);
ll_prio_enqueue (ll_dequeue ((struct chx_pq *)owner),
owner->parent);
+ chx_spin_unlock (&mutex->lock);
owner = m->owner;
continue;
}
@@ -1370,41 +1391,35 @@ chopstx_cond_broadcast (chopstx_cond_t *cond)
static void
-chx_cond_hook (struct chx_px *px, chopstx_cond_t *cond,
- chopstx_mutex_t *mutex, int (*check) (void *), void *arg)
+chx_cond_hook (struct chx_px *px, struct chx_poll_head *pd)
{
+ struct chx_poll_cond *pc = (struct chx_poll_cond *)pd;
+
chopstx_testcancel ();
- if (mutex)
- chopstx_mutex_lock (mutex);
+ if (pc->mutex)
+ chopstx_mutex_lock (pc->mutex);
- if ((*check) (arg) != 0)
- (*px->counter_p)++;
+ if ((*pc->check) (pc->arg) != 0)
+ {
+ chx_spin_lock (&px->lock);
+ (*px->counter_p)++;
+ *px->ready_p = 1;
+ chx_spin_unlock (&px->lock);
+ }
else
{ /* Condition doesn't met.
* Register the proxy to wait for the condition.
*/
chx_cpu_sched_lock ();
- chx_spin_lock (&cond->lock);
- ll_prio_enqueue ((struct chx_pq *)px, &cond->q);
- chx_spin_unlock (&cond->lock);
+ chx_spin_lock (&pc->cond->lock);
+ ll_prio_enqueue ((struct chx_pq *)px, &pc->cond->q);
+ chx_spin_unlock (&pc->cond->lock);
chx_cpu_sched_unlock ();
}
- if (mutex)
- chopstx_mutex_unlock (mutex);
-}
-
-static void
-chx_cond_unhook (struct chx_px *px, chopstx_cond_t *cond)
-{
- chx_cpu_sched_lock ();
- if (px->parent == &cond->q)
- {
- ll_dequeue ((struct chx_pq *)px);
- px->parent = NULL;
- }
- chx_cpu_sched_unlock ();
+ if (pc->mutex)
+ chopstx_mutex_unlock (pc->mutex);
}
@@ -1418,6 +1433,7 @@ chx_cond_unhook (struct chx_px *px, chopstx_cond_t *cond)
void
chopstx_claim_irq (chopstx_intr_t *intr, uint8_t irq_num)
{
+ intr->type = CHOPSTX_POLL_INTR;
intr->irq_num = irq_num;
intr->tp = running;
intr->ready = 0;
@@ -1620,7 +1636,6 @@ chopstx_join (chopstx_t thd, void **ret)
ll_prio_enqueue ((struct chx_pq *)running, &q_join.q);
running->v = (uint32_t)tp;
running->state = THREAD_JOIN;
- chx_spin_unlock (&q_join.lock);
tp->flag_join_req = 1;
if (tp->prio < running->prio)
{
@@ -1629,6 +1644,7 @@ chopstx_join (chopstx_t thd, void **ret)
|| tp->state == THREAD_WAIT_MTX || tp->state == THREAD_WAIT_CND)
ll_prio_enqueue (ll_dequeue ((struct chx_pq *)tp), tp->parent);
}
+ chx_spin_unlock (&q_join.lock);
chx_sched (CHX_SLEEP);
}
else
@@ -1641,9 +1657,10 @@ chopstx_join (chopstx_t thd, void **ret)
static void
-chx_join_hook (struct chx_px *px, chopstx_t thd)
+chx_join_hook (struct chx_px *px, struct chx_poll_head *pd)
{
- struct chx_thread *tp = (struct chx_thread *)thd;
+ struct chx_poll_join *pj = (struct chx_poll_join *)pd;
+ struct chx_thread *tp = (struct chx_thread *)pj->thd;
chopstx_testcancel ();
chx_cpu_sched_lock ();
@@ -1655,12 +1672,16 @@ chx_join_hook (struct chx_px *px, chopstx_t thd)
}
if (tp->state == THREAD_EXITED)
- (*px->counter_p)++;
+ {
+ chx_spin_lock (&px->lock);
+ (*px->counter_p)++;
+ *px->ready_p = 1;
+ chx_spin_unlock (&px->lock);
+ }
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);
@@ -1670,18 +1691,6 @@ chx_join_hook (struct chx_px *px, chopstx_t thd)
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
@@ -1745,7 +1754,13 @@ chopstx_cancel (chopstx_t thd)
p->reg[REG_PC] = (uint32_t)chopstx_exit;
if (tp->state == THREAD_WAIT_CND)
- ll_dequeue ((struct chx_pq *)tp);
+ {
+ struct chx_cond *cond = (struct chx_cond *)tp->parent;
+
+ chx_spin_lock (&cond->lock);
+ ll_dequeue ((struct chx_pq *)tp);
+ chx_spin_unlock (&cond->lock);
+ }
else if (tp->state == THREAD_WAIT_TIME || tp->state == THREAD_WAIT_POLL)
chx_timer_dequeue (tp);
@@ -1778,7 +1793,7 @@ chopstx_testcancel (void)
/**
* chopstx_setcancelstate - set cancelability state
* @cancel_disable: 0 to enable cancelation, otherwise disabled.
- *
+ *
* Calling chopstx_setcancelstate sets cancelability state.
*
* Returns old state which is 0 when it was enabled.
@@ -1803,6 +1818,8 @@ chx_proxy_init (struct chx_px *px, uint32_t *cp)
px->v = 0;
px->master = running;
px->counter_p = cp;
+ px->ready_p = NULL;
+ chx_spin_init (&px->lock);
}
@@ -1810,7 +1827,8 @@ 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
+ * @VARARGS: Pointers to an object which should be one of:
+ * struct chx_poll_cond, chx_poll_join, or chx_intr.
*
* Returns number of active descriptors.
*/
@@ -1821,7 +1839,7 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
int i;
va_list ap;
struct chx_px px[n];
- struct chx_poll_desc *pd;
+ struct chx_poll_head *pd;
chopstx_testcancel ();
@@ -1831,29 +1849,36 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
va_start (ap, n);
for (i = 0; i < n; 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);
+ pd = va_arg (ap, struct chx_poll_head *);
+ if (pd->type == CHOPSTX_POLL_COND)
+ chx_cond_hook (&px[i], pd);
else
- chx_join_hook (&px[i], pd->j.thd);
+ chx_join_hook (&px[i], pd);
+ px[i].ready_p = &pd->ready;
}
va_end (ap);
chx_cpu_sched_lock ();
+ chx_spin_lock (&px->lock);
if (counter)
- chx_cpu_sched_unlock ();
+ {
+ chx_spin_unlock (&px->lock);
+ chx_cpu_sched_unlock ();
+ }
else if (*usec_p == 0)
{
if (running->flag_sched_rr)
chx_timer_dequeue (running);
running->state = THREAD_WAIT_POLL;
+ chx_spin_unlock (&px->lock);
chx_sched (CHX_SLEEP);
}
else
{
int r;
+ chx_spin_unlock (&px->lock);
chx_cpu_sched_unlock ();
do
{
@@ -1864,23 +1889,21 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
while (r == 0);
}
- va_start (ap, n);
for (i = 0; i < n; 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]);
+ chx_cpu_sched_lock ();
+ chx_spin_lock (&px[i].lock);
+ ll_dequeue ((struct chx_pq *)&px[i]);
+ chx_spin_unlock (&px[i].lock);
+ chx_cpu_sched_unlock ();
}
- va_end (ap);
- return counter; /* Bitmap??? */
+ return counter;
}
/*
* Lower layer architecture specific exception handling entries.
- *
+ *
*/
void __attribute__ ((naked))
@@ -1923,7 +1946,7 @@ preempt (void)
* Memory clobber constraint here is not accurate, but this
* works. R7 keeps its value, but having "r7" here prevents
* use of R7 before this asm statement.
- */
+ */
: "r2", "r3", "r4", "r5", "r6", "r7", "memory");
if (tp)
diff --git a/chopstx.h b/chopstx.h
index 4b39a9c..b3b257f 100644
--- a/chopstx.h
+++ b/chopstx.h
@@ -82,12 +82,15 @@ void chopstx_cond_wait (chopstx_cond_t *cond, chopstx_mutex_t *mutex);
void chopstx_cond_signal (chopstx_cond_t *cond);
void chopstx_cond_broadcast (chopstx_cond_t *cond);
-typedef struct chx_intr {
+struct chx_intr {
+ uint16_t type;
+ uint16_t ready;
+ /**/
struct chx_intr *next;
struct chx_thread *tp;
- uint32_t ready;
uint8_t irq_num;
-} chopstx_intr_t;
+};
+typedef struct chx_intr chopstx_intr_t;
void chopstx_claim_irq (chopstx_intr_t *intr, uint8_t irq_num);
void chopstx_release_irq (chopstx_intr_t *intr);
@@ -138,9 +141,13 @@ void chopstx_wakeup_usec_wait (chopstx_t thd);
enum {
CHOPSTX_POLL_COND = 0,
CHOPSTX_POLL_JOIN,
+ CHOPSTX_POLL_INTR,
};
struct chx_poll_cond {
+ uint16_t type;
+ uint16_t ready;
+ /**/
chopstx_cond_t *cond;
chopstx_mutex_t *mutex;
int (*check) (void *);
@@ -148,15 +155,15 @@ struct chx_poll_cond {
};
struct chx_poll_join {
+ uint16_t type;
+ uint16_t ready;
+ /**/
chopstx_t thd;
};
-struct chx_poll_desc {
- int type;
- union {
- struct chx_poll_cond c;
- struct chx_poll_join j;
- };
+struct chx_poll_head {
+ uint16_t type;
+ uint16_t ready;
};
int chopstx_poll (uint32_t *usec_p, int n, ...);
diff --git a/example-cdc/sample.c b/example-cdc/sample.c
index 17b7cd5..d2951fc 100644
--- a/example-cdc/sample.c
+++ b/example-cdc/sample.c
@@ -201,13 +201,14 @@ main (int argc, const char *argv[])
{
int size;
uint32_t usec;
- struct chx_poll_desc poll_desc;
+ struct chx_poll_cond 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;
+ poll_desc.ready = 0;
+ poll_desc.cond = &st->cnd;
+ poll_desc.mutex = &st->mtx;
+ poll_desc.check = check_recv;
+ poll_desc.arg = st;
/* With chopstx_poll, we can do timed cond_wait */
usec = 3000000; /* 3.0 seconds */
diff --git a/example-fs-bb48/sample.c b/example-fs-bb48/sample.c
index b224003..39864d4 100644
--- a/example-fs-bb48/sample.c
+++ b/example-fs-bb48/sample.c
@@ -232,13 +232,14 @@ main (int argc, const char *argv[])
{
int size;
uint32_t usec;
- struct chx_poll_desc poll_desc;
+ struct chx_poll_cond 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;
+ poll_desc.ready = 0;
+ poll_desc.cond = &st->cnd;
+ poll_desc.mutex = &st->mtx;
+ poll_desc.check = check_recv;
+ poll_desc.arg = st;
/* With chopstx_poll, we can do timed cond_wait */
usec = 3000000;