blob: 77fb4e600915e40a3748076050344cafcb2631ea (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
//
// Copyright 2025 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
#include "defs.h"
#include "nng_impl.h"
#include "platform.h"
#include "socket.h"
#include <stdio.h>
#include <stdlib.h>
extern int nni_tls_sys_init(void);
extern void nni_tls_sys_fini(void);
#ifndef NNG_NUM_EXPIRE_THREADS
#define NNG_NUM_EXPIRE_THREADS (nni_plat_ncpu())
#endif
#ifndef NNG_NUM_TASKQ_THREADS
#define NNG_NUM_TASKQ_THREADS (nni_plat_ncpu() * 2)
#endif
#ifndef NNG_NUM_POLLER_THREADS
#define NNG_NUM_POLLER_THREADS (nni_plat_ncpu())
#endif
#ifndef NNG_MAX_POLLER_THREADS
#define NNG_MAX_POLLER_THREADS 8
#endif
#ifndef NNG_RESOLV_CONCURRENCY
#define NNG_RESOLV_CONCURRENCY 1
#endif
#ifndef NNG_MAX_TASKQ_THREADS
#define NNG_MAX_TASKQ_THREADS 16
#endif
#ifndef NNG_MAX_EXPIRE_THREADS
#define NNG_MAX_EXPIRE_THREADS 8
#endif
static nng_init_params init_params;
unsigned int init_count;
nni_atomic_flag init_busy;
nng_err
nng_init(const nng_init_params *params)
{
nng_init_params zero = { 0 };
nng_err rv;
// cheap spin lock
while (nni_atomic_flag_test_and_set(&init_busy)) {
continue;
}
if (init_count > 0) {
if (params != NULL) {
nni_atomic_flag_reset(&init_busy);
return (NNG_EBUSY);
}
init_count++;
nni_atomic_flag_reset(&init_busy);
return (0);
}
if (params == NULL) {
params = &zero;
}
init_params.num_task_threads = params->num_task_threads
? params->num_task_threads
: NNG_NUM_TASKQ_THREADS;
init_params.max_task_threads = params->max_task_threads
? params->max_task_threads
: NNG_MAX_TASKQ_THREADS;
init_params.num_expire_threads = params->num_expire_threads
? params->num_expire_threads
: NNG_NUM_EXPIRE_THREADS;
init_params.max_expire_threads = params->max_expire_threads
? params->max_expire_threads
: NNG_MAX_EXPIRE_THREADS;
init_params.num_poller_threads = params->num_poller_threads
? params->num_poller_threads
: NNG_NUM_POLLER_THREADS;
init_params.max_poller_threads = params->max_poller_threads
? params->max_poller_threads
: NNG_MAX_POLLER_THREADS;
init_params.num_resolver_threads = params->num_resolver_threads
? params->num_resolver_threads
: NNG_RESOLV_CONCURRENCY;
if (((rv = nni_plat_init(&init_params)) != 0) ||
((rv = nni_taskq_sys_init(&init_params)) != 0) ||
((rv = nni_reap_sys_init()) != 0) ||
((rv = nni_aio_sys_init(&init_params)) != 0) ||
((rv = nni_tls_sys_init()) != 0)) {
nni_atomic_flag_reset(&init_busy);
nng_fini();
return (rv);
}
// following never fails
nni_sp_tran_sys_init();
nng_log_notice(
"NNG-INIT", "NNG library version %s initialized", nng_version());
init_count++;
nni_atomic_flag_reset(&init_busy);
return (rv);
}
// Undocumented, for test code only
#ifdef NNG_TEST_LIB
nng_init_params *
nng_init_get_params(void)
{
return &init_params;
}
#endif
void
nng_fini(void)
{
while (nni_atomic_flag_test_and_set(&init_busy)) {
continue;
}
init_count--;
if (init_count > 0) {
nni_atomic_flag_reset(&init_busy);
return;
}
nni_sock_closeall();
nni_sp_tran_sys_fini();
// Drain everything. This is important because some of
// these subsystems can dispatch things to other ones.
// So we need them *all* to be empty before proceeding.
while ((nni_aio_sys_drain() || nni_taskq_sys_drain() ||
nni_reap_sys_drain())) {
continue;
}
nni_tls_sys_fini();
nni_taskq_sys_fini();
nni_aio_sys_fini();
nni_id_map_sys_fini();
nni_reap_sys_fini(); // must be near the end
nni_plat_fini();
nni_atomic_flag_reset(&init_busy);
}
|