tools/testing/selftests/rseq/rseq.c
Source file repositories/reference/linux-study-clean/tools/testing/selftests/rseq/rseq.c
File Facts
- System
- Linux kernel
- Corpus path
tools/testing/selftests/rseq/rseq.c- Extension
.c- Size
- 7628 bytes
- Lines
- 306
- Domain
- Support Tooling And Documentation
- Bucket
- tools
- Inferred role
- Support Tooling And Documentation: implementation source
- Status
- source implementation candidate
Why This File Exists
Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
errno.hsched.hstdio.hstdlib.hstring.hunistd.hsyscall.hassert.hsignal.hlimits.hdlfcn.hstddef.hsys/auxv.hlinux/auxvec.hlinux/compiler.hkselftest.hrseq.h
Detected Declarations
function sys_rseqfunction sys_getcpufunction rseq_availablefunction getauxvalfunction __rseq_register_current_threadfunction rseq_unregister_current_threadfunction __attribute__function getauxvalfunction __attribute__function rseq_fallback_current_cpufunction rseq_fallback_current_node
Annotated Snippet
if (RSEQ_READ_ONCE(rseq_size) > 0) {
/* Incoherent success/failure within process. */
abort();
}
return -1;
}
assert(rseq_current_cpu_raw() >= 0);
/*
* The first thread to register sets the rseq_size to mimic the libc
* behavior.
*/
if (RSEQ_READ_ONCE(rseq_size) == 0)
RSEQ_WRITE_ONCE(rseq_size, size);
return 0;
}
int rseq_unregister_current_thread(void)
{
int rc;
if (!rseq_ownership) {
/* Treat libc's ownership as a successful unregistration. */
return 0;
}
rc = sys_rseq(&__rseq.abi, rseq_alloc_size, RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG);
if (rc)
return -1;
return 0;
}
static __attribute__((constructor))
void rseq_init(void)
{
/*
* If the libc's registered rseq size isn't already valid, it may be
* because the binary is dynamically linked and not necessarily due to
* libc not having registered a restartable sequence. Try to find the
* symbols if that's the case.
*/
if (!libc_rseq_size_p || !*libc_rseq_size_p) {
libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
}
if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p &&
*libc_rseq_size_p != 0) {
unsigned int libc_rseq_size;
/* rseq registration owned by glibc */
rseq_offset = *libc_rseq_offset_p;
libc_rseq_size = *libc_rseq_size_p;
rseq_flags = *libc_rseq_flags_p;
/*
* Previous versions of glibc expose the value
* 32 even though the kernel only supported 20
* bytes initially. Therefore treat 32 as a
* special-case. glibc 2.40 exposes a 20 bytes
* __rseq_size without using getauxval(3) to
* query the supported size, while still allocating a 32
* bytes area. Also treat 20 as a special-case.
*
* Special-cases are handled by using the following
* value as active feature set size:
*
* rseq_size = min(32, get_rseq_kernel_feature_size())
*/
switch (libc_rseq_size) {
case ORIG_RSEQ_FEATURE_SIZE:
fallthrough;
case ORIG_RSEQ_ALLOC_SIZE:
{
unsigned int rseq_kernel_feature_size = get_rseq_kernel_feature_size();
if (rseq_kernel_feature_size < ORIG_RSEQ_ALLOC_SIZE)
rseq_size = rseq_kernel_feature_size;
else
rseq_size = ORIG_RSEQ_ALLOC_SIZE;
break;
}
default:
/* Otherwise just use the __rseq_size from libc as rseq_size. */
rseq_size = libc_rseq_size;
break;
}
return;
}
rseq_ownership = 1;
Annotation
- Immediate include surface: `errno.h`, `sched.h`, `stdio.h`, `stdlib.h`, `string.h`, `unistd.h`, `syscall.h`, `assert.h`.
- Detected declarations: `function sys_rseq`, `function sys_getcpu`, `function rseq_available`, `function getauxval`, `function __rseq_register_current_thread`, `function rseq_unregister_current_thread`, `function __attribute__`, `function getauxval`, `function __attribute__`, `function rseq_fallback_current_cpu`.
- Atlas domain: Support Tooling And Documentation / tools.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.