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

425 lines
16 KiB
HTML

<!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_TRACE_NP()--Macro to optionally execute code based on trace
level</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_TRACE_NP()--Macro to optionally execute code based on trace
level</h2>
<div class="box" style="width: 60%;">
<br>
&nbsp;&nbsp;Syntax:
<pre>
#include &lt;pthread.h&gt;
PTHREAD_TRACE_NP( optionalCode, desiredTraceLevel );
</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: No<br>
<!-- iddvc RMBR -->
<br>
</div>
<p>An application can use the <strong>PTHREAD_TRACE_NP</strong>() macro to
execute optional code based on the current application trace level. The
<em>optionalCode</em> to be executed can include multiple statements and can be
surrounded by the C/C++ begin/end block operators (the curly brackets { }). The
<em>optionalCode</em> can include pre-condition or post-condition logic,
tracepoint information, or any other desired C/C++ statements.</p>
<p>If the current application trace level is set to a level equal to or higher
than the <em>desiredTraceLevel</em>, then the code executes.</p>
<p>The current Pthread library trace level is set automatically when a program
or service program that uses the Pthread APIs causes the Pthread APIs to be
loaded (activated) or when the application explicitly calls the
<strong>pthread_trace_init_np</strong>() function. In either case, the Pthreads
library trace level is set based on the value of the
<strong>QIBM_PTHREAD_TRACE_LEVEL</strong> environment variable at that
time.</p>
<p>If the preprocessor value <strong>PTHREAD_TRACE_NDEBUG</strong> is defined,
then the call to <strong>PTHREAD_TRACE_NP</strong>() is compiled out and does
not generate any executable runtime code. Use
<strong>PTHREAD_TRACE_NDEBUG</strong> for production level code that should not
perform any tracing, or leave tracepoints in the code to assist user's of your
application.</p>
<p>The <strong>pthread_trace_init_np</strong>() API initializes or refreshes
both the Pthreads library trace level and the application trace level. The
Pthreads library trace level is maintained internally by the Pthreads library,
while the application trace level is stored in the <em>Qp0wTraceLevel</em>
external variable, and can be used by the <strong>PTHREAD_TRACE_NP</strong>()
macro.</p>
<p>The <strong>PTHREAD_TRACE_NP</strong>() macro uses the external variable
<em>Qp0wTraceLevel</em>. <em>Qp0wTraceLevel</em> may be used directly by the
application to set application trace level without effecting the current
Pthread library trace level. Set the value of <em>Qp0wTraceLevel</em> to one of the following:</p>
<ul>
<li><strong>PTHREAD_TRACE_NONE_NP</strong><br><br></li>
<li><strong>PTHREAD_TRACE_ERROR_NP</strong><br><br></li>
<li><strong>PTHREAD_TRACE_INFO_NP</strong><br><br></li>
<li><strong>PTHREAD_TRACE_VERBOSE_NP</strong></li>
</ul>
<p>For consistent tracing behavior, the application should use the following
table as a guide to choosing value of the <em>desiredTraceLevel</em>
parameter.</p>
<table border width="80%" cellpadding="5">
<tr>
<th valign="top">Desired Trace Level</th>
<th valign="top">Description</th>
</tr>
<tr>
<td align="left" valign="top" width="40%">
<strong>PTHREAD_TRACE_NONE_NP</strong></td>
<td align="left" valign="top" width="60%">The <em>optionalCode</em> always
runs, even when the current trace level is set to none. It is recommended that
this level is only used at development time.</td>
</tr>
<tr>
<td align="left" valign="top"><strong>PTHREAD_TRACE_ERROR_NP</strong></td>
<td align="left" valign="top">The <em>optionalCode</em> runs if the current
trace level is set to an error level or higher. Use the error level to trace
error conditions and the reasons for error return codes.</td>
</tr>
<tr>
<td align="left" valign="top"><strong>PTHREAD_TRACE_INFO_NP</strong></td>
<td align="left" valign="top">The <em>optionalCode</em> runs if the current
trace level is set to an informational level or higher. Use the informational
level to trace functions' entry and exit, functions' parameters and return
codes and major changes in control flow.</td>
</tr>
<tr>
<td align="left" valign="top"><strong>PTHREAD_TRACE_VERBOSE_NP</strong></td>
<td align="left" valign="top">The <em>optionalCode</em> runs if the current
trace level is set to a verbose level or higher. Use the Verbose level traces
informational level tracepoints, plus detailed information about application
parameters, threads and data structures including information about Pthreads
library processing information.</td>
</tr>
</table>
<p>The <strong>PTHREAD_TRACE_NP</strong>() macro can be used in conjunction
with the following APIs to put trace records into the user trace flight
recorder. The following system APIs defined in the qp0ztrc.h header file:</p>
<ul>
<li>Qp0zUprintf - print formatted trace data</li>
<li>Qp0zDump - dump formatted hex data</li>
<li>Qp0zDumpStack - dump the call stack of the calling thread</li>
<li>Qp0zDumpTargetStack - dump the call stack of the target thread</li>
</ul>
<p>The trace records are written to the user trace flight recorder and can be
accessed by the following CL commands:</p>
<ul>
<li>DMPUSRTRC - dump the contents of a specified job's trace</li>
<li>CHGUSRTRC - change attributes (size, wrapping, clear) of a specified job's
trace</li>
<li>DLTUSRTRC - delete the persistent trace object associated with a job's
trace</li>
</ul>
<br>
<h3>Authorities and Locks</h3>
<p>None.</p>
<br>
<h3>Parameters</h3>
<p>None.</p>
<br>
<h3>Return Value</h3>
<p>None.</p>
<br>
<h3>Error Conditions</h3>
<p>None.</p>
<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_h1.htm">pthread_trace_init_np()</a>--Initialize or Re-initialize
pthread tracing</li>
</ul>
<br>
<h3>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;stdlib.h&gt;
#include &lt;unistd.h&gt;
#include &lt;qp0ztrc.h&gt;
#define checkResults(string, val) { \
if (val) { \
printf("Failed with %d at %s", val, string); \
exit(1); \
} \
}
typedef struct {
int threadSpecific1;
int threadSpecific2;
} threadSpecific_data_t;
#define NUMTHREADS 2
pthread_key_t threadSpecificKey;
void foo(void);
void bar(void);
void dataDestructor(void *);
void *theThread(void *parm) {
int rc;
threadSpecific_data_t *gData;
PTHREAD_TRACE_NP({
Qp0zUprintf("Thread Entered\n");
Qp0zDump("Global Data", parm, sizeof(threadSpecific_data_t));},
PTHREAD_TRACE_INFO_NP);
gData = (threadSpecific_data_t *)parm;
rc = pthread_setspecific(threadSpecificKey, gData);
checkResults("pthread_setspecific()\n", rc);
foo();
return NULL;
}
void foo() {
threadSpecific_data_t *gData =
(threadSpecific_data_t *)pthread_getspecific(threadSpecificKey);
PTHREAD_TRACE_NP(Qp0zUprintf("foo(), threadSpecific data=%d %d\n",
gData-&gt;threadSpecific1, gData-&gt;threadSpecific2);,
PTHREAD_TRACE_INFO_NP);
bar();
PTHREAD_TRACE_NP(Qp0zUprintf("foo(): This is an error tracepoint\n");,
PTHREAD_TRACE_ERROR_NP);
}
void bar() {
threadSpecific_data_t *gData =
(threadSpecific_data_t *)pthread_getspecific(threadSpecificKey);
PTHREAD_TRACE_NP(Qp0zUprintf("bar(), threadSpecific data=%d %d\n",
gData-&gt;threadSpecific1, gData-&gt;threadSpecific2);,
PTHREAD_TRACE_INFO_NP);
PTHREAD_TRACE_NP(Qp0zUprintf("bar(): This is an error tracepoint\n");
Qp0zDumpStack("This thread's stack at time of error in bar()");,
PTHREAD_TRACE_ERROR_NP);
return;
}
void dataDestructor(void *data) {
PTHREAD_TRACE_NP(Qp0zUprintf("dataDestructor: Free data\n");,
PTHREAD_TRACE_INFO_NP);
pthread_setspecific(threadSpecificKey, NULL); free(data);
/* If doing verbose tracing we'll even write a message to the job log */
PTHREAD_TRACE_NP(Qp0zLprintf("Free'd the thread specific data\n");,
PTHREAD_TRACE_VERBOSE_NP);
}
/* Call this testcase with an optional parameter 'PTHREAD_TRACING' */
/* If the PTHREAD_TRACING parameter is specified, then the */
/* Pthread tracing environment variable will be set, and the */
/* pthread tracing will be re initialized from its previous value. */
/* NOTE: We set the trace level to informational, tracepoints cut */
/* using PTHREAD_TRACE_NP at a VERBOSE level will NOT show up*/
int main(int argc, char **argv) {
pthread_t thread[NUMTHREADS];
int rc=0;
int i;
threadSpecific_data_t *gData;
char buffer[50];
PTHREAD_TRACE_NP(Qp0zUprintf("Enter Testcase - %s\n", argv[0]);,
PTHREAD_TRACE_INFO_NP);
if (argc == 2 &amp;&amp; !strcmp("PTHREAD_TRACING", argv[1])) {
/* Turn on internal pthread function tracing support */
/* Or, use ADDENVVAR, CHGENVVAR CL commands to set this envvar*/
sprintf(buffer, "QIBM_PTHREAD_TRACE_LEVEL=%d", PTHREAD_TRACE_INFO_NP);
putenv(buffer);
/* Refresh the Pthreads internal tracing with the environment */
/* variables value. */
pthread_trace_init_np();
}
else {
/* Trace only our application, not the Pthread code */
Qp0wTraceLevel = PTHREAD_TRACE_INFO_NP;
}
rc = pthread_key_create(&amp;threadSpecificKey, dataDestructor);
checkResults("pthread_key_create()\n", rc);
for (i=0; i &lt;NUMTHREADS; ++i) {
PTHREAD_TRACE_NP(Qp0zUprintf("Create/start a thread\n");,
PTHREAD_TRACE_INFO_NP);
/* Create per-thread threadSpecific data and pass it to the thread */
gData = (threadSpecific_data_t *)malloc(sizeof (threadSpecific_data_t));
gData-&gt;threadSpecific1 = i;
gData-&gt;threadSpecific2 = (i+1)*2;
rc = pthread_create( &amp;thread[i], NULL, theThread, gData);
checkResults("pthread_create()\n", rc);
PTHREAD_TRACE_NP(Qp0zUprintf("Wait for the thread to complete, "
"and release their resources\n");,
PTHREAD_TRACE_INFO_NP);
rc = pthread_join(thread[i], NULL);
checkResults("pthread_join()\n", rc);
}
pthread_key_delete(threadSpecificKey);
PTHREAD_TRACE_NP(Qp0zUprintf("Main completed\n");,
PTHREAD_TRACE_INFO_NP);
return 0;
}
</pre>
<p><strong>Output</strong></p>
<p>Use CL command <strong>DMPUSRTRC</strong> to output the following tracing
information that the example creates. The <strong>DMPUSRTRC</strong> CL command
causes the following information to be put into file QTEMP/QAP0ZDMP or to
standard output depending on the options used for the CL command.</p>
<p>Note the following:</p>
<ul>
<li>The trace records are indented and labeled based on thread id plus a
microsecond timestamp at the time the tracepoint was cut. In the following
trace record, the value <em>0000000D</em> indicates the thread ID of the thread
that created the tracepoint. The value <em>133520</em> indicates that the
tracepoint occurred 133520 microseconds after the last timestamp indicator.
<pre>
0000000D:133520 Create/start a thread
</pre>
</li>
<li>You can use the Pthread library tracepoints to debug incorrect calls to the
Pthreads library from your application.</li>
<li>The following trace output occurs when the optional parameter
'PTHREAD_TRACING' is NOT specified when calling this program. Since
'PTHREAD_TRACING' is not specified, the application directly sets the
<em>Qp0wTraceLevel</em> external variable, causing only application level
tracing to occur, and skiping any Pthreads library tracing.</li>
</ul>
<pre>
User Trace Dump for job 096932/KULACK/PTHREADT. Size: 300K, Wrapped 0 times.
--- 11/06/1998 11:06:57 ---
0000000D:133520 Create/start a thread
0000000D:293104 Wait for the thread to complete, and release their resources
0000000E:294072 Thread Entered
0000000E:294272 DB51A4C80A:001CD0 L:0008 Global Data
0000000E:294416 DB51A4C80A:001CD0 00000000 00000002 *................*
0000000E:294496 foo(), threadSpecific data=0 2
0000000E:294568 bar(), threadSpecific data=0 2
0000000E:294624 bar(): This is an error tracepoint
0000000E:294680 Stack Dump For Current Thread
0000000E:294736 Stack: This thread's stack at time of error in bar()
0000000E:333872 Stack: Library / Program Module Stmt Procedure
0000000E:367488 Stack: QSYS / QLESPI QLECRTTH 774 : LE_Create_Thread2__FP12crtth_parm_t
0000000E:371704 Stack: QSYS / QP0WPTHR QP0WPTHR 1008 : pthread_create_part2
0000000E:371872 Stack: KULACK / PTHREADT PTHREADT 19 : theThread__FPv
0000000E:371944 Stack: KULACK / PTHREADT PTHREADT 29 : foo__Fv
0000000E:372016 Stack: KULACK / PTHREADT PTHREADT 46 : bar__Fv
0000000E:372104 Stack: QSYS / QP0ZCPA QP0ZUDBG 87 : Qp0zDumpStack
0000000E:379248 Stack: QSYS / QP0ZSCPA QP0ZSCPA 276 : Qp0zSUDumpStack
0000000E:379400 Stack: QSYS / QP0ZSCPA QP0ZSCPA 287 : Qp0zSUDumpTargetStack
0000000E:379440 Stack: Completed
0000000E:379560 foo(): This is an error tracepoint
0000000E:379656 dataDestructor: Free data
0000000D:413816 Create/start a thread
0000000D:414408 Wait for the thread to complete, and release their resources
0000000F:415672 Thread Entered
0000000F:415872 DB51A4C80A:001CD0 L:0008 Global Data
0000000F:416024 DB51A4C80A:001CD0 00000001 00000004 *................*
0000000F:416104 foo(), threadSpecific data=1 4
0000000F:416176 bar(), threadSpecific data=1 4
0000000F:416232 bar(): This is an error tracepoint
0000000F:416288 Stack Dump For Current Thread
0000000F:416344 Stack: This thread's stack at time of error in bar()
0000000F:416552 Stack: Library / Program Module Stmt Procedure
0000000F:416696 Stack: QSYS / QLESPI QLECRTTH 774 : LE_Create_Thread2__FP12crtth_parm_t
0000000F:416784 Stack: QSYS / QP0WPTHR QP0WPTHR 1008 : pthread_create_part2
0000000F:416872 Stack: KULACK / PTHREADT PTHREADT 19 : theThread__FPv
0000000F:416952 Stack: KULACK / PTHREADT PTHREADT 29 : foo__Fv
0000000F:531432 Stack: KULACK / PTHREADT PTHREADT 46 : bar__Fv
0000000F:531544 Stack: QSYS / QP0ZCPA QP0ZUDBG 87 : Qp0zDumpStack
0000000F:531632 Stack: QSYS / QP0ZSCPA QP0ZSCPA 276 : Qp0zSUDumpStack
0000000F:531704 Stack: QSYS / QP0ZSCPA QP0ZSCPA 287 : Qp0zSUDumpTargetStack
0000000F:531744 Stack: Completed
0000000F:531856 foo(): This is an error tracepoint
0000000F:531952 dataDestructor: Free data
0000000D:532528 Main completed
</pre>
<br>
<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>