Hacker News new | ask | show | jobs
by plapetomain 2335 days ago
Well you either did ask that question and answered it by using appropriate locking and concurrent data structures (which is basically implicitly asking and addressing that question..) or you wrote a lot of crash prone shitty software. Which one was it?
1 comments

Locking isn't about preemption. You can have a system without preemption and still have to use the locks and other concurrent primitives.
Not sure why the downvotes. If a system has enough CPUs, threads might never be preempted, and yet we must still use locks or concurrent primitives if we are sharing resources across multiple threads.

I don't think I've actually thought about preemption explicitly since the Nintendo64 days when thread priorities figured into our locking strategy. But then we'd also re-implemented the scheduler and, at times, turned off the official OS to go do something we needed to do without interruption. So, like I said, preemption not high on my radar these days, as it falls under the general category of "concurrency". Even an iPhone has 4 CPUs.

The question shouldn't have been about preƫmption, but rather, "what if some other thread mutates my data here?"

The effect is much the same, whether the race is caused by task scheduling, or just because another core got there first.

Or even if some random function you called fired some callback that just mutated some state you were in the middle of changing.
Locking and preemption are different but sometimes related concepts. As you mention.

Modern kernel people still have to worry about locking as well as preemption, if you look at the NT native API's you will see dispatch levels, which control whether kernel threads can be prempted for higher priority activities, linux is similar with the _irqsave() and preempt_ calls.

Is this for example important when syncing with an interrupt handler (no preempt/rt config), which is why there are both spin_lock() and spin_lock_irqsave() which implicitly blocks irq preemption. AKA if you grab a lock that is needed by say an interrupt handler, then you take said interrupt the machine will deadlock because the scheduler won't deschedule the interrupt handler.

What purpose would locks and concurrent primitives have in a system where running code is not preempted?
In addition to parallel in all senses/levels systems mentioned by the other commenter, another example would be a truely single threaded hardware with cooperative or even sequential multithreading where you'd use locking/etc. to safeguard your memory model invariants against for example compiler, JIT and hardware optimization shenanigans.
To guarantee two different threads don't try to simultaneously mutate (or in some cases access) shared resources.