*/
int32_t rseq_fallback_current_cpu(void);
-int rseq_available(void);
+enum rseq_available_query {
+ RSEQ_AVAILABLE_QUERY_KERNEL = 0,
+ RSEQ_AVAILABLE_QUERY_LIBC = 1,
+};
+
+/*
+ * Returns true if rseq is supported.
+ */
+bool rseq_available(unsigned int query);
/*
* Values returned can be either the current CPU number, -1 (rseq is
return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
}
-int rseq_available(void)
+bool rseq_available(unsigned int query)
{
int rc;
- rc = sys_rseq(NULL, 0, 0, 0);
- if (rc != -1)
- abort();
- switch (errno) {
- case ENOSYS:
- return 0;
- case EINVAL:
- return 1;
+ switch (query) {
+ case RSEQ_AVAILABLE_QUERY_KERNEL:
+ rc = sys_rseq(NULL, 0, 0, 0);
+ if (rc != -1)
+ abort();
+ switch (errno) {
+ case ENOSYS:
+ default:
+ break;
+ case EINVAL:
+ return true;
+ }
+ break;
+ case RSEQ_AVAILABLE_QUERY_LIBC:
+ if (rseq_size && !rseq_ownership)
+ return true;
+ break;
default:
- abort();
+ break;
}
+ return false;
}
int rseq_register_current_thread(void)
rseq_flags = *libc_rseq_flags_p;
return;
}
- if (!rseq_available())
+ if (!rseq_available(RSEQ_AVAILABLE_QUERY_KERNEL))
return;
rseq_ownership = 1;
rseq_offset = (void *)&__rseq_abi - rseq_thread_pointer();
{
plan_tests(NR_TESTS);
- if (!rseq_available()) {
+ if (!rseq_available(RSEQ_AVAILABLE_QUERY_KERNEL)) {
skip(NR_TESTS, "The rseq syscall is unavailable");
goto end;
}
/*
* Skip all tests if the rseq syscall is unavailable
*/
- if (rseq_available()) {
+ if (rseq_available(RSEQ_AVAILABLE_QUERY_KERNEL)) {
plan_no_plan();
} else {
plan_skip_all("The rseq syscall is unavailable");
opt_mb = 1;
break;
case 'c':
- if (rseq_available()) {
+ if (rseq_available(RSEQ_AVAILABLE_QUERY_KERNEL)) {
printf_verbose("The rseq syscall is available.\n");
goto end;
} else {