back to "index"

   This document describes and explains the  mechanism of writing and reading trace points into a buffer.
   There are constraints that we have to respect: firstly we must avoid to block the fonction which is traced, secondly we must synchronize  threads accesses in the buffer so that the maximum of trace points is written.

We need two processes: Pw for writing and Pr for reading. The two processes use a ring buffer
We also need four variables which are indexes in the array:

    - reserved: to indicate that space for writting has been reserved
    - written: to indicate that the writting is finish
    - beg_read: index where Pr starts to read
    - end_read: index where Pr stops to read

We define a new type WORD (int_32) which will be the basic unit to count space in the buffer.







I. FUNCTIONS NEEDED






                1. Init_NPTL

    This function without arguments defines the stucture trace_buffer which contains an array where trace point data are put, three variables and two flags which allow to manage buffer accesses: "reserved, written, beg_read, PAUSE,FINI".Theses indexes are initialized to 0 at the beginning. The index end_read is declared only into the process Pr .

    It also create the shared memory and the process Pr.
    It is call at the beginning of the function which is traced.


                2. Trace

  This function writes in the array.Its arguments are the datas of a trace point which will be written. It checks
if there is enough place beetween reserved and beg_read to write new data without overwrite other and reserves space in the array for all datas of the trace point.



               
3. Finish

   This boolean function tells if the user function is finished or not.





back to "index"










II. "WRITE AND READ" MECHANISM



General mechanism:




*process Pw


    if space() == TRUE

          
wait for (PAUSE != TRUE)

            reserve space for the trace point and get the index where the writing will start (atomical operation XADD)
                reserved = reserved + size of (all data to be written)

            write each data in the space reserved:
                 written = written + size of (all data written)
   
else   

        ASSERT: stop

    endif






*process Pr
 


while finish() == FALSE

   if  reserved reaches the middle of the array

   
    PAUSE = 1 (we block Pw)
 
        wait for (written == reserved)

        end_read = written

        PAUSE = 0
(we unblock Pw)

        read datas between beg_read and end_read (write in the binar file)

       
beg_read = end_read
       
    endif


wait for (written == reserved)

end_read = written

read datas between beg_read and end_read (write in the binary file)

display the binary file


  




back to "index"


Example:



user_function(...)
    {
...
            trace(TR_BARRIER_8, &th1,&bar1, lo1, le)
            ......

            trace(TR_BARRIER_1,  &bar2, &th2, lo2, &th2)
   
            ......       
            trace(TR_BARRIER_4, &bar3, &th3, lo3)

            ......
}











When the process Pr finishes to write datas into the binary file, it can display the description of trace events.

So with this example we have:

      1     
"thread  &th1,  initialized barrier  &bar2, lock= lo1, left= le "

      3      
"barrier
&bar2, is required by thread &th2, lock= lo2"
              
   3.5      
"blocked thread:
&th2"
               
      5     
"barrier &bar3, is required by thread &th3, lock= lo3"
              

            

           







           








 


       





   
However it still remains some shade points in the management of the array, notably:

        *how will Pr read when data are at the end and at the begining of the array?
       
        *the basic unit in the array is the WORD (int 32), but there are data which are on 64 bits, so will we write them in two stages?
        


We will answer these questions when we will write the functions, meanwhile there are some ideas for solutions ....
             
   


back to "index"