5 ms·
INC/DEC don’t give you a copy of the value to examine (the Windows 98 behavior described in the article). If you want that, you need a second instruction and yo
by anderskaseorg 4y ago
INC/DEC don’t give you a copy of the value to examine (the Windows 98 behavior described in the article). If you want that, you need a second instruction and you need to worry about being interrupted.
- YZF 4y agoThe parent is correct. You don't need to worry about being interrupted. If you did no program would be correct in the presence of interrupts. The entire state of the processor can be saved and restored during an interrupt as if nothing has happened. LOCK is for multi-processing. EDIT: That said you do have to worry about being interrupted mid-sequence of instructions and data races but that's what critical sections are for. So INC or DEC (which increment/decrement and set flags) are perfectly safe under interrupts. If you have more a more complex sequence then you need a critical section. However they are not safe (without the LOCK) under multi-processing. EDIT2: also to clarify you're not interrupted mid-instruction. I.e. you can't observe the undelying read/modify/write through interrupts, only through a second core/processor.
- anderskaseorg 4y agoIt’s clear from the article and the chain of parent comments that we’re talking about threads with preemptive multitasking and access to a shared integer in memory. I didn’t say INC/DEC are unsafe; I said they don’t satisfy the contract of the function in the article, the whole point of which is about the return value. If you (e.g.) combine an INC/DEC with a MOV to fetch the return value, that’s unsafe. You can make it safe with a critical section, but that may be unnecessarily inefficient. The XADD instruction referenced in the article, when it’s available (486+), can be used to satisfy the contract without this overhead.
- YZF 4y agoBut the concern with a shared integer is correctness under inc/dec. If you have a multi-processor and you don't LOCK then the value can be anything because it's racy. With multiple threads there is still correctness when multiple threads access the atomic and the flags returned are correct without the need to "lock the bus". The article just explains why the return value uses the flags - for correctness. If you have a sequence of instructions then (potentially) you don't have correctness either with multiple threads on the same core or across cores. EDIT: if your point was that you can't return the value using either LOCK INC or INC and either on a single core or multiple cores then your point is correct. I sort of read it as INC itself (the x86 instruction) is racy under multi-threading.
- anderskaseorg 4y agoThe context in which this discussion takes place is “Return Values: The function returns the resulting incremented value” and “Since Windows 98 was a uniprocessor operating system, it didn’t have to worry about a second processor changing the memory at the same time”. The concern with a shared integer in this context is that you get interrupted between INC and MOV.
- codeflo 4y agoAs the comment you reply to states: “INC/DEC don’t give you a copy of the value to examine. (…) If you want that, you need a second instruction.” Here’s what you might be missing: Even on a single processor machine, if you have multiple threads and a preemptive (!) multitasking OS like Windows 95, any locking protocol can be interrupted mid-sequence. A second OS thread (yes, they existed) may be scheduled and observe an inconsistent state. Or it may perform an update on its own and leave the first state in an inconsistent state when it resumes. And yes, this kind of stuff actually happened.
- YZF 4y agoI wrote that sort of code on those sorts of platforms ;) The bigger problem was code that assumed INC/DEC was atomic and broke when the first multi core CPUs came out. Everyone knows/knew that a sequence of instructions can be interrupted with multiple OS threads and preemption. So I don't think I'm missing that. INC/DEC give you flags but they don't give you a copy of the value. But you still need to LOCK INC or LOCK DEC for your code to be multi-core safe. And if you're sharing values you need something like "test and set" or a kernel synchronization object. EDIT: I was basically saying the comment above that was correct because the comment I was replying to seemed to suggest it wasn't. But I guess both of them are correct and we're all in agreement ;) EDIT2: So really I agree that InterlockedIncrement/Decerement were designed for multi-processing use case since they basically offer no advantage for a single core over just inc/dec (++/--) this is what the comment above the one I was replying to (gp?) was implying and the person responding to that seemed to think otherwise ;) but I think we still found out we all agree.