CINXE.COM

LKML: "tip-bot2 for Peter Zijlstra": [tip: timers/core] posix-timers: Make lock_timer() use guard()

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>LKML: "tip-bot2 for Peter Zijlstra": [tip: timers/core] posix-timers: Make lock_timer() use guard()</title><link href="/css/message.css" rel="stylesheet" type="text/css" /><link href="/css/wrap.css" rel="alternate stylesheet" type="text/css" title="wrap" /><link href="/css/nowrap.css" rel="stylesheet" type="text/css" title="nowrap" /><link href="/favicon.ico" rel="shortcut icon" /><script src="/js/simple-calendar.js" type="text/javascript"></script><script src="/js/styleswitcher.js" type="text/javascript"></script><link rel="alternate" type="application/rss+xml" title="lkml.org : last 100 messages" href="/rss.php" /><link rel="alternate" type="application/rss+xml" title="lkml.org : last messages by &quot;tip-bot2 for Peter Zijlstra&quot;" href="/groupie.php?aid=" /><!--Matomo--><script> var _paq = window._paq = window._paq || []; /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ _paq.push(["setDoNotTrack", true]); _paq.push(["disableCookies"]); _paq.push(['trackPageView']); _paq.push(['enableLinkTracking']); (function() { var u="//m.lkml.org/"; _paq.push(['setTrackerUrl', u+'matomo.php']); _paq.push(['setSiteId', '1']); var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); })(); </script><!--End Matomo Code--></head><body onload="es.jasper.simpleCalendar.init();" itemscope="itemscope" itemtype="http://schema.org/BlogPosting"><table border="0" cellpadding="0" cellspacing="0"><tr><td width="180" align="center"><a href="/"><img style="border:0;width:135px;height:32px" src="/images/toprowlk.gif" alt="lkml.org" /></a></td><td width="32">聽</td><td class="nb"><div><a class="nb" href="/lkml"> [lkml]</a> 聽 <a class="nb" href="/lkml/2025"> [2025]</a> 聽 <a class="nb" href="/lkml/2025/3"> [Mar]</a> 聽 <a class="nb" href="/lkml/2025/3/13"> [13]</a> 聽 <a class="nb" href="/lkml/last100"> [last100]</a> 聽 <a href="/rss.php"><img src="/images/rss-or.gif" border="0" alt="RSS Feed" /></a></div><div>Views: <a href="#" class="nowrap" onclick="setActiveStyleSheet('wrap');return false;">[wrap]</a><a href="#" class="wrap" onclick="setActiveStyleSheet('nowrap');return false;">[no wrap]</a> 聽 <a class="nb" href="/lkml/mheaders/2025/3/13/625" onclick="this.href='/lkml/headers'+'/2025/3/13/625';">[headers]</a>聽 <a href="/lkml/bounce/2025/3/13/625">[forward]</a>聽 </div></td><td width="32">聽</td></tr><tr><td valign="top"><div class="es-jasper-simpleCalendar" baseurl="/lkml/"></div><div class="threadlist">Messages in this thread</div><ul class="threadlist"><li class="root"><a href="/lkml/2025/3/8/426">First message in thread</a></li><li><a href="/lkml/2025/3/8/426">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/8/427">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/8/616">Frederic Weisbecker</a></li><li><a href="/lkml/2025/3/13/634">"tip-bot2 for Thomas Gleixner"</a></li></ul></li><li><a href="/lkml/2025/3/8/428">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/11/914">Frederic Weisbecker</a><ul><li><a href="/lkml/2025/3/11/977">Thomas Gleixner</a></li></ul></li><li><a href="/lkml/2025/3/13/633">"tip-bot2 for Eric Dumazet"</a></li></ul></li><li><a href="/lkml/2025/3/8/430">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/13/631">"tip-bot2 for Eric Dumazet"</a></li></ul></li><li><a href="/lkml/2025/3/8/431">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/13/630">"tip-bot2 for Thomas Gleixner"</a></li></ul></li><li><a href="/lkml/2025/3/8/432">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/13/632">"tip-bot2 for Thomas Gleixner"</a></li></ul></li><li><a href="/lkml/2025/3/8/433">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/13/629">"tip-bot2 for Thomas Gleixner"</a></li></ul></li><li><a href="/lkml/2025/3/8/434">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/13/627">"tip-bot2 for Thomas Gleixner"</a></li></ul></li><li><a href="/lkml/2025/3/8/435">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/13/626">"tip-bot2 for Thomas Gleixner"</a></li></ul></li><li><a href="/lkml/2025/3/8/436">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/10/13">Frederic Weisbecker</a><ul><li><a href="/lkml/2025/3/10/148">Thomas Gleixner</a></li></ul></li><li><a href="/lkml/2025/3/10/256">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/13/628">"tip-bot2 for Thomas Gleixner"</a></li></ul></li></ul></li><li><a href="/lkml/2025/3/8/437">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/10/634">Frederic Weisbecker</a><ul><li><a href="/lkml/2025/3/10/1329">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/10/1664">Frederic Weisbecker</a></li></ul></li></ul></li><li class="origin"><a href="">"tip-bot2 for Peter Zijlstra"</a></li></ul></li><li><a href="/lkml/2025/3/8/438">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/10/1716">Frederic Weisbecker</a></li><li><a href="/lkml/2025/3/11/927">Frederic Weisbecker</a></li><li><a href="/lkml/2025/3/13/623">"tip-bot2 for Eric Dumazet"</a></li></ul></li><li><a href="/lkml/2025/3/8/439">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/11/932">Frederic Weisbecker</a></li><li><a href="/lkml/2025/3/13/624">"tip-bot2 for Thomas Gleixner"</a></li></ul></li><li><a href="/lkml/2025/3/8/440">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/13/622">"tip-bot2 for Thomas Gleixner"</a></li></ul></li><li><a href="/lkml/2025/3/8/441">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/11/940">Frederic Weisbecker</a></li><li><a href="/lkml/2025/3/13/621">"tip-bot2 for Thomas Gleixner"</a></li><li><a href="/lkml/2025/3/13/1624">David Laight</a></li><li><a href="/lkml/2025/3/17/208">"Nysal Jan K.A."</a></li></ul></li><li><a href="/lkml/2025/3/8/442">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/11/1110">Frederic Weisbecker</a></li><li><a href="/lkml/2025/3/13/620">"tip-bot2 for Thomas Gleixner"</a></li></ul></li><li><a href="/lkml/2025/3/8/443">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/9/14">Cyrill Gorcunov</a></li><li><a href="/lkml/2025/3/11/1103">Frederic Weisbecker</a></li><li><a href="/lkml/2025/3/13/619">"tip-bot2 for Thomas Gleixner"</a></li></ul></li><li><a href="/lkml/2025/3/8/444">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/9/13">Cyrill Gorcunov</a></li><li><a href="/lkml/2025/3/11/1588">Frederic Weisbecker</a><ul><li><a href="/lkml/2025/3/11/1615">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/11/1618">Thomas Gleixner</a></li></ul></li><li><a href="/lkml/2025/3/12/649">Cyrill Gorcunov</a></li></ul></li></ul></li><li><a href="/lkml/2025/3/8/445">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/10/254">Thomas Gleixner</a><ul><li><a href="/lkml/2025/3/11/1599">Frederic Weisbecker</a></li><li><a href="/lkml/2025/3/13/617">"tip-bot2 for Thomas Gleixner"</a></li></ul></li></ul></li></ul></li></ul><div class="threadlist">Patch in this message</div><ul class="threadlist"><li><a href="/lkml/diff/2025/3/13/625/1">Get diff 1</a></li></ul></td><td width="32" rowspan="2" class="c" valign="top"><img src="/images/icornerl.gif" width="32" height="32" alt="/" /></td><td class="c" rowspan="2" valign="top" style="padding-top: 1em"><table><tr><td><table><tr><td class="lp">Date</td><td class="rp" itemprop="datePublished">Thu, 13 Mar 2025 11:31:27 -0000</td></tr><tr><td class="lp">From</td><td class="rp" itemprop="author">"tip-bot2 for Peter Zijlstra" &lt;&gt;</td></tr><tr><td class="lp">Subject</td><td class="rp" itemprop="name">[tip: timers/core] posix-timers: Make lock_timer() use guard()</td></tr></table></td><td></td></tr></table><pre itemprop="articleBody">The following commit has been merged into the timers/core branch of tip:<br /><br />Commit-ID: 538d710ec74233f99dc0fd604d45a2b6143c8e2c<br />Gitweb: <a href="https://git.kernel.org/tip/538d710ec74233f99dc0fd604d45a2b6143c8e2c">https://git.kernel.org/tip/538d710ec74233f99dc0fd604d45a2b6143c8e2c</a><br />Author: Peter Zijlstra &lt;peterz&#64;infradead.org&gt;<br />AuthorDate: Sat, 08 Mar 2025 17:48:34 +01:00<br />Committer: Thomas Gleixner &lt;tglx&#64;linutronix.de&gt;<br />CommitterDate: Thu, 13 Mar 2025 12:07:17 +01:00<br /><br />posix-timers: Make lock_timer() use guard()<br /><br />The lookup and locking of posix timers requires the same repeating pattern<br />at all usage sites:<br /><br /> tmr = lock_timer(tiner_id);<br /> if (!tmr)<br /> return -EINVAL;<br /> ....<br /> unlock_timer(tmr);<br /><br />Solve this with a guard implementation, which works in most places out of<br />the box except for those, which need to unlock the timer inside the guard<br />scope.<br /><br />Though the only places where this matters are timer_delete() and<br />timer_settime(). In both cases the timer pointer needs to be preserved<br />across the end of the scope, which is solved by storing the pointer in a<br />variable outside of the scope.<br /><br />timer_settime() also has to protect the timer with RCU before unlocking,<br />which obviously can't use guard(rcu) before leaving the guard scope as that<br />guard is cleaned up before the unlock. Solve this by providing the RCU<br />protection open coded.<br /><br />[ tglx: Made it work and added change log ]<br /><br />Signed-off-by: Peter Zijlstra &lt;peterz&#64;infradead.org&gt;<br />Signed-off-by: Thomas Gleixner &lt;tglx&#64;linutronix.de&gt;<br />Acked-by: Frederic Weisbecker &lt;frederic&#64;kernel.org&gt;<br />Link: <a href="https://lore.kernel.org/all/20250224162103.GD11590&#64;noisy.programming.kicks-ass.net">https://lore.kernel.org/all/20250224162103.GD11590&#64;noisy.programming.kicks-ass.net</a><br />Link: <a href="https://lore.kernel.org/all/20250308155624.087465658&#64;linutronix.de">https://lore.kernel.org/all/20250308155624.087465658&#64;linutronix.de</a><br /><br />---<br /> include/linux/cleanup.h | 22 +++++----<br /> kernel/time/posix-timers.c | 92 ++++++++++++++-----------------------<br /> 2 files changed, 50 insertions(+), 64 deletions(-)<br /><br />diff --git a/include/linux/cleanup.h b/include/linux/cleanup.h<br />index ec00e3f..a176abf 100644<br />--- a/include/linux/cleanup.h<br />+++ b/include/linux/cleanup.h<br />&#64;&#64; -291,11 +291,21 &#64;&#64; static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \<br /> #define __DEFINE_CLASS_IS_CONDITIONAL(_name, _is_cond) \<br /> static __maybe_unused const bool class_##_name##_is_conditional = _is_cond<br /> <br />-#define DEFINE_GUARD(_name, _type, _lock, _unlock) \<br />+#define __DEFINE_GUARD_LOCK_PTR(_name, _exp) \<br />+ static inline void * class_##_name##_lock_ptr(class_##_name##_t *_T) \<br />+ { return (void *)(__force unsigned long)*(_exp); }<br />+<br />+#define DEFINE_CLASS_IS_GUARD(_name) \<br /> __DEFINE_CLASS_IS_CONDITIONAL(_name, false); \<br />+ __DEFINE_GUARD_LOCK_PTR(_name, _T)<br />+<br />+#define DEFINE_CLASS_IS_COND_GUARD(_name) \<br />+ __DEFINE_CLASS_IS_CONDITIONAL(_name, true); \<br />+ __DEFINE_GUARD_LOCK_PTR(_name, _T)<br />+<br />+#define DEFINE_GUARD(_name, _type, _lock, _unlock) \<br /> DEFINE_CLASS(_name, _type, if (_T) { _unlock; }, ({ _lock; _T; }), _type _T); \<br />- static inline void * class_##_name##_lock_ptr(class_##_name##_t *_T) \<br />- { return (void *)(__force unsigned long)*_T; }<br />+ DEFINE_CLASS_IS_GUARD(_name)<br /> <br /> #define DEFINE_GUARD_COND(_name, _ext, _condlock) \<br /> __DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true); \<br />&#64;&#64; -375,11 +385,7 &#64;&#64; static inline void class_##_name##_destructor(class_##_name##_t *_T) \<br /> if (_T-&gt;lock) { _unlock; } \<br /> } \<br /> \<br />-static inline void *class_##_name##_lock_ptr(class_##_name##_t *_T) \<br />-{ \<br />- return (void *)(__force unsigned long)_T-&gt;lock; \<br />-}<br />-<br />+__DEFINE_GUARD_LOCK_PTR(_name, &amp;_T-&gt;lock)<br /> <br /> #define __DEFINE_LOCK_GUARD_1(_name, _type, _lock) \<br /> static inline class_##_name##_t class_##_name##_constructor(_type *l) \<br />diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c<br />index dff414b..991d12a 100644<br />--- a/kernel/time/posix-timers.c<br />+++ b/kernel/time/posix-timers.c<br />&#64;&#64; -63,9 +63,18 &#64;&#64; static struct k_itimer *__lock_timer(timer_t timer_id);<br /> <br /> static inline void unlock_timer(struct k_itimer *timr)<br /> {<br />- spin_unlock_irq(&amp;timr-&gt;it_lock);<br />+ if (likely((timr)))<br />+ spin_unlock_irq(&amp;timr-&gt;it_lock);<br /> }<br /> <br />+#define scoped_timer_get_or_fail(_id) \<br />+ scoped_cond_guard(lock_timer, return -EINVAL, _id)<br />+<br />+#define scoped_timer (scope)<br />+<br />+DEFINE_CLASS(lock_timer, struct k_itimer *, unlock_timer(_T), __lock_timer(id), timer_t id);<br />+DEFINE_CLASS_IS_COND_GUARD(lock_timer);<br />+<br /> static int hash(struct signal_struct *sig, unsigned int nr)<br /> {<br /> return hash_32(hash32_ptr(sig) ^ nr, HASH_BITS(posix_timers_hashtable));<br />&#64;&#64; -682,18 +691,10 &#64;&#64; void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)<br /> <br /> static int do_timer_gettime(timer_t timer_id, struct itimerspec64 *setting)<br /> {<br />- struct k_itimer *timr;<br />- int ret = 0;<br />-<br />- timr = lock_timer(timer_id);<br />- if (!timr)<br />- return -EINVAL;<br />-<br /> memset(setting, 0, sizeof(*setting));<br />- timr-&gt;kclock-&gt;timer_get(timr, setting);<br />-<br />- unlock_timer(timr);<br />- return ret;<br />+ scoped_timer_get_or_fail(timer_id)<br />+ scoped_timer-&gt;kclock-&gt;timer_get(scoped_timer, setting);<br />+ return 0;<br /> }<br /> <br /> /* Get the time remaining on a POSIX.1b interval timer. */<br />&#64;&#64; -747,17 +748,8 &#64;&#64; SYSCALL_DEFINE2(timer_gettime32, timer_t, timer_id,<br /> */<br /> SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id)<br /> {<br />- struct k_itimer *timr;<br />- int overrun;<br />-<br />- timr = lock_timer(timer_id);<br />- if (!timr)<br />- return -EINVAL;<br />-<br />- overrun = timer_overrun_to_int(timr);<br />- unlock_timer(timr);<br />-<br />- return overrun;<br />+ scoped_timer_get_or_fail(timer_id)<br />+ return timer_overrun_to_int(scoped_timer);<br /> }<br /> <br /> static void common_hrtimer_arm(struct k_itimer *timr, ktime_t expires,<br />&#64;&#64; -875,12 +867,9 &#64;&#64; int common_timer_set(struct k_itimer *timr, int flags,<br /> return 0;<br /> }<br /> <br />-static int do_timer_settime(timer_t timer_id, int tmr_flags,<br />- struct itimerspec64 *new_spec64,<br />+static int do_timer_settime(timer_t timer_id, int tmr_flags, struct itimerspec64 *new_spec64,<br /> struct itimerspec64 *old_spec64)<br /> {<br />- int ret;<br />-<br /> if (!timespec64_valid(&amp;new_spec64-&gt;it_interval) ||<br /> !timespec64_valid(&amp;new_spec64-&gt;it_value))<br /> return -EINVAL;<br />&#64;&#64; -888,36 +877,28 &#64;&#64; static int do_timer_settime(timer_t timer_id, int tmr_flags,<br /> if (old_spec64)<br /> memset(old_spec64, 0, sizeof(*old_spec64));<br /> <br />- for (;;) {<br />- struct k_itimer *timr = lock_timer(timer_id);<br />+ for (; ; old_spec64 = NULL) {<br />+ struct k_itimer *timr;<br /> <br />- if (!timr)<br />- return -EINVAL;<br />+ scoped_timer_get_or_fail(timer_id) {<br />+ timr = scoped_timer;<br /> <br />- if (old_spec64)<br />- old_spec64-&gt;it_interval = ktime_to_timespec64(timr-&gt;it_interval);<br />+ if (old_spec64)<br />+ old_spec64-&gt;it_interval = ktime_to_timespec64(timr-&gt;it_interval);<br /> <br />- /* Prevent signal delivery and rearming. */<br />- timr-&gt;it_signal_seq++;<br />+ /* Prevent signal delivery and rearming. */<br />+ timr-&gt;it_signal_seq++;<br /> <br />- ret = timr-&gt;kclock-&gt;timer_set(timr, tmr_flags, new_spec64, old_spec64);<br />- if (ret != TIMER_RETRY) {<br />- unlock_timer(timr);<br />- break;<br />- }<br />+ int ret = timr-&gt;kclock-&gt;timer_set(timr, tmr_flags, new_spec64, old_spec64);<br />+ if (ret != TIMER_RETRY)<br />+ return ret;<br /> <br />- /* Read the old time only once */<br />- old_spec64 = NULL;<br />- /* Protect the timer from being freed after the lock is dropped */<br />- guard(rcu)();<br />- unlock_timer(timr);<br />- /*<br />- * timer_wait_running() might drop RCU read side protection<br />- * so the timer has to be looked up again!<br />- */<br />+ /* Protect the timer from being freed when leaving the lock scope */<br />+ rcu_read_lock();<br />+ }<br /> timer_wait_running(timr);<br />+ rcu_read_unlock();<br /> }<br />- return ret;<br /> }<br /> <br /> /* Set a POSIX.1b interval timer */<br />&#64;&#64; -1028,13 +1009,12 &#64;&#64; static void posix_timer_delete(struct k_itimer *timer)<br /> /* Delete a POSIX.1b interval timer. */<br /> SYSCALL_DEFINE1(timer_delete, timer_t, timer_id)<br /> {<br />- struct k_itimer *timer = lock_timer(timer_id);<br />-<br />- if (!timer)<br />- return -EINVAL;<br />+ struct k_itimer *timer;<br /> <br />- posix_timer_delete(timer);<br />- unlock_timer(timer);<br />+ scoped_timer_get_or_fail(timer_id) {<br />+ timer = scoped_timer;<br />+ posix_timer_delete(timer);<br />+ }<br /> /* Remove it from the hash, which frees up the timer ID */<br /> posix_timer_unhash_and_free(timer);<br /> return 0;<br /></pre></td><td width="32" rowspan="2" class="c" valign="top"><img src="/images/icornerr.gif" width="32" height="32" alt="\" /></td></tr><tr><td align="right" valign="bottom"> 聽 </td></tr><tr><td align="right" valign="bottom">聽</td><td class="c" valign="bottom" style="padding-bottom: 0px"><img src="/images/bcornerl.gif" width="32" height="32" alt="\" /></td><td class="c">聽</td><td class="c" valign="bottom" style="padding-bottom: 0px"><img src="/images/bcornerr.gif" width="32" height="32" alt="/" /></td></tr><tr><td align="right" valign="top" colspan="2"> 聽 </td><td class="lm">Last update: 2025-03-13 12:33 聽聽 [W:0.291 / U:1.226 seconds]<br />漏2003-2020 <a href="http://blog.jasper.es/"><span itemprop="editor">Jasper Spaans</span></a>|hosted at <a href="https://www.digitalocean.com/?refcode=9a8e99d24cf9">Digital Ocean</a> and my Meterkast|<a href="http://blog.jasper.es/categories.html#lkml-ref">Read the blog</a></td><td>聽</td></tr></table><script language="javascript" src="/js/styleswitcher.js" type="text/javascript"></script></body></html>

Pages: 1 2 3 4 5 6 7 8 9 10