mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-22 09:58:09 +00:00
zdtm: modify rseq01 to include a thread
Testing only the thread group leader is not enough and can hide bugs. Signed-off-by: Michal Clapinski <mclapinski@google.com>
This commit is contained in:
parent
f8da250bb3
commit
6c728df1dc
@ -84,7 +84,9 @@ ptrace: LDFLAGS += -pthread
|
|||||||
fork2: CFLAGS += -D FORK2
|
fork2: CFLAGS += -D FORK2
|
||||||
thread-bomb.o: CFLAGS += -pthread
|
thread-bomb.o: CFLAGS += -pthread
|
||||||
thread-bomb: LDFLAGS += -pthread
|
thread-bomb: LDFLAGS += -pthread
|
||||||
|
rseq01: LDLIBS += -pthread
|
||||||
rseq02: CFLAGS += -D NORESTART
|
rseq02: CFLAGS += -D NORESTART
|
||||||
|
rseq02: LDLIBS += -pthread
|
||||||
|
|
||||||
%: %.sh
|
%: %.sh
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
@ -86,7 +86,7 @@ struct rseq {
|
|||||||
#endif
|
#endif
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
||||||
static volatile struct rseq *rseq_ptr;
|
static __thread volatile struct rseq *rseq_ptr;
|
||||||
static __thread volatile struct rseq __rseq_abi;
|
static __thread volatile struct rseq __rseq_abi;
|
||||||
|
|
||||||
static int sys_rseq(volatile struct rseq *rseq_abi, uint32_t rseq_len, int flags, uint32_t sig)
|
static int sys_rseq(volatile struct rseq *rseq_abi, uint32_t rseq_len, int flags, uint32_t sig)
|
||||||
@ -119,7 +119,7 @@ static void check_thread(void)
|
|||||||
|
|
||||||
#define rseq_after_asm_goto() asm volatile("" : : : "memory")
|
#define rseq_after_asm_goto() asm volatile("" : : : "memory")
|
||||||
|
|
||||||
static int rseq_addv(intptr_t *v, intptr_t count, int cpu, bool ignore_abort)
|
static int rseq_addv(intptr_t *v, intptr_t count, int cpu, bool ignore_abort, const char *id)
|
||||||
{
|
{
|
||||||
double a = 10000000000000000.0;
|
double a = 10000000000000000.0;
|
||||||
double b = -1;
|
double b = -1;
|
||||||
@ -177,7 +177,7 @@ static int rseq_addv(intptr_t *v, intptr_t count, int cpu, bool ignore_abort)
|
|||||||
);
|
);
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
rseq_after_asm_goto();
|
rseq_after_asm_goto();
|
||||||
test_msg("exit %lx %lx %f %f\n", rseq_cs1, rseq_cs2, a, b);
|
test_msg("exit %s, %lx %lx %f %f\n", id, rseq_cs1, rseq_cs2, a, b);
|
||||||
if (rseq_cs1 != rseq_cs2) {
|
if (rseq_cs1 != rseq_cs2) {
|
||||||
/*
|
/*
|
||||||
* It means that we finished critical section
|
* It means that we finished critical section
|
||||||
@ -192,19 +192,45 @@ static int rseq_addv(intptr_t *v, intptr_t count, int cpu, bool ignore_abort)
|
|||||||
return 0;
|
return 0;
|
||||||
abort:
|
abort:
|
||||||
rseq_after_asm_goto();
|
rseq_after_asm_goto();
|
||||||
test_msg("abort %lx %lx %f %f\n", rseq_cs1, rseq_cs2, a, b);
|
test_msg("abort %s, %lx %lx %f %f\n", id, rseq_cs1, rseq_cs2, a, b);
|
||||||
if (ignore_abort)
|
if (ignore_abort)
|
||||||
return 0;
|
return 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static task_waiter_t waiter;
|
||||||
|
static intptr_t *cpu_data;
|
||||||
|
bool ignore_abort = true;
|
||||||
|
int thread_ret;
|
||||||
|
|
||||||
|
void *thread_routine(void *args)
|
||||||
|
{
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
rseq_ptr = &__rseq_abi;
|
||||||
|
memset((void *)rseq_ptr, 0, sizeof(struct rseq));
|
||||||
|
register_thread();
|
||||||
|
task_waiter_complete(&waiter, 1);
|
||||||
|
task_waiter_wait4(&waiter, 2);
|
||||||
|
|
||||||
|
while (test_go()) {
|
||||||
|
cpu = RSEQ_ACCESS_ONCE(rseq_ptr->cpu_id_start);
|
||||||
|
thread_ret = rseq_addv(&cpu_data[cpu], 2, cpu, ignore_abort, "thread");
|
||||||
|
|
||||||
|
if (thread_ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_thread();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int cpu = 0;
|
int cpu = 0;
|
||||||
int ret;
|
int ret;
|
||||||
intptr_t *cpu_data;
|
|
||||||
long nr_cpus;
|
long nr_cpus;
|
||||||
bool ignore_abort = true;
|
pthread_t thread;
|
||||||
|
|
||||||
rseq_ptr = &__rseq_abi;
|
rseq_ptr = &__rseq_abi;
|
||||||
memset((void *)rseq_ptr, 0, sizeof(struct rseq));
|
memset((void *)rseq_ptr, 0, sizeof(struct rseq));
|
||||||
@ -233,21 +259,32 @@ int main(int argc, char *argv[])
|
|||||||
RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE;
|
RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
task_waiter_init(&waiter);
|
||||||
|
if (pthread_create(&thread, NULL, thread_routine, NULL)) {
|
||||||
|
fail("pthread_create");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
task_waiter_wait4(&waiter, 1);
|
||||||
|
|
||||||
test_daemon();
|
test_daemon();
|
||||||
|
task_waiter_complete(&waiter, 2);
|
||||||
|
|
||||||
while (test_go()) {
|
while (test_go()) {
|
||||||
cpu = RSEQ_ACCESS_ONCE(rseq_ptr->cpu_id_start);
|
cpu = RSEQ_ACCESS_ONCE(rseq_ptr->cpu_id_start);
|
||||||
ret = rseq_addv(&cpu_data[cpu], 2, cpu, ignore_abort);
|
ret = rseq_addv(&cpu_data[cpu], 2, cpu, ignore_abort, "task");
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
test_waitsig();
|
|
||||||
|
|
||||||
check_thread();
|
check_thread();
|
||||||
|
|
||||||
if (ret)
|
if (pthread_join(thread, NULL)) {
|
||||||
|
fail("pthread_join");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret || thread_ret)
|
||||||
fail();
|
fail();
|
||||||
else
|
else
|
||||||
pass();
|
pass();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user