Skip to content

Commit 4dd92b3

Browse files
committed
Add thread-based RCU
Add the Linux Kernel style thread-based simple RCU. It supports sparse checking[1]. thread-rcu target to use Linux Kernel Memory Model (LKMM). C11 memory model may no compatible to LKMM. Check the paper[2] to see more detail. [1] https://www.kernel.org/doc/html/latest/dev-tools/sparse.html [2] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0124r6.html
1 parent 5737c46 commit 4dd92b3

File tree

4 files changed

+414
-0
lines changed

4 files changed

+414
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ purpose of these programs is to be illustrative and educational.
3030
- [qsbr](qsbr/): An implementation of Quiescent state based reclamation (QSBR).
3131
- [list-move](list-move/): Evaluation of two concurrent linked lists: QSBR and lock-based.
3232
- [rcu\_queue](rcu_queue/): An efficient concurrent queue based on QSBR.
33+
- [thread-rcu](thread-rcu/): A Linux Kernel style thread-based simple RCU.
3334
* Applications
3435
- [httpd](httpd/): A multi-threaded web server.
3536
- [map-reduce](map-reduce/): word counting using MapReduce.

thread-rcu/Makefile

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
CFLAGS = -Wall
2+
CFLAGS += -g
3+
CFLAGS += -std=c11
4+
CFLAGS += -D'N_READERS=10'
5+
CFLAGS += -fsanitize=thread
6+
LDFLAGS += -lpthread
7+
8+
# The pthread mutex initializer will warning:
9+
# thrd_rcu.h:95:42: warning: Using plain integer as NULL pointer
10+
# We can ignore it.
11+
SPARSE_FLAGS = -Wno-non-pointer-null
12+
13+
main: main.c
14+
$(CC) -o $@ $< $(CFLAGS) $(LDFLAGS)
15+
16+
clang: CC=clang
17+
clang: main
18+
19+
all: main
20+
21+
# Semantic Checker
22+
# https://www.kernel.org/doc/html/latest/dev-tools/sparse.html
23+
sparse:
24+
sparse main.c $(CFLAGS) $(SPARSE_FLAGS)
25+
26+
indent:
27+
clang-format -i *.[ch]
28+
29+
clean:
30+
rm -f main

thread-rcu/main.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include <pthread.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
5+
#include "rcu.h"
6+
7+
struct test {
8+
unsigned int count;
9+
};
10+
11+
static struct test __rcu *dut;
12+
13+
static void *reader_func(void *argv)
14+
{
15+
struct test *tmp;
16+
17+
if (rcu_init())
18+
abort();
19+
20+
rcu_read_lock();
21+
22+
tmp = rcu_dereference(dut);
23+
24+
printf("[reader #%u] %u\n", current_tid(), tmp->count);
25+
26+
rcu_read_unlock();
27+
28+
pthread_exit(NULL);
29+
}
30+
31+
static void *updater_func(void *argv)
32+
{
33+
struct test *oldp;
34+
struct test *newval = malloc(sizeof(struct test));
35+
36+
newval->count = current_tid();
37+
38+
printf("[updater #%u]\n", newval->count);
39+
40+
oldp = rcu_assign_pointer(dut, newval);
41+
42+
synchronize_rcu();
43+
free(oldp);
44+
45+
pthread_exit(NULL);
46+
}
47+
48+
int main(int argc, char *argv[])
49+
{
50+
pthread_t reader[N_READERS];
51+
pthread_t updater;
52+
int i;
53+
54+
dut = (struct test __rcu *) malloc(sizeof(struct test));
55+
rcu_uncheck(dut)->count = 0;
56+
57+
for (i = 0; i < N_READERS / 2; i++)
58+
pthread_create(&reader[i], NULL, reader_func, NULL);
59+
60+
pthread_create(&updater, NULL, updater_func, NULL);
61+
62+
for (i = N_READERS / 2; i < N_READERS; i++)
63+
pthread_create(&reader[i], NULL, reader_func, NULL);
64+
65+
for (i = 0; i < N_READERS; i++)
66+
pthread_join(reader[i], NULL);
67+
68+
pthread_join(updater, NULL);
69+
70+
free(rcu_uncheck(dut));
71+
rcu_clean();
72+
73+
return 0;
74+
}

0 commit comments

Comments
 (0)