add cleanup rouines
This commit is contained in:
@@ -7,6 +7,12 @@
|
|||||||
considered holding cpu_sched_lock (by its equal exception
|
considered holding cpu_sched_lock (by its equal exception
|
||||||
priorities), thus no acquiring lock required.
|
priorities), thus no acquiring lock required.
|
||||||
(CHX_PRIO_MAIN): New macro.
|
(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>
|
2013-06-03 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
|||||||
111
chopstx.c
111
chopstx.c
@@ -34,7 +34,7 @@
|
|||||||
/*
|
/*
|
||||||
* Thread priority: higer has higher precedence.
|
* Thread priority: higer has higher precedence.
|
||||||
*/
|
*/
|
||||||
#if !defined(CHX_PRIO_DEFAULT)
|
#if !defined(CHX_PRIO_MAIN)
|
||||||
#define CHX_PRIO_MAIN 1
|
#define CHX_PRIO_MAIN 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -201,6 +201,7 @@ struct chx_thread {
|
|||||||
uint32_t prio : 8;
|
uint32_t prio : 8;
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
struct chx_mtx *mutex_list;
|
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;
|
q_join.next = q_join.prev = (struct chx_thread *)&q_join;
|
||||||
tp->next = tp->prev = tp;
|
tp->next = tp->prev = tp;
|
||||||
tp->mutex_list = NULL;
|
tp->mutex_list = NULL;
|
||||||
|
tp->clp = NULL;
|
||||||
tp->state = THREAD_RUNNING;
|
tp->state = THREAD_RUNNING;
|
||||||
tp->flag_detached = tp->flag_got_cancel
|
tp->flag_detached = tp->flag_got_cancel
|
||||||
= tp->flag_join_req = tp->flag_sched_rr = 0;
|
= tp->flag_join_req = tp->flag_sched_rr = 0;
|
||||||
@@ -674,21 +676,17 @@ chx_request_preemption (void)
|
|||||||
asm volatile ("" : : : "memory");
|
asm volatile ("" : : : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHX_SLEEP 0
|
||||||
|
#define CHX_YIELD 1
|
||||||
|
|
||||||
static void
|
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");
|
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. */
|
/* The RETVAL is saved into register R8. */
|
||||||
static void __attribute__((noreturn))
|
static void __attribute__((noreturn))
|
||||||
@@ -721,7 +719,7 @@ chx_exit (void *retval)
|
|||||||
}
|
}
|
||||||
chx_spin_unlock (&q_exit.lock);
|
chx_spin_unlock (&q_exit.lock);
|
||||||
asm volatile ("" : : "r" (r8) : "memory");
|
asm volatile ("" : : "r" (r8) : "memory");
|
||||||
chx_sched ();
|
chx_sched (CHX_SLEEP);
|
||||||
/* never comes here. */
|
/* never comes here. */
|
||||||
for (;;);
|
for (;;);
|
||||||
}
|
}
|
||||||
@@ -759,40 +757,18 @@ chx_mutex_unlock (chopstx_mutex_t *mutex)
|
|||||||
return prio;
|
return prio;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
chopstx_t
|
||||||
chopstx_attr_init (chopstx_attr_t *attr)
|
chopstx_create (uint8_t prio, uint32_t stack_addr, size_t stack_size,
|
||||||
{
|
|
||||||
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,
|
|
||||||
void *(thread_entry) (void *), void *arg)
|
void *(thread_entry) (void *), void *arg)
|
||||||
{
|
{
|
||||||
struct chx_thread *tp;
|
struct chx_thread *tp;
|
||||||
void *stack;
|
void *stack;
|
||||||
struct chx_stack_regs *p;
|
struct chx_stack_regs *p;
|
||||||
|
|
||||||
if (attr->size < sizeof (struct chx_thread) + 8 * sizeof (uint32_t))
|
if (stack_size < sizeof (struct chx_thread) + 8 * sizeof (uint32_t))
|
||||||
return;
|
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));
|
- sizeof (struct chx_stack_regs));
|
||||||
memset (stack, 0, sizeof (struct chx_stack_regs));
|
memset (stack, 0, sizeof (struct chx_stack_regs));
|
||||||
p = (struct chx_stack_regs *)stack;
|
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->tc.reg[REG_SP] = (uint32_t)stack;
|
||||||
tp->next = tp->prev = tp;
|
tp->next = tp->prev = tp;
|
||||||
tp->mutex_list = NULL;
|
tp->mutex_list = NULL;
|
||||||
|
tp->clp = NULL;
|
||||||
tp->state = THREAD_EXITED;
|
tp->state = THREAD_EXITED;
|
||||||
tp->flag_detached = tp->flag_got_cancel
|
tp->flag_detached = tp->flag_got_cancel
|
||||||
= tp->flag_join_req = tp->flag_sched_rr = 0;
|
= 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;
|
tp->v = 0;
|
||||||
*thd = (uint32_t)tp;
|
|
||||||
|
|
||||||
chx_cpu_sched_lock ();
|
chx_cpu_sched_lock ();
|
||||||
chx_ready_enqueue (tp);
|
chx_ready_enqueue (tp);
|
||||||
if (tp->prio > running->prio)
|
if (tp->prio > running->prio)
|
||||||
chx_yield ();
|
chx_sched (CHX_YIELD);
|
||||||
else
|
else
|
||||||
chx_cpu_sched_unlock ();
|
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_spin_lock (&q_timer.lock);
|
||||||
chx_timer_insert (running, usec0);
|
chx_timer_insert (running, usec0);
|
||||||
chx_spin_unlock (&q_timer.lock);
|
chx_spin_unlock (&q_timer.lock);
|
||||||
chx_sched ();
|
chx_sched (CHX_SLEEP);
|
||||||
usec -= usec0;
|
usec -= usec0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -903,7 +881,7 @@ chopstx_mutex_lock (chopstx_mutex_t *mutex)
|
|||||||
tp->state = THREAD_WAIT_MTX;
|
tp->state = THREAD_WAIT_MTX;
|
||||||
tp->v = (uint32_t)mutex;
|
tp->v = (uint32_t)mutex;
|
||||||
chx_spin_unlock (&mutex->lock);
|
chx_spin_unlock (&mutex->lock);
|
||||||
chx_sched ();
|
chx_sched (CHX_SLEEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -920,7 +898,7 @@ chopstx_mutex_unlock (chopstx_mutex_t *mutex)
|
|||||||
prio = chx_mutex_unlock (mutex);
|
prio = chx_mutex_unlock (mutex);
|
||||||
chx_spin_unlock (&mutex->lock);
|
chx_spin_unlock (&mutex->lock);
|
||||||
if (prio > running->prio)
|
if (prio > running->prio)
|
||||||
chx_yield ();
|
chx_sched (CHX_YIELD);
|
||||||
else
|
else
|
||||||
chx_cpu_sched_unlock ();
|
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->state = THREAD_WAIT_CND;
|
||||||
tp->v = (uint32_t)cond;
|
tp->v = (uint32_t)cond;
|
||||||
chx_spin_unlock (&cond->lock);
|
chx_spin_unlock (&cond->lock);
|
||||||
chx_sched ();
|
chx_sched (CHX_SLEEP);
|
||||||
|
|
||||||
if (mutex)
|
if (mutex)
|
||||||
chopstx_mutex_lock (mutex);
|
chopstx_mutex_lock (mutex);
|
||||||
@@ -976,7 +954,7 @@ chopstx_cond_signal (chopstx_cond_t *cond)
|
|||||||
}
|
}
|
||||||
chx_spin_unlock (&cond->lock);
|
chx_spin_unlock (&cond->lock);
|
||||||
if (yield)
|
if (yield)
|
||||||
chx_yield ();
|
chx_sched (CHX_YIELD);
|
||||||
else
|
else
|
||||||
chx_cpu_sched_unlock ();
|
chx_cpu_sched_unlock ();
|
||||||
}
|
}
|
||||||
@@ -998,7 +976,7 @@ chopstx_cond_broadcast (chopstx_cond_t *cond)
|
|||||||
}
|
}
|
||||||
chx_spin_unlock (&cond->lock);
|
chx_spin_unlock (&cond->lock);
|
||||||
if (yield)
|
if (yield)
|
||||||
chx_yield ();
|
chx_sched (CHX_YIELD);
|
||||||
else
|
else
|
||||||
chx_cpu_sched_unlock ();
|
chx_cpu_sched_unlock ();
|
||||||
}
|
}
|
||||||
@@ -1071,19 +1049,48 @@ chopstx_intr_wait (chopstx_intr_t *intr)
|
|||||||
{
|
{
|
||||||
running->state = THREAD_WAIT_INT;
|
running->state = THREAD_WAIT_INT;
|
||||||
running->v = 0;
|
running->v = 0;
|
||||||
chx_sched ();
|
chx_sched (CHX_SLEEP);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
chx_cpu_sched_unlock ();
|
||||||
intr->ready--;
|
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. */
|
/* The RETVAL is saved into register R8. */
|
||||||
void __attribute__((noreturn))
|
void __attribute__((noreturn))
|
||||||
chopstx_exit (void *retval)
|
chopstx_exit (void *retval)
|
||||||
{
|
{
|
||||||
struct chx_mtx *m, *m_next;
|
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. */
|
/* Release all mutexes this thread still holds. */
|
||||||
for (m = running->mutex_list; m; m = m_next)
|
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;
|
tp->flag_join_req = 1;
|
||||||
if (tp->prio < running->prio)
|
if (tp->prio < running->prio)
|
||||||
tp->prio = running->prio;
|
tp->prio = running->prio;
|
||||||
chx_sched ();
|
chx_sched (CHX_SLEEP);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
chx_cpu_sched_unlock ();
|
||||||
|
|
||||||
tp->state = THREAD_FINISHED;
|
tp->state = THREAD_FINISHED;
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -1166,7 +1175,7 @@ chopstx_cancel (chopstx_t thd)
|
|||||||
yield = 1;
|
yield = 1;
|
||||||
}
|
}
|
||||||
if (yield)
|
if (yield)
|
||||||
chx_yield ();
|
chx_sched (CHX_YIELD);
|
||||||
else
|
else
|
||||||
chx_cpu_sched_unlock ();
|
chx_cpu_sched_unlock ();
|
||||||
}
|
}
|
||||||
|
|||||||
29
chopstx.h
29
chopstx.h
@@ -27,18 +27,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
typedef uint32_t chopstx_t;
|
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. */
|
/* NOTE: This signature is different to PTHREAD's one. */
|
||||||
void chopstx_attr_setschedparam (chopstx_attr_t *attr, uint8_t prio);
|
chopstx_t
|
||||||
|
chopstx_create (uint8_t prio, uint32_t stack_addr, size_t stack_size,
|
||||||
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 *);
|
void *(thread_entry) (void *), void *);
|
||||||
|
|
||||||
void chopstx_usec_wait (uint32_t useconds);
|
void chopstx_usec_wait (uint32_t useconds);
|
||||||
@@ -103,6 +95,7 @@ void chopstx_exit (void *retval) __attribute__((__noreturn__));
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
CHOPSTX_ERR_NONE = 0,
|
CHOPSTX_ERR_NONE = 0,
|
||||||
|
CHOPSTX_ERR_THREAD_CREATE,
|
||||||
CHOPSTX_ERR_JOIN,
|
CHOPSTX_ERR_JOIN,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,10 +108,12 @@ enum {
|
|||||||
void chopstx_cancel (chopstx_t thd);
|
void chopstx_cancel (chopstx_t thd);
|
||||||
void chopstx_testcancel (void);
|
void chopstx_testcancel (void);
|
||||||
|
|
||||||
/*
|
struct chx_cleanup {
|
||||||
* User can define this macro (like: -DCHX_PRIO_DEFAULT=3) to specify
|
struct chx_cleanup *next;
|
||||||
* default priority.
|
void (*routine) (void *);
|
||||||
*/
|
void *arg;
|
||||||
#if !defined(CHX_PRIO_DEFAULT)
|
};
|
||||||
#define CHX_PRIO_DEFAULT 1
|
|
||||||
#endif
|
/* NOTE: This signature is different to PTHREAD's one. */
|
||||||
|
void chopstx_cleanup_push (struct chx_cleanup *clp);
|
||||||
|
void chopstx_cleanup_pop (int execute);
|
||||||
|
|||||||
4
entry.c
4
entry.c
@@ -287,8 +287,8 @@ void entry (void)
|
|||||||
"3:\n\t"
|
"3:\n\t"
|
||||||
/* Switch to PSP. */
|
/* Switch to PSP. */
|
||||||
"ldr r0, =__process0_stack_end__\n\t"
|
"ldr r0, =__process0_stack_end__\n\t"
|
||||||
"sub r0, #56\n\t"
|
"sub r0, #60\n\t" /* Size of struct chx_thread. */
|
||||||
"msr PSP, r0\n\t" /* Process (main routine) stack */
|
"msr PSP, r0\n\t" /* Process (main routine) stack. */
|
||||||
"mov r1, #2\n\t"
|
"mov r1, #2\n\t"
|
||||||
"msr CONTROL, r1\n\t"
|
"msr CONTROL, r1\n\t"
|
||||||
"isb\n\t"
|
"isb\n\t"
|
||||||
|
|||||||
@@ -116,8 +116,6 @@ static char hexchar (uint8_t x)
|
|||||||
int
|
int
|
||||||
main (int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
chopstx_t thd;
|
|
||||||
chopstx_attr_t attr;
|
|
||||||
uint8_t count;
|
uint8_t count;
|
||||||
|
|
||||||
(void)argc;
|
(void)argc;
|
||||||
@@ -132,21 +130,10 @@ main (int argc, const char *argv[])
|
|||||||
|
|
||||||
m = 10;
|
m = 10;
|
||||||
|
|
||||||
chopstx_attr_init (&attr);
|
chopstx_create (PRIO_PWM, __stackaddr_pwm, __stacksize_pwm, pwm, NULL);
|
||||||
chopstx_attr_setschedparam (&attr, PRIO_PWM);
|
chopstx_create (PRIO_BLK, __stackaddr_blk, __stacksize_blk, blk, NULL);
|
||||||
chopstx_attr_setstack (&attr, __stackaddr_pwm, __stacksize_pwm);
|
chopstx_create (PRIO_INTR, __stackaddr_intr, __stacksize_intr,
|
||||||
|
usb_intr, NULL);
|
||||||
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_usec_wait (200*1000);
|
chopstx_usec_wait (200*1000);
|
||||||
|
|
||||||
|
|||||||
@@ -66,9 +66,6 @@ const size_t __stacksize_blk = (size_t)&__process2_stack_size__;
|
|||||||
int
|
int
|
||||||
main (int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
chopstx_t thd;
|
|
||||||
chopstx_attr_t attr;
|
|
||||||
|
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
||||||
@@ -78,16 +75,8 @@ main (int argc, const char *argv[])
|
|||||||
|
|
||||||
m = 10;
|
m = 10;
|
||||||
|
|
||||||
chopstx_attr_init (&attr);
|
chopstx_create (PRIO_PWM, __stackaddr_pwm, __stacksize_pwm, pwm, NULL);
|
||||||
chopstx_attr_setschedparam (&attr, PRIO_PWM);
|
chopstx_create (PRIO_BLK, __stackaddr_blk, __stacksize_blk, blk, NULL);
|
||||||
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_usec_wait (200*1000);
|
chopstx_usec_wait (200*1000);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user