Update following changes to sys_membarrier ABI
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 29 Aug 2015 03:15:33 +0000 (23:15 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 29 Aug 2015 03:21:59 +0000 (23:21 -0400)
sys_membarrier underwent changes between its original implementation and
its upcoming inclusion into the Linux kernel. Update its use to follow
those changes.

Should the prior user-space code be built against a kernel header that
defines SYS_membarrier, and executed against that kernel, the following
scenarios may happen:

- -1 will be returned with EINVAL errno if the 2nd argument (flags) is
  non-zero (the previous ABI expected a single argument),
- (MEMBARRIER_EXPEDITED | MEMBARRIER_QUERY) defined as
  (1 << 0) | (1 << 16) will return -1 with EINVAL errno, because valid
  commands are now one-hot.

Therefore, should an incompatible user-space code try to use
sys_membarrier, it will simply think that the system does not have
membarrier support due to the negative return value upon query.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
urcu.c

diff --git a/urcu.c b/urcu.c
index e77306584d77f0fc012f6bfbae466452b3556b74..5ffeb79553b6374f0fb1a607b3862ed78dda63e2 100644 (file)
--- a/urcu.c
+++ b/urcu.c
 # define membarrier(...)               -ENOSYS
 #endif
 
-#define MEMBARRIER_EXPEDITED           (1 << 0)
-#define MEMBARRIER_DELAYED             (1 << 1)
-#define MEMBARRIER_QUERY               (1 << 16)
+enum membarrier_cmd {
+       MEMBARRIER_CMD_QUERY = 0,
+       MEMBARRIER_CMD_SHARED = (1 << 0),
+};
 
 #ifdef RCU_MEMBARRIER
 static int init_done;
@@ -167,7 +168,7 @@ static void mutex_unlock(pthread_mutex_t *mutex)
 static void smp_mb_master(int group)
 {
        if (caa_likely(rcu_has_sys_membarrier))
-               (void) membarrier(MEMBARRIER_EXPEDITED);
+               (void) membarrier(MEMBARRIER_CMD_SHARED, 0);
        else
                cmm_smp_mb();
 }
@@ -514,11 +515,15 @@ void rcu_unregister_thread(void)
 #ifdef RCU_MEMBARRIER
 void rcu_init(void)
 {
+       int ret;
+
        if (init_done)
                return;
        init_done = 1;
-       if (!membarrier(MEMBARRIER_EXPEDITED | MEMBARRIER_QUERY))
+       ret = membarrier(MEMBARRIER_CMD_QUERY, 0);
+       if (ret >= 0 && (ret & MEMBARRIER_CMD_SHARED)) {
                rcu_has_sys_membarrier = 1;
+       }
 }
 #endif
 
This page took 0.035284 seconds and 4 git commands to generate.