4 ms·
It's actually really easy. Traditional threading has a very obvious design pattern, where if someone isn't doing this you can be sure there's an issue. TL;DR,
by maldev 4y ago
It's actually really easy. Traditional threading has a very obvious design pattern, where if someone isn't doing this you can be sure there's an issue.
TL;DR, if you don't have a "getter/setter" you're doing it wrong and it's a sign of bad code.
Firstly, make sure that there's only ONE place to write. Write being changing the variable in anyway(Obviously make sure you have a lock or other primitive here). If there's multiple places, that's a big smell for a race condition, and a massive turd for a shitty design pattern.
Secondly, just like the write, all reads should be done from a single place.
And then for the advance developer, you also may need to make sure that the cache is synchronized. Pretty much all libraries will do this for you, but if you ever need to dive into internals that alot of "guides" or papers DON'T cover, you need Fences or whatever your architecture provides. I have this page bookmarked for when I need a quick refresher https://stackoverflow.com/questions/27627969/why-is-or-isnt-sfence-lfence-equivalent-to-mfence https://stackoverflow.com/questions/27627969/why-is-or-isnt-...
- gpderetta 4y agoSorry but it is not easy at all. Getter and setters do not help and can give a false sense of security. And caches do not need to be explicitly synchronized. On all common platforms the hardware will do it for you without user intervention. Fences have a different purpose.
- deleted 4y ago[deleted]
- maldev 4y agoHonestly just to prove how wrong you are and what you're saying is blatant misinformation, i'll correct you, since I don't think you're talking in good faith, or have any idea what you're saying. Regarding fences, In the intel system programming guide, section 8.1.3 " Handling Self- and Cross-Modifying Code The act of a processor writing data into a currently executing code segment with the intent of executing that data as code is called self-modifying code. IA-32 processors exhibit model-specific behavior when executing selfmodified code, depending upon how far ahead of the current execution pointer the code has been modified. As processor microarchitectures become more complex and start to speculatively execute code ahead of the retirement point (as in P6 and more recent processor families), the rules regarding which code should execute, pre- or post-modification, become blurred. To write self-modifying code and ensure that it is compliant with current and future versions of the IA-32 architectures, use one of the following coding options: (* OPTION 1 ) Store modified code (as data) into code segment; Jump to new code or an intermediate location; Execute new code; Vol. 3A 8-5 MULTIPLE-PROCESSOR MANAGEMENT ( OPTION 2 ) Store modified code (as data) into code segment; Execute a serializing instruction; ( For example, CPUID instruction ) Execute new code;" It further states, "The act of one processor writing data into the currently executing code segment of a second processor with the intent of having the second processor execute that data as code is called cross-modifying code. As with selfmodifying code, IA-32 processors exhibit model-specific behavior when executing cross-modifying code, depending upon how far ahead of the executing processors current execution pointer the code has been modified. To write cross-modifying code and ensure that it is compliant with current and future versions of the IA-32 architecture, the following processor synchronization algorithm must be implemented: ( Action of Modifying Processor ) Memory_Flag := 0; ( Set Memory_Flag to value other than 1 ) Store modified code (as data) into code segment; Memory_Flag := 1; ( Action of Executing Processor ) WHILE (Memory_Flag ≠ 1) Wait for code to update; ELIHW; Execute serializing instruction; ( For example, CPUID instruction *) Begin executing modified code;" So please tell me how the intel developer manual is wrong, how i'm wrong, and how they all server a "Different purpose" than what is given. I can link more instances from the Intel Developer manual if you want. I assume you've read it if you're trying to talk about the subject.
- gpderetta 4y agoFences are not mentioned anywhere in your quoted text. Note that serializing instructions are not fences (although there are overlaps: some fences are also serializing instructions). In any case on x86 the instruction cache is coherent with the data cache all the time, the serializing instruction is needed to flush the instruction pipeline (not the cache). I'll concede that there are some non-x86 architectures where the instruction cache is not necessarily coherent with the data cache, but it is not terribly relevant as the topic here is concurrency, not self modifying code.
- maldev 4y agoFences are meant for serializing. Although the intel documentation says CPUID, you use a fence there. This should be obvious, as if you know what a fence is, you know they're entire purpose is serialization. I'll put what the manual says on them, but it's not a hard concept, the intel manualy literally says sfence = SERAILIZES STORES. Lfence = SERIALIZES LOADS. Mfence = SERIALIZES LOADS AND STORES. You clearly have ZERO idea what you're talking about if you don't even know what these simple instructions mean. So to answer your question in the quoted text, where it says to use a serializing instruction, it means to use the appropriate fence! Not only this, but your entire premise of a properly written getter/setter being "Wrong" is entirely wrong, as the entire reason for a race condition is having improper getters and setters! Here are the following fences referenced in that article, and any good asm programmer will tell you that fences are used for this purpose(NOT CPUID) LFENCE: (Intel manual Vol. 2A 3-585) *Description* Serializes load operations Performs a serializing operation on all load-from-memory instructions that were issued prior the LFENCE instruction. MFENCE: (Intel manual 4-22 Vol. 2B) *Description* Serializes load and store operations. Performs a serializing operation on all load-from-memory and store-to-memory instructions that were issued prior SFENCE:(4-620 Vol. 2B) Description: *Serializes* store operations Orders processor execution relative to all memory stores prior to the SFENCE instruction. The processor ensures that every store prior to SFENCE is globally visible before any store after SFENCE becomes globally visible. The SFENCE instruction is ordered with respect to memory stores, other SFENCE instructions, MFENCE instructions, and any serializing instructions (such as the CPUID instruction). the MFENCE instruction. I'm not sure what you think fences are, or what they're for. But they're clearly for serializing. And were talking about concurrency, that article is from the intel manual on multiprocessor programming, which is concurrency! Do you not even know basic terms? Do you not even read replies?