The problem
About one or two weeks ago, I needed to find a problem in virtual memory allocation/de-allocation, since a process was running out of virtual memory. In our system we already had some tracing in a library in place, using conditional compilation. However, when building the entire system the trace just gave too much data.The solution
I stumbled upon an article at http://labs.hoffmanlabs.com about the C-macrotr_print
. That was just what I was looking for.The definition of the macro can be found by issueing the following command
$ libr/text sys$library:sys$lib_c.tlb /extract=vms_macros /output=tt:
Note: I used output to
tt:
, which is effectively my terminal, so I do not extract to a file, but straight to the screen. The last part of the file shows the definition of C-macro tr_print
, which was the only thing I was interested in.Since we code in HP Pascal, at first I tried to write code like is included in the
tr_print
macro, but that did not quite work out. Some issues with parameter passing, I guess. Not spending too much time on getting it to work, I decided to create a small C file with a function taking only one string parameter, and to call the C function from a Pascal module.The source code
The created C file looks like this (stripped from all mandatory style elements):writetrc_c.c
#include <vms_macros.h> #include <stdlib.h> void _write_trc_c( const char *trace_string ) { /* NOTE: THE DOUBLE PARENTHESES ARE REQUIRED IN THIS MACRO BY DESIGN */ tr_print(( trace_string )); }
and the pascal module looks like this:
writetrc.pas
[ ENVIRONMENT ( 'writetrc.pen' ) ] MODULE writetrc; [GLOBAL,ASYNCHRONOUS] PROCEDURE write_trc( p_trace_string : VARYING [$m1] OF CHAR ); {----- External Routine Declarations ------} [EXTERNAL] PROCEDURE _write_trc_c( p_trace_str : [IMMEDIATE] C_STR_T ); EXTERNAL; {---------- Variable Declarations ---------} VAR lv_trace_string : [VOLATILE] STRING($m1 + 1); { volatile to get rid of compiler warning } lv_trace_str_ptr : C_STR_T := NIL; BEGIN { Calling a C routine, so zero terminated string required } lv_trace_string := p_trace_string + CHR(0); lv_trace_str_ptr := C_STR( lv_trace_string ); { C-function checks if the trace is activated } { If not, it immediately returns } _write_trc_c( lv_trace_str_ptr ); END; { of PROCEDURE write_trc } END.
Compilation
Compilation of the C source is done as follows:$ define DECC$TEXT_LIBRARY SYS$LIBRARY:SYS$LIB_C.TLB
$ cc writetrc_c.c /debug /noopt
Logical
DECC$TEXT_LIBRARY
needs to be set to let the C compiler find vms_macros.h
.
Compilation of the Pascal source is done as follows:
$ pas writetrc /debug /noopt
Note: for development and test, we standard compile with
/debug /noopt
Linking
When linking a program that uses the functions above, you must include/SYSEXE
. The link command will then look like: $ link example writetrc.opt/opt /sysexe
Where the file
writetrc.opt
contains the following 2 lines:writetrc_c.obj
writetrc.obj
Example program
Just to demonstrate, here is a small example program, that writes "Hello, World! 2015" to screen and in the trace buffer.[ INHERIT ( 'writetrc.pen' ) ] PROGRAM example( INPUT, OUTPUT ); VAR i : INTEGER; s : STRING(40); BEGIN i := 2015; s := 'Hello, World!'; writetrc( s + DEC(i) ); WRITELN( s, ' ', i ); END.
Compile as usual and link as described earlier.
Running the example
Open a second terminal to start SDA with the correct privileges. You need at least privilege ALTPRI to start the trace, and another privilege to increase the buffer size. Since I don't know yet which one, I use priv=all for now.$ set proc /priv=all
$ analyze/system
SDA> TR LOAD
SDA> TR START TRACE ! optionally with /BUFFER=<nr of pages>
SDA>
Go back to the other terminal and run the example:
$ run example
Hello, World! 2015
$
Go back to the system analyzer session.
SDA> TR STOP TRACE
SDA> TR SHOW TRACE
You should get a screen with a header, and one trace line with timestamp and text "Hello, World! 00002015" (slightly different formatted than the output of the WRITELN statement).
Finally, exit the system analyzer with:
SDA> TR UNLOAD
SDA> EXIT
That's all, folks!