MaxScale/server/core/test/test_atomic.cc
Markus Mäkelä ef53ded057 Fix test_atomic
As the function documentation states, the expected value must be read
again after a call to atomic_cas_ptr. This is due to the fact that if the
values are not the same, the __atomic builtin version will store the
current value into the expected value.

The new value given to the atomic_cas_ptr function was the address of the
new value, not the new value itself. The behavior of the atomic_cas_ptr is
what caused the test to pass on systeems that implement the __atomic
builtins. On older systems that do not implement it, the expected value
was never modified which caused the test to hang.
2018-01-22 15:29:21 +02:00

117 lines
2.2 KiB
C++

/*
* Copyright (c) 2016 MariaDB Corporation Ab
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
*
* Change Date: 2020-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2 or later of the General
* Public License.
*/
#include <maxscale/cdefs.h>
#include <stdio.h>
#include <maxscale/atomic.h>
#include <maxscale/debug.h>
#include <maxscale/thread.h>
#define NTHR 10
static int running = 0;
static int expected = 0;
void test_add(void* data)
{
int id = (size_t)data;
while (atomic_load_int32(&running))
{
atomic_add(&expected, id);
atomic_add(&expected, -id);
ss_dassert(atomic_load_int32(&expected) >= 0);
}
}
void test_load_store(void* data)
{
int id = (size_t)data;
while (atomic_load_int32(&running))
{
if (atomic_load_int32(&expected) % NTHR == id)
{
ss_dassert(atomic_add(&expected, 1) % NTHR == id + 1);
}
}
}
static void* cas_dest = (void*)1;
void test_cas(void* data)
{
size_t id = (size_t)data - 1;
static int loops = 0;
while (atomic_load_int32(&running))
{
void* my_value;
void* my_expected;
do
{
my_value = (void*)((id + 1) % NTHR);
my_expected = (void*)id;
}
while (!atomic_cas_ptr(&cas_dest, &my_expected, my_value));
loops++;
}
ss_dassert(loops > 0);
}
int run_test(void(*func)(void*))
{
THREAD threads[NTHR];
atomic_store_int32(&expected, 0);
atomic_store_int32(&running, 1);
for (size_t i = 0; i < NTHR; i++)
{
if (thread_start(&threads[i], func, (void*)(i + 1), 0) == NULL)
{
ss_dassert(false);
}
}
thread_millisleep(2500);
atomic_store_int32(&running, 0);
for (int i = 0; i < NTHR; i++)
{
thread_wait(threads[i]);
}
return atomic_load_int32(&expected);
}
int main(int argc, char** argv)
{
int rval = 0;
printf("test_load_store\n");
run_test(test_load_store);
printf("test_add\n");
run_test(test_add);
printf("test_cas\n");
run_test(test_cas);
return rval;
}