fix race condition of handle_intr.
This commit is contained in:
@@ -1,5 +1,14 @@
|
|||||||
2013-05-29 Niibe Yutaka <gniibe@fsij.org>
|
2013-05-29 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* chopstx.c (svc): Implement race avoidance between
|
||||||
|
chx_handle_intr.
|
||||||
|
(chx_handle_intr): Increment ->ready. Put to ready queue
|
||||||
|
only when it's not running.
|
||||||
|
(chx_sched): Add an argument for race avoidance.
|
||||||
|
(chopstx_intr_wait): Fix the race condition.
|
||||||
|
|
||||||
|
* board/board-olimex-stm32-h103.h (NEUG_ADC_SETTING2_*): Add.
|
||||||
|
|
||||||
* chopstx.c (chx_mutex_unlock, chopstx_exit): New.
|
* chopstx.c (chx_mutex_unlock, chopstx_exit): New.
|
||||||
(chopstx_mutex_unlock): Use chx_mutex_unlock.
|
(chopstx_mutex_unlock): Use chx_mutex_unlock.
|
||||||
(chopstx_cond_wait): Fix race condition.
|
(chopstx_cond_wait): Fix race condition.
|
||||||
|
|||||||
@@ -22,3 +22,11 @@
|
|||||||
|
|
||||||
#define RCC_APB2ENR_IOP_EN RCC_APB2ENR_IOPCEN
|
#define RCC_APB2ENR_IOP_EN RCC_APB2ENR_IOPCEN
|
||||||
#define RCC_APB2RSTR_IOP_RST RCC_APB2RSTR_IOPCRST
|
#define RCC_APB2RSTR_IOP_RST RCC_APB2RSTR_IOPCRST
|
||||||
|
|
||||||
|
/* NeuG settings for ADC2. */
|
||||||
|
#define NEUG_ADC_SETTING2_SMPR1 ADC_SMPR1_SMP_AN10(ADC_SAMPLE_1P5) \
|
||||||
|
| ADC_SMPR1_SMP_AN11(ADC_SAMPLE_1P5)
|
||||||
|
#define NEUG_ADC_SETTING2_SMPR2 0
|
||||||
|
#define NEUG_ADC_SETTING2_SQR3 ADC_SQR3_SQ1_N(ADC_CHANNEL_IN10) \
|
||||||
|
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN11)
|
||||||
|
#define NEUG_ADC_SETTING2_NUM_CHANNELS 2
|
||||||
|
|||||||
49
chopstx.c
49
chopstx.c
@@ -402,6 +402,7 @@ svc (void)
|
|||||||
{
|
{
|
||||||
register uint32_t r0 asm ("r0");
|
register uint32_t r0 asm ("r0");
|
||||||
register uint32_t orig_r0 asm ("r2");
|
register uint32_t orig_r0 asm ("r2");
|
||||||
|
register uint32_t *orig_r1 asm ("r3");
|
||||||
|
|
||||||
asm volatile ("ldr r1, =running\n\t"
|
asm volatile ("ldr r1, =running\n\t"
|
||||||
"ldr r0, [r1]\n\t"
|
"ldr r0, [r1]\n\t"
|
||||||
@@ -414,8 +415,10 @@ svc (void)
|
|||||||
"mov r6, r11\n\t"
|
"mov r6, r11\n\t"
|
||||||
"mrs r7, PSP\n\t" /* r13(=SP) in user space. */
|
"mrs r7, PSP\n\t" /* r13(=SP) in user space. */
|
||||||
"stm r2, {r3, r4, r5, r6, r7}\n\t"
|
"stm r2, {r3, r4, r5, r6, r7}\n\t"
|
||||||
"ldr r2, [r7]"
|
"ldr r2, [r7]\n\t"
|
||||||
: "=r" (r0), "=r" (orig_r0) : /* no input */ : "memory");
|
"ldr r3, [r7, #4]\n\t"
|
||||||
|
: "=r" (r0), "=r" (orig_r0), "=r" (orig_r1)
|
||||||
|
: /* no input */ : "memory");
|
||||||
|
|
||||||
if (orig_r0)
|
if (orig_r0)
|
||||||
{
|
{
|
||||||
@@ -427,6 +430,17 @@ svc (void)
|
|||||||
"cpsie i" /* Unmask interrupts. */
|
"cpsie i" /* Unmask interrupts. */
|
||||||
: /* no output */ : /* no input */ : "memory");
|
: /* no output */ : /* no input */ : "memory");
|
||||||
}
|
}
|
||||||
|
else if (orig_r1)
|
||||||
|
{
|
||||||
|
asm volatile ("cpsid i" : : : "memory");
|
||||||
|
if (*orig_r1)
|
||||||
|
{
|
||||||
|
running->state = THREAD_RUNNING;
|
||||||
|
asm volatile ("cpsie i" : : : "memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* call sched with keeping interrupt disabled. */
|
||||||
|
}
|
||||||
|
|
||||||
asm volatile ("b sched"
|
asm volatile ("b sched"
|
||||||
: /* no output */: /* no input */ : "memory");
|
: /* no output */: /* no input */ : "memory");
|
||||||
@@ -581,6 +595,7 @@ chx_set_intr_prio (uint8_t n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static chopstx_intr_t *intr_top;
|
static chopstx_intr_t *intr_top;
|
||||||
|
static volatile uint32_t *const ICSR = (uint32_t *const)0xE000ED04;
|
||||||
|
|
||||||
void
|
void
|
||||||
chx_handle_intr (void)
|
chx_handle_intr (void)
|
||||||
@@ -597,13 +612,16 @@ chx_handle_intr (void)
|
|||||||
if (intr->irq_num == irq_num)
|
if (intr->irq_num == irq_num)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (intr && intr->tp && intr->tp->state == THREAD_WAIT_INT)
|
if (intr)
|
||||||
{
|
{
|
||||||
intr->ready++;
|
intr->ready++;
|
||||||
|
if (intr->tp != running && intr->tp->state == THREAD_WAIT_INT)
|
||||||
|
{
|
||||||
chx_ready_enqueue (intr->tp);
|
chx_ready_enqueue (intr->tp);
|
||||||
if (running == NULL || running->prio < intr->tp->prio)
|
if (running == NULL || running->prio < intr->tp->prio)
|
||||||
chx_request_preemption ();
|
chx_request_preemption ();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
asm volatile ("cpsie i" : : : "memory");
|
asm volatile ("cpsie i" : : : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -643,18 +661,17 @@ chx_init (struct chx_thread *tp)
|
|||||||
static void
|
static void
|
||||||
chx_request_preemption (void)
|
chx_request_preemption (void)
|
||||||
{
|
{
|
||||||
static volatile uint32_t *const ICSR = (uint32_t *const)0xE000ED04;
|
|
||||||
|
|
||||||
*ICSR = (1 << 28);
|
*ICSR = (1 << 28);
|
||||||
asm volatile ("" : : : "memory");
|
asm volatile ("" : : : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
chx_sched (void)
|
chx_sched (uint32_t *ptr)
|
||||||
{
|
{
|
||||||
register uint32_t r0 asm ("r0") = 0;
|
register uint32_t r0 asm ("r0") = 0;
|
||||||
|
register uint32_t r1 asm ("r1") = (uint32_t)ptr;
|
||||||
|
|
||||||
asm volatile ("svc #0" : : "r" (r0) : "memory");
|
asm volatile ("svc #0" : : "r" (r0), "r" (r1) : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -696,7 +713,7 @@ chx_exit (void *retval)
|
|||||||
running->state = THREAD_FINISHED;
|
running->state = THREAD_FINISHED;
|
||||||
chx_UNLOCK (&q_exit.lock);
|
chx_UNLOCK (&q_exit.lock);
|
||||||
asm volatile ("cpsie i" : : "r" (r4) : "memory");
|
asm volatile ("cpsie i" : : "r" (r4) : "memory");
|
||||||
chx_sched ();
|
chx_sched (NULL);
|
||||||
/* never comes here. */
|
/* never comes here. */
|
||||||
for (;;);
|
for (;;);
|
||||||
}
|
}
|
||||||
@@ -804,7 +821,7 @@ chopstx_usec_wait (uint32_t usec)
|
|||||||
uint32_t usec0 = (usec > 200*1000) ? 200*1000: usec;
|
uint32_t usec0 = (usec > 200*1000) ? 200*1000: usec;
|
||||||
|
|
||||||
chx_timer_insert (running, usec0);
|
chx_timer_insert (running, usec0);
|
||||||
chx_sched ();
|
chx_sched (NULL);
|
||||||
|
|
||||||
usec -= usec0;
|
usec -= usec0;
|
||||||
}
|
}
|
||||||
@@ -876,7 +893,7 @@ chopstx_mutex_lock (chopstx_mutex_t *mutex)
|
|||||||
tp->v = (uint32_t)mutex;
|
tp->v = (uint32_t)mutex;
|
||||||
chx_UNLOCK (&mutex->lock);
|
chx_UNLOCK (&mutex->lock);
|
||||||
asm volatile ("cpsie i" : : : "memory");
|
asm volatile ("cpsie i" : : : "memory");
|
||||||
chx_sched ();
|
chx_sched (NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -925,7 +942,7 @@ chopstx_cond_wait (chopstx_cond_t *cond, chopstx_mutex_t *mutex)
|
|||||||
chx_UNLOCK (&cond->lock);
|
chx_UNLOCK (&cond->lock);
|
||||||
asm volatile ("cpsie i" : : : "memory");
|
asm volatile ("cpsie i" : : : "memory");
|
||||||
|
|
||||||
chx_sched ();
|
chx_sched (NULL);
|
||||||
|
|
||||||
if (mutex)
|
if (mutex)
|
||||||
chopstx_mutex_lock (mutex);
|
chopstx_mutex_lock (mutex);
|
||||||
@@ -1039,12 +1056,16 @@ chopstx_intr_wait (chopstx_intr_t *intr)
|
|||||||
{
|
{
|
||||||
asm volatile ("cpsid i" : : : "memory");
|
asm volatile ("cpsid i" : : : "memory");
|
||||||
chx_enable_intr (intr->irq_num);
|
chx_enable_intr (intr->irq_num);
|
||||||
while (intr->ready == 0)
|
if (intr->ready == 0)
|
||||||
{
|
{
|
||||||
running->state = THREAD_WAIT_INT;
|
running->state = THREAD_WAIT_INT;
|
||||||
running->v = 0;
|
running->v = 0;
|
||||||
asm volatile ("cpsie i" : : : "memory");
|
asm volatile ("cpsie i" : : : "memory");
|
||||||
chx_sched ();
|
/*
|
||||||
|
* Here is the race with chx_handle_intr.
|
||||||
|
* Bring a pointer to intr->ready, so that it won't sleep when ready.
|
||||||
|
*/
|
||||||
|
chx_sched (&intr->ready);
|
||||||
asm volatile ("cpsid i" : : : "memory");
|
asm volatile ("cpsid i" : : : "memory");
|
||||||
}
|
}
|
||||||
intr->ready--;
|
intr->ready--;
|
||||||
@@ -1103,7 +1124,7 @@ chopstx_join (chopstx_t thd, void **ret)
|
|||||||
if (tp->prio < running->prio)
|
if (tp->prio < running->prio)
|
||||||
tp->prio = running->prio;
|
tp->prio = running->prio;
|
||||||
asm volatile ("cpsie i" : : : "memory");
|
asm volatile ("cpsie i" : : : "memory");
|
||||||
chx_sched ();
|
chx_sched (NULL);
|
||||||
asm volatile ("cpsid i" : : : "memory");
|
asm volatile ("cpsid i" : : : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ typedef struct chx_intr {
|
|||||||
struct chx_intr *next;
|
struct chx_intr *next;
|
||||||
struct chx_spinlock lock;
|
struct chx_spinlock lock;
|
||||||
struct chx_thread *tp;
|
struct chx_thread *tp;
|
||||||
|
uint32_t ready;
|
||||||
uint8_t irq_num;
|
uint8_t irq_num;
|
||||||
uint8_t ready;
|
|
||||||
} chopstx_intr_t;
|
} chopstx_intr_t;
|
||||||
|
|
||||||
void chopstx_claim_irq (chopstx_intr_t *intr, uint8_t irq_num);
|
void chopstx_claim_irq (chopstx_intr_t *intr, uint8_t irq_num);
|
||||||
|
|||||||
Reference in New Issue
Block a user