ibm-information-center/dist/eclipse/plugins/i5OS.ic.apis_5.4.0.1/users_72.htm

655 lines
23 KiB
HTML
Raw Permalink Normal View History

2024-04-02 14:02:31 +00:00
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Copyright" content="Copyright (c) 2006 by IBM Corporation">
<title>pthread_condattr_setpshared()--Set Process Shared Attribute in Condition
Attributes Object</title>
<!-- All rights reserved. Licensed Materials Property of IBM -->
<!-- US Government Users Restricted Rights -->
<!-- Use, duplication or disclosure restricted by -->
<!-- GSA ADP Schedule Contract with IBM Corp. -->
<!-- Begin Header Records ========================================== -->
<!-- NETMG2 SCRIPT A converted by B2H R4.1 (346) (CMS) by HOLTJM at -->
<!-- RCHVMW2 on 29 Jan 1999 at 10:01:37 -->
<!--File Edited November 2001 -->
<!--End Header Records -->
<link rel="stylesheet" type="text/css" href="../rzahg/ic.css">
</head>
<body>
<!-- Java sync-link -->
<script language="Javascript" src="../rzahg/synch.js" type="text/javascript">
</script>
<a name="Top_Of_Page"></a>
<h2>pthread_condattr_setpshared()--Set Process Shared Attribute in Condition
Attributes Object</h2>
<div class="box" style="width: 60%;">
<br>
&nbsp;&nbsp;Syntax:
<pre>
#include &lt;pthread.h&gt;
int pthread_condattr_setpshared(pthread_condattr_t *attr,
int pshared);
</pre>
&nbsp;&nbsp;Service Program Name: QP0WPTHR<br>
<!-- iddvc RMBR -->
<br>
&nbsp;&nbsp;Default Public Authority: *USE <br>
<!-- iddvc RMBR -->
<br>
&nbsp;&nbsp;Threadsafe: Yes<br>
<!-- iddvc RMBR -->
<br>
&nbsp;&nbsp;Signal Safe: Yes<br>
<!-- iddvc RMBR -->
<br>
</div>
<p>The <strong>pthread_condattr_setpshared</strong>() function sets the current
pshared attribute for the condition attributes object. The process shared
attribute indicates whether the condition that is created using the condition
attributes object can be shared between threads in separate processes
(<strong>PTHREAD_PROCESS_SHARED</strong>) or shared between threads within the
same process (<strong>PTHREAD_PROCESS_PRIVATE</strong>).</p>
<p>Even if the condition is in storage that is accessible from two separate
processes, it cannot be used from both processes unless the process shared
attribute is <strong>PTHREAD_PROCESS_SHARED</strong>.</p>
<p>The default pshared attribute for condition attributes objects is <strong>
PTHREAD_PROCESS_PRIVATE</strong>.</p>
<br>
<h3>Authorities and Locks</h3>
<p>None.</p>
<br>
<h3>Parameters</h3>
<dl>
<dt><strong>attr</strong></dt>
<dd>(Input) Address of the variable containing the condition attributes
object</dd>
<dt><strong>pshared</strong></dt>
<dd>(Input) One of <strong>PTHREAD_PROCESS_SHARED</strong> or <strong>
PTHREAD_PROCESS_PRIVATE</strong></dd>
</dl>
<br>
<h3>Return Value</h3>
<dl>
<dt><strong>0</strong></dt>
<dd><strong>pthread_condattr_setpshared</strong>() was successful.</dd>
<dt><strong>value</strong></dt>
<dd><strong>pthread_condattr_setpshared</strong>() was not successful. <em>
value</em> is set to indicate the error condition.</dd>
</dl>
<br>
<h3>Error Conditions</h3>
<p>If <strong>pthread_condattr_setpshared</strong>() was not successful, the
error condition returned usually indicates one of the following errors. Under
some conditions, the value returned could indicate an error other than those
listed here.</p>
<dl>
<dt><em>[EINVAL]</em></dt>
<dd><p>The value specified for the argument is not correct.</p></dd>
</dl>
<br>
<h3>Related Information</h3>
<ul>
<li>The &lt;<strong>pthread.h</strong>&gt; header file. See <a href=
"rzah4hed.htm">Header files for Pthread functions</a>.<br><br></li>
<li><a href="users_70.htm">pthread_condattr_getpshared()</a>--Get Process Shared
Attribute from Condition Attributes Object<br><br></li>
<li><a href="users_71.htm">pthread_condattr_init()</a>--Initialize Condition
Variable Attributes Object<br><br></li>
<li><a href="users_75.htm">pthread_cond_init()</a>--Initialize Condition
Variable</li>
</ul>
<br>
<h3><a name="371060"></a>Example</h3>
<p>See <a href="../apiref/aboutapis.htm#codedisclaimer">Code disclaimer information</a>
for information pertaining to code examples.</p>
<pre>
#define _MULTI_THREADED
#include &lt;pthread.h&gt;
#include &lt;stdio.h&gt;
#include &lt;spawn.h&gt;
#include &lt;sys/wait.h&gt;
#include &lt;unistd.h&gt;
#include &lt;sys/shm.h&gt;
#include "check.h"
typedef struct {
int eventOccured;
int numberWaiting;
int wokeup;
int reserved[1];
pthread_cond_t cond;
pthread_mutex_t mutex; /* Protects this shared data and condition
*/
} shared_data_t;
extern char **environ;
shared_data_t *sharedMem=NULL;
pid_t childPid=0;
int childStatus=-99;
int shmid=0;
/* Change this path to be the path to where you create this example program */
#define MYPATH "/QSYS.LIB/QP0WTEST.LIB/TPCOSP0.PGM"
#define NTHREADSTHISJOB 2
#define NTHREADSTOTAL 4
void parentSetup(void);
void childSetup(void);
void parentCleanup(void);
void childCleanup(void);
void *parentThreadFunc(void *parm)
{
int rc;
rc = pthread_mutex_lock(&amp;sharedMem-&gt;mutex);
checkResults("pthread_mutex_lock()\n", rc);
/* Under protection of the lock, increment the count */
++sharedMem-&gt;numberWaiting;
while (!sharedMem-&gt;eventOccured) {
printf("PARENT - Thread blocked\n");
rc = pthread_cond_wait(&amp;sharedMem-&gt;cond, &amp;sharedMem-&gt;mutex);
checkResults("pthread_cond_wait()\n", rc);
}
printf("PARENT - Thread awake!\n");
/* Under protection of the lock, decrement the count */
--sharedMem-&gt;numberWaiting;
/* After incrementing the wokeup flage and unlocking the mutex */
/* we no longer use the shared memory, the parent could destroy */
/* it. We indicate we are finished with it using the wokeup flag */
++sharedMem-&gt;wokeup;
rc = pthread_mutex_unlock(&amp;sharedMem-&gt;mutex);
checkResults("pthread_mutex_lock()\n", rc);
return NULL;
}
void *childThreadFunc(void *parm)
{
int rc;
rc = pthread_mutex_lock(&amp;sharedMem-&gt;mutex);
checkResults("pthread_mutex_lock()\n", rc);
/* Under protection of the lock, increment the count */
++sharedMem-&gt;numberWaiting;
while (!sharedMem-&gt;eventOccured) {
printf("CHILD - Thread blocked\n");
rc = pthread_cond_wait(&amp;sharedMem-&gt;cond, &amp;sharedMem-&gt;mutex);
checkResults("pthread_cond_wait()\n", rc);
}
printf("CHILD - Thread awake!\n");
/* Under protection of the lock, decrement the count */
--sharedMem-&gt;numberWaiting;
/* After incrementing the wokeup flage and unlocking the mutex */
/* we no longer use the shared memory, the parent could destroy */
/* it. We indicate we are finished with it using the wokeup flag*/
++sharedMem-&gt;wokeup;
rc = pthread_mutex_unlock(&amp;sharedMem-&gt;mutex);
checkResults("pthread_mutex_lock()\n", rc);
return NULL;
}
int main(int argc, char **argv)
{
int rc=0;
int i;
pthread_t threadid[NTHREADSTHISJOB];
int parentJob=0;
/* If we run this from the QSHELL interpreter on the system, we want */
/* it to be line buffered even if we run it in batch so the output between */
/* parent and child is intermixed. */
setvbuf(stdout,NULL,_IOLBF,4096);
/* Determine if we are running in the parent or child */
if (argc != 1 &amp;&amp; argc != 2) {
printf("Incorrect usage\n");
printf("Pass no parameters to run as the parent testcase\n");
printf("Pass one parameter `ASCHILD' to run as the child testcase\n");
exit(1);
}
if (argc == 1) {
parentJob = 1;
}
else {
if (strcmp(argv[1], "ASCHILD")) {
printf("Incorrect usage\n");
printf("Pass no parameters to run as the parent testcase\n");
printf("Pass one parameter `ASCHILD' to run as the child testcase\n");
exit(1);
}
parentJob = 0;
}
/* PARENT *****************************************************************/
if (parentJob) {
printf("PARENT - Enter Testcase - %s\n", argv[0]);
parentSetup();
printf("PARENT - Create %d threads\n", NTHREADSTHISJOB);
for (i=0; i&lt;NTHREADSTHISJOB; ++i) {
rc = pthread_create(&amp;threadid[i], NULL, parentThreadFunc, NULL);
checkResults("pthread_create()\n", rc);
}
rc = pthread_mutex_lock(&amp;sharedMem-&gt;mutex);
checkResults("pthread_mutex_lock()\n", rc);
while (sharedMem-&gt;numberWaiting != NTHREADSTOTAL) {
printf("PARENT - Waiting for %d threads to wait, "
"currently %d waiting\n",
NTHREADSTOTAL, sharedMem-&gt;numberWaiting);
rc = pthread_mutex_unlock(&amp;sharedMem-&gt;mutex);
checkResults("pthread_mutex_unlock()\n", rc);
sleep(1);
rc = pthread_mutex_lock(&amp;sharedMem-&gt;mutex);
checkResults("pthread_mutex_lock()\n", rc);
}
printf("PARENT - wake up all of the waiting threads...\n");
sharedMem-&gt;eventOccured = 1;
rc = pthread_cond_broadcast(&amp;sharedMem-&gt;cond);
checkResults("pthread_cond_signal()\n", rc);
printf("PARENT - Wait for waking threads and cleanup\n");
while (sharedMem-&gt;wokeup != NTHREADSTOTAL) {
printf("PARENT - Waiting for %d threads to wake, "
"currently %d wokeup\n",
NTHREADSTOTAL, sharedMem-&gt;wokeup);
rc = pthread_mutex_unlock(&amp;sharedMem-&gt;mutex);
checkResults("pthread_mutex_unlock()\n", rc);
sleep(1);
rc = pthread_mutex_lock(&amp;sharedMem-&gt;mutex);
checkResults("pthread_mutex_lock()\n", rc);
}
parentCleanup();
printf("PARENT - Main completed\n");
exit(0);
}
/* CHILD *****************************************************************/
{
void *status=NULL;
printf("CHILD - Enter Testcase - %s\n", argv[0]);
childSetup();
printf("CHILD - Create %d threads\n", NTHREADSTHISJOB);
for (i=0; i&lt;NTHREADSTHISJOB; ++i) {
rc = pthread_create(&amp;threadid[i], NULL, childThreadFunc, NULL);
checkResults("pthread_create()\n", rc);
}
/* The parent will wake up all of these threads using the */
/* pshared condition variable. We will just join to them... */
printf("CHILD - Joining to all threads\n");
for (i=0; i&lt;NTHREADSTHISJOB; ++i) {
rc = pthread_join(threadid[i], &amp;status);
checkResults("pthread_join()\n", rc);
if (status != NULL) {
printf("CHILD - Got a bad status from a thread, "
"%.8x %.8x %.8x %.8x\n", status);
exit(1);
}
}
/* After all the threads are awake, the parent will destroy */
/* the condition and mutex. Do not use it anymore */
childCleanup();
printf("CHILD - Main completed\n");
}
return 0;
}
/***************************************************************/
/* This function initializes the shared memory for the job, */
/* sets up the environment variable indicating where the shared*/
/* memory is, and spawns the child job. */
/* */
/* It creates and initializes the shared memory segment, and */
/* It initializes the following global variables in this */
/* job. */
/* sharedMem */
/* childPid */
/* shmid */
/* */
/* If any of this setup/initialization fails, it will exit(1) */
/* and terminate the test. */
/* */
/***************************************************************/
void parentSetup(void)
{
int rc;
/***************************************************************/
/* Create shared memory for shared_data_t above */
/* attach the shared memory */
/* set the static/global sharedMem pointer to it */
/***************************************************************/
printf("PARENT - Create the shared memory segment\n");
rc = shmget(IPC_PRIVATE, sizeof(shared_data_t), 0666);
if (rc == -1) {
printf("PARENT - Failed to create a shared memory segment\n");
exit(1);
}
shmid = rc;
printf("PARENT - Attach the shared memory\n");
sharedMem = shmat(shmid, NULL, 0);
if (sharedMem == NULL) {
shmctl(shmid, IPC_RMID, NULL);
printf("PARENT - Failed to attach shared memory\n");
exit(1);
}
/***************************************************************/
/* Initialize the mutex/condition and other shared memory data */
/***************************************************************/
{
pthread_mutexattr_t mattr;
pthread_condattr_t cattr;
printf("PARENT - Init shared memory mutex/cond\n");
memset(sharedMem, 0, sizeof(shared_data_t));
/* Process Shared Mutex */
rc = pthread_mutexattr_init(&amp;mattr);
checkResults("pthread_mutexattr_init()\n", rc);
rc = pthread_mutexattr_setpshared(&amp;mattr, PTHREAD_PROCESS_SHARED);
checkResults("pthread_mutexattr_setpshared()\n", rc);
rc = pthread_mutex_init(&amp;sharedMem-&gt;mutex, &amp;mattr);
checkResults("pthread_mutex_init()\n", rc);
/* Process Shared Condition */
rc = pthread_condattr_init(&amp;cattr);
checkResults("pthread_condattr_init()\n", rc);
rc = pthread_condattr_setpshared(&amp;cattr, PTHREAD_PROCESS_SHARED);
checkResults("pthread_condattr_setpshared()\n", rc);
rc = pthread_cond_init(&amp;sharedMem-&gt;cond, &amp;cattr);
checkResults("pthread_cond_init()\n", rc);
}
/**************************************************************/
/* Set and environment variable so that the child can inherit */
/* it and know the shared memory ID */
/**************************************************************/
{
char shmIdEnvVar[128];
sprintf(shmIdEnvVar, "TPCOSP0_SHMID=%d\n", shmid);
rc = putenv(shmIdEnvVar);
if (rc) {
printf("PARENT - Failed to store env var %s, errno=%d\n",
shmIdEnvVar, errno);
exit(1);
}
printf("PARENT - Stored shared memory id of %d\n", shmid);
}
/**************************************************/
/* Spawn the child job */
/**************************************************/
{
inheritance_t in;
char *av[3] = {NULL, NULL, NULL};
/* Allow thread creation in the spawned child */
memset(&amp;in, 0, sizeof(in));
in.flags = SPAWN_SETTHREAD_NP;
/* Set up the arguments to pass to spawn based on the */
/* arguments passed in */
av[0] = MYPATH;
av[1] = "ASCHILD";
av[2] = NULL;
/* Spawn the child that was specified, inheriting all */
/* of the environment variables. */
childPid = spawn(MYPATH, 0, NULL, &amp;in, av, environ);
if (childPid == -1) {
/* spawn failure */
printf("PARENT - spawn() failed, errno=%d\n", errno);
exit(1);
}
printf("PARENT - spawn() success, [PID=%d]\n", childPid);
}
return;
}
/***************************************************************/
/* This function attaches the shared memory for the child job, */
/* It uses the environment variable indicating where the shared*/
/* memory is. */
/* */
/* If any of this setup/initialization fails, it will exit(1) */
/* and terminate the test. */
/* */
/* It initializes the following global variables: */
/* sharedMem */
/* shmid */
/***************************************************************/
void childSetup(void)
{
int rc;
printf("CHILD - Child setup\n");
/**************************************************************/
/* Set and environment variable so that the child can inherit */
/* it and know the shared memory ID */
/**************************************************************/
{
char *shmIdEnvVar;
shmIdEnvVar = getenv("TPCOSP0_SHMID");
if (shmIdEnvVar == NULL) {
printf("CHILD - Failed to get env var \"TPCOSP0_SHMID\", errno=%d\n",
errno);
exit(1);
}
shmid = atoi(shmIdEnvVar);
printf("CHILD - Got shared memory id of %d\n", shmid);
}
/***************************************************************/
/* Create shared memory for shared_data_t above */
/* attach the shared memory */
/* set the static/global sharedMem pointer to it */
/***************************************************************/
printf("CHILD - Attach the shared memory\n");
sharedMem = shmat(shmid, NULL, 0);
if (sharedMem == NULL) {
shmctl(shmid, IPC_RMID, NULL);
printf("CHILD - Failed to attach shared memory\n");
exit(1);
}
return;
}
/***************************************************************/
/* wait for child to complete and get return code. */
/* Destroy mutex and condition in shared memory */
/* detach and remove shared memory */
/* set the child's return code in global storage */
/* */
/* If this function fails, it will call exit(1) */
/* */
/* This function sets the following global variables: */
/* sharedMem */
/* childStatus */
/* shmid */
/***************************************************************/
void parentCleanup(void)
{
int status=0;
int rc;
int waitedPid=0;
/* Even though there is no thread left in the child using the */
/* contents of the shared memory, before we destroy the mutex */
/* and condition in that shared memory, we will wait for the */
/* child job to complete, we know for 100% certainty that no */
/* threads in the child are using it then. */
printf("PARENT - Parent cleanup\n");
/* Wait for the child to complete */
waitedPid = waitpid(childPid,&amp;status,0);
if (rc == -1) {
printf("PARENT - waitpid failed, errno=%d\n", errno);
exit(1);
}
childStatus = status;
/* Cleanup resources */
rc = pthread_mutex_destroy(&amp;sharedMem-&gt;mutex);
checkResults("pthread_mutex_destroy()\n", rc);
rc = pthread_cond_destroy(&amp;sharedMem-&gt;cond);
checkResults("pthread_cond_destroy()\n", rc);
/* Detach/Remove shared memory */
rc = shmdt(sharedMem);
if (rc) {
printf("PARENT - Failed to detach shared memory, errno=%d\n", errno);
exit(1);
}
rc = shmctl(shmid, IPC_RMID, NULL);
if (rc) {
printf("PARENT - Failed to remove shared memory id=%d, errno=%d\n",
shmid, errno);
exit(1);
}
shmid = 0;
return;
}
/***************************************************************/
/* Detach the shared memory */
/* At this point, there is no serialization, so the contents */
/* of the shared memory should not be used. */
/* */
/* If this function fails, it will call exit(1) */
/* */
/* This function sets the following global variables: */
/* sharedMem */
/***************************************************************/
void childCleanup(void)
{
int rc;
printf("CHILD - Child cleanup\n");
rc = shmdt(sharedMem);
sharedMem = NULL;
if (rc) {
printf("CHILD - Failed to detach shared memory, errno=%d\n", errno);
exit(1);
}
return;
}
</pre>
<p><strong>Output:</strong></p>
<p>This example was run under the i5/OS QShell Interpreter. In the QShell
Interpreter, a program gets descriptors 0, 1, and 2 as the standard files; the
parent and child I/O is directed to the console. When run in the QShell
Interpreter, the output shows the intermixed output from both parent and child
processes and gives a feeling for the time sequence of operations occurring in
each job.</p>
<p>The QShell interpreter allows you to run multithreaded programs as if they
were interactive. See the QShell documentation for a description of the
QIBM_MULTI_THREADED shell variable, which allows you to start multithreaded
programs.</p>
<p>The QShell Interpreter is option 30 of Base i5/OS.</p>
<pre>
PARENT - Enter Testcase - QP0WTEST/TPCOSP0
PARENT - Create the shared memory segment
PARENT - Attach the shared memory
PARENT - Init shared memory mutex/cond
PARENT - Stored shared memory id of 862
PARENT - spawn() success, [PID=2651]
PARENT - Create 2 threads
PARENT - Thread blocked
PARENT - Waiting for 4 threads to wait, currently 1 waiting
PARENT - Thread blocked
CHILD - Enter Testcase - QP0WTEST/TPCOSP0
CHILD - Child setup
CHILD - Got shared memory id of 862
CHILD - Attach the shared memory
CHILD - Create 2 threads
CHILD - Thread blocked
CHILD - Joining to all threads
CHILD - Thread blocked
PARENT - wake up all of the waiting threads...
PARENT - Wait for waking threads and cleanup
PARENT - Waiting for 4 threads to wake, currently 0 wokeup
PARENT - Thread awake!
CHILD - Thread awake!
PARENT - Thread awake!
CHILD - Thread awake!
CHILD - Child cleanup
CHILD - Main completed
PARENT - Parent cleanup
PARENT - Main completed
</pre>
<hr>
API introduced: V4R3
<hr>
<center>
<table cellpadding="2" cellspacing="2">
<tr align="center">
<td valign="middle" align="center"><a href="#Top_Of_Page">Top</a> | <a href=
"rzah4mst.htm">Pthread APIs</a> | <a href="aplist.htm">APIs by
category</a></td>
</tr>
</table>
</center>
</body>
</html>