Hello,
Why does not RTX implement a reference counter for its "tsk_lock"/"tsk_unlock" mechanism? The way things are implemented at the moment, any task that calls "tsk_unlock" enables the scheduler. But this can cause problems in nested calls; And, can cause a RTX kernel corruption if some code calls this from interrupt mode while a task is executing a RTX API (which assumes scheduler is disabled). There is no indication in the user manual that the kernel can be damaged if the scheduler is enabled from interrupt mode (NOTE: enabling the scheduler from interrupt mode only sets an interrupt line which is inherently safe!). FreeRTOS has this feature (and much more). Why not RTX?
I know who I vote for...
Actually, the source of the problem was this code:
#define SERVICE_WATCHDOG tsk_lock() ;\ g_application_alive_signals |= ( (int32u)1<<(os_tsk_self() - g_first_task_id) ) ;\ tsk_unlock() ;\
Which allows tasks to set their "alive bit" regularly without servicing the watchdog directly (which happens in one place only if all alive bits are set). Originally, it used a mutex, but "tsk_lock" and "tsk_unlock" are much cheaper, computation wise. However, given the nature of the code, what should have been done is disabling of _all_ interrupts for this short period of time, not just the scheduler (thus, a mutex was insufficient as well). Then, this code was introduced into a function that was called both from user mode and interrupt mode (LPC2478) which was called during a long data transfer via the SSP bus. That was enough to cause a arbitrary, random data corruption resulting in entry into abort mode or hanging in a loop in a RTX API.
I can see no need for tsk_lock/tsk_unlock.
The g_application_alive_signals needs to be updated atomic, if accessed also from the IRQ handler. That has nothing to do with the tsk_lock()/tsk_unlock(). The usage of those function is highly deprecated.
Just a short follow up:
Keil have updated the user manual of RTX to indicate that calling "tsk_unlock" from privileged mode is not allowed.