235 lines
11 KiB
HTML
235 lines
11 KiB
HTML
|
<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<!DOCTYPE html
|
||
|
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
|
<html lang="en-us" xml:lang="en-us">
|
||
|
<head>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||
|
<meta name="security" content="public" />
|
||
|
<meta name="Robots" content="index,follow" />
|
||
|
<meta http-equiv="PICS-Label" content='(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))' />
|
||
|
<meta name="DC.Type" content="reference" />
|
||
|
<meta name="DC.Title" content="Example: Sample flight recorder output from a Pthread program" />
|
||
|
<meta name="abstract" content="This example shows a Pthread program that is using the flight recorder or tracing interfaces that are provided by the system." />
|
||
|
<meta name="description" content="This example shows a Pthread program that is using the flight recorder or tracing interfaces that are provided by the system." />
|
||
|
<meta name="DC.Relation" scheme="URI" content="rzahwflyco.htm" />
|
||
|
<meta name="copyright" content="(C) Copyright IBM Corporation 1998, 2006" />
|
||
|
<meta name="DC.Rights.Owner" content="(C) Copyright IBM Corporation 1998, 2006" />
|
||
|
<meta name="DC.Format" content="XHTML" />
|
||
|
<meta name="DC.Identifier" content="rzahwe20-e20rx" />
|
||
|
<meta name="DC.Language" content="en-us" />
|
||
|
<!-- 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. -->
|
||
|
<link rel="stylesheet" type="text/css" href="./ibmdita.css" />
|
||
|
<link rel="stylesheet" type="text/css" href="./ic.css" />
|
||
|
<title>Example: Sample flight recorder output from a Pthread program</title>
|
||
|
</head>
|
||
|
<body id="rzahwe20-e20rx"><a name="rzahwe20-e20rx"><!-- --></a>
|
||
|
<!-- Java sync-link --><script language="Javascript" src="../rzahg/synch.js" type="text/javascript"></script>
|
||
|
<h1 class="topictitle1">Example: Sample flight recorder output from a Pthread program</h1>
|
||
|
<div><p>This example shows a Pthread program that is using the flight recorder
|
||
|
or tracing interfaces that are provided by the system.</p>
|
||
|
<div class="section"><div class="note"><span class="notetitle">Note:</span> By using the code examples, you agree to the terms of the <a href="codedisclaimer.htm">Code license and disclaimer information</a>.</div>
|
||
|
</div>
|
||
|
<div class="example"> <pre>/*
|
||
|
Filename: ATEST23.QCSRC
|
||
|
Use CL command DMPUSRTRC to output the following tracing
|
||
|
information that this example traces.
|
||
|
|
||
|
This information is put into a file QTEMP/QAP0ZDMP or to
|
||
|
standard output.
|
||
|
|
||
|
The trace records are indented and labeled based on thread id,
|
||
|
and millisecond timestamp of the time the tracepoint was cut.
|
||
|
|
||
|
The following trace output occurs when the optional parameter
|
||
|
'PTHREAD_TRACING' is NOT specified when calling this program.
|
||
|
|
||
|
If the optional parameter 'PTHREAD_TRACING' is specified, many
|
||
|
more tracepoints describing pthread library processing will occur.
|
||
|
|
||
|
Use the Pthread library tracepoints to debug incorrect calls to the
|
||
|
Pthreads library from your application.
|
||
|
|
||
|
Trace output ---------
|
||
|
User Trace Dump for job 096932/MYLIB/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: MYLIB / PTHREADT PTHREADT 19 : theThread__FPv
|
||
|
0000000E:371944 Stack: MYLIB / PTHREADT PTHREADT 29 : foo__Fv
|
||
|
0000000E:372016 Stack: MYLIB / 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: MYLIB / PTHREADT PTHREADT 19 : theThread__FPv
|
||
|
0000000F:416952 Stack: MYLIB / PTHREADT PTHREADT 29 : foo__Fv
|
||
|
0000000F:531432 Stack: MYLIB / 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
|
||
|
*/
|
||
|
#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 will 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) {
|
||
|
/* 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>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div>
|
||
|
<div class="familylinks">
|
||
|
<div class="parentlink"><strong>Parent topic:</strong> <a href="rzahwflyco.htm" title="A useful way to debug multithreaded applications is to write data to a flight recorder. A flight recorder is a file, output buffer, or some other object where trace information is written so that problems in the application can be tracked.">Flight recorders</a></div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</body>
|
||
|
</html>
|