ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Crypt-Ed25519/perlmulticore.h
Revision: 1.1
Committed: Mon Jun 29 12:31:48 2015 UTC (8 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-1_02, rel-1_03
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*
2     * Author: Marc A. Lehmann <xsthreadpool@schmorp.de>
3     * License: public domain, or where this is not possible/at your option,
4     * CC0 (https://creativecommons.org/publicdomain/zero/1.0/)
5     */
6    
7     #ifndef PERL_MULTICORE_H
8     #define PERL_MULTICORE_H
9    
10     /*
11    
12     =head1 NAME
13    
14     perlmulticore.h - the Perl Multicore Specification and Implementation
15    
16     =head1 SYNOPSIS
17    
18     #include "perlmultiore.h"
19    
20     // in your XS function:
21    
22     perlinterp_release ();
23     do_the_C_thing ();
24     perlinterp_acquire ();
25    
26     =head1 DESCRIPTION
27    
28     This header file implements a simple mechanism for XS modules to allow
29     re-use of the perl interpreter for other threads while doing some lengthy
30     operation, such as cryptography, SQL queries, disk I/O and so on.
31    
32     The design goals for this mechanism were to be simple to use, very
33     efficient when not needed, low code and data size overhead and broad
34     applicability.
35    
36     The newest version of this document can be found at
37     L<http://pod.tst.eu/http://cvs.schmorp.de/Coro-Multicore/perlmulticore.h>.
38    
39     The newest version of the header file itself, which
40     includes this documentation, can be downloaded from
41     L<http://cvs.schmorp.de/Coro-Multicore/perlmulticore.h>.
42    
43     =head1 HOW DO I USE THIS IN MY MODULES?
44    
45     The usage is very simple - you include this header file in your XS module. Then, before you
46     do your lengthy operation, you release the perl interpreter:
47    
48     perlinterp_release ();
49    
50     And when you are done with your computation, you acquire it again:
51    
52     perlinterp_acquire ();
53    
54     And that's it. This doesn't load any modules and consists of only a few
55     machine instructions when no module to take advantage of it is loaded.
56    
57     Here is a simple example, an C<flock> wrapper implemented in XS. Unlike
58     perl's built-in C<flock>, it allows other threads (for example, those
59     provided by L<Coro>) to execute, instead of blocking the whole perl
60     interpreter. For the sake of this example, it requires a file descriptor
61     instead of a handle.
62    
63     #include "perlmulticore.h" // this header file
64    
65     // and in the XS portion
66     int flock (int fd, int operation)
67     CODE:
68     perlinterp_release ();
69     RETVAL = flock (fd, operation);
70     perlinterp_acquire ();
71     OUTPUT:
72     RETVAL
73    
74     Another example would be to modify L<DBD::mysql> to allow other
75     threads to execute while executing SQL queries. One way to do this
76     is find all C<mysql_st_internal_execute> and similar calls (such as
77     C<mysql_st_internal_execute41>), and adorn them with release/acquire
78     calls:
79    
80     {
81     perlinterp_release ();
82     imp_sth->row_num= mysql_st_internal_execute(sth, ...);
83     perlinterp_acquire ();
84     }
85    
86     =head2 HOW ABOUT NOT-SO LONG WORK?
87    
88     Sometimes you don't know how long your code will take - in a compression
89     library for example, compressing a few hundred Kilobyte of data can take
90     a while, while 50 Bytes will compress so fast that even attempting to do
91     something else could be more costly than just doing it.
92    
93     This is a very hard problem to solve. The best you can do at the moment is
94     to release the perl interpreter only when you think the work to be done
95     justifies the expense.
96    
97     As a rule of thumb, if you expect to need more than a few thousand cycles,
98     you should release the interpreter, else you shouldn't. When in doubt,
99     release.
100    
101     For example, in a compression library, you might want to do this:
102    
103     if (bytes_to_be_compressed > 2000) perlinterp_release ();
104     do_compress (...);
105     if (bytes_to_be_compressed > 2000) perlinterp_acquire ();
106    
107     Make sure the if conditions are exactly the same and don't change, so you
108     always call acquire when you release, and vice versa.
109    
110     When you don't have a handy indicator, you might still do something
111     useful. For example, if you do some file locking with C<fcntl> and you
112     expect the lock to be available immediately in most cases, you could try
113     with C<F_SETLK> (which doesn't wait), and only release/wait/acquire when
114     the lock couldn't be set:
115    
116     int res = fcntl (fd, F_SETLK, &flock);
117    
118     if (res)
119     {
120     // error, assume lock is held by another process and do it the slow way
121     perlinterp_release ();
122     res = fcntl (fd, F_SETLKW, &flock);
123     perlinterp_acquire ();
124     }
125    
126     =head1 THE HARD AND FAST RULES
127    
128     As with everything, there are a number of rules to follow.
129    
130     =over 4
131    
132     =item I<Never> touch any perl data structures after calling C<perlinterp_release>.
133    
134     Possibly the most important rule of them all, anything perl is
135     completely off-limits after C<perlinterp_release>, until you call
136     C<perlinterp_acquire>, after which you can access perl stuff again.
137    
138     That includes anything in the perl interpreter that you didn't prove to be
139     safe, and didn't prove to be safe in older and future versions of perl:
140     global variables, local perl scalars, even if you are sure nobody accesses
141     them and you only try to "read" their value, and so on.
142    
143     If you need to access perl things, do it before releasing the
144     interpreter with C<perlinterp_release>, or after acquiring it again with
145     C<perlinterp_acquire>.
146    
147     =item I<Always> call C<perlinterp_release> and C<perlinterp_acquire> in pairs.
148    
149     For each C<perlinterp_release> call there must be a C<perlinterp_acquire>
150     call. They don't have to be in the same function, and you can have
151     multiple calls to them, as long as every C<perlinterp_release> call is
152     followed by exactly one C<perlinterp_acquire> call.
153    
154     For example., this would be fine:
155    
156     perlinterp_release ();
157    
158     if (!function_that_fails_with_0_return_value ())
159     {
160     perlinterp_acquire ();
161     croak ("error");
162     // croak doesn't return
163     }
164    
165     perlinterp_acquire ();
166     // do other stuff
167    
168     =item I<Never> nest calls to C<perlinterp_release> and C<perlinterp_acquire>.
169    
170     That simply means that after calling C<perlinterp_release>, you must
171     call C<perlinterp_acquire> before calling C<perlinterp_release>
172     again. Likewise, after C<perlinterp_acquire>, you can call
173     C<perlinterp_release> but not another C<perlinterp_acquire>.
174    
175     =item I<Always> call C<perlinterp_release> first.
176    
177     Also simple: you I<must not> call C<perlinterp_acquire> without having
178     called C<perlinterp_release> before.
179    
180     =item I<Never> underestimate threads.
181    
182     While it's easy to add parallel execution ability to your XS module, it
183     doesn't mean it is safe. After you release the perl interpreter, it's
184     perfectly possible that it will call your XS function in another thread,
185     even while your original function still executes. In other words: your C
186     code must be thread safe, and if you use any library, that library must be
187     thread-safe, too.
188    
189     Always assume that the code between C<perlinterp_release> and
190     C<perlinterp_acquire> is executed in parallel on multiple CPUs at the same
191     time. If your code can't cope with that, you could consider using a mutex
192     to only allow one such execution, which is still better than blocking
193     everybody else from doing anything:
194    
195     static pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
196    
197     perlinterp_release ();
198     pthread_mutex_lock (&my_mutex);
199     do_your_non_thread_safe_thing ();
200     pthread_mutex_unlock (&my_mutex);
201     perlinterp_acquire ();
202    
203     =item I<Don't> get confused by having to release first.
204    
205     In many real world scenarios, you acquire a resource, do something, then
206     release it again. Don't let this confuse you, with this, you already own
207     the resource (the perl interpreter) so you have to I<release> first, and
208     I<acquire> it again later, not the other way around.
209    
210     =back
211    
212    
213     =head1 DESIGN PRINCIPLES
214    
215     This section discusses how the design goals were reached (you be the
216     judge), how it is implemented, and what overheads this implies.
217    
218     =over 4
219    
220     =item Simple to Use
221    
222     All you have to do is identify the place in your existing code where you
223     stop touching perl stuff, do your actual work, and start touching perl
224     stuff again.
225    
226     Then slap C<perlinterp_release ()> and C<perlinterp_acquire ()> around the
227     actual work code.
228    
229     You have to include F<perlmulticore.h> and distribute it with your XS
230     code, but all these things border on the trivial.
231    
232     =item Very Efficient
233    
234     The definition for C<perlinterp_release> and C<perlinterp_release> is very
235     short:
236    
237     #define perlinterp_release() perl_multicore_api->pmapi_release ()
238     #define perlinterp_acquire() perl_multicore_api->pmapi_acquire ()
239    
240     Both are macros that read a pointer from memory (perl_multicore_api),
241     dereference a function pointer stored at that place, and call the
242     function, which takes no arguments and returns nothing.
243    
244     The first call to C<perlinterp_release> will check for the presence
245     of any supporting module, and if none is loaded, will create a dummy
246     implementation where both C<pmapi_release> and C<pmapi_acquire> execute
247     this function:
248    
249     static void perl_multicore_nop (void) { }
250    
251     So in the case of no magical module being loaded, all calls except the
252     first are two memory accesses and a predictable function call of an empty
253     function.
254    
255     Of course, the overhead is much higher when these functions actually
256     implement anything useful, but you always get what you pay for.
257    
258     With L<Coro::Multicore>, every release/acquire involves two pthread
259     switches, two coro thread switches, a bunch of syscalls, and sometimes
260     interacting with the event loop.
261    
262     A dedicated thread pool such as the one L<IO::AIO> uses could reduce
263     these overheads, and would also reduce the dependencies (L<AnyEvent> is a
264     smaller and more portable dependency than L<Coro>), but it would require a
265     lot more work on the side of the module author wanting to support it than
266     this solution.
267    
268     =item Low Code and Data Size Overhead
269    
270     On a 64 bit system, F<perlmulticore.h> uses exactly C<8> octets (one
271     pointer) of your data segment, to store the C<perl_multicore_api>
272     pointer. In addition it creates a C<16> octet perl string to store the
273     function pointers in, and stores it in a hash provided by perl for this
274     purpose.
275    
276     This is pretty much the equivalent of executing this code:
277    
278     $existing_hash{perl_multicore_api} = "123456781234567812345678";
279    
280     And that's it, which is, as I think, indeed very little.
281    
282     As for code size, on my amd64 system, every call to C<perlinterp_release>
283     or C<perlinterp_acquire> results in a variation of the following 9-10
284     octet sequence:
285    
286     150> mov 0x200f23(%rip),%rax # <perl_multicore_api>
287     157> callq *0x8(%rax)
288    
289     The biggest part if the initialisation code, which consists of 11 lines of
290     typical XS code. On my system, all the code in F<perlmulticore.h> compiles
291     to less than 160 octets of read-only data.
292    
293     =item Broad Applicability
294    
295     While there are alternative ways to achieve the goal of parallel execution
296     with threads that might be more efficient, this mechanism was chosen
297     because it is very simple to retrofit existing modules with it, and it
298    
299     The design goals for this mechanism were to be simple to use, very
300     efficient when not needed, low code and data size overhead and broad
301     applicability.
302    
303     =back
304    
305    
306     =head1 DISABLING PERL MULTICORE AT COMPILE TIME
307    
308     You can disable the complete perl multicore API by defining the
309     symbol C<PERL_MULTICORE_DISABLE> to C<1> (e.g. by specifying
310     F<-DPERL_MULTICORE_DISABLE> as compiler argument).
311    
312     This will leave no traces of the API in the compiled code, suitable
313     "empty" C<perl_release> and C<perl_acquire> definitions will be provided.
314    
315     This could be added to perl's C<CPPFLAGS> when configuring perl on
316     platforms that do not support threading at all for example.
317    
318    
319     =head1 AUTHOR
320    
321     Marc A. Lehmann <perlmulticore@schmorp.de>
322     http://perlmulticore.schmorp.de/
323    
324     =head1 LICENSE
325    
326     The F<perlmulticore.h> header file is put into the public
327     domain. Where this is legally not possible, or at your
328     option, it can be licensed under creativecommons CC0
329     license: L<https://creativecommons.org/publicdomain/zero/1.0/>.
330    
331     =cut
332    
333     */
334    
335     #define PERL_MULTICORE_MAJOR 1 /* bumped on incompatible changes */
336     #define PERL_MULTICORE_MINOR 0 /* bumped on every change */
337    
338     #if PERL_MULTICORE_DISABLE
339    
340     #define perlinterp_release() do { } while (0)
341     #define perlinterp_acquire() do { } while (0)
342    
343     #else
344    
345     /* this struct is shared between all modules, and currently */
346     /* contain only the two function pointers for release/acquire */
347     struct perl_multicore_api
348     {
349     void (*pmapi_release)(void);
350     void (*pmapi_acquire)(void);
351     };
352    
353     static void perl_multicore_init (void);
354    
355     const struct perl_multicore_api perl_multicore_api_init = { perl_multicore_init, abort };
356    
357     static struct perl_multicore_api *perl_multicore_api
358     = (struct perl_multicore_api *)&perl_multicore_api_init;
359    
360     #define perlinterp_release() perl_multicore_api->pmapi_release ()
361     #define perlinterp_acquire() perl_multicore_api->pmapi_acquire ()
362    
363     /* this is the release/acquire implementation used as fallback */
364     static void
365     perl_multicore_nop (void)
366     {
367     }
368    
369     /* this is the initial implementation of "release" - it initialises */
370     /* the api and then calls the real release function */
371     static void
372     perl_multicore_init (void)
373     {
374     dTHX;
375    
376     /* check for existing API struct in PL_modglobal */
377     SV **api_svp = hv_fetch (PL_modglobal, "perl_multicore_api", sizeof ("perl_multicore_api") - 1, 1);
378    
379     if (SvPOKp (*api_svp))
380     perl_multicore_api = (struct perl_multicore_api *)SvPVX (*api_svp); /* we have one, use the existing one */
381     else
382     {
383     /* create a new one with a dummy nop implementation */
384     SV *api_sv = NEWSV (0, sizeof (*perl_multicore_api));
385     SvCUR_set (api_sv, sizeof (*perl_multicore_api));
386     SvPOK_only (api_sv);
387     perl_multicore_api = (struct perl_multicore_api *)SvPVX (api_sv);
388     perl_multicore_api->pmapi_release =
389     perl_multicore_api->pmapi_acquire = perl_multicore_nop;
390     *api_svp = api_sv;
391     }
392    
393     /* call the real (or dummy) implementation now */
394     perlinterp_release ();
395     }
396    
397     #endif
398    
399     #endif