From 46e6c6f8cb68123021e84d6f82adf73ade20faef Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Wed, 4 May 2016 10:01:36 -0400 Subject: [PATCH] microkernel: lock interrupts in _k_state_bit_[re]set() Locks interrupts in the microkernel routines _k_state_bit_reset() and _k_state_bit_set(). This is a necessary pre-requisite for allowing microkernel objects to pend on nanokernel objects since that feature will require the manipulation of the microkernel queues in the context of an ISR as well as the kernel server fiber. Change-Id: I2d263707e0d3aed75bba971df878daa3d7ae1d11 Signed-off-by: Peter Mitsis --- kernel/microkernel/k_task.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/kernel/microkernel/k_task.c b/kernel/microkernel/k_task.c index fc95b6314eb..f5e968d4f1a 100644 --- a/kernel/microkernel/k_task.c +++ b/kernel/microkernel/k_task.c @@ -49,9 +49,17 @@ ktask_t task_id_get(void) * @param X Pointer to task * @param bits Bitmask of TF_xxx bits to reset * @return N/A + * + * @internal + * When operating on microkernel objects, this routine is invoked in the + * context of the microkernel server fiber. However, since microkernel tasks + * may pend/unpend on nanokernel objects, interrupts must be locked to + * prevent data corruption. + * @endinternal */ void _k_state_bit_reset(struct k_task *X, uint32_t bits) { + unsigned int key = irq_lock(); uint32_t f_old = X->state; /* old state bits */ uint32_t f_new = f_old & ~bits; /* new state bits */ @@ -73,6 +81,8 @@ void _k_state_bit_reset(struct k_task *X, uint32_t bits) (1 << (X->priority & 0x1F)); } + irq_unlock(key); + #ifdef CONFIG_TASK_MONITOR f_new ^= f_old; if ((_k_monitor_mask & MON_STATE) && (f_new)) { @@ -98,9 +108,17 @@ void _k_state_bit_reset(struct k_task *X, uint32_t bits) * @param task_ptr Task pointer * @param bitmask of TF_xxx bits to set * @return N/A + * + * @internal + * When operating on microkernel objects, this routine is invoked in the + * context of the microkernel server fiber. However, since microkernel tasks + * may pend/unpend on nanokernel objects, interrupts must be locked to + * prevent data corruption. + * @endinternal */ void _k_state_bit_set(struct k_task *task_ptr, uint32_t bits) { + unsigned int key = irq_lock(); uint32_t old_state_bits = task_ptr->state; uint32_t new_state_bits = old_state_bits | bits; @@ -157,6 +175,8 @@ void _k_state_bit_set(struct k_task *task_ptr, uint32_t bits) } } + irq_unlock(key); + #ifdef CONFIG_TASK_MONITOR new_state_bits ^= old_state_bits; if ((_k_monitor_mask & MON_STATE) && (new_state_bits)) {