fork (BPX1FRK, BPX4FRK) — Create a new process

Function

The fork callable service creates a new process, called a child process.

Requirements

Operation Environment
Authorization: Supervisor state or problem state, PSW key 8, TCB key 8.
Dispatchable unit mode: Task
Cross memory mode: PASN = HASN
AMODE (BPX1FRK): 31-bit
AMODE (BPX4FRK): 64-bit
ASC mode: Primary mode
Interrupt status: Enabled for interrupts
Locks: Unlocked
Control parameters: All parameters must be addressable by the caller and in the primary address space.

Format

CALL BPX1FRK,(Process_ID,
              Return_code,
              Reason_code)

AMODE 64 callers use BPX4FRK with the same parameters.

Parameters

Process_ID
Returned parameter
Type:
Integer
Length:
Fullword

The name of a fullword in which the fork service places the process ID of the newly created child process, 0, or -1.

Upon successful completion, fork returns the process ID of the newly created child to the calling (parent) process.

Because the child is a duplicate, it contains the same service request to the fork service as the parent. Execution of the child begins with this fork service returning a process ID value of zero; the child then proceeds with normal execution.

If Process_ID is returned as -1, no child process was created, for the reason shown by Return_code.

Return_code
Returned parameter
Type:
Integer
Length:
Fullword
The name of a fullword in which the fork service stores the return code. The fork service returns Return_code only if Process_ID is -1. See z/OS UNIX System Services Messages and Codes for a complete list of possible return code values. The fork service can return one of the following values in the Return_code parameter:
Return_code Explanation
EAGAIN The resources required to let another process be created are not available now; or you have already reached the maximum number of processes you are allowed to run.

The following reason codes can accompany the return code: JRForkExitRcChildNoStorage, JRForkExitRcParentBadEnv, JRForkExitRcParentNoRoom, JRForkNoAccess, JRForkNoResource, JRForkVsmListTooLarge, JRKernelReady, JRMaxChild, JRMaxProc, JRMaxUIDs, JRNoSecurityProduct, JRNotKey8, and JRWlmWonErr.

EINVAL The following reason code can accompany the return code: JRJsrRacXtr.
ENOMEM The process requires more space than is available.
Reason_code
Returned parameter
Type:
Integer
Length:
Fullword

The name of a fullword where the fork service stores the reason code. The fork service returns Reason_code only if Return_value is -1. Reason_code further qualifies the Return_code value. For the reason codes, see z/OS UNIX System Services Messages and Codes.

Usage notes

  1. The new process (called the child process) is a duplicate of the process that calls the fork service (called the parent process), except for the following:
    • The child process has a unique process ID (PID) that does not match any active process group ID.
    • The child has a different parent process ID (namely, the process ID of the process that called the fork service).
    • The child has its own copy of the parent's file descriptors. Each file descriptor in the child refers to the same open file as the corresponding file descriptor in the parent.
    • If an HFS file has its FCTLCLOFORK flag set on, it is not inherited by the child process. This flag is set with the fcntl service. For more information, see fcntl (BPX1FCT, BPX4FCT) — Control open file descriptors.
    • The child has its own copy of the parent's open directory streams. Each open directory stream in the child can share directory stream positioning with the corresponding directory stream of the parent.
    • The process and system utilization times for the child are set to zero.
    • Any file locks previously set by the parent are not inherited by the child.
    • The child process has no interval timers set (similar to the results of a call to the alarm service with Wait_time specified as zero).
    • The child has no pending signals.

    In other respects, for z/OS UNIX the child is identical to the parent.

  2. The child process inherits all key 8 shared memory segments attached to the calling process. The internal values of the number of processes attached to each shared memory segment (shm_nattch) are incremented.

    BPX1FRK only supports the propagation of key 8 storage; therefore, the fork service does not propagate to the child any shared memory segments that reside in a storage key other than key 8.

  3. If the calling address space uses the macro IARVSERV to capture storage, these pages are not copied to the child address space.
  4. The semaphore adjustment values (semadj) are cleared in the child process.
  5. PSW Key 2 mmap storage areas are not propagated to the child.
  6. For AMODE 64 callers, high-memory storage is copied to the child process in the following cases:
    • All storage that is obtained by an IARV64 request made by the forking thread is copied to the child process.
    • All storage that is obtained by an IARV64 request with a user token that contains zeros in bits 0-31 and the parent process's PID in bits 32-64 is copied to the child process. In the child process, the user token is changed to the value of the child process's PID in bits 32-64.
    • All storage that is obtained by an IARV64 request with a user token that contains zeros in bits 0-31 and a nonzero value that matches ThliParentTkn in bits 32-64 (when ThliChildTkn is nonzero) is copied to the child process. In the child process, the user token is changed to the value of ThliChildTkn (from the parent process). This value is also used to initialize ThliParentTkn on the child process.
    • All authorized storage that is obtained by an IARV64 request with a user token that contains zeros in bits 32-64 and the parent process's PID in bits 0-31 is copied to the child process. In the child process, the user token is changed to the value of the child process's PID in bits 0-31.
    • All authorized storage that is obtained by an IARV64 request with a user token that contains zeros in bits 32-64 and the value of PSALAA in bits 0-31 is copied to the child process. In the child process, the user token is changed to the value of the child process's LAA in bits 0-31.

    The child process inherits the MEMLIMIT of the parent.

The child address space inherits the following address space attributes of the parent address space:
  1. Region size
  2. Time limit

Related services

Characteristics and restrictions

Following is a list of characteristics or restrictions for the fork call:
  • The fork service can be requested from either an MVS™ or kernel address space.
  • The fork service is supported from programs running in PSW key 8 only. An additional requirement is that the storage protection key value in the TCBPKF field of the task control block (TCB) must be 8. The fork service from authorized or problem-state programs with a PSW key other than 8 or a TCBPKF value other than 8 is rejected with an error code.
  • Only the following storage subpools are copied by fork: 0–127, 129–132, and 251–252.
  • With the exception of subpool 252, which is all key-0 storage, only the caller's key-8 storage is copied to the child. For subpools that support multiple keys—that is, subpool 129 to subpool 132—only storage obtained with a key of 8 is copied.
  • When the fork service is called from a single-process address space, all storage obtained by all the tasks in the calling jobstep in the given subpools are copied to the child address space.

    When the fork service is called from a multiple-process address space, only storage obtained by the tasks in the calling process in the subpools identified previously are copied to the child address space.

  • The child process always runs in problem program state key of 8, even when it is forked by an APF-authorized MVS process.
  • One task (thread) and one request block (RB) are present in the child address space after the fork service request.

    If the parent was single-task with multiple RBs, only a single RB is created in the child address space after the fork service request. If multiple tasks exist in the parent process, only the task issuing the fork service request is replicated. There is no serialization among the different tasks.

  • The TCB address and the addresses of other MVS control blocks are likely to be different in the child.
  • The fork service does not copy any system subpools or MVS control blocks from the parent to the child, except as noted.

    For example, the task I/O table (TIOT) is not copied. This means that MVS data sets that were allocated in the parent are not allocated to the child, with the exception of the propagated TASKLIB, STEPLIB, or JOBLIB DD data sets. Because user data in user subpools are copied, it is possible that some of those control blocks can point to system control blocks that are no longer present in the child.

    As another example, a user's data control block (DCB) that has been opened in the parent still appears as an opened DCB in the child, but the corresponding system control blocks pointed to by the DCB are not present in the child.

    Only services that are specifically documented as supported can be used across the fork service. For further details, see "MVS-related information" in this topic.

  • There is a limit on the total number of "living" or "zombied" children the parent can have at a time. This limit is set with the MAXPROCUSER parameter in a BPXPRMxx parmlib member. You can retrieve this count with the sysconf service (BPX1SYC, BPX4SYNC).
Although the child process resembles the parent process in many ways, it has specific differences from the parent process. Besides the differences described in POSIX.1 (under fork), the following are some examples of elements in the parent process that are not propagated to the child process:
  • Linkage stack. The caller can have a linkage stack, but the child does not inherit it. If the caller intends to do an exec service request in the child, the loss of the linkage stack is not a problem. It is a problem only if the child process executes a PR (Program Return) instruction that requires the linkage stack.
  • Access list (that is, PASN-AL, DU-AL). The parent's access lists are not propagated to the child.
  • Access registers. Access registers are not propagated to the child, because the child process does not inherit the parent's access list, which would be needed to use the access registers.
  • Virtual pages. Virtual pages that were page-fixed in the parent are not page-fixed in the child.
  • Dynamic resource managers (RESMGRs). Dynamic resource managers that were established for the parent are not propagated to the child.
  • MVS files. Any MVS files that were opened for the parent are not opened for the child process, with the exception of the TASKLIB, STEPLIB or JOBLIB DD data sets that were propagated from the parent process. Only z/OS UNIX files are opened in the child process.
  • Mutexes and condition variables. Ownership of mutexes and condition variables is on a single-thread basis; therefore, these attributes cannot be propagated on fork. Where a mutex or condition variables exists, the thread that is created in the child has access to the shared memory and can use the mutex or condition variable. When it begins running, however, it will not own any mutexes or consume any condition variables.

Examples

For an example using this callable service, see BPX1FRK (fork) example.

MVS-related information

  1. Following is a list of services in the child that relate to the services done in the parent:
    • GETMAIN or FREEMAIN, or STORAGE. If the parent process has issued a GETMAIN macro for a storage block, the child process can issue a FREEMAIN macro for the same storage block.
    • LOAD or DELETE. If a problem state parent process issues a LOAD macro for a module, the child process can issue a DELETE macro to remove the module from storage. If the child process issues a LOAD macro for the same module that was loaded in the parent, the copied version of the module is used and the use count is incremented.

      If a supervisor state parent process issues a LOAD macro for a module, the child process cannot issue a DELETE macro for the module, and it cannot use a LOAD macro to load a new copy of the module.

      A LOAD macro for global storage, however, is not reflected in the child; the child cannot issue a DELETE macro to remove a module that was loaded to a common storage by the parent.

    • CSVQUERY. The EPTOKEN (entry point token) returned as OUTEPTKN on a CSVQUERY macro in the parent can be used by the child as the INEPTKN parameter on a CSVQUERY macro to refer to the same module.
    • ESTAE. The child process can issue an ESTAE macro with a 0 parameter to delete an ESTAE routine established by the parent process.
    • ESPIE. The child process can delete an ESPIE routine established by the parent process.
      Note: No other MVS services are carried across fork. They can be freely used in either the parent process or the child process, as long as it is understood that the result of these services (if performed in the parent process) cannot be available to the child process.
  2. The system propagates the contents directory related information (including extent lists) for the job pack queue for the job step task related to the task issuing the fork call. It also propagates the information on all modules (whether private or in the LPA) that have been loaded by the task issuing the fork call.
  3. The system propagates the current task's SPIE or ESPIE and STAE or ESTAE status to the child process.
    • STAE or ESTAE control blocks representing the current RB are propagated to the child process. Control blocks associated with older RBs are not propagated, nor are STAI or ESTAI control blocks.
    • SPIE or ESPIE control blocks representing the current RB are propagated to the child process. SPIE or ESPIE control blocks associated with older RBs are not propagated.
  4. Security information from the parent's address space is propagated to the child's address space. As a result, the child has a security environment equivalent to that of the parent.
  5. The TASKLIB, STEPLIB, or JOBLIB DD data set allocations that are active for the current task are propagated to the child's address space. This causes the child address space to have the same MVS program search order as the calling parent task.
  6. The accounting information of the parent's address space is propagated to the child's address space. (See Managing accounting work in z/OS UNIX System Services Planning.)

    If the ThliForkAcctg bit is set on in BPXYTHLI — Thread-level information, the fork service creates the child with the accounting data from the RACF® WORKATTR of the user ID that is associated with the last setuid call. If no setuid call has been performed, the accounting information from the parent is used. No error is returned to the caller.

  7. The job name of the parent is propagated to the child and appended with a numeric value in the range of 1–9 if the job name is 7 characters or fewer. If the job name is 8 characters, the job name is propagated as is. When a job name is appended with a numeric value, the count wraps back to 1 when it exceeds 9.
  8. If the calling parent task is in a Work Load Manager (WLM) enclave, the child is joined to the same WLM enclave. This allows WLM to manage the parent and child as one "business unit of work" entity for system accounting and management purposes.
  9. z/OS UNIX sets a default message class of “A” for all forked or spawned processes. Unlike JES, z/OS UNIX does not have a method for accepting a user-supplied default message class, and a default had to be supplied to the converter interpreter. Message class A was chosen as the default for BPXAS initiators. There is currently no way to dynamically change this default value. The MSGCLASS for the joblog (JESMSGLG, JESJCL, JESYSMSG) is set to class A before the fork or spawn that associates the process with the BPXAS initiator is begun.
  10. The user syscall trace setting is propagated to the child process.