int __gl_unreserve_all_interrupts = 0;
int __gl_exception_tracebacks = 0;
int __gl_zero_cost_exceptions = 0;
+int __gl_detect_blocking = 0;
/* Indication of whether synchronous signal handler has already been
installed by a previous call to adainit */
int num_interrupt_states,
int unreserve_all_interrupts,
int exception_tracebacks,
- int zero_cost_exceptions)
+ int zero_cost_exceptions,
+ int detect_blocking)
{
static int already_called = 0;
__gl_task_dispatching_policy = task_dispatching_policy;
__gl_unreserve_all_interrupts = unreserve_all_interrupts;
__gl_exception_tracebacks = exception_tracebacks;
+ __gl_detect_blocking = detect_blocking;
/* ??? __gl_zero_cost_exceptions is new in 3.15 and is referenced from
a-except.adb, which is also part of the compiler sources. Since the
at all; the intention is that this be replaced by system specific
code where initialization is required. */
+/* Notes on the Zero Cost Exceptions scheme and its impact on the signal
+ handlers implemented below :
+
+ What we call Zero Cost Exceptions is implemented using the GCC eh
+ circuitry, even if the underlying implementation is setjmp/longjmp
+ based. In any case ...
+
+ The GCC unwinder expects to be dealing with call return addresses, since
+ this is the "nominal" case of what we retrieve while unwinding a regular
+ call chain. To evaluate if a handler applies at some point in this chain,
+ the propagation engine needs to determine what region the corresponding
+ call instruction pertains to. The return address may not be attached to the
+ same region as the call, so the unwinder unconditionally substracts "some"
+ amount to the return addresses it gets to search the region tables. The
+ exact amount is computed to ensure that the resulting address is inside the
+ call instruction, and is thus target dependant (think about delay slots for
+ instance).
+
+ When we raise an exception from a signal handler, e.g. to transform a
+ SIGSEGV into Storage_Error, things need to appear as if the signal handler
+ had been "called" by the instruction which triggered the signal, so that
+ exception handlers that apply there are considered. What the unwinder will
+ retrieve as the return address from the signal handler is what it will find
+ as the faulting instruction address in the corresponding signal context
+ pushed by the kernel. Leaving this address untouched may loose, because if
+ the triggering instruction happens to be the very first of a region, the
+ later adjustements performed by the unwinder would yield an address outside
+ that region. We need to compensate for those adjustments at some point,
+ which we currently do in the GCC unwinding fallback macro.
+
+ The thread at http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00343.html
+ describes a couple of issues with our current approach. Basically: on some
+ targets the adjustment to apply depends on the triggering signal, which is
+ not easily accessible from the macro, and we actually do not tackle this as
+ of today. Besides, other languages, e.g. Java, deal with this by performing
+ the adjustment in the signal handler before the raise, so our adjustments
+ may break those front-ends.
+
+ To have it all right, we should either find a way to deal with the signal
+ variants from the macro and convert Java on all targets (ugh), or remove
+ our macro adjustments and update our signal handlers a-la-java way. The
+ latter option appears the simplest, although some targets have their share
+ of subtleties to account for. See for instance the syscall(SYS_sigaction)
+ story in libjava/include/i386-signal.h. */
+
/***********************************/
/* __gnat_initialize (AIX Version) */
/***********************************/
static void __gnat_error_handler (int, int, sigcontext_t *);
+/* We are not setting the SA_SIGINFO bit in the sigaction flags when
+ connecting that handler, with the effects described in the sigaction
+ man page:
+
+ SA_SIGINFO [...]
+ If cleared and the signal is caught, the first argument is
+ also the signal number but the second argument is the signal
+ code identifying the cause of the signal. The third argument
+ points to a sigcontext_t structure containing the receiving
+ process's context when the signal was delivered.
+*/
+
static void
__gnat_error_handler (int sig, int code, sigcontext_t *sc)
{
exception = &program_error; /* ??? storage_error ??? */
msg = "SIGSEGV: (Autogrow for file failed)";
}
- else if (code == EACCES)
+ else if (code == EACCES || code == EEXIST)
{
+ /* ??? We handle stack overflows here, some of which do trigger
+ SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
+ the documented valid codes for SEGV in the signal(5) man
+ page. */
+
/* ??? Re-add smarts to further verify that we launched
the stack into a guard page, not an attempt to
write to .text or something */
/* On targets where we might be using the ZCX scheme, we need to register
the frame tables.
- For application "modules", the crtstuff objects linked in (crtbegin/endS)
- are tailored to provide this service a-la C++ constructor fashion,
- typically triggered by the dynamic loader. This is achieved by way of a
- special variable declaration in the crt object, the name of which has
- been deduced by analyzing the output of the "munching" step documented
- for C++. The de-registration call is handled symetrically, a-la C++
- destructor fashion and typically triggered by the dynamic unloader. With
- this scheme, a mixed Ada/C++ application has to be linked and loaded as
- separate modules for each language, which is not unreasonable anyway.
-
- For applications statically linked with the kernel, the module scheme
- above would lead to duplicated symbols because the VxWorks kernel build
- "munches" by default. To prevent those conflicts, we link against
- crtbegin/end objects that don't include the special variable and directly
- call the appropriate function here. We'll never unload that, so there is
- no de-registration to worry about.
+ For applications loaded as a set of "modules", the crtstuff objects
+ linked in (crtbegin/endS) are tailored to provide this service a-la C++
+ static constructor fashion, typically triggered by the VxWorks loader.
+ This is achieved by way of a special variable declaration in the crt
+ object, the name of which has been deduced by analyzing the output of the
+ "munching" step documented for C++. The de-registration call is handled
+ symetrically, a-la C++ destructor fashion and typically triggered by the
+ dynamic unloader. Note that since the tables shall be registered against
+ a common datastructure, libgcc should be one of the modules (vs beeing
+ partially linked against all the others at build time) and shall be
+ loaded first.
+
+ For applications linked with the kernel, the scheme above would lead to
+ duplicated symbols because the VxWorks kernel build "munches" by default.
+ To prevent those conflicts, we link against crtbegin/end objects that
+ don't include the special variable and directly call the appropriate
+ function here. We'll never unload that, so there is no de-registration to
+ worry about.
+
+ For whole applications loaded as a single module, we may use one scheme
+ or the other, except for the mixed Ada/C++ case in which the first scheme
+ would fail for the same reason as in the linked-with-kernel situation.
We can differentiate by looking at the __module_has_ctors value provided
- by each class of crt objects. As of today, selecting the crt set intended
- for applications to be statically linked with the kernel is triggered by
- adding "-static" to the gcc *link* command line options.
+ by each class of crt objects. As of today, selecting the crt set with the
+ static ctors/dtors capabilities (first scheme above) is triggered by
+ adding "-static" to the gcc *link* command line options. Without this,
+ the other set of crt objects is fetched.
This is a first approach, tightly synchronized with a number of GCC
configuration and crtstuff changes. We need to ensure that those changes