sampnlm.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 446 行
C
446 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <io.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 "os.h"
#include <ownwthrd.h>
extern void StartTimer( void );
extern void StopTimer( void );
extern void REPORT_TYPE report( void );
extern void WriteCodeLoad( seg_offset ovl_tbl, char *name, samp_block_kinds );
extern void WriteAddrMap( seg map_start, seg load_start, off load_offset );
extern int SampWrite( void FAR_PTR *buff, unsigned len );
extern void StopAndSave(void);
extern void SetTimerRate( char ** );
extern void SetRestoreRate( char **);
extern void fatal( void );
extern void Output( char FAR_PTR * );
extern void mfree( void FAR_PTR *chunk );
extern void FAR_PTR * alloc( int size );
extern char FAR_PTR *MsgArray[ERR_LAST_MESSAGE-ERR_FIRST_MESSAGE+1];
extern void ResolveRateDifferences(void);
/* NETWARE HOOKS */
#include "miniproc.h"
#include "loader.h"
#include "debugapi.h"
#include "aesproc.h"
#include "event.h"
extern void * ImportSymbol(unsigned long /* handle */, const char * /* symbol_name */);
int SamplerThread;
struct LoadDefinitionStructure *SampledNLM;
struct AESProcessStructure AES;
struct ResourceTagStructure *AESTag;
struct ResourceTagStructure *AllocTag;
struct ResourceTagStructure *EventTag;
struct ResourceTagStructure *SwitchModeTag;
int Suspended;
int Resumed;
#pragma aux GetCS = 0x8c 0xc8 value [ ax ];
extern short GetCS( void );
typedef struct code_load {
char buff[512];
short seg;
long off;
struct code_load *next;
samp_block_kinds kind;
} code_load;
code_load *LoadedNLMs;
void SysInit( void )
{
AllocTag = AllocateResourceTag(
(void *)GetNLMHandle(),
"Open Watcom Sampler Work Area",
AllocSignature );
SwitchModeTag = AllocateResourceTag(
(void*) GetNLMHandle(),
"Open Watcom Sampler ModeSwitchMon",
EventSignature);
}
void StopProg( void )
{
}
void CodeLoad( struct LoadDefinitionStructure *loaded, samp_block_kinds kind )
{
seg_offset ovl_tbl;
char buff[ 256 ];
ovl_tbl.segment = 0;
ovl_tbl.offset = 0;
memcpy( buff, &loaded->LDFileName[1], loaded->LDFileName[0] );
buff[ loaded->LDFileName[ 0 ] ] = '\0';
WriteCodeLoad( ovl_tbl, buff, kind );
WriteAddrMap( 1, GetCS(), loaded->LDCodeImageOffset );
}
void RecordCodeLoad( struct LoadDefinitionStructure *loaded, samp_block_kinds kind )
{
code_load *new;
new = alloc( sizeof( *new ) );
new->next = LoadedNLMs;
LoadedNLMs = new;
memcpy( new->buff, &loaded->LDFileName[1], loaded->LDFileName[0] );
new->buff[ loaded->LDFileName[ 0 ] ] = '\0';
new->seg = GetCS();
new->off = loaded->LDCodeImageOffset;
new->kind = kind;
}
void WriteRecordedLoads( void )
{
seg_offset ovl_tbl;
code_load *curr,*next;
ovl_tbl.segment = 0;
ovl_tbl.offset = 0;
for( curr = LoadedNLMs; curr != NULL; curr = next ) {
next = curr->next;
WriteCodeLoad( ovl_tbl, curr->buff, curr->kind );
WriteAddrMap( 1, curr->seg, curr->off );
mfree( curr );
}
}
static volatile unsigned nModeSwitched = 0;
void ModeSwitched( LONG dummy )
{
nModeSwitched++;
}
void WakeMeUp( LONG dummy )
{
static int Already = FALSE;
struct LoadDefinitionStructure *loaded;
if( Already )
return;
for( loaded = LoadedList; loaded != NULL; loaded = loaded->LDLink ) {
RecordCodeLoad( loaded, Already ? SAMP_CODE_LOAD : SAMP_MAIN_LOAD );
Already = TRUE;
}
Already = TRUE;
Resumed = TRUE;
if( Suspended )
ResumeThread( SamplerThread );
}
void StartProg( char *cmd, char *prog, char *args )
{
LONG events;
AESTag = AllocateResourceTag(
(void *)GetNLMHandle(),
"Open Watcom Execution Sampler Flush Process",
AESProcessSignature );
prog = prog;
args = args;
SampleIndex = 0;
Suspended = FALSE;
Resumed = FALSE;
CurrTick = 0L;
EventTag = AllocateResourceTag(
(void *)GetNLMHandle(),
"Open Watcom Execution Sampler Events",
EventSignature );
events = RegisterForEventNotification(
EventTag,
EVENT_MODULE_UNLOAD,
EVENT_PRIORITY_APPLICATION,
NULL,
WakeMeUp );
/*
// Resolve rate differences will use the restore value to calculate
// a new timer if we're running slower than the system runs normally
*/
ResolveRateDifferences();
StartTimer();
if( LoadModule( systemConsoleScreen, cmd, 0 ) != 0 )
{
StopTimer();
cputs( MsgArray[MSG_SAMPLE_1-ERR_FIRST_MESSAGE] );
cputs( cmd );
cputs( "\r\n" );
fatal();
}
SamplerThread = GetThreadID();
Suspended = TRUE;
if( !Resumed )
{
Suspended = TRUE;
SuspendThread( SamplerThread );
}
WriteRecordedLoads();
StopTimer();
UnRegisterEventNotification( events );
report();
if( Samples != NULL )
mfree( Samples );
}
void SaveOutSamples( void *dummy )
{
StopAndSave();
AES.AProcessToCall = NULL;
}
void RecordSample( union INTPACK FAR_PTR *r ) {
Samples->d.sample.sample[ SampleIndex ].offset = r->x.eip;
Samples->d.sample.sample[ SampleIndex ].segment = r->x.cs;
++SampleIndex;
if( SampleIndex > Margin )
{
if( AES.AProcessToCall == NULL )
{
AES.AProcessToCall = SaveOutSamples;
AES.AWakeUpDelayAmount = 0;
AES.AWakeUpTime = 0;
AES.ARTag = (LONG)AESTag;
ScheduleSleepAESProcessEvent( &AES );
}
}
}
/*
* These routines will be used to record callgraph information once int 3
* hooks are handled (for CommonAddr passing and for marks). 19-aug-92 CMS
*/
void GetCommArea( void )
{
}
void ResetCommArea( void )
{
}
void GetNextAddr( void )
{
}
int VersionCheck( void )
{
return( TRUE );
}
int InDOS( void )
{
return( TRUE );
}
void GetProg( char *cmd, char *eoc )
{
char save;
char volume[_MAX_VOLUME];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
char sfname[_MAX_FNAME];
save = *eoc;
*eoc = '\0';
_splitpath( cmd, volume, dir, fname, ext );
*eoc = save;
_splitpath( SampName, volume, dir, sfname, ext );
_makepath( SampName, volume, dir, sfname[0] == 0 ? fname : sfname,
ext[0] == 0 ? "SMP" : ext );
}
void fatal( void )
{
if( Samples != NULL ) mfree( Samples );
if( CallGraph != NULL ) mfree( CallGraph );
MsgFini();
exit( 0 );
}
void SysDefaultOptions( void )
{
}
extern unsigned long count_pit0( void );
extern unsigned long cpuspeed( void );
static unsigned long RoundSpeed(unsigned long speed)
{
unsigned long modulo = speed % 10;
if(modulo == 9)
speed++;
return speed;
}
static unsigned long volatile * pRealModeTimerFlag = NULL;
/*static */void EstimateRate( void )
{
char EstRate[16];
unsigned long currCount;
unsigned long hadSwitch;
unsigned long modeSwitch;
unsigned long i;
Output("Calculating...\r");
modeSwitch = RegisterForEventNotification(
SwitchModeTag,
5, /* EVENT_CHANGE_TO_REAL_MODE */
EVENT_PRIORITY_APPLICATION,
NULL,
ModeSwitched );
if(NULL == pRealModeTimerFlag)
{
pRealModeTimerFlag = (unsigned long *)ImportSymbol(GetNLMHandle(), "RealModeTimerFlag");
}
if(pRealModeTimerFlag)
while(0 != *pRealModeTimerFlag)
delay(100);
while(1)
{
nModeSwitched = 0;
hadSwitch = nModeSwitched;
currCount = RoundSpeed(cpuspeed());
if(hadSwitch == nModeSwitched)
break;
else
Output("Mode switched\n");
}
ultoa(currCount, EstRate, 10);
Output("CPU Speed - ");
Output(EstRate);
Output(" Mhz\n");
Output("Calculating...\r");
if(pRealModeTimerFlag)
while(0 != *pRealModeTimerFlag)
delay(100);
currCount = 0;
for(i = 0; i < 4; i++)
{
unsigned long x = count_pit0();
if(x > currCount)
currCount = x;
}
/*
// Don't know if this is really true but I have been informed that there is absolutely NO
// way to read from the PIT when at initial count. The best we can do is count-2 so add 2
// anyway.
*/
currCount += 2;
if(currCount > 0x0000FFFF) /* count is 16 bit - default is 0 (count of 0x10000) */
currCount = 0;
ultoa(currCount, EstRate, 10);
Output("PIT Count - ");
Output(EstRate);
Output("\n");
UnRegisterEventNotification( modeSwitch );
}
void SysParseOptions( char c, char **cmd )
{
char buff[2];
switch(c)
{
case 'r':
SetTimerRate( cmd );
break;
case 'o':
SetRestoreRate( cmd );
break;
case 'e':
EstimateRate();
fatal();
break;
default:
Output( MsgArray[MSG_INVALID_OPTION-ERR_FIRST_MESSAGE] );
buff[0] = c;
buff[1] = '\0';
Output( buff );
Output( "\r\n" );
fatal();
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?