#include <pthread.h> int pthread_trace_init_np(void);Service Program Name: QP0WPTHR
The pthread_trace_init_np() 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 Qp0wTraceLevel external variable and can be used by the PTHREAD_TRACE_NP() macro.
When a program or service program that uses the Pthread APIs causes the Pthread APIs to be loaded (activated), the Pthreads library automatically calls the pthread_trace_init_np() function in order to initialize tracing based on the value of the QIBM_PTHREAD_TRACE_LEVEL environment variable at that time.
The application can call pthread_trace_init_np() at an arbitrary time during execution to initialize or refresh the current Pthreads library tracing level and the application trace level. The trace level is set based on the value of the QIBM_PTHREAD_TRACE_LEVEL environment variable at the time of the call. The new tracing level is also returned.
The Pthreads library tracing level is used to control trace records written by the Pthreads library functions at runtime. The following table describes the preprocessor macros representing the various trace levels, the setting of the QIBM_PTHREAD_TRACE_LEVEL environment variable, and the conditions that are traced.
Trace Level | EnvVar | Description |
---|---|---|
PTHREAD_TRACE_NONE_NP | "QIBM_PTHREAD_TRACE_LEVEL=0" (or not set) |
No tracing is performed by the Pthreads library. Application tracing may still be done. |
PTHREAD_TRACE_ERROR_NP | "QIBM_PTHREAD_TRACE_LEVEL=1" | Error level traces error conditions and the causes of most error return codes. |
PTHREAD_TRACE_INFO_NP | "QIBM_PTHREAD_TRACE_LEVEL=2" | Informational level traces error level tracepoints, plus entry to and exit from functions, parameters passed to and return codes from functions, major changes in control flow. |
PTHREAD_TRACE_VERBOSE_NP | "QIBM_PTHREAD_TRACE_LEVEL=3" | Verbose level traces informational level tracepoints, plus detailed information about application parameters, threads and data structures including information about Pthreads library processing information. |
The application provides tracing support similar to the Pthreads library using the PTHREAD_TRACE_NP() macro.
The PTHREAD_TRACE_NP() macro uses the external variable Qp0wTraceLevel. Qp0wTraceLevel may be used directly by the application to set application trace level without effecting the current Pthread library trace level. Set the value of Qp0wTraceLevel to one of PTHREAD_TRACE_NONE_NP, PTHREAD_TRACE_ERROR_NP, PTHREAD_TRACE_INFO_NP, or PTHREAD_TRACE_VERBOSE_NP.
The PTHREAD_TRACE_NP() 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:
The trace records are written to the user trace flight recorder and can be accessed by the following CL commands:
None.
None.
None.
See Code disclaimer information for information pertaining to code examples.
#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; }
Output
Use CL command DMPUSRTRC to output the following tracing information that the example creates. The DMPUSRTRC 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.
Note the following:
00000018:972456 pthread_trace_init_np(): New traceLevel=2
User Trace Dump for job 097979/KULACK/PTHREADT. Size: 300K, Wrapped 0 times. --- 11/09/1998 15:15:56 --- 00000018:972456 pthread_trace_init_np(): New traceLevel=2 00000018:972592 pthread_key_create(entry): dtor=a1000000 00000000 d161cc19 45001a00 00000018:993920 destructor name is 'dataDestructor__FPv' 00000018:994048 pthread_key_create(exit): newKey=0, rc=0 00000018:994120 Create/start a thread 00000018:994224 pthread_create(entry): thread=80000000 00000000 f11d9cc7 23000400 00000018:994296 attr=00000000 00000000 00000000 00000000 00000018:994376 start_routine=a1000000 00000000 d161cc19 45006980 00000018:995320 routine name is 'theThread__FPv' 00000018:995432 arg=80000000 00000000 e7c74b3e 04001cd0 00000018:995992 pthread_create(status): Create a new thread 00000018:996088 Joinable-1 00000018:996152 PrioInheritSched-EXPLICIT Prio-0 00000018:997488 pthread_create(exit): Success 00000018:997632 tcb=80000000 00000000 feb52907 07001000 00000018:997704 thread id=00000000 00000019 handle=00000007 00000018:997792 Wait for the thread to complete, and release their resources 00000018:997896 pthread_join_processor(entry):Target 00000000 00000019,Detach=1,time=00000000 sec,00000000 nanosec. 00000018:997968 statusp = 00000000 00000000 00000000 00000000 00000019:998720 pthread_create_part2(status): run the new thread: 00000000 00000019 00000019:998864 Thread Entered 00000019:998984 E7C74B3E04:001CD0 L:0008 Global Data 00000019:999144 E7C74B3E04:001CD0 00000000 00000002 *................* 00000019:999240 pthread_setspecific(entry): value=80000000 00000000 e7c74b3e 04001cd0, key=0 00000019:999320 pthread_getspecific(entry): key=0 00000019:999392 foo(), threadSpecific data=0 2 00000019:999464 pthread_getspecific(entry): key=0 00000019:999536 bar(), threadSpecific data=0 2 00000019:999600 bar(): This is an error tracepoint 00000019:999664 Stack Dump For Current Thread 00000019:999728 Stack: This thread's stack at time of error in bar() --- 11/09/1998 15:15:57 --- 00000019:000304 Stack: Library / Program Module Stmt Procedure 00000019:000472 Stack: QSYS / QLESPI QLECRTTH 774 : LE_Create_Thread2__FP12crtth_parm_t 00000019:000560 Stack: QSYS / QP0WPTHR QP0WPTHR 1008 : pthread_create_part2 00000019:000656 Stack: KULACK / PTHREADT PTHREADT 19 : theThread__FPv 00000019:000728 Stack: KULACK / PTHREADT PTHREADT 29 : foo__Fv 00000019:000808 Stack: KULACK / PTHREADT PTHREADT 46 : bar__Fv 00000019:000888 Stack: QSYS / QP0ZCPA QP0ZUDBG 87 : Qp0zDumpStack 00000019:007416 Stack: QSYS / QP0ZSCPA QP0ZSCPA 276 : Qp0zSUDumpStack 00000019:007504 Stack: QSYS / QP0ZSCPA QP0ZSCPA 287 : Qp0zSUDumpTargetStack 00000019:007544 Stack: Completed 00000019:007664 foo(): This is an error tracepoint 00000019:007752 pthread_create_part2(status):return from start routine,status=00000000 00000000 00000000 00000000 00000019:007816 pthread_cleanup(entry): Thread termination started 00000019:007888 Qp0wTlsVector::invokeHandlers(entry): 00000019:007952 Qp0wTlsVector::invokeHandler(invoke): key=0 00000019:008040 dtor=a1000000 00000000 d161cc19 45001a00, 00000019:010792 destructor name is 'dataDestructor__FPv' 00000019:010920 arg=80000000 00000000 e7c74b3e 04001cd0 00000019:011008 dataDestructor: Free data 00000019:011096 pthread_setspecific(entry): value=00000000 00000000 00000000 00000000, key=0 00000019:011184 pthread_cleanup(exit): returning 00000018:011624 pthread_join_processor(status):target status=00000000 00000000 00000000 00000000,state=0x03, YES 00000018:011752 Create/start a thread 00000018:011880 pthread_create(entry): thread=80000000 00000000 f11d9cc7 23000430 00000018:011952 attr=00000000 00000000 00000000 00000000 00000018:012032 start_routine=a1000000 00000000 d161cc19 45006980 00000018:013464 routine name is 'theThread__FPv' 00000018:013576 arg=80000000 00000000 e7c74b3e 04001cd0 00000018:013704 Qp0wTcb::Qp0wTcb(status): Tcb was reused: tcb=80000000 00000000 feb52907 07001000 00000018:013784 pthread_create(status): Create a new thread 00000018:013848 Joinable-1 00000018:013912 PrioInheritSched-EXPLICIT Prio-0 00000018:014736 pthread_create(exit): Success 00000018:014912 tcb=80000000 00000000 feb52907 07001000 00000018:014984 thread id=00000000 0000001a handle=00000007 00000018:015072 Wait for the thread to complete, and release their resources 00000018:015168 pthread_join_processor(entry):Target 00000000 0000001a,Detach=1,time=00000000 sec,00000000 nanosec. 00000018:015240 statusp = 00000000 00000000 00000000 00000000 0000001A:015696 pthread_create_part2(status): run the new thread: 00000000 0000001a 0000001A:015840 Thread Entered 0000001A:015968 E7C74B3E04:001CD0 L:0008 Global Data 0000001A:016128 E7C74B3E04:001CD0 00000001 00000004 *................* 0000001A:016232 pthread_setspecific(entry): value=80000000 00000000 e7c74b3e 04001cd0, key=0 0000001A:016304 pthread_getspecific(entry): key=0 0000001A:016384 foo(), threadSpecific data=1 4 0000001A:016456 pthread_getspecific(entry): key=0 0000001A:016528 bar(), threadSpecific data=1 4 0000001A:016584 bar(): This is an error tracepoint 0000001A:016648 Stack Dump For Current Thread 0000001A:016712 Stack: This thread's stack at time of error in bar() 0000001A:016904 Stack: Library / Program Module Stmt Procedure 0000001A:017048 Stack: QSYS / QLESPI QLECRTTH 774 : LE_Create_Thread2__FP12crtth_parm_t 0000001A:017144 Stack: QSYS / QP0WPTHR QP0WPTHR 1008 : pthread_create_part2 0000001A:017232 Stack: KULACK / PTHREADT PTHREADT 19 : theThread__FPv 0000001A:018680 Stack: KULACK / PTHREADT PTHREADT 29 : foo__Fv 0000001A:018760 Stack: KULACK / PTHREADT PTHREADT 46 : bar__Fv 0000001A:018840 Stack: QSYS / QP0ZCPA QP0ZUDBG 87 : Qp0zDumpStack 0000001A:018928 Stack: QSYS / QP0ZSCPA QP0ZSCPA 276 : Qp0zSUDumpStack 0000001A:019000 Stack: QSYS / QP0ZSCPA QP0ZSCPA 287 : Qp0zSUDumpTargetStack 0000001A:019040 Stack: Completed 0000001A:019136 foo(): This is an error tracepoint 0000001A:019224 pthread_create_part2(status):return from start routine,status=00000000 00000000 00000000 00000000 0000001A:019288 pthread_cleanup(entry): Thread termination started 0000001A:019352 Qp0wTlsVector::invokeHandlers(entry): 0000001A:019424 Qp0wTlsVector::invokeHandler(invoke): key=0 0000001A:019504 dtor=a1000000 00000000 d161cc19 45001a00, 0000001A:021360 destructor name is 'dataDestructor__FPv' 0000001A:021496 arg=80000000 00000000 e7c74b3e 04001cd0 0000001A:021576 dataDestructor: Free data 0000001A:021664 pthread_setspecific(entry): value=00000000 00000000 00000000 00000000, key=0 0000001A:021752 pthread_cleanup(exit): returning 00000018:022112 pthread_join_processor(status):target status=00000000 00000000 00000000 00000000,state=0x03, YES 00000018:022272 pthread_key_delete(entry): key=0 00000018:022336 pthread_key_delete(exit): rc=0 00000018:022408 Main completed
Top | Pthread APIs | APIs by category |