From c9bbe8eb574fe10ff16cc71a23fcc9b31fb8ed04 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sun, 5 Dec 2021 22:11:24 -0500 Subject: Use static initialization for lists and mutexes. This eliminates some run-time initialization, moving it to compile time. Additional follow up work will expand on this to simplify initialization and reduce the need for certain locks. --- src/core/dialer.c | 4 +--- src/core/idhash.h | 26 +++++++++++++------------- src/core/init.c | 47 +++++------------------------------------------ src/core/init.h | 19 ------------------- src/core/list.h | 10 ++++++++++ src/core/listener.c | 4 +--- src/core/socket.c | 20 +++++--------------- src/core/stats.c | 29 +++++++++++------------------ 8 files changed, 46 insertions(+), 113 deletions(-) (limited to 'src/core') diff --git a/src/core/dialer.c b/src/core/dialer.c index 3a749085..e3f435db 100644 --- a/src/core/dialer.c +++ b/src/core/dialer.c @@ -21,20 +21,18 @@ static void dialer_connect_cb(void *); static void dialer_timer_cb(void *); static nni_id_map dialers; -static nni_mtx dialers_lk; +static nni_mtx dialers_lk = NNI_MTX_INITIALIZER; void nni_dialer_sys_init(void) { nni_id_map_init(&dialers, 1, 0x7fffffff, false); - nni_mtx_init(&dialers_lk); } void nni_dialer_sys_fini(void) { nni_reap_drain(); - nni_mtx_fini(&dialers_lk); nni_id_map_fini(&dialers); } diff --git a/src/core/idhash.h b/src/core/idhash.h index 0c9043ce..b2259853 100644 --- a/src/core/idhash.h +++ b/src/core/idhash.h @@ -1,5 +1,5 @@ // -// Copyright 2020 Staysail Systems, Inc. +// Copyright 2021 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -23,28 +23,28 @@ // use table sizes that are powers of two. Note that hash items // must be non-NULL. The table is protected by an internal lock. -typedef struct nni_id_map nni_id_map; -typedef struct nni_id_entry nni_id_entry; +typedef struct nni_id_map nni_id_map; +typedef struct nni_id_entry nni_id_entry; // NB: These details are entirely private to the hash implementation. // They are provided here to facilitate inlining in structures. struct nni_id_map { - size_t id_cap; - size_t id_count; - size_t id_load; - size_t id_min_load; // considers placeholders - size_t id_max_load; + uint32_t id_cap; + uint32_t id_count; + uint32_t id_load; + uint32_t id_min_load; // considers placeholders + uint32_t id_max_load; uint32_t id_min_val; uint32_t id_max_val; uint32_t id_dyn_val; nni_id_entry *id_entries; }; -extern void nni_id_map_init(nni_id_map *, uint32_t, uint32_t, bool); -extern void nni_id_map_fini(nni_id_map *); +extern void nni_id_map_init(nni_id_map *, uint32_t, uint32_t, bool); +extern void nni_id_map_fini(nni_id_map *); extern void *nni_id_get(nni_id_map *, uint32_t); -extern int nni_id_set(nni_id_map *, uint32_t, void *); -extern int nni_id_alloc(nni_id_map *, uint32_t *, void *); -extern int nni_id_remove(nni_id_map *, uint32_t); +extern int nni_id_set(nni_id_map *, uint32_t, void *); +extern int nni_id_alloc(nni_id_map *, uint32_t *, void *); +extern int nni_id_remove(nni_id_map *, uint32_t); #endif // CORE_IDHASH_H diff --git a/src/core/init.c b/src/core/init.c index c923fdf0..f9dee9e2 100644 --- a/src/core/init.c +++ b/src/core/init.c @@ -14,21 +14,16 @@ #include #include -static nni_mtx nni_init_mtx; -static nni_list nni_init_list; -static bool nni_inited = false; - -extern int nni_tls_sys_init(void); +extern int nni_tls_sys_init(void); extern void nni_tls_sys_fini(void); +static bool nni_inited = false; + static int nni_init_helper(void) { int rv; - nni_mtx_init(&nni_init_mtx); - NNI_LIST_INIT(&nni_init_list, nni_initializer, i_node); - nni_inited = true; #ifdef NNG_TEST_LIB static bool cleanup = false; if (!cleanup) { @@ -54,6 +49,8 @@ nni_init_helper(void) nni_pipe_sys_init(); nni_sp_tran_sys_init(); + nni_inited = true; + return (0); } @@ -69,19 +66,6 @@ nni_fini(void) if (!nni_inited) { return; } - if (!nni_list_empty(&nni_init_list)) { - nni_initializer *init; - - nni_mtx_lock(&nni_init_mtx); - while ((init = nni_list_first(&nni_init_list)) != NULL) { - if (init->i_fini != NULL) { - init->i_fini(); - } - init->i_once = 0; - nni_list_remove(&nni_init_list, init); - } - nni_mtx_unlock(&nni_init_mtx); - } nni_sp_tran_sys_fini(); nni_tls_sys_fini(); nni_pipe_sys_fini(); @@ -95,27 +79,6 @@ nni_fini(void) nni_reap_sys_fini(); // must be before timer and aio (expire) nni_stat_sys_fini(); - nni_mtx_fini(&nni_init_mtx); nni_plat_fini(); nni_inited = false; } - -int -nni_initialize(nni_initializer *init) -{ - int rv; - if (init->i_once) { - return (0); - } - nni_mtx_lock(&nni_init_mtx); - if (init->i_once) { - nni_mtx_unlock(&nni_init_mtx); - return (0); - } - if ((rv = init->i_init()) == 0) { - init->i_once = 1; - nni_list_append(&nni_init_list, init); - } - nni_mtx_unlock(&nni_init_mtx); - return (rv); -} diff --git a/src/core/init.h b/src/core/init.h index d21bb4c5..7875ba4c 100644 --- a/src/core/init.h +++ b/src/core/init.h @@ -23,23 +23,4 @@ int nni_init(void); // that all resources used by the library are released back to the system. void nni_fini(void); -typedef struct nni_initializer { - int (*i_init)(void); // i_init is called exactly once - void (*i_fini)(void); // i_fini is called on shutdown - int i_once; // private -- initialize to zero - nni_list_node i_node; // private -- initialize to zero -} nni_initializer; - -// nni_initialize will call the initialization routine exactly once. This is -// done efficiently, so that if the caller has initialized already, then -// subsequent calls are "cheap" (no synchronization cost). The initialization -// function must not itself cause any further calls to nni_initialize; the -// function should limit itself to initialization of locks and static data -// structures. When shutting down, the finalizer will be called. The -// order in which finalizers are called is unspecified. -// -// An initializer may fail (due to resource exhaustion), in which case the -// return value of nni_initialize will be non-zero. -int nni_initialize(nni_initializer *); - #endif // CORE_INIT_H diff --git a/src/core/list.h b/src/core/list.h index 204057a2..d3c703bb 100644 --- a/src/core/list.h +++ b/src/core/list.h @@ -29,6 +29,16 @@ extern void nni_list_init_offset(nni_list *list, size_t offset); #define NNI_LIST_INIT(list, type, field) \ nni_list_init_offset(list, offsetof(type, field)) +// NNI_LIST_INITIALIZER is used to initialize structures at declaration time. +// The list argument is the structure being initialized and the type and +// offset determine where the node lives within each item. +#define NNI_LIST_INITIALIZER(list, type, field) \ + { \ + .ll_head.ln_next = &(list).ll_head, \ + .ll_head.ln_prev = &(list).ll_head, \ + .ll_offset = offsetof(type, field) \ + } + #define NNI_LIST_NODE_INIT(node) \ do { \ (node)->ln_prev = (node)->ln_next = 0; \ diff --git a/src/core/listener.c b/src/core/listener.c index 74e5e22b..4d4a4e24 100644 --- a/src/core/listener.c +++ b/src/core/listener.c @@ -22,20 +22,18 @@ static void listener_accept_cb(void *); static void listener_timer_cb(void *); static nni_id_map listeners; -static nni_mtx listeners_lk; +static nni_mtx listeners_lk = NNI_MTX_INITIALIZER; void nni_listener_sys_init(void) { nni_id_map_init(&listeners, 1, 0x7fffffff, false); - nni_mtx_init(&listeners_lk); } void nni_listener_sys_fini(void) { nni_reap_drain(); - nni_mtx_fini(&listeners_lk); nni_id_map_fini(&listeners); } diff --git a/src/core/socket.c b/src/core/socket.c index 6c43e43d..d9ac12b6 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -16,12 +16,6 @@ // Socket implementation. -static nni_list sock_list; -static nni_id_map sock_ids; -static nni_mtx sock_lk; -static nni_id_map ctx_ids; -static bool inited; - struct nni_ctx { nni_list_node c_node; nni_sock *c_sock; @@ -107,6 +101,11 @@ struct nni_socket { #endif }; +static nni_list sock_list = NNI_LIST_INITIALIZER(sock_list, nni_sock, s_node); +static nni_mtx sock_lk = NNI_MTX_INITIALIZER; +static nni_id_map sock_ids; +static nni_id_map ctx_ids; + static void nni_ctx_destroy(nni_ctx *); #define SOCK(s) ((nni_sock *) (s)) @@ -611,12 +610,8 @@ nni_sock_create(nni_sock **sp, const nni_proto *proto) void nni_sock_sys_init(void) { - NNI_LIST_INIT(&sock_list, nni_sock, s_node); - nni_mtx_init(&sock_lk); - nni_id_map_init(&sock_ids, 1, 0x7fffffff, false); nni_id_map_init(&ctx_ids, 1, 0x7fffffff, false); - inited = true; } void @@ -624,8 +619,6 @@ nni_sock_sys_fini(void) { nni_id_map_fini(&sock_ids); nni_id_map_fini(&ctx_ids); - nni_mtx_fini(&sock_lk); - inited = false; } int @@ -822,9 +815,6 @@ nni_sock_closeall(void) { nni_sock *s; - if (!inited) { - return; - } for (;;) { nni_mtx_lock(&sock_lk); if ((s = nni_list_first(&sock_list)) == NULL) { diff --git a/src/core/stats.c b/src/core/stats.c index e4765078..f7e52fb0 100644 --- a/src/core/stats.c +++ b/src/core/stats.c @@ -19,21 +19,21 @@ struct nng_stat { const nni_stat_info *s_info; const nni_stat_item *s_item; // Used during snapshot collection nni_list s_children; - nni_stat * s_parent; + nni_stat *s_parent; nni_list_node s_node; nni_time s_timestamp; union { int sv_id; bool sv_bool; uint64_t sv_value; - char * sv_string; + char *sv_string; } s_val; }; #ifdef NNG_ENABLE_STATS static nni_stat_item stats_root; -static nni_mtx stats_lock; -static nni_mtx stats_val_lock; +static nni_mtx stats_lock = NNI_MTX_INITIALIZER; +static nni_mtx stats_val_lock = NNI_MTX_INITIALIZER; #endif void @@ -171,7 +171,7 @@ nni_stat_set_string(nni_stat_item *item, const char *s) { #ifdef NNG_ENABLE_STATS const nni_stat_info *info = item->si_info; - char * old = item->si_u.sv_string; + char *old = item->si_u.sv_string; nni_mtx_lock(&stats_val_lock); if ((s != NULL) && (old != NULL) && (strcmp(s, old) == 0)) { @@ -235,7 +235,7 @@ nng_stats_free(nni_stat *st) static int stat_make_tree(nni_stat_item *item, nni_stat **sp) { - nni_stat * stat; + nni_stat *stat; nni_stat_item *child; if ((stat = NNI_ALLOC_STRUCT(stat)) == NULL) { @@ -266,8 +266,8 @@ stat_update(nni_stat *stat) { const nni_stat_item *item = stat->s_item; const nni_stat_info *info = item->si_info; - char * old; - char * str; + char *old; + char *str; switch (info->si_type) { case NNG_STAT_SCOPE: @@ -397,7 +397,6 @@ nng_stat_bool(nni_stat *stat) return (stat->s_val.sv_bool); } - const char * nng_stat_string(nng_stat *stat) { @@ -498,8 +497,6 @@ nni_stat_sys_init(void) .si_desc = "all statistics", .si_type = NNG_STAT_SCOPE, }; - nni_mtx_init(&stats_lock); - nni_mtx_init(&stats_val_lock); nni_stat_init(&stats_root, &root); #endif return (0); @@ -508,10 +505,6 @@ nni_stat_sys_init(void) void nni_stat_sys_fini(void) { -#ifdef NNG_ENABLE_STATS - nni_mtx_fini(&stats_lock); - nni_mtx_fini(&stats_val_lock); -#endif } #ifdef NNG_ENABLE_STATS @@ -538,10 +531,10 @@ nng_stats_dump(nng_stat *stat) #ifdef NNG_ENABLE_STATS static char buf[128]; // to minimize recursion, not thread safe int len; - char * scope; - char * indent = " "; + char *scope; + char *indent = " "; unsigned long long val; - nni_stat * child; + nni_stat *child; switch (nng_stat_type(stat)) { case NNG_STAT_SCOPE: -- cgit v1.2.3-70-g09d2