aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2016-05-13 16:35:35 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2016-05-13 16:35:35 +0900
commit5046dd45f2e675c37e505d42ecce746cb64b64f9 (patch)
tree3c1f7d860705d6e99984b571c15e76c2ded2b896
parentdb6e66852440a50e607c1df4cdf309c52a861430 (diff)
IRQ handling is now merged into polling
-rw-r--r--ChangeLog15
-rw-r--r--NEWS10
-rw-r--r--chopstx.c184
-rw-r--r--chopstx.h39
-rw-r--r--example-cdc/sample.c1
-rw-r--r--example-fs-bb48/sample.c1
-rw-r--r--example-primer2/primer2-ts.c4
7 files changed, 112 insertions, 142 deletions
diff --git a/ChangeLog b/ChangeLog
index f64d911..f763c72 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
2016-05-13 NIIBE Yutaka <gniibe@fsij.org>
+ * chopstx.c (chopstx_exit): Don't call chx_release_irq_thread.
+ (chx_release_irq_thread): Remove.
+ (q_intr): New variable.
+ (intr_top): Remove.
+ (chx_handle_intr, chx_init, chopstx_claim_irq)
+ (chopstx_intr_wait): Use Q_INTR.
+ (chx_intr_hook): New.
+ (chopstx_poll): Support CHOPSTX_POLL_INTR.
+ (chopstx_release_irq): Remove.
+ (chx_release_irq): New internal function.
+ (THREAD_WAIT_INT): Remove.
+ (chopstx_intr_wait): Remove, now offered as a macro.
+
+2016-05-13 NIIBE Yutaka <gniibe@fsij.org>
+
* chopstx.c (chx_sched) [__ARM_ARCH_6M__]: Fix asm.
(chx_handle_intr, chx_wakeup, chopstx_cancel): Fix for polling
with no timeout.
diff --git a/NEWS b/NEWS
index fb2166f..ad079b8 100644
--- a/NEWS
+++ b/NEWS
@@ -7,13 +7,19 @@ NEWS - Noteworthy changes
** New feature: polling
New function chopstx_poll is added to watch multiple condition
-variables simultaneously with timeout.
+variables, threads' exit, or IRQ simultaneously with timeout.
+
+** Remove the function chopstx_release_irq
+Releasing irq is now called automaticall, internally.
+
+** Function chopstx_intr_wait is deprecated
+It's now a macro with chopstx_poll.
** FS-BB48: Kinetis L MCU
Support for FS-BB48 board with Kinetis L MCU is added.
** No HardFault at context switch on Cortex-M0
-By its design, Chopstx does context switch hodling scheduler lock.
+By its design, Chopstx does context switch holding the scheduler lock.
This is implemented with the feature of BASEPRI on Cortex-M3. Because
Cortex-M0 doesn't have support of BASEPRI, the context switch (before
version 0.11) always caused HardFault exception. Since Cortex-M0
diff --git a/chopstx.c b/chopstx.c
index 3171215..ff9439d 100644
--- a/chopstx.c
+++ b/chopstx.c
@@ -239,12 +239,13 @@ static struct chx_queue q_ready;
/* Queue of threads waiting for timer. */
static struct chx_queue q_timer;
-/* Queue of threads which wait exit of some thread. */
+/* Queue of threads which wait for the exit of some thread. */
static struct chx_queue q_join;
/* Forward declaration(s). */
static void chx_request_preemption (uint16_t prio);
+static int chx_wakeup (struct chx_thread *tp);
/**************/
@@ -440,7 +441,6 @@ enum {
THREAD_WAIT_MTX,
THREAD_WAIT_CND,
THREAD_WAIT_TIME,
- THREAD_WAIT_INT,
THREAD_WAIT_POLL,
THREAD_JOIN,
/**/
@@ -612,44 +612,30 @@ chx_timer_expired (void)
chx_spin_unlock (&q_timer.lock);
}
-static chopstx_intr_t *intr_top;
-static struct chx_spinlock intr_lock;
+/* Queue of threads which wait for some interrupts. */
+static struct chx_queue q_intr;
void
chx_handle_intr (void)
{
- chopstx_intr_t *intr;
+ struct chx_pq *p;
register uint32_t irq_num;
asm volatile ("mrs %0, IPSR\n\t"
"sub %0, #16" /* Exception # - 16 = interrupt number. */
: "=r" (irq_num) : /* no input */ : "memory");
chx_disable_intr (irq_num);
- chx_spin_lock (&intr_lock);
- for (intr = intr_top; intr; intr = intr->next)
- if (intr->irq_num == irq_num)
- break;
-
- if (intr)
- {
- intr->ready++;
- if (intr->tp != running)
- {
- if (intr->tp->state == THREAD_WAIT_POLL)
- {
- if (intr->tp->parent == &q_timer.q)
- chx_timer_dequeue (intr->tp);
- chx_ready_enqueue (intr->tp);
- chx_request_preemption (intr->tp->prio);
- }
- else if (intr->tp->state == THREAD_WAIT_INT)
- {
- chx_ready_enqueue (intr->tp);
- chx_request_preemption (intr->tp->prio);
- }
- }
- }
- chx_spin_unlock (&intr_lock);
+ chx_spin_lock (&q_intr.lock);
+ for (p = q_intr.q.next; p != (struct chx_pq *)&q_intr.q; p = p->next)
+ if (p->v == irq_num)
+ { /* should be one at most. */
+ struct chx_thread *tp = (struct chx_thread *)p;
+
+ ll_dequeue (p);
+ chx_wakeup (tp);
+ break;
+ }
+ chx_spin_unlock (&q_intr.lock);
}
void
@@ -672,7 +658,6 @@ chopstx_t chopstx_main;
void
chx_init (struct chx_thread *tp)
{
- chx_spin_init (&intr_lock);
chx_prio_init ();
memset (&tp->tc, 0, sizeof (tp->tc));
q_ready.q.next = q_ready.q.prev = (struct chx_pq *)&q_ready.q;
@@ -681,6 +666,8 @@ chx_init (struct chx_thread *tp)
chx_spin_init (&q_timer.lock);
q_join.q.next = q_join.q.prev = (struct chx_pq *)&q_join.q;
chx_spin_init (&q_join.lock);
+ q_intr.q.next = q_intr.q.prev = (struct chx_pq *)&q_intr.q;
+ chx_spin_init (&q_intr.lock);
tp->next = tp->prev = (struct chx_pq *)tp;
tp->mutex_list = NULL;
tp->clp = NULL;
@@ -1421,6 +1408,19 @@ chx_cond_hook (struct chx_px *px, struct chx_poll_head *pd)
}
+/*
+ * Release the interrupt request.
+ */
+static void
+chx_release_irq (chopstx_intr_t *intr)
+{
+ chx_cpu_sched_lock ();
+ chx_spin_lock (&q_intr.lock);
+ chx_enable_intr (intr->irq_num);
+ chx_spin_unlock (&q_intr.lock);
+ chx_cpu_sched_unlock ();
+}
+
/**
* chopstx_claim_irq - Claim interrupt request to handle by this thread
* @intr: Pointer to INTR structure
@@ -1432,105 +1432,48 @@ 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;
+ intr->irq_num = irq_num;
+ intr->cln.routine = (void (*)(void *))chx_release_irq;
+ intr->cln.arg = (void *)intr;
+ chopstx_cleanup_push (&intr->cln);
+
chx_cpu_sched_lock ();
+ chx_spin_lock (&q_intr.lock);
chx_disable_intr (irq_num);
chx_set_intr_prio (irq_num);
- chx_spin_lock (&intr_lock);
- intr->next = intr_top;
- intr_top = intr;
- chx_spin_unlock (&intr_lock);
- chx_cpu_sched_unlock ();
-}
-
-
-/**
- * chopstx_realease_irq - Unregister interrupt request
- * @intr0: Interrupt request to be unregistered
- *
- * Release the interrupt request specified by @intr0.
- */
-void
-chopstx_release_irq (chopstx_intr_t *intr0)
-{
- chopstx_intr_t *intr, *intr_prev;
-
- chx_cpu_sched_lock ();
- chx_enable_intr (intr0->irq_num);
- chx_spin_lock (&intr_lock);
- intr_prev = intr_top;
- for (intr = intr_top; intr; intr = intr->next)
- if (intr == intr0)
- break;
-
- if (intr == intr_top)
- intr_top = intr_top->next;
- else
- intr_prev->next = intr->next;
- chx_spin_unlock (&intr_lock);
+ chx_spin_unlock (&q_intr.lock);
chx_cpu_sched_unlock ();
}
static void
-chx_release_irq_thread (struct chx_thread *tp)
+chx_intr_hook (struct chx_px *px, struct chx_poll_head *pd)
{
- chopstx_intr_t *intr, *intr_prev;
+ struct chx_intr *intr = (struct chx_intr *)pd;
+ chopstx_testcancel ();
chx_cpu_sched_lock ();
- chx_spin_lock (&intr_lock);
- intr_prev = intr_top;
- for (intr = intr_top; intr; intr = intr->next)
+ if (intr->ready)
{
- if (intr->tp == tp)
- break;
- intr_prev = intr;
+ chx_spin_lock (&px->lock);
+ (*px->counter_p)++;
+ *px->ready_p = 1;
+ chx_spin_unlock (&px->lock);
}
-
- if (intr)
+ else
{
+ px->v = intr->irq_num;
+ chx_spin_lock (&q_intr.lock);
chx_enable_intr (intr->irq_num);
- if (intr == intr_top)
- intr_top = intr_top->next;
- else
- intr_prev->next = intr->next;
+ ll_prio_enqueue ((struct chx_pq *)px, &q_intr.q);
+ chx_spin_unlock (&q_intr.lock);
}
- chx_spin_unlock (&intr_lock);
chx_cpu_sched_unlock ();
}
/**
- * chopstx_intr_wait - Wait for interrupt request from hardware
- * @intr: Pointer to INTR structure
- *
- * Wait for the interrupt @intr to be occured.
- */
-void
-chopstx_intr_wait (chopstx_intr_t *intr)
-{
- chopstx_testcancel ();
- chx_cpu_sched_lock ();
- if (intr->ready == 0)
- {
- chx_enable_intr (intr->irq_num);
- if (running->flag_sched_rr)
- chx_timer_dequeue (running);
- running->state = THREAD_WAIT_INT;
- running->parent = NULL;
- running->v = 0;
- chx_sched (CHX_SLEEP);
- chx_clr_intr (intr->irq_num);
- }
- else
- chx_cpu_sched_unlock ();
- intr->ready--;
-}
-
-
-/**
* chopstx_cleanup_push - Register a clean-up
* @clp: Pointer to clean-up structure
*
@@ -1598,7 +1541,6 @@ chopstx_exit (void *retval)
chx_cpu_sched_unlock ();
}
- chx_release_irq_thread (running);
chx_exit (retval);
}
@@ -1742,8 +1684,8 @@ chopstx_cancel (chopstx_t thd)
}
/* Cancellation points: cond_wait, intr_wait, and usec_wait. */
- if (tp->state == THREAD_WAIT_CND || tp->state == THREAD_WAIT_INT
- || tp->state == THREAD_WAIT_TIME || tp->state == THREAD_WAIT_POLL)
+ if (tp->state == THREAD_WAIT_CND || tp->state == THREAD_WAIT_TIME
+ || tp->state == THREAD_WAIT_POLL)
{
/* Throw away registers on stack and direct to chopstx_exit. */
/* This is pretty much violent, but it works. */
@@ -1823,11 +1765,11 @@ 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
+ * chopstx_poll - wait for condition variable, thread's exit, or IRQ
+ * @usec_p: Pointer to usec for timeout. Forever if NULL.
* @n: Number of poll descriptors
* @VARARGS: Pointers to an object which should be one of:
- * struct chx_poll_cond, chx_poll_join, or chx_intr.
+ * chopstx_poll_cond_t, chopstx_poll_join_t, or chopstx_intr_t.
*
* Returns number of active descriptors.
*/
@@ -1851,6 +1793,8 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
pd = va_arg (ap, struct chx_poll_head *);
if (pd->type == CHOPSTX_POLL_COND)
chx_cond_hook (&px[i], pd);
+ else if (pd->type == CHOPSTX_POLL_INTR)
+ chx_intr_hook (&px[i], pd);
else
chx_join_hook (&px[i], pd);
px[i].ready_p = &pd->ready;
@@ -1864,7 +1808,7 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
chx_spin_unlock (&px->lock);
chx_cpu_sched_unlock ();
}
- else if (*usec_p == 0)
+ else if (usec_p == NULL)
{
if (running->flag_sched_rr)
chx_timer_dequeue (running);
@@ -1888,14 +1832,24 @@ 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_head *);
+ if (pd->type == CHOPSTX_POLL_INTR)
+ {
+ struct chx_intr *intr = (struct chx_intr *)pd;
+ if (intr->ready)
+ chx_clr_intr (intr->irq_num);
+ }
+
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;
}
diff --git a/chopstx.h b/chopstx.h
index b3b257f..a9c2bcc 100644
--- a/chopstx.h
+++ b/chopstx.h
@@ -82,21 +82,6 @@ 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);
-struct chx_intr {
- uint16_t type;
- uint16_t ready;
- /**/
- struct chx_intr *next;
- struct chx_thread *tp;
- uint8_t irq_num;
-};
-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);
-
-void chopstx_intr_wait (chopstx_intr_t *intr);
-
/*
* Library provides default implementation as weak reference.
* User can replace it.
@@ -125,14 +110,14 @@ void chopstx_testcancel (void);
/* NOTE: This signature is different to PTHREAD's one. */
int chopstx_setcancelstate (int);
-struct chx_cleanup {
+typedef struct chx_cleanup {
struct chx_cleanup *next;
void (*routine) (void *);
void *arg;
-};
+} chopstx_cleanup_t;
/* NOTE: This signature is different to PTHREAD's one. */
-void chopstx_cleanup_push (struct chx_cleanup *clp);
+void chopstx_cleanup_push (chopstx_cleanup_t *clp);
void chopstx_cleanup_pop (int execute);
@@ -140,8 +125,8 @@ void chopstx_wakeup_usec_wait (chopstx_t thd);
enum {
CHOPSTX_POLL_COND = 0,
- CHOPSTX_POLL_JOIN,
CHOPSTX_POLL_INTR,
+ CHOPSTX_POLL_JOIN,
};
struct chx_poll_cond {
@@ -153,6 +138,7 @@ struct chx_poll_cond {
int (*check) (void *);
void *arg;
};
+typedef struct chx_poll_cond chopstx_poll_cond_t;
struct chx_poll_join {
uint16_t type;
@@ -160,6 +146,21 @@ struct chx_poll_join {
/**/
chopstx_t thd;
};
+typedef struct chx_poll_join chopstx_poll_join_t;
+
+struct chx_intr {
+ uint16_t type;
+ uint16_t ready;
+ /**/
+ uint8_t irq_num;
+ struct chx_cleanup cln;
+};
+typedef struct chx_intr chopstx_intr_t;
+
+void chopstx_claim_irq (chopstx_intr_t *intr, uint8_t irq_num);
+
+#define chopstx_intr_wait(intr) chopstx_poll (NULL, 1, intr)
+
struct chx_poll_head {
uint16_t type;
diff --git a/example-cdc/sample.c b/example-cdc/sample.c
index d2951fc..ee6d23f 100644
--- a/example-cdc/sample.c
+++ b/example-cdc/sample.c
@@ -92,7 +92,6 @@ usb_intr (void *arg)
usb_interrupt_handler ();
}
- chopstx_release_irq (&interrupt);
return NULL;
}
diff --git a/example-fs-bb48/sample.c b/example-fs-bb48/sample.c
index 39864d4..9250700 100644
--- a/example-fs-bb48/sample.c
+++ b/example-fs-bb48/sample.c
@@ -115,7 +115,6 @@ usb_intr (void *arg)
usb_interrupt_handler ();
}
- chopstx_release_irq (&interrupt);
return NULL;
}
diff --git a/example-primer2/primer2-ts.c b/example-primer2/primer2-ts.c
index eb1c4ec..c6952f1 100644
--- a/example-primer2/primer2-ts.c
+++ b/example-primer2/primer2-ts.c
@@ -113,10 +113,6 @@ void adc3_conversion (uint32_t *result)
void adc3_stop (void)
{
-#if USE_ADC3_INTR
- chopstx_release_irq (&adc3_intr);
-#endif
-
/* Power off. */
ADC3->CR1 = 0;
ADC3->CR2 = 0;