The synchronization should be performed by semaphores. In a thread, any variety of semaphore operations can be used. This includes the blocking rtkSemaphoreP and the potentially context switching rtkSemaphoreV.
However, in an ISR, care must be taken not to use rtkSemaphoreP or rtkSemaphoreV. This is because no context switching should occur inside an ISR. Instead, rtkSemaphoreTryP should be used, as it only returns whether the ‘P’ operation is done, but it does not block. For ‘V’ operations, the function rtkSemaphoreVNoCS should be used, as it does not trigger a context switch.
Note that the use of rtkSemaphoreVNoCS means that any freed thread will only get a chance to resume execution at the next context switch triggered either by a voluntary yield (by rtkYield or rtkThreadSchedule) or a forced context switch triggered by the timer due to time slicing or priority levels.