… | |
… | |
13 | |
13 | |
14 | /* |
14 | /* |
15 | |
15 | |
16 | =head1 NAME |
16 | =head1 NAME |
17 | |
17 | |
18 | perlmulticore.h - the Perl Multicore Specification and Implementation |
18 | perlmulticore.h - implements the Perl Multicore Specification |
19 | |
19 | |
20 | =head1 SYNOPSIS |
20 | =head1 SYNOPSIS |
21 | |
21 | |
22 | #include "perlmultiore.h" |
22 | #include "perlmulticore.h" |
23 | |
23 | |
24 | // in your XS function: |
24 | // in your XS function: |
25 | |
25 | |
26 | perlinterp_release (); |
26 | perlinterp_release (); |
27 | do_the_C_thing (); |
27 | do_the_C_thing (); |
28 | perlinterp_acquire (); |
28 | perlinterp_acquire (); |
|
|
29 | |
|
|
30 | // optional, in BOOT section: |
|
|
31 | |
|
|
32 | perlmulticore_support (); |
29 | |
33 | |
30 | =head1 DESCRIPTION |
34 | =head1 DESCRIPTION |
31 | |
35 | |
32 | This documentation is the abridged version of the full documention at |
36 | This documentation is the abridged version of the full documention at |
33 | L<http://perlmulticore.schmorp.de/>. It's recommended to go there instead |
37 | L<http://perlmulticore.schmorp.de/>. It's recommended to go there instead |
… | |
… | |
118 | |
122 | |
119 | This could be added to perl's C<CPPFLAGS> when configuring perl on |
123 | This could be added to perl's C<CPPFLAGS> when configuring perl on |
120 | platforms that do not support threading at all for example. |
124 | platforms that do not support threading at all for example. |
121 | |
125 | |
122 | |
126 | |
|
|
127 | =head1 ADVERTISING MULTICORE API SUPPORT |
|
|
128 | |
|
|
129 | To help users find out whether a particular build of your module is, in |
|
|
130 | fact, multicore enabled, you can invoke the C<perlmulticore_support> |
|
|
131 | macro in your C<BOOT:> section, e.g.: |
|
|
132 | |
|
|
133 | |
|
|
134 | MODULE = My::Mod PACKAGE = My::Mod::Pkg |
|
|
135 | |
|
|
136 | BOOT: |
|
|
137 | perlmulticore_support (); |
|
|
138 | |
|
|
139 | What this does is set the C<$My::Mod::PERLMULTICORE_SUPPORT> variable to |
|
|
140 | the major API version * 1000 + minor version, for example, version C<1002> |
|
|
141 | introduced this feature. |
|
|
142 | |
|
|
143 | For this to work, the C<cv> parameter passed to C<BOOT:> must still be |
|
|
144 | in scope. To ensure this, either invoke the macro early in your C<BOOT:> |
|
|
145 | section, or don't declare a local variable called C<cv>, either of which |
|
|
146 | should be easy to do. |
|
|
147 | |
|
|
148 | Note that this is I<optional>, so you don't have to do that. |
|
|
149 | |
|
|
150 | |
123 | =head1 AUTHOR |
151 | =head1 AUTHOR |
124 | |
152 | |
125 | Marc A. Lehmann <perlmulticore@schmorp.de> |
153 | Marc A. Lehmann <perlmulticore@schmorp.de> |
126 | http://perlmulticore.schmorp.de/ |
154 | http://perlmulticore.schmorp.de/ |
127 | |
155 | |
… | |
… | |
135 | =cut |
163 | =cut |
136 | |
164 | |
137 | */ |
165 | */ |
138 | |
166 | |
139 | #define PERL_MULTICORE_MAJOR 1 /* bumped on incompatible changes */ |
167 | #define PERL_MULTICORE_MAJOR 1 /* bumped on incompatible changes */ |
140 | #define PERL_MULTICORE_MINOR 0 /* bumped on every change */ |
168 | #define PERL_MULTICORE_MINOR 2 /* bumped on every change */ |
141 | |
169 | |
142 | #if PERL_MULTICORE_DISABLE |
170 | #if PERL_MULTICORE_DISABLE |
143 | |
171 | |
144 | #define perlinterp_release() do { } while (0) |
172 | #define perlinterp_release() do { } while (0) |
145 | #define perlinterp_acquire() do { } while (0) |
173 | #define perlinterp_acquire() do { } while (0) |
|
|
174 | #define perlmulticore_support() do { } while (0) |
146 | |
175 | |
147 | #else |
176 | #else |
|
|
177 | |
|
|
178 | START_EXTERN_C |
148 | |
179 | |
149 | /* this struct is shared between all modules, and currently */ |
180 | /* this struct is shared between all modules, and currently */ |
150 | /* contain only the two function pointers for release/acquire */ |
181 | /* contain only the two function pointers for release/acquire */ |
151 | struct perl_multicore_api |
182 | struct perl_multicore_api |
152 | { |
183 | { |
… | |
… | |
154 | void (*pmapi_acquire)(void); |
185 | void (*pmapi_acquire)(void); |
155 | }; |
186 | }; |
156 | |
187 | |
157 | static void perl_multicore_init (void); |
188 | static void perl_multicore_init (void); |
158 | |
189 | |
159 | const struct perl_multicore_api perl_multicore_api_init = { perl_multicore_init, 0 }; |
190 | static const struct perl_multicore_api perl_multicore_api_init |
|
|
191 | = { perl_multicore_init, 0 }; |
160 | |
192 | |
161 | static struct perl_multicore_api *perl_multicore_api |
193 | static struct perl_multicore_api *perl_multicore_api |
162 | = (struct perl_multicore_api *)&perl_multicore_api_init; |
194 | = (struct perl_multicore_api *)&perl_multicore_api_init; |
163 | |
195 | |
164 | #define perlinterp_release() perl_multicore_api->pmapi_release () |
196 | #define perlinterp_release() perl_multicore_api->pmapi_release () |
… | |
… | |
167 | /* this is the release/acquire implementation used as fallback */ |
199 | /* this is the release/acquire implementation used as fallback */ |
168 | static void |
200 | static void |
169 | perl_multicore_nop (void) |
201 | perl_multicore_nop (void) |
170 | { |
202 | { |
171 | } |
203 | } |
|
|
204 | |
|
|
205 | static const char perl_multicore_api_key[] = "perl_multicore_api"; |
172 | |
206 | |
173 | /* this is the initial implementation of "release" - it initialises */ |
207 | /* this is the initial implementation of "release" - it initialises */ |
174 | /* the api and then calls the real release function */ |
208 | /* the api and then calls the real release function */ |
175 | static void |
209 | static void |
176 | perl_multicore_init (void) |
210 | perl_multicore_init (void) |
177 | { |
211 | { |
178 | dTHX; |
212 | dTHX; |
179 | |
213 | |
180 | /* check for existing API struct in PL_modglobal */ |
214 | /* check for existing API struct in PL_modglobal */ |
181 | SV **api_svp = hv_fetch (PL_modglobal, "perl_multicore_api", sizeof ("perl_multicore_api") - 1, 1); |
215 | SV **api_svp = hv_fetch (PL_modglobal, perl_multicore_api_key, |
|
|
216 | sizeof (perl_multicore_api_key) - 1, 1); |
182 | |
217 | |
183 | if (SvPOKp (*api_svp)) |
218 | if (SvPOKp (*api_svp)) |
184 | perl_multicore_api = (struct perl_multicore_api *)SvPVX (*api_svp); /* we have one, use the existing one */ |
219 | perl_multicore_api = (struct perl_multicore_api *)SvPVX (*api_svp); /* we have one, use the existing one */ |
185 | else |
220 | else |
186 | { |
221 | { |
187 | /* create a new one with a dummy nop implementation */ |
222 | /* create a new one with a dummy nop implementation */ |
|
|
223 | #ifdef NEWSV |
188 | SV *api_sv = NEWSV (0, sizeof (*perl_multicore_api)); |
224 | SV *api_sv = NEWSV (0, sizeof (*perl_multicore_api)); |
|
|
225 | #else |
|
|
226 | SV *api_sv = newSV ( sizeof (*perl_multicore_api)); |
|
|
227 | #endif |
189 | SvCUR_set (api_sv, sizeof (*perl_multicore_api)); |
228 | SvCUR_set (api_sv, sizeof (*perl_multicore_api)); |
190 | SvPOK_only (api_sv); |
229 | SvPOK_only (api_sv); |
191 | perl_multicore_api = (struct perl_multicore_api *)SvPVX (api_sv); |
230 | perl_multicore_api = (struct perl_multicore_api *)SvPVX (api_sv); |
192 | perl_multicore_api->pmapi_release = |
231 | perl_multicore_api->pmapi_release = |
193 | perl_multicore_api->pmapi_acquire = perl_multicore_nop; |
232 | perl_multicore_api->pmapi_acquire = perl_multicore_nop; |
… | |
… | |
196 | |
235 | |
197 | /* call the real (or dummy) implementation now */ |
236 | /* call the real (or dummy) implementation now */ |
198 | perlinterp_release (); |
237 | perlinterp_release (); |
199 | } |
238 | } |
200 | |
239 | |
|
|
240 | #define perlmulticore_support() \ |
|
|
241 | sv_setiv (get_sv ( \ |
|
|
242 | form ("%s::PERLMULTICORE_SUPPORT", HvNAME (GvSTASH (CvGV (cv)))), \ |
|
|
243 | GV_ADD | GV_ADDMULTI), \ |
|
|
244 | PERL_MULTICORE_MAJOR * 1000 + PERL_MULTICORE_MINOR); \ |
|
|
245 | |
|
|
246 | END_EXTERN_C |
|
|
247 | |
201 | #endif |
248 | #endif |
202 | |
249 | |
203 | #endif |
250 | #endif |
|
|
251 | |