425 lines
16 KiB
HTML
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>
|
||
|
Syntax:
|
||
|
|
||
|
<pre>
|
||
|
#include <pthread.h>
|
||
|
PTHREAD_TRACE_NP( optionalCode, desiredTraceLevel );
|
||
|
</pre>
|
||
|
Service Program Name: QP0WPTHR<br>
|
||
|
<!-- iddvc RMBR -->
|
||
|
<br>
|
||
|
Default Public Authority: *USE<br>
|
||
|
<!-- iddvc RMBR -->
|
||
|
<br>
|
||
|
Threadsafe: Yes<br>
|
||
|
<!-- iddvc RMBR -->
|
||
|
<br>
|
||
|
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 <<strong>pthread.h</strong>> 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 <pthread.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <unistd.h>
|
||
|
#include <qp0ztrc.h>
|
||
|
|
||
|
#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->threadSpecific1, gData->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->threadSpecific1, gData->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 && !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(&threadSpecificKey, dataDestructor);
|
||
|
checkResults("pthread_key_create()\n", rc);
|
||
|
|
||
|
for (i=0; i <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->threadSpecific1 = i;
|
||
|
gData->threadSpecific2 = (i+1)*2;
|
||
|
rc = pthread_create( &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>
|
||
|
|