samppls.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 327 行
C
327 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: PharLap performance sampling core.
*
****************************************************************************/
#define WATCOM 1
#define CMPLR WATCOM
#define __STKCALL cdecl
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <dos.h>
#include <ctype.h>
#include <string.h>
#include <process.h>
#include <malloc.h>
#include <conio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "sample.h"
#include "smpstuff.h"
#include "wmsg.h"
#include "pltypes.h"
#include "hw386.h"
#include "dilintf.h"
#include "dilproto.h"
#define DEFVARS
#include "timermod.h"
static MSB Mach;
static SEL_REMAP SelBlk;
static PTR386 CommonAddr = { 0, 0 };
unsigned short InitialCS;
unsigned short InitialSS;
char CGBreak;
char FakeBreak;
char SavedByte;
char XVersion;
char RateChanged;
extern void GrabVects();
extern void ReleVects();
extern void ReadRealClk( int *hour, int *min, int *sec );
extern void SetBiosClk( int count );
unsigned NextThread( unsigned tid )
{
return( !tid );
}
int VersionCheck()
{
return( TRUE );
}
void RecordSample( unsigned offset, unsigned short segment )
{
if( InsiderTime == 1 && SamplerOff == 0 ) {
LastSampleIndex = SampleIndex;
if( SampleIndex == 0 ) {
Samples->pref.tick = CurrTick;
CallGraph->pref.tick = CurrTick;
}
++CurrTick;
Samples->d.sample.sample[ SampleIndex ].offset = offset;
Samples->d.sample.sample[ SampleIndex ].segment = segment;
++SampleIndex;
++SampleCount;
}
/*
* Call Graph information still has to be written. If this sample occurred
* in the program code (as opposed to OS code which might be called from
* the program), and int 3 is placed at the interrupt return address. This
* again triggers the sampler and RecordCGraph() is called. If the sample
* occurred elsewhere, we are unable to get access to the current callgraph
* stack, so a dummy callgraph record is written. The code doing this is
* found in timer.asm, and is executed immediately upon returning from
* RecordSample().
*/
}
void DummyCGraph()
{
Samples->d.sample.sample[ SampleIndex ].offset = 0;
Samples->d.sample.sample[ SampleIndex ].segment = -1;
++SampleIndex;
}
void GetCommArea()
{
if( CommonAddr.selector == 0 ) { /* can't get the common region yet */
Comm.cgraph_top = 0;
Comm.top_ip = 0;
Comm.top_cs = 0;
Comm.pop_no = 0;
Comm.push_no = 0;
Comm.in_hook = 1; /* don't record this sample */
} else {
dbg_pread( &CommonAddr, sizeof( Comm ), (UCHAR *)&Comm );
}
}
void ResetCommArea()
{
if( CommonAddr.selector != 0 ) { /* reset common variables */
Comm.pop_no = 0;
Comm.push_no = 0;
CommonAddr.offset += 11;
dbg_pwrite( &CommonAddr, 4, (UCHAR *)&Comm.pop_no );
CommonAddr.offset -= 11;
}
}
void GetNextAddr()
{
PTR386 addr;
struct {
unsigned long ptr;
seg cs;
off ip;
} stack_entry;
if( CommonAddr.selector == 0 ) {
CGraphOff = 0;
CGraphSeg = 0;
} else {
addr.selector = CommonAddr.selector;
addr.offset = Comm.cgraph_top;
dbg_pread( &addr, sizeof( stack_entry ), (UCHAR *)&stack_entry );
CGraphOff = stack_entry.ip;
CGraphSeg = stack_entry.cs;
Comm.cgraph_top = stack_entry.ptr;
}
}
static void check( int x )
{
if( x != 0 ) {
Output( MsgArray[MSG_SAMPLE_1-ERR_FIRST_MESSAGE] );
Output( "\r\n" );
MsgFini();
_exit( -1 );
}
}
void StopProg()
{
}
#include "exceptv.h"
#define BSIZE 256
static int bcd2hex( int i )
{
return( ( i & 0xf ) + ( ( ( i >> 4 ) & 0xf ) * 10 ) );
}
void FixTime( void )
{
int hour,min,sec,count;
if( !RateChanged ) return;
ReadRealClk( &hour, &min, &sec );
hour = bcd2hex( hour );
min = bcd2hex( min );
sec = bcd2hex( sec );
count = ( hour * 65543 )
+ ( hour / 3 )
+ ( min * 1092 )
+ ( min / 3 )
+ ( sec * 18 )
+ ( sec / 5 );
SetBiosClk( count );
}
void StartProg( char *cmd, char *prog, char *args )
{
PTR386 addr;
char buff[BSIZE];
int len;
seg_offset where;
cmd = cmd;
SampleIndex = 0;
CurrTick = 0L;
FakeBreak = 0;
CGBreak = 0;
TimerMod = TimerMult;
check( dbg_init( &SelBlk ) );
check( dbg_edebug() );
GrabVects();
FixTime();
if( dbg_load( prog, NULL, args ) != 0 ) {
Output( MsgArray[MSG_SAMPLE_2-ERR_FIRST_MESSAGE] );
Output( prog );
Output( "\r\n" );
ReleVects();
MsgFini();
_exit( -1 );
}
check( dbg_rdmsb( &Mach ) );
where.offset = 0;
where.segment = 0;
WriteCodeLoad( where, ExeName, SAMP_MAIN_LOAD );
WriteAddrMap( 1, Mach.msb_cs, 0 );
InitialCS = Mach.msb_cs;
InitialSS = Mach.msb_ss;
outp( TIMER0, DIVISOR & 0xff );
outp( TIMER0, DIVISOR >> 8 );
for( ;; ) {
check( dbg_go() );
check( dbg_rdmsb( &Mach ) );
if( Mach.msb_event == EV_SLBA ) continue;
FixTime();
if( Mach.msb_event != EV_BKPT ) break;
if( FakeBreak || CGBreak ) {
if( CGBreak ) {
RecordCGraph();
}
if( FakeBreak ) {
StopAndSave();
}
Mach.msb_eip--;
dbg_wrmsb( &Mach );
addr.selector = Mach.msb_cs;
addr.offset = Mach.msb_eip;
dbg_pwrite( &addr, 1, &SavedByte );
FakeBreak = 0;
} else if(( Mach.msb_edx & 0xffff ) != 0 ) { /* this is a mark */
len = 0;
addr.selector = Mach.msb_edx & 0xffff;
addr.offset = Mach.msb_eax;
for( ;; ) {
dbg_pread( &addr, 1, buff+len );
if( len == BSIZE ) buff[ len ] = '\0';
if( buff[len] == '\0' ) break;
++len;
addr.offset++;
}
where.segment = Mach.msb_cs;
where.offset = Mach.msb_eip;
WriteMark( buff, where );
} else { /* remember common storage */
CommonAddr.selector = Mach.msb_ecx & 0xffff; /* area ... */
CommonAddr.offset = Mach.msb_ebx;
}
}
outp( TIMER0, 0 );
outp( TIMER0, 0 );
FixTime();
if( Mach.msb_event <= 16 ) {
Output( MsgArray[MSG_SAMPLE_3-ERR_FIRST_MESSAGE] );
Output( MsgArray[Exceptions[Mach.msb_event]+MSG_EXCEPT_0-ERR_FIRST_MESSAGE] );
Output( "\r\n" );
} else if( Mach.msb_event != EV_TERM ) {
char buff[10];
Output( MsgArray[MSG_SAMPLE_4-ERR_FIRST_MESSAGE] );
Output( itoa( Mach.msb_event, buff, 10 ) );
Output( "\r\n" );
}
ReleVects();
dbg_exit();
report();
}
void SysDefaultOptions( void )
{
RateChanged = 0;
}
void SysParseOptions( char c, char **cmd )
{
char buff[2];
switch( c ) {
case 'r':
RateChanged = 1;
SetTimerRate( cmd );
break;
default:
Output( MsgArray[MSG_INVALID_OPTION-ERR_FIRST_MESSAGE] );
buff[0] = c;
buff[1] = '\0';
Output( buff );
Output( "\r\n" );
fatal();
break;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?