blob: bb883254f1942665b29c64b0ae3ea5ff96af68d4 [file] [log] [blame]
/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
#include "util.h"
/**
* This test makes sure that replay does not fail if the instruction after a
* system call is non-idempotent. For each architecture, the assembly sequence
* should issue a system call, followed immediately by an increment operation
* or other non-idempotent operation on a memory address.
*/
int main(void) {
int var = 41;
#ifdef __i386__
__asm__ __volatile__("int $0x80\n\t"
"incl %0\n\t"
: "+m"(var)
: "a"(SYS_gettid));
#elif defined(__x86_64__)
__asm__ __volatile__("syscall\n\t"
"incl %0\n\t"
: "+m"(var)
: "a"(SYS_gettid));
#elif defined(__aarch64__)
// We use an atomic instruction here, because we need to do a read-modify
// write cycle all in one instruction. Everything else would be idempotent
register long x8 __asm__("x8") = SYS_gettid;
register long x1 __asm__("x1") = 1;
register long x0 __asm__("x0") = 0;
__asm__ __volatile__("svc #0\n\t"
"stadd w1, %0\n\t"
: "+Q"(var), "+r"(x0)
: "r"(x8), "r"(x1));
#else
#error Define your architecture here
#endif
test_assert(var == 42);
atomic_puts("EXIT-SUCCESS");
return 0;
}