]> code.delx.au - gnu-emacs/blob - src/module.c
Rename emacs_module.h to module.h
[gnu-emacs] / src / module.c
1 /* module.c - Module loading and runtime implementation
2
3 Copyright (C) 2015 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include <stdbool.h>
21 #include <stddef.h>
22 #include <stdint.h>
23 #include <stdio.h>
24
25 #include <config.h>
26 #include "lisp.h"
27 #include "module.h"
28 #include "dynlib.h"
29 #include "coding.h"
30 #include "verify.h"
31
32 \f
33 /* Feature tests */
34
35 enum {
36 /* 1 if we have __attribute__((cleanup(...))), 0 otherwise */
37 module_has_cleanup =
38 #ifdef HAVE_VAR_ATTRIBUTE_CLEANUP
39 1
40 #else
41 0
42 #endif
43 };
44
45 /* Handle to the main thread. Used to verify that modules call us in
46 the right thread. */
47 #if defined(HAVE_THREADS_H)
48 #include <threads.h>
49 static thrd_t main_thread;
50 #elif defined(HAVE_PTHREAD)
51 #include <pthread.h>
52 static pthread_t main_thread;
53 #elif defined(WINDOWSNT)
54 #include <windows.h>
55 /* On Windows, we store both a handle to the main thread and the
56 thread ID because the latter can be reused when a thread
57 terminates. */
58 static HANDLE main_thread;
59 static DWORD main_thread_id;
60 #endif
61
62 \f
63 /* Implementation of runtime and environment functions */
64
65 static emacs_env* module_get_environment (struct emacs_runtime *ert);
66
67 static emacs_value module_make_global_ref (emacs_env *env,
68 emacs_value ref);
69 static void module_free_global_ref (emacs_env *env,
70 emacs_value ref);
71 static enum emacs_funcall_exit module_non_local_exit_check (emacs_env *env);
72 static void module_non_local_exit_clear (emacs_env *env);
73 static enum emacs_funcall_exit module_non_local_exit_get (emacs_env *env, emacs_value *sym, emacs_value *data);
74 static void module_non_local_exit_signal (emacs_env *env, emacs_value sym, emacs_value data);
75 static void module_non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value);
76 static emacs_value module_make_function (emacs_env *env,
77 int min_arity,
78 int max_arity,
79 emacs_subr subr,
80 const char *documentation,
81 void *data);
82 static emacs_value module_funcall (emacs_env *env,
83 emacs_value fun,
84 int nargs,
85 emacs_value args[]);
86 static emacs_value module_intern (emacs_env *env, const char *name);
87 static emacs_value module_type_of (emacs_env *env, emacs_value value);
88 static bool module_is_not_nil (emacs_env *env, emacs_value value);
89 static bool module_eq (emacs_env *env, emacs_value a, emacs_value b);
90 static int64_t module_extract_integer (emacs_env *env, emacs_value n);
91 static emacs_value module_make_integer (emacs_env *env, int64_t n);
92 static emacs_value module_make_float (emacs_env *env, double d);
93 static double module_extract_float (emacs_env *env, emacs_value f);
94 static bool module_copy_string_contents (emacs_env *env,
95 emacs_value value,
96 char *buffer,
97 size_t* length);
98 static emacs_value module_make_string (emacs_env *env, const char *str, size_t lenght);
99 static emacs_value module_make_user_ptr (emacs_env *env,
100 emacs_finalizer_function fin,
101 void *ptr);
102 static void* module_get_user_ptr (emacs_env *env, emacs_value uptr);
103 static void module_set_user_ptr (emacs_env *env, emacs_value uptr, void *ptr);
104 static emacs_finalizer_function module_get_user_finalizer (emacs_env *env, emacs_value uptr);
105 static void module_set_user_finalizer (emacs_env *env,
106 emacs_value uptr,
107 emacs_finalizer_function fin);
108
109 \f
110 /* Helper functions */
111
112 /* If checking is enabled, abort if the current thread is not the
113 Emacs main thread. */
114 static void check_main_thread (void);
115
116 /* Internal versions of `module_non_local_exit_signal' and `module_non_local_exit_throw'. */
117 static void module_non_local_exit_signal_1 (emacs_env *env, Lisp_Object sym, Lisp_Object data);
118 static void module_non_local_exit_throw_1 (emacs_env *env, Lisp_Object tag, Lisp_Object value);
119
120 /* Module version of `wrong_type_argument'. */
121 static void module_wrong_type (emacs_env *env, Lisp_Object predicate, Lisp_Object value);
122
123 /* Signal an out-of-memory condition to the caller. */
124 static void module_out_of_memory (emacs_env *env);
125
126 /* Signal arguments are out of range. */
127 static void module_args_out_of_range (emacs_env *env, Lisp_Object a1, Lisp_Object a2);
128
129 \f
130 /* Value conversion */
131
132 /* Converts an `emacs_value' to the corresponding internal object.
133 Never fails. */
134 static Lisp_Object value_to_lisp (emacs_value v);
135
136 /* Converts an internal object to an `emacs_value'. Allocates storage
137 from the environment; returns NULL if allocation fails. */
138 static emacs_value lisp_to_value (emacs_env *env, Lisp_Object o);
139
140 \f
141 /* Memory management */
142
143 /* An `emacs_value' is just a pointer to a structure holding an
144 internal Lisp object. */
145 struct emacs_value_tag { Lisp_Object v; };
146
147 /* Local value objects use a simple fixed-sized block allocation
148 scheme without explicit deallocation. All local values are
149 deallocated when the lifetime of their environment ends. We keep
150 track of a current frame from which new values are allocated,
151 appending further dynamically-allocated frames if necessary. */
152
153 enum { value_frame_size = 512 };
154
155 /* A block from which `emacs_value' object can be allocated. */
156 struct emacs_value_frame {
157 /* Storage for values */
158 struct emacs_value_tag objects[value_frame_size];
159
160 /* Index of the next free value in `objects' */
161 size_t offset;
162
163 /* Pointer to next frame, if any */
164 struct emacs_value_frame *next;
165 };
166
167 /* Must be called for each frame before it can be used for
168 allocation. */
169 static void initialize_frame (struct emacs_value_frame *frame);
170
171 /* A structure that holds an initial frame (so that the first local
172 values require no dynamic allocation) and keeps track of the
173 current frame. */
174 static struct emacs_value_storage {
175 struct emacs_value_frame initial;
176 struct emacs_value_frame *current;
177 } global_storage;
178
179 /* Must be called for any storage object before it can be used for
180 allocation. */
181 static void initialize_storage (struct emacs_value_storage *storage);
182
183 /* Must be called for any initialized storage object before its
184 lifetime ends. Frees all dynamically-allocated frames. */
185 static void finalize_storage (struct emacs_value_storage *storage);
186
187 /* Allocates a new value from STORAGE and stores OBJ in it. Returns
188 NULL if allocations fails and uses ENV for non local exit reporting. */
189 static emacs_value allocate_emacs_value (emacs_env *env, struct emacs_value_storage *storage,
190 Lisp_Object obj);
191
192 \f
193 /* Private runtime and environment members */
194
195 /* The private part of an environment stores the current non local exit state
196 and holds the `emacs_value' objects allocated during the lifetime
197 of the environment. */
198 struct emacs_env_private {
199 enum emacs_funcall_exit pending_non_local_exit;
200
201 /* Dedicated storage for non-local exit symbol and data so that we always
202 have storage available for them, even in an out-of-memory
203 situation. */
204 struct emacs_value_tag non_local_exit_symbol, non_local_exit_data;
205
206 struct emacs_value_storage storage;
207 };
208
209 /* Combines public and private parts in one structure. This structure
210 is used whenever an environment is created. */
211 struct env_storage {
212 emacs_env pub;
213 struct emacs_env_private priv;
214 };
215
216 /* Must be called before the environment can be used. */
217 static void initialize_environment (struct env_storage *env);
218
219 /* Must be called before the lifetime of the environment object
220 ends. */
221 static void finalize_environment (struct env_storage *env);
222
223 /* The private parts of an `emacs_runtime' object contain the initial
224 environment. */
225 struct emacs_runtime_private {
226 struct env_storage environment;
227 };
228
229 \f
230 /* Convenience macros for non-local exit handling */
231
232 /* Emacs uses setjmp(3) and longjmp(3) for non-local exits, but we
233 can't allow module frames to be skipped because they are in general
234 not prepared for long jumps (e.g. the behavior in C++ is undefined
235 if objects with nontrivial destructors would be skipped).
236 Therefore we catch all non-local exits. There are two kinds of
237 non-local exits: `signal' and `throw'. The macros in this section
238 can be used to catch both. We use macros so that we don't have to
239 write lots of additional variants of `internal_condition_case'
240 etc. and don't have to worry about passing information to the
241 handler functions. */
242
243 /* Called on `signal'. ERR will be a cons cell (SYMBOL . DATA), which
244 gets stored in the environment. Sets the pending non-local exit flag. */
245 static void module_handle_signal (emacs_env *env, Lisp_Object err);
246
247 /* Called on `throw'. TAG_VAL will be a cons cell (TAG . VALUE),
248 which gets stored in the environment. Sets the pending non-local exit
249 flag. */
250 static void module_handle_throw (emacs_env *env, Lisp_Object tag_val);
251
252 /* Must be called after setting up a handler immediately before
253 returning from the function. See the comments in lisp.h and the
254 code in eval.c for details. The macros below arrange for this
255 function to be called automatically. DUMMY is ignored. */
256 static void module_reset_handlerlist (const int *dummy);
257
258 /* Place this macro at the beginning of a function returning a number
259 or a pointer to handle signals. The function must have an ENV
260 parameter. The function will return 0 (or NULL) if a signal is
261 caught. */
262 #define MODULE_HANDLE_SIGNALS MODULE_HANDLE_SIGNALS_RETURN(0)
263
264 /* Place this macro at the beginning of a function returning void to
265 handle signals. The function must have an ENV parameter. */
266 #define MODULE_HANDLE_SIGNALS_VOID MODULE_HANDLE_SIGNALS_RETURN()
267
268 #define MODULE_HANDLE_SIGNALS_RETURN(retval) \
269 MODULE_SETJMP(CONDITION_CASE, module_handle_signal, retval)
270
271 /* Place this macro at the beginning of a function returning a pointer
272 to handle non-local exits via `throw'. The function must have an
273 ENV parameter. The function will return NULL if a `throw' is
274 caught. */
275 #define MODULE_HANDLE_THROW \
276 MODULE_SETJMP(CATCHER_ALL, module_handle_throw, NULL)
277
278 #define MODULE_SETJMP(handlertype, handlerfunc, retval) \
279 MODULE_SETJMP_1(handlertype, handlerfunc, retval, \
280 internal_handler_##handlertype, \
281 internal_cleanup_##handlertype)
282
283 #define MODULE_SETJMP_1(handlertype, handlerfunc, retval, c, dummy) \
284 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return); \
285 struct handler *c; \
286 /* It is very important that pushing the handler doesn't itself raise a \
287 signal. */ \
288 if (!push_handler_nosignal(&c, Qt, handlertype)) { \
289 module_out_of_memory(env); \
290 return retval; \
291 } \
292 verify(module_has_cleanup); \
293 /* We can install the cleanup only after the handler has been pushed. Use \
294 __attribute__((cleanup)) to avoid non-local-exit-prone manual cleanup. */ \
295 const int dummy __attribute__((cleanup(module_reset_handlerlist))); \
296 if (sys_setjmp(c->jmp)) { \
297 (handlerfunc)(env, c->val); \
298 return retval; \
299 } \
300 /* Force the macro to be followed by a semicolon. */ \
301 do { \
302 } while (0)
303
304 \f
305 /* Function environments */
306
307 /* A function environment is an auxiliary structure used by
308 `module_make_function' to store information about a module
309 function. It is stored in a save pointer and retrieved by
310 `module-call'. Its members correspond to the arguments given to
311 `module_make_function'. */
312
313 struct module_fun_env
314 {
315 int min_arity, max_arity;
316 emacs_subr subr;
317 void *data;
318 };
319
320 /* Returns a string object that contains a user-friendly
321 representation of the function environment. */
322 static Lisp_Object module_format_fun_env (const struct module_fun_env *env);
323
324 /* Holds the function definition of `module-call'. `module-call' is
325 uninterned because user code couldn't meaningfully use it, so we
326 have to keep its definition around somewhere else. */
327 static Lisp_Object module_call_func;
328
329 \f
330 /* Implementation of runtime and environment functions */
331
332 /* We catch signals and throws only if the code can actually signal or
333 throw. */
334
335 static emacs_env* module_get_environment (struct emacs_runtime *ert)
336 {
337 check_main_thread ();
338 return &ert->private_members->environment.pub;
339 }
340
341 /*
342 * To make global refs (GC-protected global values) we keep a hash
343 * that maps global Lisp objects to reference counts.
344 */
345
346 static emacs_value module_make_global_ref (emacs_env *env,
347 emacs_value ref)
348 {
349 check_main_thread ();
350 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
351 MODULE_HANDLE_SIGNALS;
352 eassert (HASH_TABLE_P (Vmodule_refs_hash));
353 struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
354 Lisp_Object new_obj = value_to_lisp (ref);
355 EMACS_UINT hashcode;
356 ptrdiff_t i = hash_lookup (h, new_obj, &hashcode);
357
358 if (i >= 0)
359 {
360 Lisp_Object value = HASH_VALUE (h, i);
361 eassert (NATNUMP (value));
362 const EMACS_UINT refcount = XFASTINT (value);
363 if (refcount >= MOST_POSITIVE_FIXNUM)
364 {
365 module_non_local_exit_signal_1 (env, Qoverflow_error, Qnil);
366 return NULL;
367 }
368 XSETFASTINT (value, refcount + 1);
369 set_hash_value_slot (h, i, value);
370 }
371 else
372 {
373 hash_put (h, new_obj, make_natnum (1), hashcode);
374 }
375
376 return allocate_emacs_value (env, &global_storage, new_obj);
377 }
378
379 static void module_free_global_ref (emacs_env *env,
380 emacs_value ref)
381 {
382 check_main_thread ();
383 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
384 /* TODO: This probably never signals. */
385 MODULE_HANDLE_SIGNALS_VOID;
386 eassert (HASH_TABLE_P (Vmodule_refs_hash));
387 struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
388 Lisp_Object obj = value_to_lisp (ref);
389 EMACS_UINT hashcode;
390 ptrdiff_t i = hash_lookup (h, obj, &hashcode);
391
392 if (i >= 0)
393 {
394 Lisp_Object value = HASH_VALUE (h, i);
395 eassert (NATNUMP (value));
396 const EMACS_UINT refcount = XFASTINT (value);
397 eassert (refcount > 0);
398 if (refcount > 1)
399 {
400 XSETFASTINT (value, refcount - 1);
401 set_hash_value_slot (h, i, value);
402 }
403 else
404 {
405 hash_remove_from_table (h, value);
406 }
407 }
408 }
409
410 static enum emacs_funcall_exit module_non_local_exit_check (emacs_env *env)
411 {
412 check_main_thread ();
413 return env->private_members->pending_non_local_exit;
414 }
415
416 static void module_non_local_exit_clear (emacs_env *env)
417 {
418 check_main_thread ();
419 env->private_members->pending_non_local_exit = emacs_funcall_exit_return;
420 }
421
422 static enum emacs_funcall_exit module_non_local_exit_get (emacs_env *env, emacs_value *sym, emacs_value *data)
423 {
424 check_main_thread ();
425 struct emacs_env_private *const p = env->private_members;
426 if (p->pending_non_local_exit != emacs_funcall_exit_return)
427 {
428 *sym = &p->non_local_exit_symbol;
429 *data = &p->non_local_exit_data;
430 }
431 return p->pending_non_local_exit;
432 }
433
434 /*
435 * Like for `signal', DATA must be a list
436 */
437 static void module_non_local_exit_signal (emacs_env *env, emacs_value sym, emacs_value data)
438 {
439 check_main_thread ();
440 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
441 module_non_local_exit_signal_1 (env, value_to_lisp (sym), value_to_lisp (data));
442 }
443
444 static void module_non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value)
445 {
446 check_main_thread ();
447 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
448 module_non_local_exit_throw_1 (env, value_to_lisp (tag), value_to_lisp (value));
449 }
450
451 /*
452 * A module function is lambda function that calls `module-call',
453 * passing the function pointer of the module function along with the
454 * module emacs_env pointer as arguments.
455 *
456 * (function
457 * (lambda
458 * (&rest arglist)
459 * (module-call
460 * envobj
461 * arglist)))
462 *
463 */
464 static emacs_value module_make_function (emacs_env *env,
465 int min_arity,
466 int max_arity,
467 emacs_subr subr,
468 const char *const documentation,
469 void *data)
470 {
471 check_main_thread ();
472 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
473 MODULE_HANDLE_SIGNALS;
474
475 if (min_arity > MOST_POSITIVE_FIXNUM || max_arity > MOST_POSITIVE_FIXNUM)
476 xsignal0 (Qoverflow_error);
477
478 if (min_arity < 0 ||
479 (max_arity >= 0 && max_arity < min_arity) ||
480 (max_arity < 0 && max_arity != emacs_variadic_function))
481 xsignal2 (Qinvalid_arity, make_number (min_arity), make_number (max_arity));
482
483 Lisp_Object envobj;
484
485 /* XXX: This should need to be freed when envobj is GC'd */
486 struct module_fun_env *envptr = xzalloc (sizeof (*envptr));
487 envptr->min_arity = min_arity;
488 envptr->max_arity = max_arity;
489 envptr->subr = subr;
490 envptr->data = data;
491 envobj = make_save_ptr (envptr);
492
493 Lisp_Object ret = list4 (Qlambda,
494 list2 (Qand_rest, Qargs),
495 documentation ? build_string (documentation) : Qnil,
496 list3 (module_call_func,
497 envobj,
498 Qargs));
499
500 return lisp_to_value (env, ret);
501 }
502
503 static emacs_value module_funcall (emacs_env *env,
504 emacs_value fun,
505 int nargs,
506 emacs_value args[])
507 {
508 check_main_thread ();
509 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
510 MODULE_HANDLE_SIGNALS;
511 MODULE_HANDLE_THROW;
512
513 /*
514 * Make a new Lisp_Object array starting with the function as the
515 * first arg, because that's what Ffuncall takes
516 */
517 Lisp_Object newargs[nargs + 1];
518 newargs[0] = value_to_lisp (fun);
519 for (int i = 0; i < nargs; i++)
520 newargs[1 + i] = value_to_lisp (args[i]);
521 return lisp_to_value (env, Ffuncall (nargs + 1, newargs));
522 }
523
524 static emacs_value module_intern (emacs_env *env, const char *name)
525 {
526 check_main_thread ();
527 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
528 MODULE_HANDLE_SIGNALS;
529 return lisp_to_value (env, intern (name));
530 }
531
532 static emacs_value module_type_of (emacs_env *env, emacs_value value)
533 {
534 check_main_thread ();
535 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
536 return lisp_to_value (env, Ftype_of (value_to_lisp (value)));
537 }
538
539 static bool module_is_not_nil (emacs_env *env, emacs_value value)
540 {
541 check_main_thread ();
542 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
543 return ! NILP (value_to_lisp (value));
544 }
545
546 static bool module_eq (emacs_env *env, emacs_value a, emacs_value b)
547 {
548 check_main_thread ();
549 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
550 return EQ (value_to_lisp (a), value_to_lisp (b));
551 }
552
553 static int64_t module_extract_integer (emacs_env *env, emacs_value n)
554 {
555 verify (INT64_MIN <= MOST_NEGATIVE_FIXNUM);
556 verify (INT64_MAX >= MOST_POSITIVE_FIXNUM);
557 check_main_thread ();
558 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
559 const Lisp_Object l = value_to_lisp (n);
560 if (! INTEGERP (l))
561 {
562 module_wrong_type (env, Qintegerp, l);
563 return 0;
564 }
565 return XINT (l);
566 }
567
568 static emacs_value module_make_integer (emacs_env *env, int64_t n)
569 {
570 check_main_thread ();
571 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
572 if (n < MOST_NEGATIVE_FIXNUM)
573 {
574 module_non_local_exit_signal_1 (env, Qunderflow_error, Qnil);
575 return NULL;
576 }
577 if (n > MOST_POSITIVE_FIXNUM)
578 {
579 module_non_local_exit_signal_1 (env, Qoverflow_error, Qnil);
580 return NULL;
581 }
582 return lisp_to_value (env, make_number (n));
583 }
584
585 static double module_extract_float (emacs_env *env, emacs_value f)
586 {
587 check_main_thread ();
588 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
589 const Lisp_Object lisp = value_to_lisp (f);
590 if (! FLOATP (lisp))
591 {
592 module_wrong_type (env, Qfloatp, lisp);
593 return 0;
594 }
595 return XFLOAT_DATA (lisp);
596 }
597
598 static emacs_value module_make_float (emacs_env *env, double d)
599 {
600 check_main_thread ();
601 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
602 MODULE_HANDLE_SIGNALS;
603 return lisp_to_value (env, make_float (d));
604 }
605
606 static bool module_copy_string_contents (emacs_env *env,
607 emacs_value value,
608 char *buffer,
609 size_t* length)
610 {
611 check_main_thread ();
612 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
613 MODULE_HANDLE_SIGNALS;
614 Lisp_Object lisp_str = value_to_lisp (value);
615 if (! STRINGP (lisp_str))
616 {
617 module_wrong_type (env, Qstringp, lisp_str);
618 return false;
619 }
620
621 size_t raw_size = SBYTES (lisp_str);
622
623 /*
624 * Emacs internal encoding is more-or-less UTF8, let's assume utf8
625 * encoded emacs string are the same byte size.
626 */
627
628 if (!buffer || length == 0 || *length-1 < raw_size)
629 {
630 *length = raw_size + 1;
631 return false;
632 }
633
634 Lisp_Object lisp_str_utf8 = ENCODE_UTF_8 (lisp_str);
635 eassert (raw_size == SBYTES (lisp_str_utf8));
636 *length = raw_size + 1;
637 memcpy (buffer, SDATA (lisp_str_utf8), SBYTES (lisp_str_utf8));
638 buffer[raw_size] = 0;
639
640 return true;
641 }
642
643 static emacs_value module_make_string (emacs_env *env, const char *str, size_t length)
644 {
645 check_main_thread ();
646 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
647 MODULE_HANDLE_SIGNALS;
648 if (length > PTRDIFF_MAX)
649 {
650 module_non_local_exit_signal_1 (env, Qoverflow_error, Qnil);
651 return NULL;
652 }
653 /* Assume STR is utf8 encoded */
654 return lisp_to_value (env, make_string (str, length));
655 }
656
657 static emacs_value module_make_user_ptr (emacs_env *env,
658 emacs_finalizer_function fin,
659 void *ptr)
660 {
661 check_main_thread ();
662 return lisp_to_value (env, make_user_ptr (fin, ptr));
663 }
664
665 static void* module_get_user_ptr (emacs_env *env, emacs_value uptr)
666 {
667 check_main_thread ();
668 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
669 const Lisp_Object lisp = value_to_lisp (uptr);
670 if (! USER_PTRP (lisp))
671 {
672 module_wrong_type (env, Quser_ptr, lisp);
673 return NULL;
674 }
675 return XUSER_PTR (lisp)->p;
676 }
677
678 static void module_set_user_ptr (emacs_env *env, emacs_value uptr, void *ptr)
679 {
680 check_main_thread ();
681 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
682 const Lisp_Object lisp = value_to_lisp (uptr);
683 if (! USER_PTRP (lisp)) module_wrong_type (env, Quser_ptr, lisp);
684 XUSER_PTR (lisp)->p = ptr;
685 }
686
687 static emacs_finalizer_function module_get_user_finalizer (emacs_env *env, emacs_value uptr)
688 {
689 check_main_thread ();
690 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
691 const Lisp_Object lisp = value_to_lisp (uptr);
692 if (! USER_PTRP (lisp))
693 {
694 module_wrong_type (env, Quser_ptr, lisp);
695 return NULL;
696 }
697 return XUSER_PTR (lisp)->finalizer;
698 }
699
700 static void module_set_user_finalizer (emacs_env *env,
701 emacs_value uptr,
702 emacs_finalizer_function fin)
703 {
704 check_main_thread ();
705 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
706 const Lisp_Object lisp = value_to_lisp (uptr);
707 if (! USER_PTRP (lisp)) module_wrong_type (env, Quser_ptr, lisp);
708 XUSER_PTR (lisp)->finalizer = fin;
709 }
710
711 static void module_vec_set (emacs_env *env,
712 emacs_value vec,
713 size_t i,
714 emacs_value val)
715 {
716 check_main_thread ();
717 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
718 if (i > MOST_POSITIVE_FIXNUM)
719 {
720 module_non_local_exit_signal_1 (env, Qoverflow_error, Qnil);
721 return;
722 }
723 Lisp_Object lvec = value_to_lisp (vec);
724 if (! VECTORP (lvec))
725 {
726 module_wrong_type (env, Qvectorp, lvec);
727 return;
728 }
729 if (i >= ASIZE (lvec))
730 {
731 module_args_out_of_range (env, lvec, make_number (i));
732 return;
733 }
734 ASET (lvec, i, value_to_lisp (val));
735 }
736
737 static emacs_value module_vec_get (emacs_env *env,
738 emacs_value vec,
739 size_t i)
740 {
741 /* Type of ASIZE (lvec) is ptrdiff_t, make sure it fits */
742 verify (PTRDIFF_MAX <= SIZE_MAX);
743 check_main_thread ();
744 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
745 if (i > MOST_POSITIVE_FIXNUM)
746 {
747 module_non_local_exit_signal_1 (env, Qoverflow_error, Qnil);
748 return NULL;
749 }
750 Lisp_Object lvec = value_to_lisp (vec);
751 if (! VECTORP (lvec))
752 {
753 module_wrong_type (env, Qvectorp, lvec);
754 return NULL;
755 }
756 /* Prevent error-prone comparison between types of different signedness. */
757 const size_t size = ASIZE (lvec);
758 eassert (size >= 0);
759 if (i >= size)
760 {
761 if (i > MOST_POSITIVE_FIXNUM)
762 i = (size_t) MOST_POSITIVE_FIXNUM;
763 module_args_out_of_range (env, lvec, make_number (i));
764 return NULL;
765 }
766 return lisp_to_value (env, AREF (lvec, i));
767 }
768
769 static size_t module_vec_size (emacs_env *env,
770 emacs_value vec)
771 {
772 /* Type of ASIZE (lvec) is ptrdiff_t, make sure it fits */
773 verify (PTRDIFF_MAX <= SIZE_MAX);
774 check_main_thread ();
775 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
776 Lisp_Object lvec = value_to_lisp (vec);
777 if (! VECTORP (lvec))
778 {
779 module_wrong_type (env, Qvectorp, lvec);
780 return 0;
781 }
782 eassert (ASIZE (lvec) >= 0);
783 return ASIZE (lvec);
784 }
785
786 \f
787 /* Subroutines */
788
789 DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0,
790 doc: /* Load module FILE. */)
791 (Lisp_Object file)
792 {
793 dynlib_handle_ptr handle;
794 emacs_init_function module_init;
795 void *gpl_sym;
796
797 CHECK_STRING (file);
798 handle = dynlib_open (SDATA (file));
799 if (!handle)
800 error ("Cannot load file %s: %s", SDATA (file), dynlib_error ());
801
802 gpl_sym = dynlib_sym (handle, "plugin_is_GPL_compatible");
803 if (!gpl_sym)
804 error ("Module %s is not GPL compatible", SDATA (file));
805
806 module_init = (emacs_init_function) dynlib_sym (handle, "emacs_module_init");
807 if (!module_init)
808 error ("Module %s does not have an init function.", SDATA (file));
809
810 struct {
811 struct emacs_runtime pub;
812 struct emacs_runtime_private priv;
813 } runtime = {
814 .pub = {
815 .size = sizeof runtime.pub,
816 .get_environment = module_get_environment,
817 .private_members = &runtime.priv
818 }
819 };
820 initialize_environment (&runtime.priv.environment);
821 int r = module_init (&runtime.pub);
822 finalize_environment (&runtime.priv.environment);
823
824 if (r != 0)
825 {
826 if (r < MOST_NEGATIVE_FIXNUM)
827 xsignal0 (Qunderflow_error);
828 if (r > MOST_POSITIVE_FIXNUM)
829 xsignal0 (Qoverflow_error);
830 xsignal2 (Qmodule_load_failed, file, make_number (r));
831 }
832
833 return Qt;
834 }
835
836 DEFUN ("module-call", Fmodule_call, Smodule_call, 2, 2, 0,
837 doc: /* Internal function to call a module function.
838 ENVOBJ is a save pointer to a module_fun_env structure.
839 ARGLIST is a list of arguments passed to SUBRPTR. */)
840 (Lisp_Object envobj, Lisp_Object arglist)
841 {
842 const struct module_fun_env *const envptr =
843 (const struct module_fun_env *) XSAVE_POINTER (envobj, 0);
844 const EMACS_INT len = XINT (Flength (arglist));
845 eassert (len >= 0);
846 if (len > MOST_POSITIVE_FIXNUM)
847 xsignal0 (Qoverflow_error);
848 if (len > INT_MAX || len < envptr->min_arity || (envptr->max_arity >= 0 && len > envptr->max_arity))
849 xsignal2 (Qwrong_number_of_arguments, module_format_fun_env (envptr), make_number (len));
850
851 struct env_storage env;
852 initialize_environment (&env);
853
854 emacs_value *args = xzalloc (len * sizeof (*args));
855 int i;
856
857 for (i = 0; i < len; i++)
858 {
859 args[i] = lisp_to_value (&env.pub, XCAR (arglist));
860 if (! args[i]) memory_full (sizeof *args[i]);
861 arglist = XCDR (arglist);
862 }
863
864 emacs_value ret = envptr->subr (&env.pub, len, args, envptr->data);
865 xfree (args);
866
867 switch (env.priv.pending_non_local_exit)
868 {
869 case emacs_funcall_exit_return:
870 finalize_environment (&env);
871 if (ret == NULL) xsignal1 (Qinvalid_module_call, module_format_fun_env (envptr));
872 return value_to_lisp (ret);
873 case emacs_funcall_exit_signal:
874 {
875 const Lisp_Object symbol = value_to_lisp (&env.priv.non_local_exit_symbol);
876 const Lisp_Object data = value_to_lisp (&env.priv.non_local_exit_data);
877 finalize_environment (&env);
878 xsignal (symbol, data);
879 }
880 case emacs_funcall_exit_throw:
881 {
882 const Lisp_Object tag = value_to_lisp (&env.priv.non_local_exit_symbol);
883 const Lisp_Object value = value_to_lisp (&env.priv.non_local_exit_data);
884 finalize_environment (&env);
885 Fthrow (tag, value);
886 }
887 }
888 }
889
890 \f
891 /* Helper functions */
892
893 static void check_main_thread (void)
894 {
895 #if defined(HAVE_THREADS_H)
896 eassert (thrd_equal (thdr_current (), main_thread);
897 #elif defined(HAVE_PTHREAD)
898 eassert (pthread_equal (pthread_self (), main_thread));
899 #elif defined(WINDOWSNT)
900 /* CompareObjectHandles would be perfect, but is only available in
901 Windows 10. Also check whether the thread is still running to
902 protect against thread identifier reuse. */
903 eassert (GetCurrentThreadId () == main_thread_id
904 && WaitForSingleObject (main_thread, 0) == WAIT_TIMEOUT);
905 #endif
906 }
907
908 static void module_non_local_exit_signal_1 (emacs_env *env, Lisp_Object sym, Lisp_Object data)
909 {
910 struct emacs_env_private *const p = env->private_members;
911 eassert (p->pending_non_local_exit == emacs_funcall_exit_return);
912 p->pending_non_local_exit = emacs_funcall_exit_signal;
913 p->non_local_exit_symbol.v = sym;
914 p->non_local_exit_data.v = data;
915 }
916
917 static void module_non_local_exit_throw_1 (emacs_env *env, Lisp_Object tag, Lisp_Object value)
918 {
919 struct emacs_env_private *const p = env->private_members;
920 eassert (p->pending_non_local_exit == emacs_funcall_exit_return);
921 p->pending_non_local_exit = emacs_funcall_exit_throw;
922 p->non_local_exit_symbol.v = tag;
923 p->non_local_exit_data.v = value;
924 }
925
926 static void module_wrong_type (emacs_env *env, Lisp_Object predicate, Lisp_Object value)
927 {
928 module_non_local_exit_signal_1 (env, Qwrong_type_argument, list2 (predicate, value));
929 }
930
931 static void module_out_of_memory (emacs_env *env)
932 {
933 // TODO: Reimplement this so it works even if memory-signal-data has been modified.
934 module_non_local_exit_signal_1 (env, XCAR (Vmemory_signal_data), XCDR (Vmemory_signal_data));
935 }
936
937 static void module_args_out_of_range (emacs_env *env, Lisp_Object a1, Lisp_Object a2)
938 {
939 module_non_local_exit_signal_1 (env, Qargs_out_of_range, list2 (a1, a2));
940 }
941
942 \f
943 /* Value conversion */
944
945 static Lisp_Object value_to_lisp (emacs_value v)
946 {
947 return v->v;
948 }
949
950 static emacs_value lisp_to_value (emacs_env *env, Lisp_Object o)
951 {
952 struct emacs_env_private *const p = env->private_members;
953 if (p->pending_non_local_exit != emacs_funcall_exit_return) return NULL;
954 return allocate_emacs_value (env, &p->storage, o);
955 }
956
957 \f
958 /* Memory management */
959
960 static void initialize_frame (struct emacs_value_frame *frame)
961 {
962 frame->offset = 0;
963 frame->next = NULL;
964 }
965
966 static void initialize_storage (struct emacs_value_storage *storage)
967 {
968 initialize_frame (&storage->initial);
969 storage->current = &storage->initial;
970 }
971
972 static void finalize_storage (struct emacs_value_storage *storage)
973 {
974 struct emacs_value_frame *next = storage->initial.next;
975 while (next != NULL)
976 {
977 struct emacs_value_frame *const current = next;
978 next = current->next;
979 free (current);
980 }
981 }
982
983 static emacs_value allocate_emacs_value (emacs_env *env, struct emacs_value_storage *storage,
984 Lisp_Object obj)
985 {
986 eassert (storage->current);
987 eassert (storage->current->offset < value_frame_size);
988 eassert (! storage->current->next);
989 if (storage->current->offset == value_frame_size - 1)
990 {
991 storage->current->next = malloc (sizeof *storage->current->next);
992 if (! storage->current->next)
993 {
994 module_out_of_memory (env);
995 return NULL;
996 }
997 initialize_frame (storage->current->next);
998 storage->current = storage->current->next;
999 }
1000 const emacs_value value = storage->current->objects + storage->current->offset;
1001 value->v = obj;
1002 ++storage->current->offset;
1003 return value;
1004 }
1005
1006 /* Mark all objects allocated from local environments so that they
1007 don't get garbage-collected. */
1008 void mark_modules (void)
1009 {
1010 for (Lisp_Object tem = Vmodule_environments; CONSP (tem); tem = XCDR (tem))
1011 {
1012 const struct env_storage *const env = XSAVE_POINTER (tem, 0);
1013 for (const struct emacs_value_frame *frame = &env->priv.storage.initial; frame != NULL; frame = frame->next)
1014 for (size_t i = 0; i < frame->offset; ++i)
1015 mark_object (frame->objects[i].v);
1016 }
1017 }
1018
1019 \f
1020 /* Environment lifetime management */
1021
1022 static void initialize_environment (struct env_storage *env)
1023 {
1024 env->priv.pending_non_local_exit = emacs_funcall_exit_return;
1025 initialize_storage (&env->priv.storage);
1026 env->pub.size = sizeof env->pub;
1027 env->pub.private_members = &env->priv;
1028 env->pub.make_global_ref = module_make_global_ref;
1029 env->pub.free_global_ref = module_free_global_ref;
1030 env->pub.non_local_exit_check = module_non_local_exit_check;
1031 env->pub.non_local_exit_clear = module_non_local_exit_clear;
1032 env->pub.non_local_exit_get = module_non_local_exit_get;
1033 env->pub.non_local_exit_signal = module_non_local_exit_signal;
1034 env->pub.non_local_exit_throw = module_non_local_exit_throw;
1035 env->pub.make_function = module_make_function;
1036 env->pub.funcall = module_funcall;
1037 env->pub.intern = module_intern;
1038 env->pub.type_of = module_type_of;
1039 env->pub.is_not_nil = module_is_not_nil;
1040 env->pub.eq = module_eq;
1041 env->pub.extract_integer = module_extract_integer;
1042 env->pub.make_integer = module_make_integer;
1043 env->pub.extract_float = module_extract_float;
1044 env->pub.make_float = module_make_float;
1045 env->pub.copy_string_contents = module_copy_string_contents;
1046 env->pub.make_string = module_make_string;
1047 env->pub.make_user_ptr = module_make_user_ptr;
1048 env->pub.get_user_ptr = module_get_user_ptr;
1049 env->pub.set_user_ptr = module_set_user_ptr;
1050 env->pub.get_user_finalizer = module_get_user_finalizer;
1051 env->pub.set_user_finalizer = module_set_user_finalizer;
1052 env->pub.vec_set = module_vec_set;
1053 env->pub.vec_get = module_vec_get;
1054 env->pub.vec_size = module_vec_size;
1055 Vmodule_environments = Fcons (make_save_ptr (env), Vmodule_environments);
1056 }
1057
1058 static void finalize_environment (struct env_storage *env)
1059 {
1060 finalize_storage (&env->priv.storage);
1061 Vmodule_environments = XCDR (Vmodule_environments);
1062 }
1063
1064 \f
1065 /* Non-local exit handling */
1066
1067 static void module_reset_handlerlist(const int *dummy)
1068 {
1069 handlerlist = handlerlist->next;
1070 }
1071
1072 static void module_handle_signal (emacs_env *const env, const Lisp_Object err)
1073 {
1074 module_non_local_exit_signal_1 (env, XCAR (err), XCDR (err));
1075 }
1076
1077 static void module_handle_throw (emacs_env *const env, const Lisp_Object tag_val)
1078 {
1079 module_non_local_exit_throw_1 (env, XCAR (tag_val), XCDR (tag_val));
1080 }
1081
1082 \f
1083 /* Function environments */
1084
1085 static Lisp_Object module_format_fun_env (const struct module_fun_env *const env)
1086 {
1087 /* Try to print a function name if possible. */
1088 const char *path, *sym;
1089 if (dynlib_addr (env->subr, &path, &sym))
1090 {
1091 const char *const format = "#<module function %s from %s>";
1092 const int size = snprintf (NULL, 0, format, sym, path);
1093 eassert (size > 0);
1094 char buffer[size + 1];
1095 snprintf (buffer, sizeof buffer, format, sym, path);
1096 return make_unibyte_string (buffer, size);
1097 }
1098 else
1099 {
1100 const char *const format = "#<module function at %p>";
1101 const void *const subr = env->subr;
1102 const int size = snprintf (NULL, 0, format, subr);
1103 eassert (size > 0);
1104 char buffer[size + 1];
1105 snprintf (buffer, sizeof buffer, format, subr);
1106 return make_unibyte_string (buffer, size);
1107 }
1108 }
1109
1110 \f
1111 /* Segment initializer */
1112
1113 void syms_of_module (void)
1114 {
1115 DEFSYM (Qmodule_refs_hash, "module-refs-hash");
1116 DEFVAR_LISP ("module-refs-hash", Vmodule_refs_hash,
1117 doc: /* Module global referrence table. */);
1118
1119 Vmodule_refs_hash = make_hash_table (hashtest_eq, make_number (DEFAULT_HASH_SIZE),
1120 make_float (DEFAULT_REHASH_SIZE),
1121 make_float (DEFAULT_REHASH_THRESHOLD),
1122 Qnil);
1123 Funintern (Qmodule_refs_hash, Qnil);
1124
1125 DEFSYM (Qmodule_environments, "module-environments");
1126 DEFVAR_LISP ("module-environments", Vmodule_environments,
1127 doc: /* List of active module environments. */);
1128 Vmodule_environments = Qnil;
1129 /* Unintern `module-environments' because it is only used
1130 internally. */
1131 Funintern (Qmodule_environments, Qnil);
1132
1133 DEFSYM (Qmodule_load_failed, "module-load-failed");
1134 Fput (Qmodule_load_failed, Qerror_conditions,
1135 listn (CONSTYPE_PURE, 2, Qmodule_load_failed, Qerror));
1136 Fput (Qmodule_load_failed, Qerror_message,
1137 build_pure_c_string ("Module load failed"));
1138
1139 DEFSYM (Qinvalid_module_call, "invalid-module-call");
1140 Fput (Qinvalid_module_call, Qerror_conditions,
1141 listn (CONSTYPE_PURE, 2, Qinvalid_module_call, Qerror));
1142 Fput (Qinvalid_module_call, Qerror_message,
1143 build_pure_c_string ("Invalid module call"));
1144
1145 DEFSYM (Qinvalid_arity, "invalid-arity");
1146 Fput (Qinvalid_arity, Qerror_conditions,
1147 listn (CONSTYPE_PURE, 2, Qinvalid_arity, Qerror));
1148 Fput (Qinvalid_arity, Qerror_message,
1149 build_pure_c_string ("Invalid function arity"));
1150
1151 initialize_storage (&global_storage);
1152
1153 /* Unintern `module-refs-hash' because it is internal-only and Lisp
1154 code or modules should not access it. */
1155 Funintern (Qmodule_refs_hash, Qnil);
1156
1157 defsubr (&Smodule_load);
1158
1159 /* Don't call defsubr on `module-call' because that would intern it,
1160 but `module-call' is an internal function that users cannot
1161 meaningfully use. Instead, assign its definition to a private
1162 variable. */
1163 XSETPVECTYPE (&Smodule_call, PVEC_SUBR);
1164 XSETSUBR (module_call_func, &Smodule_call);
1165 }
1166
1167 /* Unlike syms_of_module, this initializer is called even from an
1168 * initialized (dumped) Emacs. */
1169
1170 void module_init (void)
1171 {
1172 /* It is not guaranteed that dynamic initializers run in the main thread,
1173 therefore we detect the main thread here. */
1174 #if defined(HAVE_THREADS_H)
1175 main_thread = thrd_current ();
1176 #elif defined(HAVE_PTHREAD)
1177 main_thread = pthread_self ();
1178 #elif defined(WINDOWSNT)
1179 /* This calls APIs that are only available on Vista and later. */
1180 #if 0
1181 /* GetCurrentProcess returns a pseudohandle, which we have to duplicate. */
1182 if (! DuplicateHandle (GetCurrentProcess(), GetCurrentThread(),
1183 GetCurrentProcess(), &main_thread,
1184 SYNCHRONIZE | THREAD_QUERY_INFORMATION,
1185 FALSE, 0))
1186 emacs_abort ();
1187 #else
1188 /* GetCurrentThread returns a pseudohandle, which we have to duplicate. */
1189 HANDLE th = GetCurrentThread ();
1190 if (!DuplicateHandle (GetCurrentProcess (), th,
1191 GetCurrentProcess (), &main_thread, 0, FALSE,
1192 DUPLICATE_SAME_ACCESS))
1193 emacs_abort ();
1194 main_thread_id = GetCurrentThreadId ();
1195 #endif
1196 #endif
1197 }