Implement availability API checks
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 3 Oct 2018 21:24:09 +0000 (17:24 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 3 Oct 2018 21:25:39 +0000 (17:25 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Makefile
include/rseq/cpu-op.h
include/rseq/percpu-op.h
include/rseq/rseq.h
src/cpu-op.c
src/percpu-op.c [new file with mode: 0644]
src/rseq.c

index 1a8e5b0644bde3c58f4a49b63831e5811281cdd8..38898a996b18205f143a58a9211d21a9c85d8d94 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -20,9 +20,9 @@ all: librseq.so
 
 INCLUDES=$(wildcard include/rseq/*.h)
 
-librseq.so: src/rseq.c src/cpu-op.c ${INCLUDES}
+librseq.so: src/rseq.c src/cpu-op.c src/percpu-op.c ${INCLUDES}
        $(CC) $(CFLAGS) $(LDFLAGS) $(CPPFLAGS) -shared -fpic \
-                       src/rseq.c src/cpu-op.c -o $@
+                       src/rseq.c src/cpu-op.c src/percpu-op.c -o $@
 
 .PHONY: clean install uninstall
 
index 0d3c1bfb5b0810ccd911c5b0a168fcdd605483ba..58402a65e0b41f3898d964ad40d85f6f71279406 100644 (file)
@@ -14,6 +14,7 @@
 
 int cpu_opv(struct cpu_op *cpuopv, int cpuopcnt, int cpu, int flags);
 int cpu_op_get_current_cpu(void);
+int cpu_op_available(void);
 
 int cpu_op_cmpxchg(void *v, void *expect, void *old, void *_new, size_t len,
                   int cpu);
index 61df793dbe717eb5efe401dc7f53fcdca27d26d0..92b9b52a2732c76ac3932079951ec411451317cd 100644 (file)
@@ -15,6 +15,8 @@
 #include <rseq/rseq.h>
 #include <rseq/cpu-op.h>
 
+int percpu_op_available(void);
+
 static inline __attribute__((always_inline))
 int percpu_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv,
                         int cpu)
index 1777c2170ea5ecb10d3fa582b57b598fefb64bdc..dd1199a24fbcf8ff1615db3fc9ddb06be945327c 100644 (file)
@@ -100,6 +100,8 @@ int rseq_unregister_current_thread(void);
  */
 int32_t rseq_fallback_current_cpu(void);
 
+int rseq_available(void);
+
 /*
  * Values returned can be either the current CPU number, -1 (rseq is
  * uninitialized), or -2 (rseq initialization has failed).
index f02e0b9082fbdc3e0ee926e16a69b72b855abb04..60c33c10b2c64a8f15d1fcc4f1e448f2f0b87b00 100644 (file)
@@ -39,6 +39,16 @@ int cpu_opv(struct cpu_op *cpu_opv, int cpuopcnt, int cpu, int flags)
        return syscall(__NR_cpu_opv, cpu_opv, cpuopcnt, cpu, flags);
 }
 
+int cpu_op_available(void)
+{
+       int rc;
+
+       rc = cpu_opv(NULL, 0, 0, CPU_OP_NR_FLAG);
+       if (rc >= 0)
+               return 1;
+       return 0;
+}
+
 int cpu_op_get_current_cpu(void)
 {
        int cpu;
diff --git a/src/percpu-op.c b/src/percpu-op.c
new file mode 100644 (file)
index 0000000..cf97b2b
--- /dev/null
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * percpu-op.c
+ *
+ * Copyright (C) 2017 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+#define _GNU_SOURCE
+#include <rseq/rseq.h>
+#include <rseq/cpu-op.h>
index 2b69589dee5b65a769cef795519d97c947cda09b..e503918ad17cb468379f2582f5f2c7a788a4f2a4 100644 (file)
@@ -30,6 +30,8 @@
 
 #define ARRAY_SIZE(arr)        (sizeof(arr) / sizeof((arr)[0]))
 
+#define RSEQ_FLAG_UNDEFINED 0x80000000
+
 /*
  * linux/rseq.h defines struct rseq as aligned on 32 bytes. The kernel ABI
  * size is 20 bytes. For support of multiple rseq users within a process,
@@ -54,6 +56,29 @@ volatile struct libc_rseq __lib_rseq_abi = {
 extern __attribute__((weak, alias("__lib_rseq_abi"))) __thread
 volatile struct rseq __rseq_abi;
 
+static int sys_rseq(volatile struct rseq *rseq_abi, uint32_t rseq_len,
+                   int flags, uint32_t sig)
+{
+       return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
+}
+
+int rseq_available(void)
+{
+       int rc;
+
+       rc = sys_rseq(NULL, 0, RSEQ_FLAG_UNDEFINED, 0);
+       if (rc != -1)
+               abort();
+       switch (errno) {
+       case ENOSYS:
+               return 0;
+       case EINVAL:
+               return 1;
+       default:
+               abort();
+       }
+}
+
 static void signal_off_save(sigset_t *oldset)
 {
        sigset_t set;
@@ -74,12 +99,6 @@ static void signal_restore(sigset_t oldset)
                abort();
 }
 
-static int sys_rseq(volatile struct rseq *rseq_abi, uint32_t rseq_len,
-                   int flags, uint32_t sig)
-{
-       return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
-}
-
 int rseq_register_current_thread(void)
 {
        int rc, ret = 0;
This page took 0.036214 seconds and 4 git commands to generate.