{"id":20663,"date":"2008-10-03T10:00:00","date_gmt":"2008-10-03T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2008\/10\/03\/acquire-and-release-sound-like-bass-fishing-terms-but-they-also-apply-to-memory-models\/"},"modified":"2008-10-03T10:00:00","modified_gmt":"2008-10-03T10:00:00","slug":"acquire-and-release-sound-like-bass-fishing-terms-but-they-also-apply-to-memory-models","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20081003-00\/?p=20663","title":{"rendered":"Acquire and release sound like bass fishing terms, but they also apply to memory models"},"content":{"rendered":"<p><P>\nMany of the normal interlocked operations\ncome with variants called\n<CODE>InterlockedXxxAcquire<\/CODE> and <CODE>InterlockedXxxRelease<\/CODE>.\nWhat do the terms <CODE>Acquire<\/CODE> and\n<CODE>Release<\/CODE> mean here?\n<\/P>\n<P>\nThey have to do with the memory model and how aggressively\nthe CPU can reorder operations around it.\n<\/P>\n<P>\nAn operation with <I>acquire<\/I> semantics is one which does not\npermit subsequent memory operations to be advanced before it.\nConversely,\nan operation with <I>release<\/I> semantics is one which does not\npermit preceding memory operations to be delayed past it.\n(This is pretty much the same thing that\n<A HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa490209.aspx\">\nMSDN says on the subject of Acquire and Release Semantics<\/A>.)\n<\/P>\n<P>\nConsider the following code fragment:\n<\/P>\n<PRE>\nint adjustment = CalculateAdjustment();\nwhile (InterlockedCompareExchangeAcquire(&amp;lock, 1, 0) != 0)\n  { \/* spin lock *\/ }\nfor (Node *node = ListHead; node; node = node-&gt;Next)\n   node-&gt;value += adjustment;\nInterlockedExchangeRelease(&amp;lock, 0);\n<\/PRE>\n<P>\nApplying <I>Acquire<\/I> semantics to the first operation\noperation ensures that the operations on the linked list\nare performed\nonly after the <CODE>lock<\/CODE> variable\nhas been updated.\nThis is obviously desired here, since the purpose of the\nupdating the <CODE>lock<\/CODE> variable is ensure that\nno other threads are updating the list while we&#8217;re walking it.\nOnly after we have successfully set the lock to&nbsp;1\nis it safe to read from <CODE>ListHead<\/CODE>.\nOn the other hand,\nthe <I>Acquire<\/I> operation imposes no constraints upon when\nthe store to the <CODE>adjustment<\/CODE> variable can be\ncompleted to memory.\n(Of course, there may very well be\nother constraints on the <CODE>adjustment<\/CODE>\nvariable,\nbut the Acquire does not add any new constraints.)\n<\/P>\n<P>\nConversely, <I>Release<\/I> semantics for an interlocked\noperation prevent pending memory operations from being delayed\npast the operation.\nIn our example, this means that the stores to\n<CODE>node-&gt;value<\/CODE> must all complete\nbefore the interlocked variable&#8217;s value changes\nback to zero.\nThis is also desired, because the purpose of the lock\nis to control access to the linked list.\nIf we had completed the stores after the lock was released,\nthen somebody else could have snuck in, taken the lock,\nand, say, deleted an entry from the linked list.\nAnd then when our pending writes completed, they would end up\nwriting to memory that has been freed. Oops.\n<\/P>\n<P>\nThe easy way to remember the difference between <I>Acquire<\/I>\nand <I>Release<\/I>\nis that <I>Acquire<\/I> is typically used when you are acquiring a resource\n(in this case, taking a lock),\nwhereas\n<I>Release<\/I> is typically used when you are releasing the resource.\n<\/P>\n<P>\nAs\n<A HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa490209.aspx\">\nthe MSDN article on acquire and release semantics<\/A> already notes,\nthe plain versions of the interlocked functions impose both acquire\nand release semantics.\n<\/P>\n<P>\n<B>Bonus reading<\/B>:\n<A HREF=\"http:\/\/blogs.msdn.com\/kangsu\/\">Kang Su<\/A>\ndiscusses\n<A HREF=\"http:\/\/blogs.msdn.com\/kangsu\/archive\/2007\/07\/16\/volatile-acquire-release-memory-fences-and-vc2005.aspx\">\nhow VC2005 converts volatile memory accesses\ninto acquires and releases<\/A>.\n<\/P>\n<P>\n[Raymond is currently away; this message was pre-recorded.]\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Many of the normal interlocked operations come with variants called InterlockedXxxAcquire and InterlockedXxxRelease. What do the terms Acquire and Release mean here? They have to do with the memory model and how aggressively the CPU can reorder operations around it. An operation with acquire semantics is one which does not permit subsequent memory operations to [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-20663","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Many of the normal interlocked operations come with variants called InterlockedXxxAcquire and InterlockedXxxRelease. What do the terms Acquire and Release mean here? They have to do with the memory model and how aggressively the CPU can reorder operations around it. An operation with acquire semantics is one which does not permit subsequent memory operations to [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/20663","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=20663"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/20663\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=20663"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=20663"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=20663"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}