mikeash.com pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html commentshttp://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#commentsmikeash.com Recent CommentsFri, 29 Mar 2024 05:18:59 GMTPyRSS2Gen-1.0.0http://blogs.law.harvard.edu/tech/rssSteven - 2014-01-08 08:41:42http://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#commentsBrent's remark shows that cv qualifiers should never be written on the left of the declaration. Everybody's who has ever run into the infinitely optimized loop will agree, I'm sure.2c4ffe3367bdc1897be07b59d22e102eWed, 08 Jan 2014 08:41:42 GMTDavid H - 2013-04-14 14:18:31http://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#commentsCan you provide a reference backing this: "Unfortunately, after some additional investigation, I discovered that OSQueue is not entirely thread safe and thus should not be used." I goggled around and did not trip on anything.4d96116e8651f607df43db60cb8158bdSun, 14 Apr 2013 14:18:31 GMTSean M - 2011-03-16 14:16:52http://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#commentsMike, nice article. Nitpick: the 64 bit variants, like OSAtomicAdd64, are available on PowerPC, but only ppc64, not ppc32.75177076b80d198ce07d16189545c350Wed, 16 Mar 2011 14:16:52 GMTBrent Priddy - 2011-03-12 18:40:37http://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#commentsAndre, the volatile keyword is the correct thing to use but in the example the volatile keyword is need to describe the pointer (I am not sure of Mike's usage of the struct to merit a volatile on the contents of the Struct as well). Mike, The while loop in your example if compiled with gcc and -O3 will be an infinite loop because of the compiler optimizing the assignment (thinking that the gStructure pointer does not change since the pointer is not volatile). <br /> <br />It should be: <br /><code> <br />Structure * volatile gStructure <br /></code> <br /> <br />This type of volatile usage is the way to solve this common problem with memory mapped io and aggressive optimizers.eb6c74f52073e736d711a2b45940862bSat, 12 Mar 2011 18:40:37 GMTmikeash - 2011-03-08 02:57:29http://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#commentsA minor quibble: reentrant and thread-safe are not synonyms. The former means that the code can safely be called on the same thread while it's already being called (for example, you can call back in from a callback, or a much worse case, you can safely call it from a signal handler) whereas the latter means multiple threads can hit code simultaneously. They're definitely related though, in that they both require similar concepts, and I think that any code which exclusively uses atomics for safety will automatically gain both properties. <br /> <br />That quibble aside, thanks for the historical view. I had no idea that these things went back that far.b46bd8fbd9bd8ee3abae538030f35c60Tue, 08 Mar 2011 02:57:29 GMTjayc - 2011-03-07 23:40:33http://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#commentsExcellent article!. <br /> <br />As a historical note the IBM mainframe has had "CompareAndSwap" and "TestAndSet' and a few other related instructions as part of its machine instruction set architecture since day 1 (in the 1960s) The design of the OS in 1966 dictated that all system code be reentrant (eg. threadsafe) and it always has been. Even though the first machines were not multi-core the OS simulated it in the low level dispatcher. Later when multiple physical cores we added nothing had to change. Machine level semantics for memory barriers were added later but are part of the ISA today. <br /> <br />The point of all this history is that the concepts presented here are bedrock principles from the early days of computers. They have stood the test of time and provide the most efficient way to be threadsafe at a low level which can be, as the author states, very subtle and tricky. 01a7d72f8b33557f1b9fc8edd8ccc02aMon, 07 Mar 2011 23:40:33 GMTmikeash - 2011-03-07 23:19:04http://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#commentsThus providing an illustration of why I propose to use a memory barrier whenever in doubt. Thanks.b8067c9f2a50b48840c22b7f6de836d4Mon, 07 Mar 2011 23:19:04 GMTgparker - 2011-03-07 22:51:54http://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#comments<div class="blogcommentquote"><div class="blogcommentquoteinner">Technically, the barrier in the second thread should not be necassary, as the second read depends on the first. (The value of s needs to be available before the value of s-&gt;field2 can be retrieved.) </div></div> <br /> <br />You know that you want the second read to depend on the first, but not all CPU architectures actually enforce that dependency without a barrier. 2a56a52b71ebeee9df41d71327e10607Mon, 07 Mar 2011 22:51:54 GMTmikeash - 2011-03-07 04:23:16http://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#commentsIt's needed for the first example in the memory barriers section to make sense, of course. Aside from that, it's more of a reminder than anything. It shouldn't make any difference either way, but it at least helps to point out the fact that this value is being used in tricky ways.6e19cca207c57784422ea53262d0af2bMon, 07 Mar 2011 04:23:16 GMTAndre Pang - 2011-03-07 04:12:21http://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#commentsI'm slightly surprised at your use of volatile, Mike. Given your excellent explanation of memory barriers and atomic operations here, why use volatile at all? I can't see it being needed in any of the examples above. Otherwise, awesome write-up, as always.bc9502b5d60b9ed2ae4c6caede11f247Mon, 07 Mar 2011 04:12:21 GMTmikeash - 2011-03-07 01:31:32http://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#commentsI've been talking offline with a couple of anonymous readers and wanted to briefly summarize the important bits here. <br /> <br />First: if you're using garbage collection, the OSAtomic functions will bypass the mandatory GC write barriers when used with object pointers (or other strong pointers). If you are writing a GC app and want atomic operations on strong pointers, check out the <code>objc_atomicCompareAndSwapPtr</code> function and its friends in <code>objc/objc-auto.h</code>. <br /> <br />Second: there was a strong disagreement with my proposition to use a memory barrier when in doubt. It was proposed that, if you don't know whether you need a memory barrier, you probably need to think things through more rather than adding them just to be safe. You may have missed an important barrier otherwise. While I still hold my position, this is definitely a good point.3439f97262e42f69f6ef0d22b8b45b63Mon, 07 Mar 2011 01:31:32 GMTSteve Weller - 2011-03-04 23:46:51http://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#commentsThe docs on OSAtomicCompareAndSwap32 are poor. They say it returns bool, yet do not document its value for different circumstances. You claim the return value is success. The docs claim that it "Returns the original value referenced by __theValue." I think that is left over from some hardware docs that are describing the actual swap that takes place between two values in memory in some implementations. <br /> <br /><a href="http://developer.apple.com/library/mac/#documentation/DriversKernelHardware/Reference/libkern_ref/OSAtomic_h/index.html%23//apple_ref/c/func/OSAtomicCompareAndSwap32">http://developer.apple.com/library/mac/#documentation/DriversKernelHardware/Reference/libkern_ref/OSAtomic_h/index.html%23//apple_ref/c/func/OSAtomicCompareAndSwap32</a>6485e6dd43e9b5d74c3e76c7f2665961Fri, 04 Mar 2011 23:46:51 GMTVasi - 2011-03-04 23:32:17http://www.mikeash.com/?page=pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html#commentsThanks for the Q&amp;A. Folks should note that another good reference to the OSAtomic tools can be found in 'man atomic'.abcdcc6f60326735988e3bf66e95d6c1Fri, 04 Mar 2011 23:32:17 GMT