context switch observed inside S-locked state Topic is solved

Report here problems in any of ChibiOS components. This forum is NOT for support.
faisal
Posts: 290
Joined: Wed Jul 19, 2017 12:44 am
Has thanked: 38 times
Been thanked: 39 times

Re: context switch observed inside S-locked state

Postby faisal » Sun May 02, 2021 1:26 am

Also, the documentation says that interrupts are disabled in S locked state, but there is code like the following which works. So.are interrupts disabled or not? [I know they are not, I'm just trying to come up with a coherent understanding of the lock states .... And to reconcile language in the documentation]

Thread:
ChSysLock
chThdSuspendS
...

ISR
ChSysLockISR
chThdResumeI
...

User avatar
Giovanni
Site Admin
Posts: 13629
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 888 times
Been thanked: 768 times
Contact:

Re: context switch observed inside S-locked state

Postby Giovanni » Sun May 02, 2021 5:16 am

Hi Faisal,

The S state is where context switch happens, it is meant to happen in that state if you call an S function (S functions are exactly those functions that can do a context switch inside).

Everywhere in the kernel you will see something like this:

Code: Select all

chSysLock();
...
chSomethingS();
...
chSysUnlock();


The critical section does not guarantee atomicity across the call to S-function. Interrupt are indeed disabled but could be serviced in there "on the other side" of the context switch, the other thread will call chSysUnlock() after exiting from its own S-function.

You should see this as:

Code: Select all

chSysLock();
...
chSysUnlock();
chSomething();
chSysLock();
...
chSysUnlock();


If you need atomicity then do:

Code: Select all

chSysLock();
...
chSomethingI();
...
chSomethingI();
...
chSchRescheduleS();
chSysUnlock();


This delays the context switch to the point where you want it to happen, you can also call multiple "I" functions and then reschedule atomically in one point (common use case, imagine you want to signal 2 semaphores atomically).

Giovanni

faisal
Posts: 290
Joined: Wed Jul 19, 2017 12:44 am
Has thanked: 38 times
Been thanked: 39 times

Re: context switch observed inside S-locked state

Postby faisal » Sun May 02, 2021 5:25 am

So, given that - do you think the documentation needs to elaborate some more on what S-locked means?

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


So they are disabled until an S class API call is made. As you explained, to imagine it as:

Code: Select all

chSysLock();
...
chSysUnlock(); // imagined
chSomething();
chSysLock(); // imagined
...
chSysUnlock();


So interrupts really truly are disabled after chSysLock() until the first call to S class function? At what point are interrupts enabled again, and what type of S class functions will result in interrupts being enabled? Knowing the side effects of system calls with regards to when interrupts are enabled/disabled should be clear (they aren't crystal clear in my head, I have to rediscover this every now and then, and forget eventually).

User avatar
Giovanni
Site Admin
Posts: 13629
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 888 times
Been thanked: 768 times
Contact:

Re: context switch observed inside S-locked state

Postby Giovanni » Sun May 02, 2021 6:07 am

Interrupts are not enabled by the S function but the function performs a context switch, it is the OTHER thread re-enabling interrupts, the context switch is always performed from a critical section so after a switch an unlock follows on the other side.

Giovanni

User avatar
sabdulqadir
Posts: 48
Joined: Fri Mar 23, 2018 7:29 pm
Has thanked: 12 times
Been thanked: 4 times

Re: context switch observed inside S-locked state

Postby sabdulqadir » Mon May 03, 2021 6:33 pm

Giovanni wrote:I-class functions never perform a context switch, s-class can do that.
...

The ambiguity is that chSchRescheduleS() could not be required depending on which I-class functions you are using, it does not hurt anyway. In general, those I-class functions that can wakeup other threads require the final reschedule.

See this article: http://chibios.org/dokuwiki/doku.php?id ... :kb:atomic

Giovanni


Hi Giovanni,
Can you update the link here?

Thanks,
AQ

User avatar
Giovanni
Site Admin
Posts: 13629
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 888 times
Been thanked: 768 times
Contact:

Re: context switch observed inside S-locked state

Postby Giovanni » Mon May 03, 2021 7:10 pm


User avatar
sabdulqadir
Posts: 48
Joined: Fri Mar 23, 2018 7:29 pm
Has thanked: 12 times
Been thanked: 4 times

Re: context switch observed inside S-locked state

Postby sabdulqadir » Mon May 03, 2021 11:49 pm

Hi Giovanni,
Thanks for the input here. This does sound confusing. Specially when the documentation does not make it any clearer. Consider this example:

Thread:
ChSysLock()
chThdSuspendTimeoutS()
ChSysUnlock()


It seems that the thread locks the system (no interrupts) and then goes to sleep. Even if we assume that rescheduling would happen and next ready thread would take over, I am still unsure who unlocks the system.

Would the next ready thread have to explicitly unlock the system?

Thanks,
AQ

faisal
Posts: 290
Joined: Wed Jul 19, 2017 12:44 am
Has thanked: 38 times
Been thanked: 39 times

Re: context switch observed inside S-locked state

Postby faisal » Tue May 04, 2021 12:04 am

sabdulqadir wrote:Hi Giovanni,
Thanks for the input here. This does sound confusing. Specially when the documentation does not make it any clearer. Consider this example:

Thread:
ChSysLock()
chThdSuspendTimeoutS()
ChSysUnlock()


It seems that the thread locks the system (no interrupts) and then goes to sleep. Even if we assume that rescheduling would happen and next ready thread would take over, I am still unsure who unlocks the system.

Would the next ready thread have to explicitly unlock the system?

Thanks,
AQ


So, let's expand this the way Giovanni did previously:

Code: Select all

ChSysLock()
ChSysUnlock() /* Implicit */

chSysLock() /* Implicit */
chThdSuspendTimeoutS()
/* Port level context switch to idle thread if that is the only thread ready to run */
chSysUnlock() /* Implicit */

chSysLock() /* Implicit */
ChSysUnlock()


Since chThdSuspendTimeoutS() is an S-class API, it could (and does in this case) re-run the scheduler and context switches if necessary. In this case, since the thread is going to sleep, it will context switch to the next thread which is ready to run with the highest priority. Once the context switch occurs, interrupts are re-enabled (unless the context switch occurs and we happen to end up in the S-locked state in another context which is ready to run). If no thread is ready to run, it will switch to the idle thread because it is always ready to run.

faisal
Posts: 290
Joined: Wed Jul 19, 2017 12:44 am
Has thanked: 38 times
Been thanked: 39 times

Re: context switch observed inside S-locked state

Postby faisal » Tue May 04, 2021 12:27 am

This helps: Get the notion out of your head that the "Lock" ind ChSysLock() means that you are establishing a critical zone as you would in other RTOSes. It's not true that interrupts are completely disabled from your ChSysLock() invocation to your next ChSysUnlock() invocation. S-Class APIs can and will context switch if needed when you invoke them. Once you context switch, the thread that you context switch to now exits "S-Lock" state if necessary and interrupts will be enabled. I said will exit "S-lock" state if necessary, because it's possible that it may not. For example, you context switch to another thread which was already in an S-lock state when it was taken out of the ready queue.

Code: Select all

//Thread 1 (low priority)
ChSysLock();
for (i = 0; i < 10; i++) chFifoSendObjectS();
ChSysUnlock();

//Thread 2A (high priority)
ChSysLock();
while (chFifoReceiveObjectTimeoutS() == MSG_OK);
ChSysUnlock();


In the above scenario thread 1 will keep pushing objects into the FIFO. As soon as an object is pushed, it will context switch to the higher priority thread 2A that is waiting on the fifo. Thread 2A will process the item, then will go back to waiting on the fifo and a context switch will happen again back to thread 1. And this will repeat. All the while, I believe that interrupts will *not* be enabled. Now, if the higher priority thread were this instead:

Code: Select all

// Thread 2B (high priority)
while (chFifoReceiveObjectTimeoutS() == MSG_OK);


... each time the context switch happens from thread 1 to thread 2B, interrupts will be enabled as soon as execution context returns to thread 2B (because it wasn't in a S-lock state when it was pre-emptied/went to sleep).

In order to turn your chSysLock() <-> chSysUnlock() region of code into a true "critical zone" (no interrupts, or scheduler running) you have to be conscious of what you put in there. It's not as simple as do a lock(), then do whatever, then unlock(). S-class API calls can and will reschedule and interrupts could end up being enabled. You will have to look at the documentation/source code for whichever S-class API you intend to use in your S-locked state to figure out if it's possible for a reschedule to happen. To be safe, just don't call any S-class APIs in your S-lock state if you want the guarantee of no interrupts or scheduling. You can use I-class APIs - which are guaranteed not to reschedule. The downside of that is that if the side effects of calling those I-class APIs is that a reschedule should happen (when exiting the S-lock state), you need to explicitly call the scheduler before exiting S-lock state.

Follow the article Giovanni referenced and you'll be golden.

Hope this long winded explanation of basically what's in that article helps. I know I've head to convince myself of this a few times already :).

User avatar
Giovanni
Site Admin
Posts: 13629
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 888 times
Been thanked: 768 times
Contact:

Re: context switch observed inside S-locked state

Postby Giovanni » Tue May 04, 2021 6:09 am

I know it is a bit non-obvious, the whole RTOS has been designed around that lock-switch-unlock concept, lock/unlock are not about disabling interrupts, there are enable/suspend/disable for that.

In SMP mode lock/unlock also manage the kernel spinlock because kernel structures are accessed by multiple cores so it becomes lock-do_shared_kernel_things-unlock and it ensures consistency among multiple OS instances.

Giovanni


Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 5 guests