__dsa_prev() — Chain back to previous DSA

Purpose

The __dsa_prev() function returns the address of the DSA prior to dsa_p on the Language Environment® stack. Two types of backchaining request are supported -- logical and physical. The req_type parameter is used to select either logical or physical backchaining. For physical backchaining, the address of the DSA immediately prior to dsa_p is always returned. That DSA can be a transition or overflow DSA, or the DSA of a normal routine. For logical backchaining, __dsa_prev() keeps looking backward on the Language Environment stack until a normal DSA is found, skipping over any transition or overflow DSAs.

If the dummy Language Environment DSA is reached while backchaining, a NULL pointer is returned, and errno is set to ESRCH.

__dsa_prev() can be used when the Language Environment stack of interest is not in the current address space. To access storage outside the current address space, the user must provide the callback_p parameter. callback_p is a pointer to a user-written function that fetches all required data for __dsa_prev(). Generally, the (*callback_p)() function would obtain the data using some application-dependent method (like BPX1PTR) and move it into the current address space, where __dsa_prev() can access it directly. If the Language Environment stack of interest is in the same address space and is directly accessible to __dsa_prev(), callback_p can be NULL.

Syntax

#include <edcwccwi.h>

void __dsa_prev(const void * dsa_p, int req_type, int dsa_fmt, void * (*callback_p)(void *data_p, size_t data_l), const void *caa_p, int *prev_fmt, void **ph_callee_dsa_p, int *ph_callee_dsa_fmt);

const void *dsa_p
Pointer to the current DSA. __dsa_prev() returns a pointer to the DSA logically or physically previous to dsa_p, depending on the value of the req_type parameter. dsa_p may point to a DSA in another address space or in some other place not directly accessible by __dsa_prev(). If this address is not directly accessible, the callback_p parameter must be non-NULL. The callback function will be used to access dsa_p indirectly.
int req_type
Controls if transition DSAs are returned. The allowed values for req_type are:
__EDCWCCWI_PHYSICAL
Physical backchaining causes __dsa_prev() to return the address of the DSA immediately prior to dsa_p. The returned DSA can be either a transition or normal DSA.
__EDCWCCWI_LOGICAL
Logical backchaining causes __dsa_prev() to skip over any transition DSAs that it finds while backchaining, and not pass them back. The address of the most recent normal DSA previous to dsa_p is returned. Doing logical backchaining is the same as doing physical backchaining one or more times, stopping when a normal DSA is found.
int dsa_fmt
The format of the DSA pointed to by dsa_p. The allowed value for dsa_fmt is:
__EDCWCCWI_DOWN
This value indicates that dsa_p points to a 64–bit DSA.
void * (*callback_p)()
Pointer to a user-provided function that fetches data not normally accessible by __dsa_prev(). If callback_p is NULL, __dsa_prev() accesses dsa_p and any other required Language Environment data areas directly in the current address space. The Language Environment stack and all other data needed for backchaining must be directly accessible to __dsa_prev() in this case.

The user-provided (*callback_p)() function is passed the address and length of data to access. It must fetch the data in some application-dependent manner, and make the data available in the current address space in a place accessible to __dsa_prev(). (*callback_p )() must return a pointer to the copied data. This data must remain available to __dsa_prev() until the next call to (*callback_p)(), or until __dsa_prev() returns to its caller, whichever happens first. On subsequent calls, (*callback_p)() is allowed to reuse the same data passback area.

There is no provision for (*callback_p)() to pass back an error return code, indicating that the requested data could not be obtained. If (* callback_p)() cannot return the requested data, it must not return to __dsa_prev(). When an error occurs, (*callback_p)() may:
  • longjmp() back to some error return point in the user code that called __dsa_prev().
  • ABEND or otherwise terminate abnormally.
  • exit(), pthread_exit(), etc.
  • Raise a caught signal where the catcher does longjmp() so as not to return to __dsa_prev().
  • Use Language Environment condition management to bypass __dsa_prev() after the error and resume in user code.
  • Recover in some other way that does not involve returning to __dsa_prev().
__dsa_prev() calls (*callback_p)() with two parameters:
void *data_p
Pointer to the start of the required data. This address might not be in the current address space.
size_t data_l
The number of bytes of data required. data_l will never exceed 16 bytes. If (*callback_p)() cannot pass back the complete data requested, it must not return to __dsa_prev().
const void *caa_p
Pointer to the Language Environment CAA for the thread owning the dsa_p DSA. This parameter must be non-NULL whenever callback_p is non-NULL, and it may point to a CAA in some other address space. If callback_p is NULL, caa_p may also be NULL. If caa_p is NULL, the current CAA (of the thread where __dsa_prev() is running) is used. In this case, it is assumed that dsa_p points to a DSA on the Language Environment stack for the caller's thread.
int *prev_fmt
Pointer to an optional passback area where __dsa_prev() will return the DSA format of the prior DSA. The possible values passed back in this field are the same as the values for dsa_fmt.

If prev_fmt is NULL, the DSA format for the previous DSA is not passed back. If __dsa_prev() cannot find the previous DSA and returns a NULL value, the field pointed to by prev_fmt is not altered.

void **ph_callee_dsa_p
Pointer to an optional passback area where __dsa_prev() will return the address of the DSA of the physical callee. The physical callee is the function called by the function owning the returned DSA. The physical callee can be a Language Environment overflow or stack expansion routine, or it can be a normal user or Language Environment function. If physical backchaining is requested, *ph_callee_dsa_p will be the same as dsa_p after __dsa_fmt() returns.

If ph_callee_dsa_p is NULL, the address of the physical callee DSA is not passed back.

If __dsa_prev() cannot find the previous DSA and returns a NULL value, the field pointed to by ph_callee_dsa_p is not altered.

int *ph_callee_dsa_fmt
ph_callee_dsa_fmt is a pointer to an optional passback area where __dsa_prev() will return the DSA format of the physical callee's DSA. The possible values passed back in this field are the same as the values for dsa_fmt.

If ph_callee_dsa_fmt is NULL, the format of the physical callee DSA is not passed back. If __dsa_prev() cannot find the previous DSA and returns a NULL value, the field pointed to by ph_callee_dsa_fmt is not altered.

Return values

  • If successful, __dsa_prev() returns the address of the previous DSA. In addition, if errno is zero when __dsa_prev() is called, one of the following errno values may be set to pass back additional information:
    EACCES
    TIndicates that the returned DSA pointer is for the Language Environment dummy DSA (pointed to by the CAA ceecaaddsa field). This is not an error, and all returned or passed-back information is valid.
    EALREADY
    Indicates that the input DSA pointer (dsa_p) is for the Language Environment dummy DSA (pointed to by the CAA CEECAADDSA field). This is not an error, and all returned or passed-back information is valid.
  • If unsuccessful, __dsa_prev() returns a NULL pointer, and sets errno to one of the following values:
    ESRCH
    Indicates that there was no DSA previous to dsa_p that could satisfy the physical or logical backchaining request. This error also occurs if dsa_p is NULL when __dsa_prev() is called.
    EINVAL
    This error can occur if:
    • caa_p was NULL and callback_p was not NULL.
    • req_type was not __EDCWCCWI_PHYSICAL or __EDCWCCWI_LOGICAL.
    • dsa_fmt was not __EDCWCCWI_DOWN.

Usage notes

  • If the return code from __dsa_prev() is NULL, the listed errno values are set even if errno was non-zero when __dsa_pr() was called. When the return code from __dsa_pr() is not NULL, errno is not changed if it was not zero when __dsa_prev() was called.
  • __dsa_prev() may cause program checks if it accesses invalid addresses. This is especially likely to happen if callback_p is NULL and the Language Environment stack being looked at is corrupted. For this reason, the caller should consider having a signal catcher set up to handle SIGSEGV with appropriate error recovery.
  • The Vendor Interfaces header file, <edcwccwi.h>, is located in member EDCWCCWI of the SCEESAMP data set. In order to include <edcwccwi.h> in an application, the header file must be copied into a PDS or into a directory in the z/OS® UNIX file system where the C/C++ compiler will find it.