If the ABL procedure that has the ABL CALL statement is deployed to a PAS for OpenEdge instance, ensure the C source code is thread safe to take advantage of the multi-threaded functionality of the PAS for OpenEdge multi-session agent. Otherwise, C function calls are serialized.

Use the following guidelines to ensure your C source code is thread safe:
  • Change calls to non-thread safe C run-time library functions in your C source code to thread safe implementations:
    1. Make a list of all the C run-time library function calls in the C source code.
    2. Classify the calls as thread safe and non-thread safe.
      Note: Interposing a function is the act of substituting an original function with a custom wrapper function.
    3. For non-thread safe function calls, ignore function calls that are interposed in the following Progress executables:
      • _progres for the ABL client
      • _mproapsv for the PAS for OpenEdge multi-session agent
      You are left with references to C run-time library functions that do not have thread safe implementations.

      For the complete list of C run-time library functions interposed in OpenEdge, see C run-time library functions interposed in the OpenEdge code.

    4. Change the remaining references to their thread safe versions.
  • Reduce the usage of non-constant global variables in your source code:
    1. Make a list of all the non-constant global variables in your source code.
    2. Review the list.
    3. If there are global variables in the list which can be marked constant, then mark them so.
  • Localize the remaining non-constant global variables:
    1. Move your global variables into a single structure.

      For example:

      struct myglobaldata { /* obviously, name this whatever you want*/ 
      int tls_foo; /* global called foo */
      struct datastruct *tls_pmydata; /* global called pmydata etc. */
      };
    2. Allocate and initialize the myglobaldata structure each time proHLC_InitSession() is called.
    3. Register myglobaldata with proSetGlobalStruct().

      When proHLC_ExitSession() is called, clean up your global pointers and release myglobaldata.

      Whenever the C code needs to access a non-constant global variable, the code:
      1. Retrieves the allocated structure by calling proGetGlobalStruct().
      2. Accesses the non-constant global variable in the retrieved structure.
    4. Define a thread variable for your myglobaldata structure. For example:

      On Unix

      __thread struct myglobaldata *pmygd; /* defined once */
      extern __thread struct myglobaldata *pmygd; /* everywhere you need access */

      On Windows

      _declspec (thread) struct myglobaldata *pmygd; /* defined once */
      _declspec (thread) __thread struct myglobaldata *pmygd; /* everywhere you need it */
    5. Set the thread variable each time PRODSP() is called. For example:
      pmygd = (struct myglobaldata *) proGetGlobalStruct(); /* retrieves */
    6. Change global references so the code accesses them via the thread variable.

      For example, foo = 10; becomes pmygd->tls_foo = 10;. Since pmygd is set when PRODSP() is called, it is available for as long as you need it.

    7. If you have multiple global references, consider using a #define schema in your code. Include a #define schema wherever you need access to a global variable. For example:

      #define foo pmygd->tls_foo

  • Avoid loading an extra DLL or shared object from the C source code. If you must load an extra DLL or shared object:
    • Confirm the DLL or shared object is thread safe.
    • Serialize the loading operation using synchronization mechanisms available in the C library.
    • Ensure the DLL or shared object is loaded only once and not by multiple threads.
  • After you build the HLC library, perform the following checks:
    • Validate the global variables in the HLC library are thread safe (for example, using the nm command).
    • Validate the C run-time library function calls made by the HLC library are thread safe (for example, using the nm command). When you build your HLC library on AIX, include csmtcrt.o so that the library uses thread safe implementations of the C run-time library functions.