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 /nooptLogical
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 /nooptNote: for development and test, we standard compile with
/debug /nooptLinking
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 /sysexeWhere the file
writetrc.opt contains the following 2 lines:writetrc_c.objwritetrc.objExample 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/systemSDA> TR LOADSDA> TR START TRACE ! optionally with /BUFFER=<nr of pages>SDA>Go back to the other terminal and run the example:
$ run exampleHello, World! 2015$ Go back to the system analyzer session.
SDA> TR STOP TRACESDA> TR SHOW TRACEYou 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 UNLOADSDA> EXITThat's all, folks!
Uh oh, seems like the timestamps get messed up. I have been tracing on Apr 28, 8:45. A lot of the timestamps in TR SHOW TRACE output show Feb 25th 8:07. I hope the trace is still in order and only the timestamps are wrong. Another bug in TR$SDA.EXE?
ReplyDelete