1

I have a process P and a kernel thread KT. I want to synchronize execution of P with KT. KT is basically an event handler. But my requirement is that KT should not go ahead processing events if P is running. So I need to pause P and then go ahead with event processing in KT and resume P. So my question is, from KT, how do I force preempt P ? For resuming later, I can just use wake_up_process().

For scheduling out a process, commonly used trick is to set the state as TASK_INTERRUPTIBLE and call schedule(). Would it work if I have task_struct pointer of P saved, then from KT, to schedule out P, I set state of P(instead of current) as TASK_INTERRUPTIBLE and call schedule ? It is a hack, would it work ? Do you see any clean way that I am missing ?

Is there some signal I can send P to ask it to preempt ?

bladeWalker
  • 978
  • 1
  • 13
  • 30
  • 2
    If synchronization is desired, why not use a synchronization primitive (such as a futex) instead of some obscure tricks? Have the process block and wake it up when there's something to process. – Damon May 21 '13 at 09:31
  • `SIGSTOP` (since you asked for signals) is similar -- why apply such a hack? Using several threads implies parallelism (it does not really make a lot of sense otherwise -- if threads only ever run exclusively, you can as well use a single thread for everything). So, let the consuming thread (application) block on a futex or on an eventfd (via epoll if you like) and the producer (kernel thread) notify that when there's something to do. It's much less failure-prone too. – Damon May 21 '13 at 09:36
  • Thanks Damon. I redesigned to use locks instead of hack. – bladeWalker Aug 28 '13 at 00:32

1 Answers1

2

You cannot do what you are asking. Sure you could set state to TASK_INTERRUPTIBLE from another process/thread running on the same or on a different CPU/core. But you can't invoke schedule() on another CPU/core (for the same reason you can't invoke any other function on another CPU/core). Consider that schedule() does not take CPU/core ID as an argument so how would you tell it that core1 should reschedule?

Another popular solution to these types of synchronization requirements is to use real-time priorities. This is almost as ugly as what you proposed but it can actually work if you have a kernel that supports real-time priorities. The idea here is simple, process P has a higher priority than KT and it will preempt KT when it is ready to run. Use CPU affinity to force both processes onto the same CPU/core (this is important, it won't work otherwise!). BTW, there isn't any real synchronization in this approach -- you are strictly relying on RT priorities to enforce when P and KT run with respect to one another.

I suggest you take the advice of Damon and re-design since there is no real clean way to do what you ask but there are many clean ways to synchronize two processes.

slowjelj
  • 562
  • 4
  • 4
  • 1
    If you can't remotely wake a thread waiting on an event, it would imply that a thread leaving a mutex which is being waited on by another thread could not wake the waiting thread, but certainly it does (and the waiting thread doesn't wait until the next timer tick to start executing). How could that work then? – BeeOnRope Aug 18 '17 at 23:01
  • @BeeOnRope - You can't use a mutex to signal an event (see [here](https://stackoverflow.com/questions/12551341/when-is-a-condition-variable-needed-isnt-a-mutex-enough/12569318#12569318)) but you _can_ use a condition variable which includes a mutex but also uses semaphore-style event notification. And, yes, you can remotely wake a thread but, with mutexes, semaphores, and condition variables it isn't **you** that is scheduling the thread, _the kernel is_! Using thread state and kernel scheduling primitives for thread synchronization is doomed to fail. That was my point. – slowjelj Oct 28 '17 at 00:06
  • What I mean is that code on one core triggers code on another core _all the time_. For example, when a thread leaves a `mutex` and another thread was waiting for that mutex, that "other thread" will generally start running on _another_ core (since the code that just left the mutex is still running on its core). I don't know why you are referring to events or condition variable: I just picked mutex as the simplest example of a concurrency control object, the the same applies to semaphores, barriers, condition variables whatever. – BeeOnRope Oct 29 '17 at 05:25
  • The common theme is that it is _very common_ for code running on one core to trigger code to on another core. If I understand what you're saying, that can't occur. Yes, of course it's the _kernel_ that does it, but did I claim otherwise? The userspace code calls into the kernel, which wakes code on another core as needed, usually via an IPI, or `monitor`/`mwait` type constructs. – BeeOnRope Oct 29 '17 at 05:27
  • Either you don't understand what I'm saying or I don't understand what you are saying. But do please point to where I said code on one core cannot trigger code on another core. It seems like you are arguing against a point I never made. And I know how mutexes work, but thank you for the refresher. – slowjelj Nov 02 '17 at 20:07
  • Yeah sorry I probably misunderstood. I thought you were saying that in general scheduling won't result in something starting on another core, but I think you were talking just specifically about a specific `schedule()` call in the Linux kernel as the OP mentioned. Yes, what he's suggesting won't work. Using existing synchronization mechanisms makes the most sense. – BeeOnRope Nov 02 '17 at 21:57