What is RTOS Kernel Locking and When Do You Need to Use It?

982 views Asked by At

I'm using ChibiOS RTOS and I have some questions that might seem basic, but kind of escape me a bit.

ChibiOS has a function called:

chSysLock();

and

chSysUnlock();

It's my understanding that these two functions will lock and unlock the kernel respectively.

So my questions are:

  1. What does locking the kernel do?
  2. Why do you want to lock the kernel?

And lastly, lets use this example:

static void sem_cb(void) {
    chSysLock();
    chBSemSignalI(&sem_1);
    chSysUnlock();
}

This function just signals a semaphore for what ever thread is waiting for it.

So my last question is:

  1. What is the point of locking the kernel just to signal a semaphore? If I don't then ChibiOS will complain and won't compile without the system lock.
1

There are 1 answers

0
Clifford On BEST ANSWER

In general in an RTOS kernel locking simply the scheduler will not run so context switches will not occur. Often some or all interrupts are disabled too. Locking is used for critical sections - sections of code that must run without interruption or preemption.

I am no expert in ChibiOS, but it seems somewhat over-complicated in this respect and is not very comprehensively documented. The kernel states are described here. It has two lock modes, and chSysLock() invokes the S-Locked state, where

"Kernel locked and regular interrupt sources disabled. Fast interrupt sources are enabled. S-Class and I-Class APIs are invokable in this state."

It is not clear from the documentation whether that means that only I/S-Class APIs may be used or that I/S-mode APIs may only be called when locked. The whole state and its purpose is not well defined IMO. However it is common in some RTOS to have special versions of functions that do not invoke the scheduler, this saves regular API functions from the overhead of having to check the kernel state or interrupt context and is a minor optimization (at the expense of safety in my opinion). This is borne out by the documentation for chBSemSignalI:

Note

This function does not reschedule.

[...]

Function Class:

This is an I-Class API, this function can be invoked from within a system lock zone by both threads and interrupt handlers.

In your example, what is happening is the the semaphore is given, but the scheduler will not run so any waiting thread will not be immediately made ready. It is not clear whether chSysUnlock() causes the scheduler to run - the documentation says "Special function, this function has special requirements see the notes.", but gives no clue regarding where these notes may be found.

I would expect the scheduler to run, and on the face of it the function sem_cb() would seem to serve little purpose; however I would also expect chSysLock()/chSysUnlock() to be nestable, in which case the purpose of the function makes more sense. It allows a single semaphore-give function (sem_cb()) to be used regardless of the kernel state. That is to say it is safe to call in both normal and S-State, but adds the overhead that the separate S-State/Normal state APIs are intended to avoid. Personally I'd always go for safety (though not necessarily implement it in this manner) at least until it could be shown that the overhead was unacceptable. It essentially says "_give the semaphore and if the kernel is not locked reschedule, otherwise defer rescheduling until the kernel is unlocked - i.e. after the last nested unlock".

It does not allow however sem_cb() to be called from an interrupt context since that would require chSysLockFromISR().

The above makes a lot of assumptions from the documentation and "expected" RTOS behaviour. If I happened to be using ChibOS in the face of such scant documentation, I'd check the source code to determine the exact behaviour.