<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div></div><div><br></div><div><br>On Oct 17, 2017, at 5:40 PM, Tobin C. Harding &lt;<a href="mailto:me@tobin.cc">me@tobin.cc</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><span>Hi,</span><br><span></span><br><span>Do we have an atomic test and set function in the kernel. I have tried</span><br></div></blockquote><div><br></div>Yes and it is used very much inside the kernel.<br><blockquote type="cite"><div><span></span><br><span>const int KEY_FLAG_BIT = 1;</span><br><span></span><br><span>...</span><br><span></span><br><span> &nbsp; &nbsp;static siphash_key_t ptr_secret __read_mostly;</span><br><span> &nbsp; &nbsp;static unsigned long have_key = 0;</span><br><span></span><br><span> &nbsp; &nbsp;if (test_and_set_bit(KEY_FLAG_BIT, &amp;have_key))</span><br><span> &nbsp; &nbsp; &nbsp; &nbsp;get_random_bytes(&amp;ptr_secret, sizeof(ptr_secret));</span><br><span></span><br><span></span><br><span>But that doesn't work.</span><br></div></blockquote><div><br></div>What doesn't work? What you expected and how is the result different?<br><blockquote type="cite"><div><span></span><br><span>I looked in include/linux/atomic.h and thought about using</span><br><span></span><br><span> &nbsp; &nbsp;static atomic_t have_key = ATOMIC_INIT(0);</span><br><span></span><br><span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (atomic_xchg(&amp;have_key, 1) == 0)</span><br><span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;get_random_bytes(&amp;ptr_secret, sizeof(ptr_secret));</span><br><span></span><br><span></span><br><span>This works. My question is; does this code LOAD the value at have_key and STORE the argument on</span><br><span>every call? Or does it LOAD the value, check if it is the same as the argument, and STORE _only_ if</span><br><span>it is different? </span><br></div></blockquote><div><br></div>Did you read this&nbsp;<a href="https://www.mjmwired.net/kernel/Documentation/atomic_ops.txt">https://www.mjmwired.net/kernel/Documentation/atomic_ops.txt</a>&nbsp;?<br><blockquote type="cite"><div><span>(Is this whole discussion just premature optimization?)</span><br></div></blockquote><div><br></div>This has nothing to do with optimization but rather the requirement. In kernel atomic variables are used to avoid race conditions generally.<br><blockquote type="cite"><div><span></span><br><span>I cannot grok the macros in atomic.h, they seem circular. Here is the macro definitions in call</span><br><span>chain order starting with atomic_xchg()</span><br></div></blockquote><div><br></div>Implementation would differ based on the architecture. In some architectures it would be a single instruction and in others it may not be the case.<br><blockquote type="cite"><div><span></span><br><span></span><br><span>#define &nbsp;atomic_xchg(...) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\</span><br><span> &nbsp; &nbsp;__atomic_op_fence(atomic_xchg, __VA_ARGS__)</span><br><span></span><br><span>#define __atomic_op_fence(op, args...) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\</span><br><span>({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\</span><br><span> &nbsp; &nbsp;typeof(op##_relaxed(args)) __ret; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\</span><br><span> &nbsp; &nbsp;smp_mb__before_atomic(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\</span><br><span> &nbsp; &nbsp;__ret = op##_relaxed(args); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\</span><br><span> &nbsp; &nbsp;smp_mb__after_atomic(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\</span><br><span> &nbsp; &nbsp;__ret; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\</span><br><span>})</span><br><span></span><br><span>#define &nbsp;atomic_xchg_release(...) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\</span><br><span> &nbsp; &nbsp;__atomic_op_release(atomic_xchg, __VA_ARGS__)</span><br><span></span><br><span>#define __atomic_op_release(op, args...) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\</span><br><span>({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\</span><br><span> &nbsp; &nbsp;smp_mb__before_atomic(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\</span><br><span> &nbsp; &nbsp;op##_relaxed(args); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\</span><br><span>})</span><br><span></span><br><span>#define &nbsp;atomic_xchg_relaxed &nbsp; &nbsp; &nbsp; &nbsp;atomic_xchg</span><br><span></span><br><span>thanks,</span><br><span>Tobin.</span><br><span></span><br><span>_______________________________________________</span><br><span>Kernelnewbies mailing list</span><br><span><a href="mailto:Kernelnewbies@kernelnewbies.org">Kernelnewbies@kernelnewbies.org</a></span><br><span><a href="https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies">https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies</a></span><br></div></blockquote></body></html>