aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2013-05-27 09:08:17 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2013-05-27 09:08:17 +0900
commitb0cfda694f030d0b160a074c1d7f99bb12cbbcbf (patch)
treeae86341eee81b055b085205f6795331e81361ebe
parentcf4a340023cda2819d11d2911bbf983bb6be9240 (diff)
Add join and exit
-rw-r--r--ChangeLog4
-rw-r--r--chopstx.c82
-rw-r--r--chopstx.h9
-rw-r--r--example-cdc/sample.c2
4 files changed, 86 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 38609ef..74bf763 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-05-27 Niibe Yutaka <gniibe@fsij.org>
+
+ * chopstx.c (chx_fatal, chopstx_exit, chopstx_join): New.
+
2013-05-24 Niibe Yutaka <gniibe@fsij.org>
* chopstx.c (chx_request_preemption): Rename from chx_preempt.
diff --git a/chopstx.c b/chopstx.c
index c7ef882..41dd603 100644
--- a/chopstx.c
+++ b/chopstx.c
@@ -31,6 +31,14 @@
#include <string.h>
#include <chopstx.h>
+void __attribute__((weak))
+chx_fatal (uint32_t err_code)
+{
+ (void)err_code;
+ for (;;);
+}
+
+
/* RUNNING: the current thread. */
struct chx_thread *running;
@@ -59,7 +67,12 @@ struct chx_timer {
/* threads waiting for timer. */
static struct chx_timer q_timer;
-/* XXX: q_exit; Queue for threads already exited. */
+/* Queue of threads which have been exited. */
+static struct chx_timer q_exit;
+
+/* Queue of threads which wait exit of some thread. */
+static struct chx_timer q_waitexit;
+
/* Forward declaration(s). */
static void chx_request_preemption (void);
@@ -226,7 +239,7 @@ ll_prio_enqueue (struct chx_thread *tp0, void *head)
*/
#define THREAD_WAIT_MTX 0x00000001
#define THREAD_WAIT_CND 0x00000002
-#define THREAD_WAITTIME 0x00000003
+#define THREAD_WAIT_OBJ 0x00000003 /* Timer (24-bit), thread */
#define THREAD_RUNNING 0x00000000
#define THREAD_WAIT_INT 0x00000004
@@ -408,7 +421,7 @@ chx_set_timer (struct chx_thread *q, uint32_t ticks)
*SYST_RVR = 0;
}
else
- q->v = (ticks<<8)|THREAD_WAITTIME;
+ q->v = (ticks<<8)|THREAD_WAIT_OBJ;
}
static void
@@ -508,12 +521,12 @@ chx_set_intr_prio (uint8_t n)
NVIC_IPR (n) = (NVIC_IPR(n) & ~(0xFF << sh)) | (INTR_PRIO << sh);
}
-static chopstix_intr_t *intr_top;
+static chopstx_intr_t *intr_top;
void
chx_handle_intr (void)
{
- chopstix_intr_t *intr;
+ chopstx_intr_t *intr;
register uint32_t irq_num;
asm volatile ("cpsid i\n\t"
@@ -838,7 +851,7 @@ chopstx_cond_broadcast (chopstx_cond_t *cond)
void
-chopstx_intr_register (chopstix_intr_t *intr, uint8_t irq_num)
+chopstx_intr_register (chopstx_intr_t *intr, uint8_t irq_num)
{
intr->irq_num = irq_num;
intr->t = running;
@@ -853,7 +866,7 @@ chopstx_intr_register (chopstix_intr_t *intr, uint8_t irq_num)
void
-chopstx_wait_intr (chopstix_intr_t *intr)
+chopstx_wait_intr (chopstx_intr_t *intr)
{
asm volatile ("cpsid i" : : : "memory");
chx_enable_intr (intr->irq_num);
@@ -868,3 +881,58 @@ chopstx_wait_intr (chopstix_intr_t *intr)
intr->ready--;
asm volatile ("cpsie i" : : : "memory");
}
+
+
+/* The RETVAL is saved into register R4. */
+void __attribute__((noreturn))
+chopstx_exit (void *retval)
+{
+ register uint32_t r4 __asm__ ("r4") = (uint32_t)retval;
+ struct chx_thread *q;
+
+ asm volatile ("cpsid i" : : : "memory");
+ /* wake up a thread waiting to join */
+ chx_LOCK (&q_waitexit.lock);
+ for (q = q_waitexit.next; q != (struct chx_thread *)&q_waitexit; q = q->next)
+ if ((q->v & ~3) == (uint32_t)running)
+ { /* should be one at most. */
+ ll_dequeue (q);
+ chx_ready_enqueue (q);
+ break;
+ }
+ chx_UNLOCK (&q_waitexit.lock);
+
+ chx_LOCK (&q_exit.lock);
+ ll_insert (running, &q_exit);
+ running->v = THREAD_EXITED;
+ chx_UNLOCK (&q_exit.lock);
+ asm volatile ("cpsie i" : : "r" (r4) : "memory");
+ chx_sched ();
+ /* never comes here. */
+ for (;;);
+}
+
+int
+chopstx_join (chopstx_t thd, void **ret)
+{
+ struct chx_thread *tp = (struct chx_thread *)thd;
+
+ /* XXX: check if another thread is waiting same thread and return error. */
+ /* XXX: dead lock detection (waiting each other) and return error. */
+
+ asm volatile ("cpsid i" : : : "memory");
+ if (tp->v != THREAD_EXITED)
+ {
+ chx_LOCK (&q_waitexit.lock);
+ ll_insert (running, &q_waitexit);
+ running->v = ((uint32_t) tp) | THREAD_WAIT_OBJ;
+ chx_UNLOCK (&q_waitexit.lock);
+ asm volatile ("cpsie i" : : : "memory");
+ chx_sched ();
+ }
+ else
+ asm volatile ("cpsie i" : : : "memory");
+
+ *ret = (void *)tp->tc.reg[0];
+ return 0;
+}
diff --git a/chopstx.h b/chopstx.h
index 4f8635d..52e457d 100644
--- a/chopstx.h
+++ b/chopstx.h
@@ -84,8 +84,11 @@ typedef struct chx_intr {
struct chx_thread *t;
uint8_t irq_num;
uint8_t ready;
-} chopstix_intr_t;
+} chopstx_intr_t;
-void chopstx_intr_register (chopstix_intr_t *intr, uint8_t irq_num);
+void chopstx_intr_register (chopstx_intr_t *intr, uint8_t irq_num);
-void chopstx_wait_intr (chopstix_intr_t *intr);
+void chopstx_wait_intr (chopstx_intr_t *intr);
+
+/* Library provides default as weak reference. User can replace it. */
+void chx_fatal (uint32_t err_code);
diff --git a/example-cdc/sample.c b/example-cdc/sample.c
index 6534a26..0c0481d 100644
--- a/example-cdc/sample.c
+++ b/example-cdc/sample.c
@@ -63,7 +63,7 @@ usb_intr (void *arg)
extern void usb_lld_init (uint8_t feature);
extern void usb_interrupt_handler (void);
- chopstix_intr_t interrupt;
+ chopstx_intr_t interrupt;
(void)arg;
asm volatile ("cpsid i" : : : "memory");