Module Name:    src
Committed By:   ryo
Date:           Tue Mar 19 08:16:51 UTC 2019

Modified Files:
        src/share/man/man9: RUN_ONCE.9
        src/sys/kern: subr_once.c
        src/sys/sys: once.h param.h

Log Message:
add INIT_ONCE(9), FINI_ONCE(9) with changing once_t.

Welcome to 8.99.36


To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 src/share/man/man9/RUN_ONCE.9
cvs rdiff -u -r1.6 -r1.7 src/sys/kern/subr_once.c
cvs rdiff -u -r1.6 -r1.7 src/sys/sys/once.h
cvs rdiff -u -r1.583 -r1.584 src/sys/sys/param.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/share/man/man9/RUN_ONCE.9
diff -u src/share/man/man9/RUN_ONCE.9:1.9 src/share/man/man9/RUN_ONCE.9:1.10
--- src/share/man/man9/RUN_ONCE.9:1.9	Mon Jul  3 21:28:48 2017
+++ src/share/man/man9/RUN_ONCE.9	Tue Mar 19 08:16:51 2019
@@ -1,4 +1,4 @@
-.\"	$NetBSD: RUN_ONCE.9,v 1.9 2017/07/03 21:28:48 wiz Exp $
+.\"	$NetBSD: RUN_ONCE.9,v 1.10 2019/03/19 08:16:51 ryo Exp $
 .\"
 .\" Copyright (c)2005 YAMAMOTO Takashi,
 .\" All rights reserved.
@@ -25,12 +25,14 @@
 .\" SUCH DAMAGE.
 .\"
 .\" ------------------------------------------------------------
-.Dd July 7, 2010
+.Dd Mar 19, 2019
 .Dt RUN_ONCE 9
 .Os
 .\" ------------------------------------------------------------
 .Sh NAME
-.Nm RUN_ONCE
+.Nm RUN_ONCE ,
+.Nm INIT_ONCE ,
+.Nm FINI_ONCE
 .Nd Run a function exactly once
 .\" ------------------------------------------------------------
 .Sh SYNOPSIS
@@ -41,6 +43,12 @@
 .Ft int
 .Fn RUN_ONCE \
 "once_t *control" "int (*init_func)(void)"
+.Ft int
+.Fn INIT_ONCE \
+"once_t *control" "int (*init_func)(void)"
+.Ft void
+.Fn FINI_ONCE \
+"once_t *control" "void (*fini_func)(void)"
 .\" ------------------------------------------------------------
 .Sh DESCRIPTION
 .Fn RUN_ONCE
@@ -59,6 +67,25 @@ will try again each time it is called.
 .Pp
 .Fn RUN_ONCE
 can sleep if it's called concurrently.
+.Pp
+.Fn INIT_ONCE
+is used in pair with
+.Fn FINI_ONCE .
+.Fn INIT_ONCE
+will only be run once similar with
+.Fn RUN_ONCE .
+.Fn FINI_ONCE
+will only be run at last time if it is called as many times as calling
+.Fn INIT_ONCE .
+When
+.Fn FINI_ONCE
+is executed, the next call to
+.Fn INIT_ONCE
+will be executed again. That is,
+.Fn INIT_ONCE
+and
+.Fn FINI_ONCE
+can be nested.
 .\" ------------------------------------------------------------
 .Sh RETURN VALUES
 On failure,

Index: src/sys/kern/subr_once.c
diff -u src/sys/kern/subr_once.c:1.6 src/sys/kern/subr_once.c:1.7
--- src/sys/kern/subr_once.c:1.6	Sun Mar 15 17:14:40 2009
+++ src/sys/kern/subr_once.c	Tue Mar 19 08:16:51 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_once.c,v 1.6 2009/03/15 17:14:40 cegger Exp $	*/
+/*	$NetBSD: subr_once.c,v 1.7 2019/03/19 08:16:51 ryo Exp $	*/
 
 /*-
  * Copyright (c)2005 YAMAMOTO Takashi,
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_once.c,v 1.6 2009/03/15 17:14:40 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_once.c,v 1.7 2019/03/19 08:16:51 ryo Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -48,13 +48,17 @@ once_init(void)
 }
 
 int
-_run_once(once_t *o, int (*fn)(void))
+_init_once(once_t *o, int (*fn)(void))
 {
-
 	/* Fastpath handled by RUN_ONCE() */
 
+	int error;
+
 	mutex_enter(&oncemtx);
-	if (o->o_status == ONCE_VIRGIN) {
+	while (o->o_status == ONCE_RUNNING)
+		cv_wait(&oncecv, &oncemtx);
+
+	if (o->o_refcnt++ == 0) {
 		o->o_status = ONCE_RUNNING;
 		mutex_exit(&oncemtx);
 		o->o_error = fn();
@@ -62,10 +66,32 @@ _run_once(once_t *o, int (*fn)(void))
 		o->o_status = ONCE_DONE;
 		cv_broadcast(&oncecv);
 	}
-	while (o->o_status != ONCE_DONE)
+	KASSERT(o->o_refcnt != 0);	/* detect overflow */
+
+	while (o->o_status == ONCE_RUNNING)
 		cv_wait(&oncecv, &oncemtx);
+	error = o->o_error;
 	mutex_exit(&oncemtx);
 
-	KASSERT(o->o_status == ONCE_DONE);
-	return o->o_error;
+	return error;
+}
+
+void
+_fini_once(once_t *o, void (*fn)(void))
+{
+	mutex_enter(&oncemtx);
+	while (o->o_status == ONCE_RUNNING)
+		cv_wait(&oncecv, &oncemtx);
+
+	KASSERT(o->o_refcnt != 0);	/* we need to call _init_once() once */
+	if (--o->o_refcnt == 0) {
+		o->o_status = ONCE_RUNNING;
+		mutex_exit(&oncemtx);
+		fn();
+		mutex_enter(&oncemtx);
+		o->o_status = ONCE_VIRGIN;
+		cv_broadcast(&oncecv);
+	}
+
+	mutex_exit(&oncemtx);
 }

Index: src/sys/sys/once.h
diff -u src/sys/sys/once.h:1.6 src/sys/sys/once.h:1.7
--- src/sys/sys/once.h:1.6	Sat Mar  3 19:21:59 2018
+++ src/sys/sys/once.h	Tue Mar 19 08:16:51 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: once.h,v 1.6 2018/03/03 19:21:59 jdolecek Exp $	*/
+/*	$NetBSD: once.h,v 1.7 2019/03/19 08:16:51 ryo Exp $	*/
 
 /*-
  * Copyright (c)2005 YAMAMOTO Takashi,
@@ -31,23 +31,29 @@
 #define	_SYS_ONCE_H_
 
 typedef struct {
-	unsigned o_status;
 	int o_error;
+	uint16_t o_refcnt;
+	uint16_t o_status;
 #define	ONCE_VIRGIN	0
 #define	ONCE_RUNNING	1
 #define	ONCE_DONE	2
 } once_t;
 
 void once_init(void);
-int _run_once(once_t *, int (*)(void));
+int _init_once(once_t *, int (*)(void));
+void _fini_once(once_t *, void (*)(void));
 
 #define	ONCE_DECL(o) \
-	once_t (o) __read_mostly = { \
+	once_t (o) = { \
 		.o_status = 0, \
+		.o_refcnt = 0, \
 	};
 
 #define	RUN_ONCE(o, fn) \
     (__predict_true((o)->o_status == ONCE_DONE) ? \
-      ((o)->o_error) : _run_once((o), (fn)))
+      ((o)->o_error) : _init_once((o), (fn)))
+
+#define	INIT_ONCE(o, fn)	_init_once((o), (fn))
+#define	FINI_ONCE(o, fn)	_fini_once((o), (fn))
 
 #endif /* _SYS_ONCE_H_ */

Index: src/sys/sys/param.h
diff -u src/sys/sys/param.h:1.583 src/sys/sys/param.h:1.584
--- src/sys/sys/param.h:1.583	Fri Mar  1 03:03:19 2019
+++ src/sys/sys/param.h	Tue Mar 19 08:16:51 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: param.h,v 1.583 2019/03/01 03:03:19 christos Exp $	*/
+/*	$NetBSD: param.h,v 1.584 2019/03/19 08:16:51 ryo Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -67,7 +67,7 @@
  *	2.99.9		(299000900)
  */
 
-#define	__NetBSD_Version__	899003500	/* NetBSD 8.99.35 */
+#define	__NetBSD_Version__	899003600	/* NetBSD 8.99.36 */
 
 #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
     (m) * 1000000) + (p) * 100) <= __NetBSD_Version__)

Reply via email to