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
|
@ -22,6 +22,8 @@ void test_cpu_pointer(void)
|
|||
CPU_ZERO(&test_affinity);
|
||||
for (i = 0; i < CPU_SETSIZE; i++) {
|
||||
if (CPU_ISSET(i, &affinity)) {
|
||||
int node;
|
||||
|
||||
CPU_SET(i, &test_affinity);
|
||||
sched_setaffinity(0, sizeof(test_affinity),
|
||||
&test_affinity);
|
||||
|
@ -29,6 +31,8 @@ void test_cpu_pointer(void)
|
|||
assert(rseq_current_cpu() == i);
|
||||
assert(rseq_current_cpu_raw() == i);
|
||||
assert(rseq_cpu_start() == i);
|
||||
node = rseq_fallback_current_node();
|
||||
assert(rseq_current_node_id() == node);
|
||||
CPU_CLR(i, &test_affinity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,6 +147,14 @@ struct rseq_abi {
|
|||
*/
|
||||
__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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
static int sys_getcpu(unsigned *cpu, unsigned *node)
|
||||
{
|
||||
return syscall(__NR_getcpu, cpu, node, NULL);
|
||||
}
|
||||
|
||||
int rseq_available(void)
|
||||
{
|
||||
int rc;
|
||||
|
@ -201,3 +206,16 @@ int32_t rseq_fallback_current_cpu(void)
|
|||
}
|
||||
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 "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.
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* 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
|
||||
* uninitialized), or -2 (rseq initialization has failed).
|
||||
|
@ -163,6 +177,20 @@ static inline uint32_t rseq_current_cpu(void)
|
|||
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)
|
||||
{
|
||||
RSEQ_WRITE_ONCE(rseq_get_abi()->rseq_cs.arch.ptr, 0);
|
||||
|
|
Loading…
Reference in New Issue