… | |
… | |
19 | static pthread_key_t current_key; |
19 | static pthread_key_t current_key; |
20 | |
20 | |
21 | static s_epipe ep; |
21 | static s_epipe ep; |
22 | static void *perl_thx; |
22 | static void *perl_thx; |
23 | static sigset_t cursigset, fullsigset; |
23 | static sigset_t cursigset, fullsigset; |
|
|
24 | |
|
|
25 | static int global_enable = 1; |
|
|
26 | static int thread_enable; /* 0 undefined, 1 disabled, 2 enabled */ |
24 | |
27 | |
25 | struct tctx |
28 | struct tctx |
26 | { |
29 | { |
27 | void *coro; |
30 | void *coro; |
28 | xcond_t wait_c; |
31 | xcond_t wait_c; |
… | |
… | |
122 | } |
125 | } |
123 | |
126 | |
124 | static void |
127 | static void |
125 | pmapi_release (void) |
128 | pmapi_release (void) |
126 | { |
129 | { |
|
|
130 | if (!(thread_enable ? thread_enable & 1 : global_enable)) |
|
|
131 | { |
|
|
132 | pthread_setspecific (current_key, 0); |
|
|
133 | return; |
|
|
134 | } |
|
|
135 | |
127 | struct tctx *ctx = tctx_get (); |
136 | struct tctx *ctx = tctx_get (); |
128 | ctx->coro = SvREFCNT_inc_NN (CORO_CURRENT); |
137 | ctx->coro = SvREFCNT_inc_NN (CORO_CURRENT); |
129 | ctx->wait_f = 0; |
138 | ctx->wait_f = 0; |
130 | |
139 | |
131 | pthread_setspecific (current_key, ctx); |
140 | pthread_setspecific (current_key, ctx); |
… | |
… | |
143 | static void |
152 | static void |
144 | pmapi_acquire (void) |
153 | pmapi_acquire (void) |
145 | { |
154 | { |
146 | struct tctx *ctx = pthread_getspecific (current_key); |
155 | struct tctx *ctx = pthread_getspecific (current_key); |
147 | |
156 | |
|
|
157 | if (!ctx) |
|
|
158 | return; |
|
|
159 | |
148 | X_LOCK (wait_m); |
160 | X_LOCK (wait_m); |
149 | |
161 | |
150 | if (waiters_count >= waiters_max) |
162 | if (waiters_count >= waiters_max) |
151 | { |
163 | { |
152 | waiters_max = waiters_max ? waiters_max * 2 : 16; |
164 | waiters_max = waiters_max ? waiters_max * 2 : 16; |
… | |
… | |
162 | |
174 | |
163 | tctx_put (ctx); |
175 | tctx_put (ctx); |
164 | pthread_sigmask (SIG_SETMASK, &cursigset, 0); |
176 | pthread_sigmask (SIG_SETMASK, &cursigset, 0); |
165 | } |
177 | } |
166 | |
178 | |
|
|
179 | static void |
|
|
180 | set_enable_0 (pTHX) |
|
|
181 | { |
|
|
182 | thread_enable = 0; |
|
|
183 | } |
|
|
184 | |
|
|
185 | static void |
|
|
186 | set_enable_1 (pTHX) |
|
|
187 | { |
|
|
188 | thread_enable = 1; |
|
|
189 | } |
|
|
190 | |
|
|
191 | static void |
|
|
192 | set_enable_2 (pTHX) |
|
|
193 | { |
|
|
194 | thread_enable = 2; |
|
|
195 | } |
|
|
196 | |
167 | MODULE = Coro::Multicore PACKAGE = Coro::Multicore |
197 | MODULE = Coro::Multicore PACKAGE = Coro::Multicore |
168 | |
198 | |
169 | PROTOTYPES: DISABLE |
199 | PROTOTYPES: DISABLE |
170 | |
200 | |
171 | BOOT: |
201 | BOOT: |
… | |
… | |
186 | /* not perfectly efficient to do it this way, but it's simple */ |
216 | /* not perfectly efficient to do it this way, but it's simple */ |
187 | perl_multicore_init (); |
217 | perl_multicore_init (); |
188 | perl_multicore_api->pmapi_release = pmapi_release; |
218 | perl_multicore_api->pmapi_release = pmapi_release; |
189 | perl_multicore_api->pmapi_acquire = pmapi_acquire; |
219 | perl_multicore_api->pmapi_acquire = pmapi_acquire; |
190 | } |
220 | } |
|
|
221 | |
|
|
222 | bool |
|
|
223 | enable (bool enable = NO_INIT) |
|
|
224 | CODE: |
|
|
225 | RETVAL = global_enable; |
|
|
226 | if (items) |
|
|
227 | global_enable = enable; |
|
|
228 | OUTPUT: |
|
|
229 | RETVAL |
|
|
230 | |
|
|
231 | void |
|
|
232 | scoped_enable () |
|
|
233 | CODE: |
|
|
234 | LEAVE; /* see Guard.xs */ |
|
|
235 | CORO_ENTERLEAVE_SCOPE_HOOK (set_enable_1, set_enable_0); |
|
|
236 | ENTER; /* see Guard.xs */ |
|
|
237 | |
|
|
238 | void |
|
|
239 | scoped_disable () |
|
|
240 | CODE: |
|
|
241 | LEAVE; /* see Guard.xs */ |
|
|
242 | CORO_ENTERLEAVE_SCOPE_HOOK (set_enable_2, set_enable_0); |
|
|
243 | ENTER; /* see Guard.xs */ |
191 | |
244 | |
192 | U32 |
245 | U32 |
193 | max_idle_threads (U32 max = NO_INIT) |
246 | max_idle_threads (U32 max = NO_INIT) |
194 | CODE: |
247 | CODE: |
195 | X_LOCK (wait_m); |
248 | X_LOCK (wait_m); |