Sample code for hazptr. This should go away or get more polished when
hazptr support is added into rcutorture.
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
---
samples/Kconfig | 6 +++
samples/Makefile | 1 +
samples/hazptr/hazptr_test.c | 87 ++++++++++++++++++++++++++++++++++++
3 files changed, 94 insertions(+)
create mode 100644 samples/hazptr/hazptr_test.c
diff --git a/samples/Kconfig b/samples/Kconfig
index b288d9991d27..9b42cde35dca 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -293,6 +293,12 @@ config SAMPLE_CGROUP
source "samples/rust/Kconfig"
+config SAMPLE_HAZPTR
+ bool "Build hazptr sample code"
+ help
+ Build samples that shows hazard pointer usage. Currently only
+ builtin usage is supported.
+
endif # SAMPLES
config HAVE_SAMPLE_FTRACE_DIRECT
diff --git a/samples/Makefile b/samples/Makefile
index b85fa64390c5..0be21edc8a30 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -39,3 +39,4 @@ obj-$(CONFIG_SAMPLE_KMEMLEAK) += kmemleak/
obj-$(CONFIG_SAMPLE_CORESIGHT_SYSCFG) += coresight/
obj-$(CONFIG_SAMPLE_FPROBE) += fprobe/
obj-$(CONFIG_SAMPLES_RUST) += rust/
+obj-$(CONFIG_SAMPLE_HAZPTR) += hazptr/
diff --git a/samples/hazptr/hazptr_test.c b/samples/hazptr/hazptr_test.c
new file mode 100644
index 000000000000..3cf0cdc8a83a
--- /dev/null
+++ b/samples/hazptr/hazptr_test.c
@@ -0,0 +1,87 @@
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/hazptr.h>
+
+struct foo {
+ int i;
+ struct callback_head head;
+};
+
+static void simple_func(struct callback_head *head)
+{
+ struct foo *ptr = container_of(head, struct foo, head);
+
+ printk("callback called %px, i is %d\n", ptr, ptr->i);
+ kfree(ptr);
+}
+
+static void simple(void)
+{
+ struct hazptr_context ctx;
+ struct foo *dummy, *tmp, *other;
+ hazptr_t *hptr;
+ hazptr_t *hptr2;
+
+ dummy = kzalloc(sizeof(*dummy), GFP_KERNEL);
+ dummy->i = 42;
+
+ other = kzalloc(sizeof(*dummy), GFP_KERNEL);
+ other->i = 43;
+
+ if (!dummy || !other) {
+ printk("allocation failed, skip test\n");
+ return;
+ }
+
+ init_hazptr_context(&ctx);
+ hptr = hazptr_alloc(&ctx);
+ BUG_ON(!hptr);
+
+ // Get a second hptr.
+ hptr2 = hazptr_alloc(&ctx);
+ BUG_ON(!hptr2);
+
+ // No one is modifying 'dummy', protection must succeed.
+ BUG_ON(!hazptr_tryprotect(hptr, dummy, head));
+
+ // Simulate changing a global pointer.
+ tmp = dummy;
+ WRITE_ONCE(dummy, other);
+
+ // Callback will run after no active readers.
+ printk("callback added, %px\n", tmp);
+
+ call_hazptr(&tmp->head, simple_func);
+
+ // No one is modifying 'dummy', protection must succeed.
+ tmp = hazptr_protect(hptr2, dummy, head);
+
+ printk("reader2 got %px, i is %d\n", tmp, tmp->i);
+
+ // The above callback should run after this.
+ hazptr_clear(hptr);
+ printk("first reader is out\n");
+
+ for (int i = 0; i < 10; i++)
+ schedule(); // yield a few times.
+
+ // Simulate freeing a global pointer.
+ tmp = dummy;
+ WRITE_ONCE(dummy, NULL);
+ printk("callback added, %px\n", tmp);
+ call_hazptr(&tmp->head, simple_func);
+
+ cleanup_hazptr_context(&ctx);
+ printk("no reader here\n");
+
+ for (int i = 0; i < 10; i++)
+ schedule(); // yield a few times.
+}
+
+static int hazptr_test(void)
+{
+ simple();
+ printk("test ends\n");
+ return 0;
+}
+module_init(hazptr_test);
--
2.45.2