Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src add INIT_ONCE(9), FINI_ONCE(9) with changing once_t.
details: https://anonhg.NetBSD.org/src/rev/1befc3caa927
branches: trunk
changeset: 840060:1befc3caa927
user: ryo <ryo%NetBSD.org@localhost>
date: Tue Mar 19 08:16:51 2019 +0000
description:
add INIT_ONCE(9), FINI_ONCE(9) with changing once_t.
Welcome to 8.99.36
diffstat:
share/man/man9/RUN_ONCE.9 | 33 ++++++++++++++++++++++++++++++---
sys/kern/subr_once.c | 42 ++++++++++++++++++++++++++++++++++--------
sys/sys/once.h | 16 +++++++++++-----
sys/sys/param.h | 4 ++--
4 files changed, 77 insertions(+), 18 deletions(-)
diffs (201 lines):
diff -r 90cc6aeeabb7 -r 1befc3caa927 share/man/man9/RUN_ONCE.9
--- a/share/man/man9/RUN_ONCE.9 Tue Mar 19 07:08:43 2019 +0000
+++ b/share/man/man9/RUN_ONCE.9 Tue Mar 19 08:16:51 2019 +0000
@@ -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 @@
.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,
diff -r 90cc6aeeabb7 -r 1befc3caa927 sys/kern/subr_once.c
--- a/sys/kern/subr_once.c Tue Mar 19 07:08:43 2019 +0000
+++ b/sys/kern/subr_once.c Tue Mar 19 08:16:51 2019 +0000
@@ -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 @@
}
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 @@
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);
+}
diff -r 90cc6aeeabb7 -r 1befc3caa927 sys/sys/once.h
--- a/sys/sys/once.h Tue Mar 19 07:08:43 2019 +0000
+++ b/sys/sys/once.h Tue Mar 19 08:16:51 2019 +0000
@@ -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_ */
diff -r 90cc6aeeabb7 -r 1befc3caa927 sys/sys/param.h
--- a/sys/sys/param.h Tue Mar 19 07:08:43 2019 +0000
+++ b/sys/sys/param.h Tue Mar 19 08:16:51 2019 +0000
@@ -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__)
Home |
Main Index |
Thread Index |
Old Index