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/446a07542f2e
branches:  trunk
changeset: 449742:446a07542f2e
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 f3e063bdd1a3 -r 446a07542f2e 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 f3e063bdd1a3 -r 446a07542f2e 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 f3e063bdd1a3 -r 446a07542f2e 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 f3e063bdd1a3 -r 446a07542f2e 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