*/
#include <config.h>
-
+#undef NDEBUG
+#include "fatal-signal.h"
#include "ovs-atomic.h"
-#include "util.h"
#include "ovstest.h"
#include "ovs-thread.h"
+#include "timeval.h"
+#include "util.h"
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(test_atomic);
#define TEST_ATOMIC_TYPE(ATOMIC_TYPE, BASE_TYPE) \
{ \
static uint32_t a;
struct atomic_aux {
- atomic_uint32_t count;
+ ATOMIC(uint64_t) count;
uint32_t b;
ATOMIC(uint32_t *) data;
+ ATOMIC(uint64_t) data64;
};
static ATOMIC(struct atomic_aux *) paux = ATOMIC_VAR_INIT(NULL);
static struct atomic_aux *auxes = NULL;
#define ATOMIC_ITEM_COUNT 1000000
+#define DURATION 5000
static void *
atomic_consumer(void * arg1 OVS_UNUSED)
{
struct atomic_aux *old_aux = NULL;
- uint32_t count;
+ uint64_t count;
+ long long int stop_time = time_msec() + DURATION;
do {
struct atomic_aux *aux;
ovs_assert(b == count + 42);
old_aux = aux;
- } while (count < ATOMIC_ITEM_COUNT - 1);
+ } while (count < ATOMIC_ITEM_COUNT - 1 && time_msec() < stop_time);
+
+ if (time_msec() >= stop_time) {
+ if (count < 10) {
+ VLOG_WARN("atomic_consumer test stopped due to excessive runtime. "
+ "Count = %"PRIu64, count);
+ }
+ }
return NULL;
}
atomic_reader(void *aux_)
{
struct atomic_aux *aux = aux_;
- uint32_t count;
- uint32_t *data;
+ uint64_t count;
+ uint64_t data;
+ long long int now = time_msec();
+ long long int stop_time = now + DURATION;
do {
/* Non-synchronized add. */
atomic_add_explicit(&aux->count, 1, &count, memory_order_relaxed);
do {
- atomic_read_explicit(&aux->data, &data, memory_order_acquire);
- } while (!data);
+ atomic_read_explicit(&aux->data64, &data, memory_order_acquire);
+ } while (!data && (now = time_msec()) < stop_time);
- ovs_assert(*data == a && *data == aux->b && a == aux->b);
+ if (now >= stop_time) {
+ if (count < 10) {
+ VLOG_WARN("atomic_reader test stopped due to excessive "
+ "runtime. Count = %"PRIu64, count);
+ }
+ break;
+ }
+
+ ovs_assert(data == a && data == aux->b && a == aux->b);
atomic_read_explicit(&aux->count, &count, memory_order_relaxed);
- ovs_assert(count == 2 * a && count == 2 * aux->b && count == 2 * *data);
+ ovs_assert(count == 2 * a && count == 2 * aux->b && count == 2 * data);
- atomic_store_explicit(&aux->data, NULL, memory_order_release);
+ atomic_store_explicit(&aux->data64, UINT64_C(0), memory_order_release);
} while (count < 2 * ATOMIC_ITEM_COUNT);
return NULL;
atomic_writer(void *aux_)
{
struct atomic_aux *aux = aux_;
- uint32_t old_count;
- uint32_t *data;
+ uint64_t old_count;
+ uint64_t data;
size_t i;
+ long long int now = time_msec();
+ long long int stop_time = now + DURATION;
for (i = 0; i < ATOMIC_ITEM_COUNT; i++) {
/* Wait for the reader to be done with the data. */
do {
- atomic_read_explicit(&aux->data, &data, memory_order_acquire);
- } while (data);
+ atomic_read_explicit(&aux->data64, &data, memory_order_acquire);
+ } while (data && (now = time_msec()) < stop_time);
+
+ if (now >= stop_time) {
+ if (i < 10) {
+ VLOG_WARN("atomic_writer test stopped due to excessive "
+ "runtime, Count = %"PRIuSIZE, i);
+ }
+ break;
+ }
a = i + 1;
atomic_add_explicit(&aux->count, 1, &old_count, memory_order_relaxed);
aux->b++;
- atomic_store_explicit(&aux->data,
- (i & 1) ? &aux->b : &a, memory_order_release);
+ atomic_store_explicit(&aux->data64,
+ (i & 1) ? (uint64_t)aux->b : a, memory_order_release);
}
return NULL;
aux->count = ATOMIC_VAR_INIT(0);
atomic_init(&aux->data, NULL);
+ aux->data64 = ATOMIC_VAR_INIT(0);
reader = ovs_thread_create("reader", atomic_reader, aux);
writer = ovs_thread_create("writer", atomic_writer, aux);
static void
test_atomic_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
+ fatal_signal_init();
test_atomic_plain();
test_atomic_relaxed();
test_atomic_consume();