diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2013-06-04 14:42:26 +0900 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2013-06-04 14:42:26 +0900 |
commit | 8056415dd270d9bd555302b1e04be2376591218d (patch) | |
tree | 985aeacc923daf1e3a7e7db1a71880239d880c38 | |
parent | ba594d5eaebe0885b09f9633b58ae55b1b03b246 (diff) |
add cleanup rouines
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | chopstx.c | 111 | ||||
-rw-r--r-- | chopstx.h | 31 | ||||
-rw-r--r-- | entry.c | 4 | ||||
-rw-r--r-- | example-cdc/sample.c | 21 | ||||
-rw-r--r-- | example-led/sample.c | 15 |
6 files changed, 87 insertions, 101 deletions
@@ -7,6 +7,12 @@ considered holding cpu_sched_lock (by its equal exception priorities), thus no acquiring lock required. (CHX_PRIO_MAIN): New macro. + (chopstx_create): Change API. + (chopstx_attr_init, chopstx_attr_setschedparam) + (chopstx_attr_setstack): Remove. + (chopstx_intr_wait, chopstx_join): Call chx_cpu_sched_unlock. + (chopstx_cleanup_push, chopstx_cleanup_pop): New. + (chopstx_exit): Call cleanup routines. 2013-06-03 Niibe Yutaka <gniibe@fsij.org> @@ -34,7 +34,7 @@ /* * Thread priority: higer has higher precedence. */ -#if !defined(CHX_PRIO_DEFAULT) +#if !defined(CHX_PRIO_MAIN) #define CHX_PRIO_MAIN 1 #endif @@ -201,6 +201,7 @@ struct chx_thread { uint32_t prio : 8; uint32_t v; struct chx_mtx *mutex_list; + struct chx_cleanup *clp; }; @@ -657,6 +658,7 @@ chx_init (struct chx_thread *tp) q_join.next = q_join.prev = (struct chx_thread *)&q_join; tp->next = tp->prev = tp; tp->mutex_list = NULL; + tp->clp = NULL; tp->state = THREAD_RUNNING; tp->flag_detached = tp->flag_got_cancel = tp->flag_join_req = tp->flag_sched_rr = 0; @@ -674,21 +676,17 @@ chx_request_preemption (void) asm volatile ("" : : : "memory"); } +#define CHX_SLEEP 0 +#define CHX_YIELD 1 + static void -chx_sched (void) +chx_sched (uint32_t arg) { - register uint32_t r0 asm ("r0") = 0; + register uint32_t r0 asm ("r0") = arg; asm volatile ("svc #0" : : "r" (r0): "memory"); } -static void -chx_yield (void) -{ - register uint32_t r0 asm ("r0") = 1; - - asm volatile ("svc #0" : : "r" (r0) : "memory"); -} /* The RETVAL is saved into register R8. */ static void __attribute__((noreturn)) @@ -721,7 +719,7 @@ chx_exit (void *retval) } chx_spin_unlock (&q_exit.lock); asm volatile ("" : : "r" (r8) : "memory"); - chx_sched (); + chx_sched (CHX_SLEEP); /* never comes here. */ for (;;); } @@ -759,40 +757,18 @@ chx_mutex_unlock (chopstx_mutex_t *mutex) return prio; } -void -chopstx_attr_init (chopstx_attr_t *attr) -{ - attr->prio = CHX_PRIO_DEFAULT; - attr->addr = 0; - attr->size = 0; -} - -void -chopstx_attr_setschedparam (chopstx_attr_t *attr, uint8_t prio) -{ - attr->prio = prio; -} - -void -chopstx_attr_setstack (chopstx_attr_t *attr, uint32_t addr, size_t size) -{ - attr->addr = addr; - attr->size = size; -} - - -void -chopstx_create (chopstx_t *thd, const chopstx_attr_t *attr, +chopstx_t +chopstx_create (uint8_t prio, uint32_t stack_addr, size_t stack_size, void *(thread_entry) (void *), void *arg) { struct chx_thread *tp; void *stack; struct chx_stack_regs *p; - if (attr->size < sizeof (struct chx_thread) + 8 * sizeof (uint32_t)) - return; + if (stack_size < sizeof (struct chx_thread) + 8 * sizeof (uint32_t)) + chx_fatal (CHOPSTX_ERR_THREAD_CREATE); - stack = (void *)(attr->addr + attr->size - sizeof (struct chx_thread) + stack = (void *)(stack_addr + stack_size - sizeof (struct chx_thread) - sizeof (struct chx_stack_regs)); memset (stack, 0, sizeof (struct chx_stack_regs)); p = (struct chx_stack_regs *)stack; @@ -806,19 +782,21 @@ chopstx_create (chopstx_t *thd, const chopstx_attr_t *attr, tp->tc.reg[REG_SP] = (uint32_t)stack; tp->next = tp->prev = tp; tp->mutex_list = NULL; + tp->clp = NULL; tp->state = THREAD_EXITED; tp->flag_detached = tp->flag_got_cancel = tp->flag_join_req = tp->flag_sched_rr = 0; - tp->prio_orig = tp->prio = attr->prio; + tp->prio_orig = tp->prio = prio; tp->v = 0; - *thd = (uint32_t)tp; chx_cpu_sched_lock (); chx_ready_enqueue (tp); if (tp->prio > running->prio) - chx_yield (); + chx_sched (CHX_YIELD); else chx_cpu_sched_unlock (); + + return (uint32_t)tp; } @@ -833,7 +811,7 @@ chopstx_usec_wait (uint32_t usec) chx_spin_lock (&q_timer.lock); chx_timer_insert (running, usec0); chx_spin_unlock (&q_timer.lock); - chx_sched (); + chx_sched (CHX_SLEEP); usec -= usec0; } } @@ -903,7 +881,7 @@ chopstx_mutex_lock (chopstx_mutex_t *mutex) tp->state = THREAD_WAIT_MTX; tp->v = (uint32_t)mutex; chx_spin_unlock (&mutex->lock); - chx_sched (); + chx_sched (CHX_SLEEP); } return; @@ -920,7 +898,7 @@ chopstx_mutex_unlock (chopstx_mutex_t *mutex) prio = chx_mutex_unlock (mutex); chx_spin_unlock (&mutex->lock); if (prio > running->prio) - chx_yield (); + chx_sched (CHX_YIELD); else chx_cpu_sched_unlock (); } @@ -952,7 +930,7 @@ chopstx_cond_wait (chopstx_cond_t *cond, chopstx_mutex_t *mutex) tp->state = THREAD_WAIT_CND; tp->v = (uint32_t)cond; chx_spin_unlock (&cond->lock); - chx_sched (); + chx_sched (CHX_SLEEP); if (mutex) chopstx_mutex_lock (mutex); @@ -976,7 +954,7 @@ chopstx_cond_signal (chopstx_cond_t *cond) } chx_spin_unlock (&cond->lock); if (yield) - chx_yield (); + chx_sched (CHX_YIELD); else chx_cpu_sched_unlock (); } @@ -998,7 +976,7 @@ chopstx_cond_broadcast (chopstx_cond_t *cond) } chx_spin_unlock (&cond->lock); if (yield) - chx_yield (); + chx_sched (CHX_YIELD); else chx_cpu_sched_unlock (); } @@ -1071,19 +1049,48 @@ chopstx_intr_wait (chopstx_intr_t *intr) { running->state = THREAD_WAIT_INT; running->v = 0; - chx_sched (); + chx_sched (CHX_SLEEP); } + else + chx_cpu_sched_unlock (); intr->ready--; } +void +chopstx_cleanup_push (struct chx_cleanup *clp) +{ + clp->next = running->clp; + running->clp = clp; +} + +void +chopstx_cleanup_pop (int execute) +{ + struct chx_cleanup *clp = running->clp; + + if (clp) + { + running->clp = clp->next; + if (execute) + clp->routine (clp->arg); + } +} + + /* The RETVAL is saved into register R8. */ void __attribute__((noreturn)) chopstx_exit (void *retval) { struct chx_mtx *m, *m_next; + struct chx_cleanup *clp = running->clp; - /* XXX: Call registered "release" routines here. */ + running->clp = NULL; + while (clp) + { + clp->routine (clp->arg); + clp = clp->next; + } /* Release all mutexes this thread still holds. */ for (m = running->mutex_list; m; m = m_next) @@ -1127,8 +1134,10 @@ chopstx_join (chopstx_t thd, void **ret) tp->flag_join_req = 1; if (tp->prio < running->prio) tp->prio = running->prio; - chx_sched (); + chx_sched (CHX_SLEEP); } + else + chx_cpu_sched_unlock (); tp->state = THREAD_FINISHED; if (ret) @@ -1166,7 +1175,7 @@ chopstx_cancel (chopstx_t thd) yield = 1; } if (yield) - chx_yield (); + chx_sched (CHX_YIELD); else chx_cpu_sched_unlock (); } @@ -27,19 +27,11 @@ */ typedef uint32_t chopstx_t; -struct struct_attr { uint32_t prio; uint32_t addr; size_t size; }; -typedef struct struct_attr chopstx_attr_t; - -void chopstx_attr_init (chopstx_attr_t *attr); /* NOTE: This signature is different to PTHREAD's one. */ -void chopstx_attr_setschedparam (chopstx_attr_t *attr, uint8_t prio); - -void chopstx_attr_setstack (chopstx_attr_t *attr, uint32_t addr, - size_t size); - -void chopstx_create (chopstx_t *thd, const chopstx_attr_t *attr, - void *(thread_entry) (void *), void *); +chopstx_t +chopstx_create (uint8_t prio, uint32_t stack_addr, size_t stack_size, + void *(thread_entry) (void *), void *); void chopstx_usec_wait (uint32_t useconds); @@ -103,6 +95,7 @@ void chopstx_exit (void *retval) __attribute__((__noreturn__)); enum { CHOPSTX_ERR_NONE = 0, + CHOPSTX_ERR_THREAD_CREATE, CHOPSTX_ERR_JOIN, }; @@ -115,10 +108,12 @@ enum { void chopstx_cancel (chopstx_t thd); void chopstx_testcancel (void); -/* - * User can define this macro (like: -DCHX_PRIO_DEFAULT=3) to specify - * default priority. - */ -#if !defined(CHX_PRIO_DEFAULT) -#define CHX_PRIO_DEFAULT 1 -#endif +struct chx_cleanup { + struct chx_cleanup *next; + void (*routine) (void *); + void *arg; +}; + +/* NOTE: This signature is different to PTHREAD's one. */ +void chopstx_cleanup_push (struct chx_cleanup *clp); +void chopstx_cleanup_pop (int execute); @@ -287,8 +287,8 @@ void entry (void) "3:\n\t" /* Switch to PSP. */ "ldr r0, =__process0_stack_end__\n\t" - "sub r0, #56\n\t" - "msr PSP, r0\n\t" /* Process (main routine) stack */ + "sub r0, #60\n\t" /* Size of struct chx_thread. */ + "msr PSP, r0\n\t" /* Process (main routine) stack. */ "mov r1, #2\n\t" "msr CONTROL, r1\n\t" "isb\n\t" diff --git a/example-cdc/sample.c b/example-cdc/sample.c index fbb7bac..0451049 100644 --- a/example-cdc/sample.c +++ b/example-cdc/sample.c @@ -116,8 +116,6 @@ static char hexchar (uint8_t x) int main (int argc, const char *argv[]) { - chopstx_t thd; - chopstx_attr_t attr; uint8_t count; (void)argc; @@ -132,21 +130,10 @@ main (int argc, const char *argv[]) m = 10; - chopstx_attr_init (&attr); - chopstx_attr_setschedparam (&attr, PRIO_PWM); - chopstx_attr_setstack (&attr, __stackaddr_pwm, __stacksize_pwm); - - chopstx_create (&thd, &attr, pwm, NULL); - - chopstx_attr_setschedparam (&attr, PRIO_BLK); - chopstx_attr_setstack (&attr, __stackaddr_blk, __stacksize_blk); - - chopstx_create (&thd, &attr, blk, NULL); - - chopstx_attr_setschedparam (&attr, PRIO_INTR); - chopstx_attr_setstack (&attr, __stackaddr_intr, __stacksize_intr); - - chopstx_create (&thd, &attr, usb_intr, NULL); + chopstx_create (PRIO_PWM, __stackaddr_pwm, __stacksize_pwm, pwm, NULL); + chopstx_create (PRIO_BLK, __stackaddr_blk, __stacksize_blk, blk, NULL); + chopstx_create (PRIO_INTR, __stackaddr_intr, __stacksize_intr, + usb_intr, NULL); chopstx_usec_wait (200*1000); diff --git a/example-led/sample.c b/example-led/sample.c index 8c994ce..c1036d6 100644 --- a/example-led/sample.c +++ b/example-led/sample.c @@ -66,9 +66,6 @@ const size_t __stacksize_blk = (size_t)&__process2_stack_size__; int main (int argc, const char *argv[]) { - chopstx_t thd; - chopstx_attr_t attr; - (void)argc; (void)argv; @@ -78,16 +75,8 @@ main (int argc, const char *argv[]) m = 10; - chopstx_attr_init (&attr); - chopstx_attr_setschedparam (&attr, PRIO_PWM); - chopstx_attr_setstack (&attr, __stackaddr_pwm, __stacksize_pwm); - - chopstx_create (&thd, &attr, pwm, NULL); - - chopstx_attr_setschedparam (&attr, PRIO_BLK); - chopstx_attr_setstack (&attr, __stackaddr_blk, __stacksize_blk); - - chopstx_create (&thd, &attr, blk, NULL); + chopstx_create (PRIO_PWM, __stackaddr_pwm, __stacksize_pwm, pwm, NULL); + chopstx_create (PRIO_BLK, __stackaddr_blk, __stacksize_blk, blk, NULL); chopstx_usec_wait (200*1000); |