pthread_trace_init_np()--Initialize or Reinitialize Pthread Tracing


  Syntax:
 #include <pthread.h>
 int pthread_trace_init_np(void);  
  Service Program Name: QP0WPTHR

  Default Public Authority: *USE

  Threadsafe: Yes

  Signal Safe: No

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:


Authorities and Locks

None.


Parameters

None.


Return Value

value
The new trace level. One of PTHREAD_TRACE_NONE_NP, PTHREAD_TRACE_ERROR_NP, PTHREAD_TRACE_INFO_NP, or PTHREAD_TRACE_VERBOSE_NP.

Error Conditions

None.


Related Information


Example

Note: By using the code examples, you agree to the terms of the Code license and disclaimer information.

#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:

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


API introduced: V4R3

[ Back to top | Pthread APIs | APIs by category ]