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.f...@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


Reply via email to