m_fork(3P)
m_fork, m_kill_procs, m_set_procs, m_get_numprocs, m_get_myid, m_next, m_lock, m_unlock, m_park_procs, m_rele_procs, m_sync - parallel programming primitives
Showing IRIX 6.5.30 (default release). Unchanged since IRIX 6.5.
NAME m_fork, m_kill_procs, m_set_procs, m_get_numprocs, m_get_myid, m_next, m_lock, m_unlock, m_park_procs, m_rele_procs, m_sync - parallel programming primitives C SYNOPSIS #include <ulocks.h> #include <task.h> int m_fork (void (*func)(), ...); int m_kill_procs (void); int m_set_procs (int numprocs); int m_get_numprocs (void); int m_get_myid (void); unsigned m_next (void); void m_lock (void); void m_unlock (void); int m_park_procs (void); int m_rele_procs (void); void m_sync (void); DESCRIPTION The m_fork routine creates n-1 processes that execute the given func in parallel with the calling process. The processes are created using the sproc(2) system call, and share all attributes (virtual address space, file descriptors, uid, etc.). Once the processes are all created, they each start executing the subprogram func taking up to six arguments as passed to m_fork. The arguments passed must not be larger than pointers in size, i.e. floating point numbers must be passed by reference. The processes execute the subprogram and wait until they all return, at which point the m_fork call returns. The other threads are left busy- wait spinning until the master again calls m_fork. The overhead of creating the additional process was done in the first call to m_fork and is not repeated. m_fork sets a flag (see prctl(2)) so that if any of the threads terminate, they will all receive a SIGTERM signal. Certain operations such as profiling require that the various threads exit normally (via the exit(2)) call. This can best be done by using m_kill_procs to terminate the slave threads, then have the master itself exit. The number of subtasks n can be set and queried using m_set_procs and m_get_numprocs, where the default is the number of processors in the system (and hence the maximum number of processes that can truly be run in parallel). Note that although up to 256 tasks may be requested, the busy-wait rendezvous mechanism will usually result in a large performance loss with any more threads than processors. If sproc(2) is used with the PR_SADDR flag (share virtual address space), m_set_procs should not be called more than once in the same program with different values. To set the number of tasks more than once (with different values) in the same program, either use sproc(2) without the PR_SADDR (shared virtual address space) option or use fork instead of sproc(2). When the processes are created, each is assigned a unique thread identifier (its tid). This identifier can be obtained through m_get_myid. Thread id's range from 0 to n-1. A global counter and a global lock are provided to simplify synchronization between the processes. On each m_fork call, the counter is reset to zero. The counter value is gotten and post incremented through the m_next routine. The first time m_next is called, it returns a zero. The global lock is set and unset through m_lock and m_unlock. The m_park_procs and m_rele_procs are provided to suspend and resume the child processes created by m_fork. This is useful if you have a phase of the program where the parent will do setup or reinitialization code and you do not want to have the children spinning and wasting resources. m_park_procs should not be called when processes are already suspended. m_sync is provided to synchronize all threads at some point in the code. When m_sync is called by each thread, it waits at that point for all other threads to call m_sync. The global counter is reset, and all threads resume after the m_sync call. m_kill_procs terminates the processes created from the previous m_fork. Most errors from m_fork come from either sproc(2) or usinit(3P). See those manual pages for more information on errors. NOTES These primitives are based on the Sequent Computer Systems parallel programming primitives, but may not conform to all Sequent semantics. Diagnostic output analyzing the failures in m_lock(3P) and the routines that m_fork calls can be gotten using the _utrace mechanism discussed in the usinit(3P) manual page. m_fork will not work properly if the parent of the current process has also called it. To avoid this problem, the parent should call m_kill_procs prior to forking. SEE ALSO sproc(2), blockproc(2), prctl(2), barrier(3P), usinit(3P), ussetlock(3P). DIAGNOSTICS m_fork, m_set_procs, m_park_procs, m_rele_procs, and m_kill_procs return a 0 when successful, and a -1 with errno set upon failure. m_get_numprocs, m_get_myid, and m_next all return integers. m_lock, m_unlock, and m_sync return no value.