1 //
2 // Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
3 //
4 // This software is supplied under the terms of the MIT License, a
5 // copy of which should be located in the distribution where this
6 // file was obtained (LICENSE.txt).  A copy of the license may also be
7 // found online at https://opensource.org/licenses/MIT.
8 //
9 
10 #include "core/nng_impl.h"
11 
12 void
nni_mtx_init(nni_mtx * mtx)13 nni_mtx_init(nni_mtx *mtx)
14 {
15 	nni_plat_mtx_init(mtx);
16 }
17 
18 void
nni_mtx_fini(nni_mtx * mtx)19 nni_mtx_fini(nni_mtx *mtx)
20 {
21 	nni_plat_mtx_fini(mtx);
22 }
23 
24 void
nni_mtx_lock(nni_mtx * mtx)25 nni_mtx_lock(nni_mtx *mtx)
26 {
27 	nni_plat_mtx_lock(mtx);
28 }
29 
30 void
nni_mtx_unlock(nni_mtx * mtx)31 nni_mtx_unlock(nni_mtx *mtx)
32 {
33 	nni_plat_mtx_unlock(mtx);
34 }
35 
36 void
nni_cv_init(nni_cv * cv,nni_mtx * mtx)37 nni_cv_init(nni_cv *cv, nni_mtx *mtx)
38 {
39 	nni_plat_cv_init(cv, mtx);
40 }
41 
42 void
nni_cv_fini(nni_cv * cv)43 nni_cv_fini(nni_cv *cv)
44 {
45 	nni_plat_cv_fini(cv);
46 }
47 
48 void
nni_cv_wait(nni_cv * cv)49 nni_cv_wait(nni_cv *cv)
50 {
51 	nni_plat_cv_wait(cv);
52 }
53 
54 int
nni_cv_until(nni_cv * cv,nni_time until)55 nni_cv_until(nni_cv *cv, nni_time until)
56 {
57 	// Some special cases for times.  Catching these here means that
58 	// platforms can assume a valid time is presented to them.
59 	if (until == NNI_TIME_NEVER) {
60 		nni_plat_cv_wait(cv);
61 		return (0);
62 	}
63 	if (until == NNI_TIME_ZERO) {
64 		return (NNG_EAGAIN);
65 	}
66 
67 	return (nni_plat_cv_until(cv, until));
68 }
69 
70 void
nni_cv_wake(nni_cv * cv)71 nni_cv_wake(nni_cv *cv)
72 {
73 	nni_plat_cv_wake(cv);
74 }
75 
76 void
nni_cv_wake1(nni_cv * cv)77 nni_cv_wake1(nni_cv *cv)
78 {
79 	nni_plat_cv_wake1(cv);
80 }
81 
82 static void
nni_thr_wrap(void * arg)83 nni_thr_wrap(void *arg)
84 {
85 	nni_thr *thr = arg;
86 	int      start;
87 
88 	nni_plat_mtx_lock(&thr->mtx);
89 	while (((start = thr->start) == 0) && (thr->stop == 0)) {
90 		nni_plat_cv_wait(&thr->cv);
91 	}
92 	nni_plat_mtx_unlock(&thr->mtx);
93 	if ((start) && (thr->fn != NULL)) {
94 		thr->fn(thr->arg);
95 	}
96 	nni_plat_mtx_lock(&thr->mtx);
97 	thr->done = 1;
98 	nni_plat_cv_wake(&thr->cv);
99 	nni_plat_mtx_unlock(&thr->mtx);
100 }
101 
102 int
nni_thr_init(nni_thr * thr,nni_thr_func fn,void * arg)103 nni_thr_init(nni_thr *thr, nni_thr_func fn, void *arg)
104 {
105 	int rv;
106 
107 	thr->done  = 0;
108 	thr->start = 0;
109 	thr->stop  = 0;
110 	thr->fn    = fn;
111 	thr->arg   = arg;
112 
113 	nni_plat_mtx_init(&thr->mtx);
114 	nni_plat_cv_init(&thr->cv, &thr->mtx);
115 
116 	if (fn == NULL) {
117 		thr->init = 1;
118 		thr->done = 1;
119 		return (0);
120 	}
121 	if ((rv = nni_plat_thr_init(&thr->thr, nni_thr_wrap, thr)) != 0) {
122 		thr->done = 1;
123 		nni_plat_cv_fini(&thr->cv);
124 		nni_plat_mtx_fini(&thr->mtx);
125 		return (rv);
126 	}
127 	thr->init = 1;
128 	return (0);
129 }
130 
131 void
nni_thr_run(nni_thr * thr)132 nni_thr_run(nni_thr *thr)
133 {
134 	nni_plat_mtx_lock(&thr->mtx);
135 	thr->start = 1;
136 	nni_plat_cv_wake(&thr->cv);
137 	nni_plat_mtx_unlock(&thr->mtx);
138 }
139 
140 void
nni_thr_fini(nni_thr * thr)141 nni_thr_fini(nni_thr *thr)
142 {
143 	if (!thr->init) {
144 		return;
145 	}
146 	nni_plat_mtx_lock(&thr->mtx);
147 	thr->stop = 1;
148 	nni_plat_cv_wake(&thr->cv);
149 	while (!thr->done) {
150 		nni_plat_cv_wait(&thr->cv);
151 	}
152 	nni_plat_mtx_unlock(&thr->mtx);
153 	if (thr->fn != NULL) {
154 		nni_plat_thr_fini(&thr->thr);
155 	}
156 
157 	nni_plat_cv_fini(&thr->cv);
158 	nni_plat_mtx_fini(&thr->mtx);
159 	thr->init = 0;
160 }
161 
162 bool
nni_thr_is_self(nni_thr * thr)163 nni_thr_is_self(nni_thr *thr)
164 {
165 	if (!thr->init) {
166 		return (false);
167 	}
168 	return (nni_plat_thr_is_self(&thr->thr));
169 }
170 
171 void
nni_thr_set_name(nni_thr * thr,const char * name)172 nni_thr_set_name(nni_thr *thr, const char *name)
173 {
174 	nni_plat_thr_set_name(thr != NULL ? &thr->thr : NULL, name);
175 }