blob: 6bbba7f6221e58660b5236353eca0e6a9ad60a92 [file] [log] [blame]
/*
* Copyright (c) 2013 The Native Client Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* This test ensures that the PNaCl backends can deal with C++11
* synchronization primitives as would be written by regular users,
* including PNaCl's ABI stabilization and target lowering.
*
* See other synchronization_* tests in this directory.
*
* This is a syntactical check as we do not run this multithreaded. Some
* real testing is done here: tests/threads/thread_test.c
*/
#include <atomic>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define STR_(A) #A
#define STR(A) STR_(A)
#define CHECK_EQ(LHS, RHS, MSG) do { \
printf("\t" MSG ":\t" STR(LHS) "=%" PRIu64 \
" and " STR(RHS) "=%" PRIu64 "\n", \
(uint64_t)(LHS), (uint64_t)(RHS)); \
if ((LHS) != (RHS)) { \
fprintf(stderr, "ERROR: " MSG ": `" \
STR(LHS) " != " STR(RHS) "` " \
"\n"); \
exit(1); \
} \
} while (0)
/*
* ATOMIC_*_LOCK_FREE
*
* These macros must be compile-time constants, and for PNaCl the value
* should be 1, which means that the corresponding type may be
* lock-free: we can't guarantee that all our platforms are lock-free.
*/
void test_lock_free_macros() {
#if defined(__pnacl__)
static_assert(ATOMIC_BOOL_LOCK_FREE == 1, "should be compile-time 1");
static_assert(ATOMIC_CHAR_LOCK_FREE == 1, "should be compile-time 1");
static_assert(ATOMIC_CHAR16_T_LOCK_FREE == 1, "should be compile-time 1");
static_assert(ATOMIC_CHAR32_T_LOCK_FREE == 1, "should be compile-time 1");
static_assert(ATOMIC_WCHAR_T_LOCK_FREE == 1, "should be compile-time 1");
static_assert(ATOMIC_SHORT_LOCK_FREE == 1, "should be compile-time 1");
static_assert(ATOMIC_INT_LOCK_FREE == 1, "should be compile-time 1");
static_assert(ATOMIC_LONG_LOCK_FREE == 1, "should be compile-time 1");
static_assert(ATOMIC_LLONG_LOCK_FREE == 1, "should be compile-time 1");
static_assert(ATOMIC_POINTER_LOCK_FREE == 1, "should be compile-time 1");
#elif defined(__x86_64__) || defined(__i386__) || defined(__arm__)
static_assert(ATOMIC_BOOL_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_CHAR_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_CHAR16_T_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_CHAR32_T_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_WCHAR_T_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_SHORT_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_INT_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_LONG_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_LLONG_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_POINTER_LOCK_FREE == 2, "should be compile-time 2");
#elif defined(__mips__)
static_assert(ATOMIC_BOOL_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_CHAR_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_CHAR16_T_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_CHAR32_T_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_WCHAR_T_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_SHORT_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_INT_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_LONG_LOCK_FREE == 2, "should be compile-time 2");
static_assert(ATOMIC_LLONG_LOCK_FREE == 1, "should be compile-time 1");
static_assert(ATOMIC_POINTER_LOCK_FREE == 2, "should be compile-time 2");
# else
#error "unknown arch"
#endif
}
#if defined(__mips__)
bool isMips = true;
#else
bool isMips = false;
#endif
#define TEST_IS_LOCK_FREE(TYPE) do { \
bool expectLockFree = !((sizeof(TYPE) == 8) && isMips); \
CHECK_EQ(std::atomic<TYPE>().is_lock_free(), expectLockFree, \
"expected lock-free for `" STR(TYPE) "`"); \
} while (0)
void test_is_lock_free() {
TEST_IS_LOCK_FREE(bool);
// Table 145.
TEST_IS_LOCK_FREE(char);
TEST_IS_LOCK_FREE(signed char);
TEST_IS_LOCK_FREE(unsigned char);
TEST_IS_LOCK_FREE(short);
TEST_IS_LOCK_FREE(unsigned short);
TEST_IS_LOCK_FREE(int);
TEST_IS_LOCK_FREE(unsigned int);
TEST_IS_LOCK_FREE(long);
TEST_IS_LOCK_FREE(unsigned long);
TEST_IS_LOCK_FREE(long long);
TEST_IS_LOCK_FREE(unsigned long long);
TEST_IS_LOCK_FREE(char16_t);
TEST_IS_LOCK_FREE(char32_t);
TEST_IS_LOCK_FREE(wchar_t);
// Table 146.
TEST_IS_LOCK_FREE(int_least8_t);
TEST_IS_LOCK_FREE(uint_least8_t);
TEST_IS_LOCK_FREE(int_least16_t);
TEST_IS_LOCK_FREE(uint_least16_t);
TEST_IS_LOCK_FREE(int_least32_t);
TEST_IS_LOCK_FREE(uint_least32_t);
TEST_IS_LOCK_FREE(int_least64_t);
TEST_IS_LOCK_FREE(uint_least64_t);
TEST_IS_LOCK_FREE(int_fast8_t);
TEST_IS_LOCK_FREE(uint_fast8_t);
TEST_IS_LOCK_FREE(int_fast16_t);
TEST_IS_LOCK_FREE(uint_fast16_t);
TEST_IS_LOCK_FREE(int_fast32_t);
TEST_IS_LOCK_FREE(uint_fast32_t);
TEST_IS_LOCK_FREE(int_fast64_t);
TEST_IS_LOCK_FREE(uint_fast64_t);
TEST_IS_LOCK_FREE(intptr_t);
TEST_IS_LOCK_FREE(uintptr_t);
TEST_IS_LOCK_FREE(size_t);
TEST_IS_LOCK_FREE(ptrdiff_t);
TEST_IS_LOCK_FREE(intmax_t);
TEST_IS_LOCK_FREE(uintmax_t);
}
// TODO(jfb) Test C++11 atomic features.
// - std::atomic and their functions (including is_lock_free).
// - std::atomic_flag.
// - std::atomic_thread_fence (atomic_signal_fence currently unsupported).
// - 6 memory orders.
int main() {
test_lock_free_macros();
test_is_lock_free();
return 0;
}