Node:Multiple SICStus Run-Times in C, Next:, Previous:Multiple SICStus Run-Times in Java, Up:Multiple SICStus Run-Times



Multiple SICStus Run-Times in C

Unless otherwise noted, this section documents the behavior when using dynamic linking to access a SICStus run-time.

The key implementation feature that makes it possible to use multiple run-times is that all calls from C to the SICStus API (SP_query, etc.) go through a dispatch vector. Two run-times can be loaded at the same time since their APIs are accessed through different dispatch vectors.

By default, there will be a single dispatch vector, referenced from a global variable (sp_GlobalSICStus). A SICStus API functions, such as SP_query, is then defined as a macro that expands to something similar to sp_GlobalSICStus->SP_query_pointer. The name of the global dispatch vector is subject to change without notice; it should not be referenced directly. If you need to access the dispatch vector, use the C macro SICStusDISPATCHVAR instead, see below.

Using a Single SICStus Run-Time

When building an application with spld, by default only one SICStus run-time can be loaded in the process. This is similar to the case in SICStus versions prior to 3.9. For most applications built with spld, the changes necessary to support multiple SICStus run-times should be invisible, and old code should only need to be rebuilt with spld.

In order to maintain backward compatibility, the global dispatch vector is automatically set up by SP_initialize. Other SICStus API functions will not set up the dispatch vector, and will therefore lead to memory access errors if called before SP_initialize. Currently, hook functions such as SP_set_memalloc_hooks also set up the dispatch vector to allow them to be called before SP_initialize. However, only SP_initialize is guaranteed to set up the dispatch vector. The hook installation functions may change to use a different mechanism in the future. The SICStus API functions that perform automatic setup of the dispatch vector are marked with SPEXPFLAG_PREINIT in sicstus.h.

Using More than One SICStus Run-Time

Using more than one SICStus run-time in a process is only supported when the dynamic library version of the SICStus run-time is used (e.g, sprt39.dll, libsprt39.so).

An application that wants to use more than one SICStus run-time needs to be built using the --multi-sp-aware argument to spld. C-code compiled by spld --multi-sp-aware will have the C preprocessor macro MULTI_SP_AWARE defined and non-zero.

Unlike the single run-time case described above, an application built with --multi-sp-aware will not have a global variable that holds the dispatch vector. Instead, your code will have to take steps to ensure that the appropriate dispatch vector is used when switching between SICStus run-times.

There are several steps needed to access a SICStus run-time from an application built with --multi-sp-aware.

  1. You must obtain the dispatch vector of the initial SICStus run-time using SP_get_dispatch(). Note that this function is special in that it is not accessed through the dispatch vector; instead, it is exported in the ordinary manner from the SICStus run-time dynamic library (sprt39.dll on Windows and, typically, libsprt39.so on UNIX).
  2. You must ensure that SICStusDISPATCHVAR expands to something that references the dispatch vector obtained in step 1.

    The C pre-processor macro SICStusDISPATCHVAR should expand to a SICSTUS_API_STRUCT_TYPE *, that is, a pointer to the dispatch vector that should be used. When --multi-sp-aware is not used SICStusDISPATCHVAR expands to sp_GlobalSICStus as described above. When using --multi-sp-aware it is probably best to let SICStusDISPATCHVAR expand to a local variable.

  3. Once you have access to the SICStus API of the initial SICStus run-time you can call the SICStus API function SP_load_sicstus_run_time to load additional run-times.
     SICSTUS_API_STRUCT_TYPE *SP_get_dispatch(void *reserved);
     

SP_get_dispatch returns the dispatch vector of the SICStus run-time. The argument reserved should be NULL. This function can be called from any thread.

     typedef SICSTUS_API_STRUCT_TYPE *SP_get_dispatch_type(void *);
     
     int SP_load_sicstus_run_time(SP_get_dispatch_type **ppfunc, void **phandle);
     

SP_load_sicstus_run_time loads a new SICStus run-time. SP_load_sicstus_run_time returns zero if a new run-time could not be loaded. If a new run-time could be loaded a non-zero value is returned and the address of the SP_get_dispatch function of the newly loaded SICStus run-time is stored at the address ppfunc. The second argument, phandle, is reserved and should be NULL.

As a special case, if SP_load_sicstus_run_time is called from a SICStus run-time that has not been initialized (with SP_initialize) and that has not previously been loaded as the result of calling SP_load_sicstus_run_time, then no new run-time is loaded. Instead, the SP_get_dispatch of the run-time itself is returned. In particular, the first time SP_load_sicstus_run_time is called on the initial SICStus run-time, and if this happens before the initial SICStus run-time is initialized, then no new run-time is loaded.

Calling SP_load_sicstus_run_time from a particular run-time can be done from any thread.

An application that links statically with the SICStus run-time should not call SP_load_sicstus_run_time.

You should not use pre-linked foreign resources when using multiple SICStus run-times in the same process.

For an example of loading and using multiple SICStus run-times, see library/jasper/spnative.c that implements this functionality for the Java interface Jasper.