0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00
bird/lib/locking_test.c
2023-12-04 10:39:32 +01:00

90 lines
1.7 KiB
C

#include "test/birdtest.h"
#include "test/bt-utils.h"
#include "lib/locking.h"
#include <stdatomic.h>
#include <pthread.h>
#define FOO_PUBLIC \
const char *name; \
_Atomic uint counter; \
DOMAIN(proto) lock; \
struct foo_private {
struct { FOO_PUBLIC; };
struct foo_private **locked_at;
uint private_counter;
};
typedef union foo {
struct { FOO_PUBLIC; };
struct foo_private priv;
} foo;
LOBJ_UNLOCK_CLEANUP(foo, proto);
#define FOO_LOCK(_foo, _fpp) LOBJ_LOCK(_foo, _fpp, foo, proto)
#define FOO_LOCKED(_foo, _fpp) LOBJ_LOCKED(_foo, _fpp, foo, proto)
#define FOO_IS_LOCKED(_foo) LOBJ_IS_LOCKED(_foo, proto)
static uint
inc_public(foo *f)
{
return atomic_fetch_add_explicit(&f->counter, 1, memory_order_relaxed) + 1;
}
static uint
inc_private(foo *f)
{
FOO_LOCKED(f, fp) return ++fp->private_counter;
bug("Returning always");
}
#define BLOCKCOUNT 4096
#define THREADS 16
#define REPEATS 128
static void *
thread_run(void *_foo)
{
foo *f = _foo;
for (int i=0; i<REPEATS; i++)
if (i % 2)
for (int j=0; j<BLOCKCOUNT; j++)
inc_public(f);
else
for (int j=0; j<BLOCKCOUNT; j++)
inc_private(f);
return NULL;
}
static int
t_locking(void)
{
pthread_t thr[THREADS];
foo f = { .lock = DOMAIN_NEW(proto), };
for (int i=0; i<THREADS; i++)
bt_assert(pthread_create(&thr[i], NULL, thread_run, &f) == 0);
for (int i=0; i<THREADS; i++)
bt_assert(pthread_join(thr[i], NULL) == 0);
bt_assert(f.priv.private_counter == atomic_load_explicit(&f.counter, memory_order_relaxed));
bt_assert(f.priv.private_counter == THREADS * BLOCKCOUNT * REPEATS / 2);
return 1;
}
int
main(int argc, char **argv)
{
bt_init(argc, argv);
bt_bird_init();
bt_test_suite(t_locking, "Testing locks");
return bt_exit_value();
}