[PATCH 1/5] lib: introduce call_once()

Akinobu Mita
2008-03-10T15:04:51Z

call_once() is an utility function which has similar functionality of
pthread_once().

Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
---
include/linux/once.h | 42 ++++++++++++++++++++++++++++++++++++++++++
lib/Makefile | 2 +-
lib/once.c | 18 ++++++++++++++++++
3 files changed, 61 insertions(+), 1 deletion(-)

Index: 2.6-rc/include/linux/once.h
===================================================================
--- /dev/null
+++ 2.6-rc/include/linux/once.h
@@ -0,0 +1,42 @@
+#ifndef __LINUX_ONCE_H
+#define __LINUX_ONCE_H
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+
+struct once_control {
+ struct mutex lock;
+ int done;
+};
+
+#define __ONCE_INITIALIZER(name) { \
+ .lock = __MUTEX_INITIALIZER(name.lock), \
+ .done = 0, \
+ }
+
+#define DEFINE_ONCE(name) struct once_control name = __ONCE_INITIALIZER(name)
+
+extern int call_once_slow(struct once_control *once_control,
+ int (*init_rouine)(void));
+
+/*
+ * call_once - call the initialization function only once
+ *
+ * @once_control: guarantee that the init_routine will be called only once
+ * @init_routine: initialization function
+ *
+ * The first call to call_once(), with a given once_control, shall call the
+ * init_routine with no arguments and return the value init_routine returned.
+ * If the init_routine returns zero which indicates the initialization
+ * succeeded, subsequent calls of call_once() with the same once_control shall
+ * not call the init_routine and return zero.
+ */
+
+static inline int call_once(struct once_control *once_control,
+ int (*init_rouine)(void))
+{
+ return likely(once_control->done) ? 0
+ : call_once_slow(once_control, init_rouine);
+}
+
+#endif /* __LINUX_ONCE_H */
Index: 2.6-rc/lib/once.c
===================================================================
--- /dev/null
+++ 2.6-rc/lib/once.c
@@ -0,0 +1,18 @@
+#include <linux/module.h>
+#include <linux/once.h>
+
+int call_once_slow(struct once_control *once_control, int (*init_rouine)(void))
+{
+ int err = 0;
+
+ mutex_lock(&once_control->lock);
+ if (!once_control->done) {
+ err = init_rouine();
+ if (!err)
+ once_control->done = 1;
+ }
+ mutex_unlock(&once_control->lock);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(call_once_slow);
Index: 2.6-rc/lib/Makefile
===================================================================
--- 2.6-rc.orig/lib/Makefile
+++ 2.6-rc/lib/Makefile
@@ -14,7 +14,7 @@ lib-$(CONFIG_SMP) += cpumask.o
lib-y += kobject.o kref.o klist.o

obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
- bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o
+ bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o once.o

ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG