selftests/rseq: Implement rseq numa node id field selftest
Test the NUMA node id extension rseq field. Compare it against the value returned by the getcpu(2) system call while pinned on a specific core. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/20221122203932.231377-7-mathieu.desnoyers@efficios.com
This commit is contained in:
parent
03f5c0272d
commit
99babd04b2
4 changed files with 58 additions and 0 deletions
|
@ -22,6 +22,8 @@ void test_cpu_pointer(void)
|
||||||
CPU_ZERO(&test_affinity);
|
CPU_ZERO(&test_affinity);
|
||||||
for (i = 0; i < CPU_SETSIZE; i++) {
|
for (i = 0; i < CPU_SETSIZE; i++) {
|
||||||
if (CPU_ISSET(i, &affinity)) {
|
if (CPU_ISSET(i, &affinity)) {
|
||||||
|
int node;
|
||||||
|
|
||||||
CPU_SET(i, &test_affinity);
|
CPU_SET(i, &test_affinity);
|
||||||
sched_setaffinity(0, sizeof(test_affinity),
|
sched_setaffinity(0, sizeof(test_affinity),
|
||||||
&test_affinity);
|
&test_affinity);
|
||||||
|
@ -29,6 +31,8 @@ void test_cpu_pointer(void)
|
||||||
assert(rseq_current_cpu() == i);
|
assert(rseq_current_cpu() == i);
|
||||||
assert(rseq_current_cpu_raw() == i);
|
assert(rseq_current_cpu_raw() == i);
|
||||||
assert(rseq_cpu_start() == i);
|
assert(rseq_cpu_start() == i);
|
||||||
|
node = rseq_fallback_current_node();
|
||||||
|
assert(rseq_current_node_id() == node);
|
||||||
CPU_CLR(i, &test_affinity);
|
CPU_CLR(i, &test_affinity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,14 @@ struct rseq_abi {
|
||||||
*/
|
*/
|
||||||
__u32 flags;
|
__u32 flags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restartable sequences node_id field. Updated by the kernel. Read by
|
||||||
|
* user-space with single-copy atomicity semantics. This field should
|
||||||
|
* only be read by the thread which registered this data structure.
|
||||||
|
* Aligned on 32-bit. Contains the current NUMA node ID.
|
||||||
|
*/
|
||||||
|
__u32 node_id;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flexible array member at end of structure, after last feature field.
|
* Flexible array member at end of structure, after last feature field.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -79,6 +79,11 @@ static int sys_rseq(struct rseq_abi *rseq_abi, uint32_t rseq_len,
|
||||||
return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
|
return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sys_getcpu(unsigned *cpu, unsigned *node)
|
||||||
|
{
|
||||||
|
return syscall(__NR_getcpu, cpu, node, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
int rseq_available(void)
|
int rseq_available(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -201,3 +206,16 @@ int32_t rseq_fallback_current_cpu(void)
|
||||||
}
|
}
|
||||||
return cpu;
|
return cpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t rseq_fallback_current_node(void)
|
||||||
|
{
|
||||||
|
uint32_t cpu_id, node_id;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = sys_getcpu(&cpu_id, &node_id);
|
||||||
|
if (ret) {
|
||||||
|
perror("sys_getcpu()");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return (int32_t) node_id;
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,15 @@
|
||||||
#include "rseq-abi.h"
|
#include "rseq-abi.h"
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
|
|
||||||
|
#ifndef rseq_sizeof_field
|
||||||
|
#define rseq_sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef rseq_offsetofend
|
||||||
|
#define rseq_offsetofend(TYPE, MEMBER) \
|
||||||
|
(offsetof(TYPE, MEMBER) + rseq_sizeof_field(TYPE, MEMBER))
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Empty code injection macros, override when testing.
|
* Empty code injection macros, override when testing.
|
||||||
* It is important to consider that the ASM injection macros need to be
|
* It is important to consider that the ASM injection macros need to be
|
||||||
|
@ -128,6 +137,11 @@ int rseq_unregister_current_thread(void);
|
||||||
*/
|
*/
|
||||||
int32_t rseq_fallback_current_cpu(void);
|
int32_t rseq_fallback_current_cpu(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restartable sequence fallback for reading the current node number.
|
||||||
|
*/
|
||||||
|
int32_t rseq_fallback_current_node(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Values returned can be either the current CPU number, -1 (rseq is
|
* Values returned can be either the current CPU number, -1 (rseq is
|
||||||
* uninitialized), or -2 (rseq initialization has failed).
|
* uninitialized), or -2 (rseq initialization has failed).
|
||||||
|
@ -163,6 +177,20 @@ static inline uint32_t rseq_current_cpu(void)
|
||||||
return cpu;
|
return cpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool rseq_node_id_available(void)
|
||||||
|
{
|
||||||
|
return (int) rseq_feature_size >= rseq_offsetofend(struct rseq_abi, node_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Current NUMA node number.
|
||||||
|
*/
|
||||||
|
static inline uint32_t rseq_current_node_id(void)
|
||||||
|
{
|
||||||
|
assert(rseq_node_id_available());
|
||||||
|
return RSEQ_ACCESS_ONCE(rseq_get_abi()->node_id);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void rseq_clear_rseq_cs(void)
|
static inline void rseq_clear_rseq_cs(void)
|
||||||
{
|
{
|
||||||
RSEQ_WRITE_ONCE(rseq_get_abi()->rseq_cs.arch.ptr, 0);
|
RSEQ_WRITE_ONCE(rseq_get_abi()->rseq_cs.arch.ptr, 0);
|
||||||
|
|
Loading…
Add table
Reference in a new issue