1 /*  Part of SWI-Prolog
2 
3     Author:        Jan Wielemaker
4     E-mail:        J.Wielemaker@vu.nl
5     WWW:           http://www.swi-prolog.org
6     Copyright (c)  1997-2020, University of Amsterdam
7                               VU University Amsterdam
8 			      CWI, Amsterdam
9     All rights reserved.
10 
11     Redistribution and use in source and binary forms, with or without
12     modification, are permitted provided that the following conditions
13     are met:
14 
15     1. Redistributions of source code must retain the above copyright
16        notice, this list of conditions and the following disclaimer.
17 
18     2. Redistributions in binary form must reproduce the above copyright
19        notice, this list of conditions and the following disclaimer in
20        the documentation and/or other materials provided with the
21        distribution.
22 
23     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27     COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34     POSSIBILITY OF SUCH DAMAGE.
35 */
36 
37 #ifndef PL_GLOBAL_H_INCLUDED
38 #define PL_GLOBAL_H_INCLUDED
39 #include "pl-allocpool.h"
40 
41 #ifndef GLOBAL			/* global variables */
42 #define GLOBAL extern
43 #endif
44 
45 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
46 This module packs SWI-Prolog global data-structures into two structures.
47 The structure PL_global_data contains all global data that is related to
48 the state of the system as a  whole, and PL_local_data contains all data
49 that is related to a Prolog thread.
50 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
51 
52 		 /*******************************
53 		 *	     CODE DATA		*
54 		 *******************************/
55 
56 typedef struct
57 {
58 #if VMCODE_IS_ADDRESS
59   unsigned char   *_dewam_table;	/* decoding table */
60   intptr_t	  _dewam_table_offset;	/* offset of 1st */
61   void  **_interpreter_jmp_table;	/* interpreters table */
62 					/* must be last! (why?) */
63   code    _wam_table[I_HIGHEST];	/* code --> address */
64 #else
65   int	  struct_may_not_be_empty;	/* empty structure is illegal */
66 #endif
67   struct				/* see initSupervisors() */
68   { code exit[3];			/* I_EXIT */
69     code next_clause[3];		/* S_NEXTCLAUSE */
70     code virgin[3];			/* S_VIRGIN */
71     code undef[3];			/* S_UNDEF */
72     code dynamic[3];			/* S_DYNAMIC */
73     code incr_dynamic[3];		/* S_INCR_DYNAMIC */
74     code thread_local[3];		/* S_THREAD_LOCAL */
75     code multifile[3];			/* S_MULTIFILE */
76     code staticp[3];			/* S_STATIC */
77     code wrapper[3];			/* S_WRAP */
78     code trie_gen[3];			/* S_TRIE_GEN */
79   } supervisors;
80 } PL_code_data_t;
81 
82 typedef struct
83 { atom_t	file;			/* current source file */
84   IOPOS		position;		/* Line, line pos, char and byte */
85 } source_location;
86 
87 		 /*******************************
88 		 *	    GLOBAL DATA		*
89 		 *******************************/
90 
91 struct PL_global_data
92 { pl_defaults_t	defaults;		/* system default settings */
93   pl_options_t	options;		/* command-line options */
94   State		stateList;		/* list of loaded states */
95   int		initialised;		/* Heap is initialised */
96   int		io_initialised;		/* I/O system has been initialised */
97   cleanup_status cleaning;		/* Inside PL_cleanup() */
98   int		halt_cancelled;		/* Times halt was cancelled */
99   int		bootsession;		/* -b boot compilation */
100   int		debug_level;		/* Maintenance debugging: 0..9 */
101   struct bit_vector *debug_topics;	/* debug topics enabled */
102 
103   struct
104   { void *	DB;			/* program resource database */
105     atom_t	handle;			/* Symbol for DB */
106   } resources;
107 
108   struct
109   { sig_handler handlers[MAXSIGNAL];	/* How Prolog preceives signals */
110 #ifdef HAVE_SIGNAL
111     int		sig_alert;		/* our alert signal */
112 #endif
113   } signals;
114 #ifdef O_LOGICAL_UPDATE
115   volatile ggen_t _generation;		/* generation of the database */
116 #ifdef ATOMIC_GENERATION_HACK
117   volatile gen_t _last_generation;	/* see pl-inline.h, global_generation() */
118 #endif
119 #endif
120 
121   struct
122   { int		os_argc;		/* main(int argc, char **argv) */
123     char **	os_argv;
124     int		appl_argc;		/* Application options */
125     char **	appl_argv;
126     int		notty;			/* -tty: do not use ioctl() */
127     int		optimise;		/* -O: optimised compilation */
128     int		packs;			/* --no-packs: no packs */
129   } cmdline;
130 
131   struct
132   { char *	CWDdir;
133     size_t	CWDlen;
134     char *	executable;		/* Running executable */
135 #ifdef __WINDOWS__
136     char *	module;			/* argv[0] module passed */
137 #endif
138   } paths;
139 
140   struct
141   { size_t	atoms;			/* No. of atoms defined */
142     size_t	atom_string_space;	/* # bytes used to store atoms */
143     size_t	atom_string_space_freed;/* # bytes in freed atoms */
144     size_t	stack_space;		/* # bytes on stacks */
145     int		functors;		/* No. of functors defined */
146     int		predicates;		/* No. of predicates defined */
147     int		modules;		/* No. of modules in the system */
148     size_t	clauses;		/* No. clauses */
149     size_t	codes;			/* No. of VM codes generated */
150     double	user_cputime;		/* User CPU time (whole process) */
151     double	system_cputime;		/* Kernel CPU time (whole process) */
152     struct
153     { int	created;		/* # created hash tables */
154       int	destroyed;		/* # destroyed hash tables */
155     } indexes;
156 #ifdef O_PLMT
157     int		threads_created;	/* # threads created */
158     int		threads_finished;	/* # finished threads */
159     int		engines_created;	/* # engines created */
160     int		engines_finished;	/* # engines threads */
161     double	thread_cputime;		/* Total CPU time of threads */
162 #endif
163   } statistics;
164 
165 #ifdef O_PROFILE
166   struct
167   { struct PL_local_data *thread;	/* Thread being profiled */
168   } profile;
169 #endif
170 
171   struct
172   { Module	user;			/* user module */
173     Module	system;			/* system predicate module */
174   } modules;
175 
176   struct
177   { Table	modules;		/* atom --> module */
178   } tables;
179 
180 #if O_PLMT
181   struct				/* Shared table data */
182   { struct trie *variant_table;		/* Variant --> table */
183     alloc_pool *node_pool;		/* Node allocation pool for tries */
184     counting_mutex  mutex;		/* Sync completion */
185 #ifdef __WINDOWS__
186     CONDITION_VARIABLE cvar;
187 #else
188     pthread_cond_t cvar;
189 #endif
190     struct trie_array *waiting;		/* thread --> trie we are waiting for */
191   } tabling;
192 #endif
193 
194   struct
195   { Table	record_lists;		/* Available record lists */
196   } recorded_db;
197 
198   struct
199   { ArithF     *functions;		/* index --> function */
200     size_t	functions_allocated;	/* Size of above array */
201   } arith;
202 
203   struct
204   { size_t	highest;		/* Highest atom index */
205     atom_array	array;
206     AtomTable	table;			/* hash-table */
207     int		lookups;		/* # atom lookups */
208     int		cmps;			/* # string compares for lookup */
209     int		initialised;		/* atoms have been initialised */
210 #ifdef O_ATOMGC
211     int		gc;			/* # atom garbage collections */
212     int		gc_active;		/* Atom-GC is in progress */
213     int		rehashing;		/* Atom-rehash in progress */
214     size_t	builtin;		/* Locked atoms (atom-gc) */
215     size_t	no_hole_before;		/* You won't find a hole before here */
216     size_t	margin;			/* # atoms to grow before collect */
217     size_t	non_garbage;		/* # atoms for after last AGC */
218     int64_t	collected;		/* # collected atoms */
219     size_t	unregistered;		/* # candidate GC atoms */
220     double	gc_time;		/* Time spent on atom-gc */
221     PL_agc_hook_t gc_hook;		/* Current hook */
222 #endif
223     atom_t     *for_code[256];		/* code --> one-char-atom */
224     PL_blob_t  *types;			/* registered atom types */
225     int		text_rank;		/* next rank for text types */
226     int		nontext_rank;		/* next rank for non-text types */
227   } atoms;
228 
229   struct
230   { Table	breakpoints;		/* Breakpoint table */
231   } comp;
232 
233   struct
234   { ExtensionCell _ext_head;		/* head of registered extensions */
235     ExtensionCell _ext_tail;		/* tail of this chain */
236 
237     InitialiseHandle initialise_head;	/* PL_initialise_hook() */
238     InitialiseHandle initialise_tail;
239     PL_dispatch_hook_t dispatch_events; /* PL_dispatch_hook() */
240 
241     unsigned int  signature;		/* Foreign predicate signature */
242     int		  _loaded;		/* system extensions are loaded */
243   } foreign;
244 
245 #ifdef O_GMP
246   struct
247   { int initialised;			/* is GMP initialised? */
248     int keep_alloc_functions;		/* do not change allocation */
249   } gmp;
250 #endif
251 
252   struct				/* pl-format.c */
253   { Table	predicates;
254   } format;
255 
256   struct
257   { Table	table;			/* flag key --> flag */
258   } flags;
259 
260   struct
261   { Table	table;			/* global (read-only) features */
262   } prolog_flag;
263 
264   struct
265   { size_t	highest;		/* Next index to handout */
266     functor_array array;		/* index --> functor */
267     FunctorTable table;			/* hash-table */
268     int		 rehashing;		/* Table is being rehashed */
269   } functors;
270 
271   struct
272   { Code	catch_exit_address;	/* See findCatchExit() */
273   } exceptions;
274 
275   struct
276   { struct
277     { struct event_list *onabort;	/* Thread aborted */
278       struct event_list *onerase;	/* erased clause or dbref */
279       struct event_list *onbreak;	/* breakpoint change */
280       struct event_list *onframefinish; /* Debugged frame finished */
281 #ifdef O_PLMT
282       struct event_list *onthreadexit;	/* thread exit hook */
283 #endif
284       struct event_list *onuntable;	/* Untable after reload */
285     } hook;
286   } event;
287 
288   struct
289   { Table		tmp_files;	/* Known temporary files */
290     struct
291     { CanonicalDir     *entries;
292       unsigned		size;
293     } dir_table;			/* Canonical OS dirs */
294     char *		myhome;		/* expansion of ~ */
295     char *		fred;		/* last expanded ~user */
296     char *		fredshome;	/* home of fred */
297     OnHalt		on_halt_list;	/* list of onhalt hooks */
298     OnHalt		exit_hooks;	/* how to exit from PL_halt() */
299     int			halting;	/* process is shutting down */
300     int			gui_app;	/* Win32: Application is a gui app */
301     IOFUNCTIONS		iofunctions;	/* initial IO functions */
302     IOFUNCTIONS		org_terminal;	/* IO+Prolog terminal functions */
303   } os;
304 
305   struct
306   { Procedure	dgarbage_collect1;
307     Procedure	catch3;
308     Procedure	reset3;
309     Procedure	dmeta_call1;		/* $meta_call/1 */
310     Procedure	true0;
311     Procedure	fail0;
312     Procedure	equals2;		/* =/2 */
313     Procedure	is2;			/* is/2 */
314     Procedure	strict_equal2;		/* ==/2 */
315     Procedure	not_strict_equal2;	/* \==/2 */
316     Procedure	exception_hook4;
317     Procedure	print_message2;
318     Procedure	foreign_registered2;	/* $foreign_registered/2 */
319     Procedure	prolog_trace_interception4;
320     Procedure	prolog_break_hook6;	/* prolog:break_hook/6 */
321     Procedure	portray;		/* portray/1 */
322     Procedure   dcall1;			/* $call/1 */
323     Procedure   call3;			/* call/3*/
324     Procedure	setup_call_catcher_cleanup4; /* setup_call_catcher_cleanup/4 */
325     Procedure	undefinterc4;		/* $undefined_procedure/4 */
326     Procedure   dthread_init0;		/* $thread_init/0 */
327     Procedure   dc_call_prolog0;	/* $c_call_prolog/0 */
328     Procedure   dinit_goal3;		/* $init_goal/3 */
329 #ifdef O_ATTVAR
330     Procedure	dwakeup1;		/* system:$wakeup/1 */
331     Procedure	portray_attvar1;	/* $attvar:portray_attvar/1 */
332 #endif
333     Procedure   comment_hook3;		/* prolog:comment_hook/3 */
334     Procedure	tune_gc3;		/* prolog:tune_gc */
335     Procedure	trie_gen_compiled2;
336     Procedure	trie_gen_compiled3;
337 
338     int		static_dirty;		/* #static dirty procedures */
339 #ifdef O_CLAUSEGC
340     Table	dirty;			/* Table of dirty procedures */
341 #endif
342   } procedures;
343 
344   struct
345   { ClauseRef	lingering;		/* Unlinked clause refs */
346     size_t	lingering_count;	/* # Unlinked clause refs */
347     int		cgc_active;		/* CGC is running */
348     int64_t	cgc_count;		/* # clause GC calls */
349     int64_t	cgc_reclaimed;		/* # clauses reclaimed */
350     double	cgc_time;		/* Total time spent in CGC */
351     size_t	dirty;			/* # dirty clauses */
352     size_t	erased;			/* # erased pending clauses */
353     size_t	erased_size;		/* memory used by them */
354     size_t	erased_size_last;	/* memory used by them after last CGC */
355     size_t	db_erased_refs;		/* Clause references on erased clauses */
356     int		cgc_space_factor;	/* Max total/margin garbage */
357     double	cgc_stack_factor;	/* Price to scan stack space */
358     double	cgc_clause_factor;	/* Pce to scan clauses */
359   } clauses;
360 
361   struct
362   { size_t	highest;		/* highest source file index */
363     size_t	no_hole_before;		/* All filled before here */
364     srcfile_array array;		/* index --> file */
365     Table	table;			/* name  --> file */
366   } files;
367 
368 #ifdef HAVE_TGETENT
369   struct
370   { int    initialised;			/* initialisation status */
371     char  *_string_area;		/* static area for tgetent */
372     char  *_buf_area;			/* another one */
373     Table  _capabilities;		/* User-level capability table */
374   } terminal;
375 #endif
376 
377 #ifdef O_PLMT
378   struct
379   { int			enabled;	/* threads are enabled */
380     Table		mutexTable;	/* Name --> mutex table */
381     int			mutex_next_id;	/* next id for anonymous mutexes */
382 #ifdef __WINDOWS__
383     HINSTANCE		instance;	/* Win32 process instance */
384 #endif
385     counting_mutex     *mutexes;	/* Registered mutexes */
386     PL_thread_info_t   *free;		/* Free threads */
387     int			highest_allocated; /* Highest with info struct */
388     int			thread_max;	/* Size of threads array */
389     int			highest_id;	/* Highest Id of life thread  */
390     int			peak_id;	/* Highest Id of any thread  */
391     PL_thread_info_t  **threads;	/* Pointers to thread-info */
392     struct
393     { pthread_mutex_t	mutex;
394       pthread_cond_t	cond;
395       unsigned int	requests;
396       unsigned int	initialized;	/* mutex and condvar are initialized */
397     } gc;
398     struct
399     { pthread_mutex_t	mutex;
400       pthread_cond_t	cond;
401     } index;
402   } thread;
403 #endif /*O_PLMT*/
404 
405 #ifdef O_LOCALE
406   struct
407   { Table		localeTable;	/* Name --> locale table */
408     PL_locale	       *default_locale;	/* System wide default */
409   } locale;
410 #endif
411 
412   struct stack		combined_stack; /* ID for combined stack */
413 };
414 
415 
416 		 /*******************************
417 		 *	     LOCAL DATA		*
418 		 *******************************/
419 
420 #define LD_MAGIC	0x3cfd82b4	/* Valid local-data structure */
421 
422 struct PL_local_data
423 { uintptr_t	magic;			/* LD_MAGIC */
424   LocalFrame    environment;		/* Current local frame */
425   Choice	choicepoints;		/* Choice-point chain */
426   FliFrame      foreign_environment;	/* Current foreign context */
427   QueryFrame    query;			/* Currently open query */
428   Word		mark_bar;		/* Mark globals > this one */
429 #ifdef O_GVAR
430   Word		frozen_bar;		/* Frozen part of the global stack */
431 #endif
432   Code		fast_condition;		/* Fast condition support */
433   pl_stacks_t   stacks;			/* Prolog runtime stacks */
434   uintptr_t	bases[STG_MASK+1];	/* area base addresses */
435   int		alerted;		/* Special mode. See updateAlerted() */
436   int		slow_unify;		/* do not use inline unification */
437   int		critical;		/* heap is being modified */
438   int		break_level;		/* current break level */
439   Stack		outofstack;		/* thread is out of stack */
440   int		trim_stack_requested;	/* perform a trim-stack */
441 #ifdef O_PLMT
442   int		exit_requested;		/* Thread is asked to exit */
443 #endif
444   int		in_arithmetic;		/* doing arithmetic */
445   int		in_print_message;	/* Inside printMessage() */
446   gen_t		gen_reload;		/* reload generation */
447   void *	glob_info;		/* pl-glob.c */
448   IOENC		encoding;		/* default I/O encoding */
449   struct PL_local_data *next_free;	/* see maybe_free_local_data() */
450 
451   struct
452   { int		pending[2];		/* PL_raise() pending signals */
453     int		current;		/* currently processing signal */
454     int		is_sync;		/* current signal is synchronous */
455   } signal;
456 
457   struct
458   { int		active;			/* doing pipe I/O */
459     jmp_buf	context;		/* context of longjmp() */
460   } pipe;
461 
462   struct
463   { char       *getstr_buffer;		/* getString() buffer */
464     size_t	getstr_buffer_size;	/* size of getstr_buffer */
465     struct wic_state *current_state;	/* qlf-creation state */
466   } qlf;
467 
468   struct
469   { atom_t	current;		/* current global prompt */
470     atom_t	first;			/* how to prompt first line */
471     int		first_used;		/* did we do the first line? */
472     int		next;			/* prompt on next read operation */
473   } prompt;
474 
475   source_location read_source;		/* file, line, char of last term */
476 
477   struct
478   { term_t	term;			/* exception term */
479     term_t	bin;			/* temporary handle for exception */
480     term_t	printed;		/* already printed exception */
481     term_t	tmp;			/* tmp for errors */
482     term_t	pending;		/* used by the debugger */
483     term_t	fr_rewritten;		/* processed by exception_hook() */
484     int		in_hook;		/* inside exception_hook() */
485     int		processing;		/* processing an exception */
486     exception_frame *throw_environment;	/* PL_throw() environments */
487   } exception;
488 
489 #ifdef O_ATTVAR
490   struct
491   { term_t	head;			/* Head of wakeup list */
492     term_t	tail;			/* Tail of this list */
493     term_t	gc_attvars;		/* place for attvars during GC */
494     Word	attvars;		/* linked list of all attvars */
495     int		call_residue_vars_count; /* # call_residue_vars/2 active */
496   } attvar;
497 #endif
498 
499   struct
500   { term_t	dummy;			/* see trimStacks() */
501   } trim;
502 
503   struct
504   { term_t	h[TMP_PTR_SIZE];	/* temporary handles. See unify_ptrs */
505     int		top;			/* Top-of-stack index */
506   } tmp;
507 
508 #ifdef O_GVAR
509   struct
510   { Table	nb_vars;		/* atom --> value */
511     int		grefs;			/* references to global stack */
512   } gvar;
513 #endif
514 
515   struct
516   { int64_t	inferences;		/* inferences in this thread */
517     uintptr_t	last_cputime;		/* milliseconds last CPU time */
518     uintptr_t	last_systime;		/* milliseconds last SYSTEM time */
519     uintptr_t	last_real_time;		/* Last Real Time (seconds since Epoch) */
520     double	start_time;		/* When Thread was started */
521     double	last_walltime;		/* Last Wall time (m-secs since start) */
522     double	user_cputime;		/* User saved CPU time */
523     double	system_cputime;		/* Kernel saved CPU time */
524   } statistics;
525 
526 #ifdef O_GMP
527   struct
528   { int		persistent;		/* do persistent operations */
529     size_t	allocated;		/* memory allocated */
530     ar_context *context;		/* current allocation context */
531     mp_mem_header *head;		/* linked list of allocated chunks */
532     mp_mem_header *tail;
533   } gmp;
534 #endif
535 
536 #ifdef O_PROFILE
537   struct
538   { int		active;			/* profiler is on */
539     int		accounting;		/* we are accounting */
540     int		sum_ok;			/* siblings are counted */
541     struct call_node *current;		/* `current' node */
542     struct call_node *roots;		/* list of root-nodes */
543     uintptr_t	samples;		/* profile samples */
544     uintptr_t	ticks;			/* profile ticks total */
545     uintptr_t	accounting_ticks;	/* Ticks in profCall() and friends */
546     uintptr_t	nodes;			/* #Recorded nodes */
547     double	time_at_last_tick;	/* Time at last statistics tick */
548     double	time_at_start;		/* Time at last start */
549     double	time;			/* recorded CPU time */
550   } profile;
551 #endif /* O_PROFILE */
552 
553   struct
554   { Module	typein;			/* module for type in goals */
555     Module	source;			/* module we are reading clauses in */
556   } modules;
557 
558   struct
559   { intptr_t	generator;		/* See PL_atom_generator() */
560     atom_t	unregistering;		/* See PL_unregister_atom() */
561   } atoms;
562 
563   struct
564   { VarDef *	vardefs;		/* compiler variable analysis */
565     int		nvardefs;
566     int		filledVars;
567   } comp;
568 
569   struct
570   { Buffer	buffered;		/* Buffered events */
571     int		delay_nesting;		/* How deeply is delay nested? */
572 
573 #ifdef O_PLMT
574     struct
575     { struct event_list *onthreadexit;	/* thread exit hook */
576     } hook;
577 #endif
578   } event;
579 
580   struct
581   { struct
582     { Number	base;
583       Number	top;
584       Number	max;
585     } stack;
586 #ifdef O_GMP
587     struct
588     { gmp_randstate_t state;
589       int initialised;
590     } random;
591     struct
592     { size_t max_rational_size;
593       atom_t max_rational_size_action;
594     } rat;
595 #endif
596     struct
597     { unsigned int flags;		/* FTL_* */
598     } f;
599   } arith;
600 
601 #if O_CYCLIC
602   struct
603   { segstack lstack;			/* Stack for cycle-links */
604     segstack vstack;			/* Stack for visited marks */
605   } cycle;
606 #endif
607 
608   struct
609   { struct tbl_component *component;    /* active component */
610     struct trie *variant_table;		/* Variant --> table */
611     alloc_pool *node_pool;		/* Node allocation pool for tries */
612     int	has_scheduling_component;	/* A leader was created */
613     int in_answer_completion;		/* Running answer completion */
614     term_t delay_list;			/* Global delay list */
615     term_t idg_current;			/* Current node in IDG (trie symbol) */
616     struct
617     { atom_t max_table_subgoal_size_action;
618       size_t max_table_subgoal_size;
619       atom_t max_table_answer_size_action;
620       size_t max_table_answer_size;
621       atom_t max_answers_for_subgoal_action;
622       size_t max_answers_for_subgoal;
623     } restraint;
624   } tabling;
625 
626   struct
627   {
628 #ifdef __BEOS__
629     status_t	dl_error;		/* dlopen() emulation in pl-beos.c */
630 #endif
631     int		rand_initialised;	/* have we initialised random? */
632 #ifdef O_DDE
633     unsigned	dde_instance;		/* Actually DWORD */
634 #endif
635   } os;
636 
637   struct
638   { Table	  table;		/* Feature table */
639     pl_features_t mask;			/* Masked access to booleans */
640     int		  write_attributes;	/* how to write attvars? */
641     occurs_check_t occurs_check;	/* Unify and occurs check */
642     access_level_t access_level;	/* Current access level */
643   } prolog_flag;
644 
645   struct
646   { FindData	find;			/* /<ports> <goal> in tracer */
647   } trace;
648 
649   struct
650   { struct findall_bag *bags;		/* Known bags */
651     struct findall_bag *default_bag;	/* Bag we keep around */
652 #if defined(O_ATOMGC) && defined(O_PLMT)
653     simpleMutex mutex;			/* Atom GC scanning synchronization */
654 #endif
655   } bags;
656 
657   struct
658   { AbortHandle	_abort_head;		/* PL_abort_hook() */
659     AbortHandle _abort_tail;
660 
661     buffer	_discardable_buffer;	/* PL_*() character buffers */
662     string_stack string_buffers;	/* PL_*() string buffers */
663 
664     int		SP_state;		/* For SICStus interface */
665   } fli;
666 
667   struct				/* Local IO stuff */
668   { IOSTREAM *streams[6];		/* handles for standard streams */
669     st_check stream_type_check;		/* Check bin/text streams? */
670 					/* do not copy from parent */
671     struct input_context *input_stack;	/* maintain input stream info */
672     struct output_context *output_stack; /* maintain output stream info */
673     int	portray_nesting;		/* depth of portray nesting */
674   } IO;
675 
676   struct
677   { fid_t	numbervars_frame;	/* Numbervars choice-point */
678   } var_names;
679 
680 #ifdef O_LIMIT_DEPTH
681   struct
682   { uintptr_t limit;
683     uintptr_t reached;
684   } depth_info;
685 #endif
686 
687 #ifdef O_INFERENCE_LIMIT
688   struct
689   { int64_t limit;			/* Raise at this count */
690   } inference_limit;
691 #endif
692 
693   definition_refs predicate_references;	/* Referenced predicates */
694 
695   pl_shift_status_t shift_status;	/* Stack shifter status */
696   pl_debugstatus_t _debugstatus;	/* status of the debugger */
697   struct btrace *btrace_store;		/* C-backtraces */
698 
699 #ifdef O_PLMT
700   struct
701   { intptr_t   magic;			/* PL_THREAD_MAGIC (checking) */
702     struct _PL_thread_info_t *info;	/* info structure */
703 					/* Communication */
704     message_queue messages;		/* Message queue */
705     struct _thread_sig   *sig_head;	/* Head of signal queue */
706     struct _thread_sig   *sig_tail;	/* Tail of signal queue */
707     DefinitionChain local_definitions;	/* P_THREAD_LOCAL predicates */
708     simpleMutex scan_lock;		/* Hold for asynchronous scans */
709     alert_channel alert;		/* How to alert the thread */
710   } thread;
711 #endif
712 
713 #ifdef O_LOCALE
714   struct
715   { PL_locale *current;			/* Current locale */
716   } locale;
717 #endif
718 
719   struct
720   { size_t	erased_skipped;		/* # erased clauses skipped */
721     int64_t	cgc_inferences;		/* Inferences at last cgc consider */
722   } clauses;
723 
724   struct
725   { DefinitionChain nesting;		/* Nesting chain in the autoloader */
726     Definition	loop;			/* We are looping on this def */
727   } autoload;
728 
729   struct
730   { intptr_t _total_marked;		/* # marked global cells */
731     intptr_t _trailcells_deleted;	/* # garbage trailcells */
732     intptr_t _relocation_chains;	/* # relocation chains (debugging) */
733     intptr_t _relocation_cells;		/* # relocation cells */
734     intptr_t _relocated_cells;		/* # relocated cells */
735     intptr_t _needs_relocation;		/* # cells that need relocation */
736     intptr_t _local_marked;		/* # marked local -> global ptrs */
737     intptr_t _marks_swept;		/* # marks swept */
738     intptr_t _marks_unswept;		/* # marks swept */
739     intptr_t _alien_relocations;	/* # alien_into_relocation_chain() */
740     intptr_t _local_frames;		/* frame count for debugging */
741     intptr_t _choice_count;		/* choice-point count for debugging */
742     int  *_start_map;			/* bitmap with legal global starts */
743     sigset_t saved_sigmask;		/* Saved signal mask */
744     int64_t inferences;			/* #inferences at last GC */
745     pl_gc_status_t	status;		/* Garbage collection status */
746 #ifdef O_CALL_RESIDUE
747     int			marked_attvars;	/* do not GC attvars */
748 #endif
749     int active;				/* GC is running in this thread */
750     gc_stats stats;			/* GC performance history */
751 
752 					/* These must be at the end to be */
753 					/* able to define O_DEBUG in only */
754 					/* some modules */
755 #if defined(O_DEBUG) || defined(SECURE_GC)
756     intptr_t _trailtops_marked;		/* # marked trailtops */
757     Word *_mark_base;			/* Array of marked cells addresses */
758     Word *_mark_top;			/* Top of this array */
759     Table _check_table;			/* relocation address table */
760     Table _local_table;			/* marked local variables */
761     int  _relocated_check;		/* Verify relocated addresses? */
762     unsigned int incr_seed;		/* Seed for random stack increments */
763 #endif
764   } gc;
765 };
766 
767 GLOBAL PL_global_data_t PL_global_data;
768 GLOBAL PL_code_data_t	PL_code_data;
769 GLOBAL PL_local_data_t  PL_local_data;
770 #ifdef O_MULTIPLE_ENGINES
771 GLOBAL PL_local_data_t *PL_current_engine_ptr;
772 #endif
773 
774 #define GD (&PL_global_data)
775 #define CD (&PL_code_data)
776 
777 #define functor_array		(GD->functors.array)
778 #define systemDefaults		(GD->defaults)
779 
780 #define environment_frame	(LD->environment)
781 #define fli_context		(LD->foreign_environment)
782 #define source_file_name	(LD->read_source.file)
783 #define source_line_no		(LD->read_source.position.lineno)
784 #define source_line_pos		(LD->read_source.position.linepos)
785 #define source_char_no		(LD->read_source.position.charno)
786 #define source_byte_no		(LD->read_source.position.byteno)
787 #define exception_term		(LD->exception.term)
788 #define exception_bin		(LD->exception.bin)
789 #define exception_printed	(LD->exception.printed)
790 #define gc_status		(LD->gc.status)
791 #define debugstatus		(LD->_debugstatus)
792 #define depth_limit		(LD->depth_info.limit)
793 #define depth_reached		(LD->depth_info.reached)
794 #define base_addresses		(LD->bases)
795 #define Suser_input		(LD->IO.streams[0])
796 #define Suser_output		(LD->IO.streams[1])
797 #define Suser_error		(LD->IO.streams[2])
798 #define Scurin			(LD->IO.streams[3])
799 #define Scurout			(LD->IO.streams[4])
800 #define Sprotocol		(LD->IO.streams[5])
801 #define Sdin			Suser_input		/* not used for now */
802 #define Sdout			Suser_error
803 
804 #ifdef VMCODE_IS_ADDRESS
805 #define dewam_table		(CD->_dewam_table)
806 #define dewam_table_offset	(CD->_dewam_table_offset)
807 #define wam_table		(CD->_wam_table)
808 #define interpreter_jmp_table	(CD->_interpreter_jmp_table)
809 #endif /*VMCODE_IS_ADDRESS*/
810 
811 #endif /*PL_GLOBAL_H_INCLUDED*/
812