sampos2.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 600 行 · 第 1/2 页
C
600 行
/****************************************************************************
*
* 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: OS/2 1.x performance sampling core.
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <i86.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "sample.h"
#include "wmsg.h"
#include "smpstuff.h"
#define INCL_BASE
#define INCL_DOSDEVICES
#define INCL_DOSMEMMGR
#define INCL_DOSPROCESS
#include "os2.h"
#include "os2dbg.h"
#define BUFF_SIZE 512
static char UtilBuff[BUFF_SIZE];
static TRACEBUF Buff;
static USHORT Pid;
static USHORT InitialCS;
static USHORT MainMod = 0;
static USHORT SleepTime;
static unsigned *SampleIndexP;
static unsigned *SampleCountP;
static samp_block * FAR_PTR *SamplesP;
static samp_block * FAR_PTR *CallGraphP;
static unsigned MaxThread = 1;
static USHORT OSVer;
static int NewSession;
static seg_offset CommonAddr;
#define STACK_SIZE 4096
static char near Stack[STACK_SIZE];
unsigned NextThread( unsigned tid )
{
if( tid == MaxThread ) return( 0 );
Samples = SamplesP[ tid ];
SampleIndex = SampleIndexP[ tid ];
if( CallGraphMode ) {
CallGraph = CallGraphP[ tid ];
SampleCount = SampleCountP[ tid ];
}
return( tid+1 );
}
void InitTimerRate()
{
SleepTime = 55;
}
void SetTimerRate( char **cmd )
{
SleepTime = GetNumber( 1, 1000, cmd, 10 );
}
unsigned long TimerRate()
{
return( 1000L * SleepTime );
}
unsigned SafeMargin()
{
return( Ceiling-10 );
}
#define EXE_LX 0x584c
#define EXE_NE 0x454e
static int IsLX()
{
int f;
unsigned_32 offset;
unsigned_16 sig;
unsigned_16 flags;
f = open( ExeName, O_BINARY | O_RDONLY );
if( f == -1 ) return( 0 );
if( lseek( f, 0x3c, SEEK_SET ) != 0x3c ) return( 0 );
if( read( f, &offset, sizeof( offset ) ) != sizeof( offset ) ) return( 0 );
if( lseek( f, offset, SEEK_SET ) != offset ) return( 0 );
if( read( f, &sig, sizeof( sig ) ) != sizeof( sig ) ) return( 0 );
if( sig == EXE_NE ) {
offset += 12;
if( lseek( f, offset, SEEK_SET ) != offset ) return( 0 );
if( read( f, &flags, sizeof(flags) ) != sizeof(flags) ) return( 0 );
if( (flags & 0x0300) == 0x0300 ) {
/* PM app */
NewSession = 1;
}
}
close( f );
return( sig == EXE_LX );
}
#define OS22SAMPLER "WSMPOS22.EXE"
/*
If we're running on OS/2 2.x and it's an LX style file, spawn off the
OS/2 2.x sampler to collect things
*/
int VersionCheck()
{
USHORT env_sel;
USHORT cmd_off;
RESULTCODES res;
DosGetVersion( &OSVer );
if( OSVer >= 0x1400 && IsLX() ) {
if( DosSearchPath( 0x0003, "PATH", OS22SAMPLER,
UtilBuff, sizeof( UtilBuff ) ) ) {
InternalError( MsgArray[MSG_SAMPLE_8-ERR_FIRST_MESSAGE] );
}
DosGetEnv( &env_sel, &cmd_off );
if( DosExecPgm( NULL, 0, EXEC_ASYNC, MK_FP( env_sel, cmd_off ),
NULL, &res, UtilBuff ) != 0 ) {
InternalError( MsgArray[MSG_SAMPLE_9-ERR_FIRST_MESSAGE] );
}
_exit( 0 );
}
return( OSVer >= 0x0a14 );
}
static void GrowArrays( unsigned tid )
{
unsigned max;
max = MaxThread;
SamplesP = realloc( SamplesP, tid*sizeof( void * ) );
SampleIndexP = realloc( SampleIndexP, tid*sizeof( void * ) );
if( CallGraphMode ) {
CallGraphP = realloc( CallGraphP, tid*sizeof( void * ) );
SampleCountP = realloc( SampleCountP, tid*sizeof( void * ) );
}
while( max < tid ) {
AllocSamples( max+1 );
SamplesP[ max ] = Samples;
SampleIndexP[ max ] = SampleIndex;
if( CallGraphMode ) {
CallGraphP[ max ] = CallGraph;
SampleCountP[ max ] = SampleCount;
}
++max;
}
MaxThread = max;
}
void RecordSample( unsigned offset, unsigned short segment, USHORT tid )
{
samp_block FAR_PTR *old_samples;
unsigned old_sample_index;
unsigned old_sample_count;
if( tid > MaxThread ) {
GrowArrays( tid );
}
--tid;
LastSampleIndex = SampleIndexP[ tid ];
if( SampleIndexP[ tid ] == 0 ) {
SamplesP[ tid ]->pref.tick = CurrTick;
if( CallGraphMode ) {
CallGraphP[ tid ]->pref.tick = CurrTick;
}
}
++CurrTick;
SamplesP[ tid ]->d.sample.sample[ SampleIndexP[ tid ] ].offset = offset;
SamplesP[ tid ]->d.sample.sample[ SampleIndexP[ tid ] ].segment = segment;
SampleIndexP[ tid ]++;
if( CallGraphMode ) {
SampleCountP[ tid ]++;
}
if( CallGraphMode && tid == 0 ) {
old_sample_count = SampleCount;
old_samples = Samples; /* since RecordCGraph isn't */
old_sample_index = SampleIndex; /* used to threads, we fool */
Samples = SamplesP[ tid ]; /* it into storing the info */
SampleIndex = SampleIndexP[ tid ]; /* in the right place by */
SampleCount = SampleCountP[ tid ];
RecordCGraph(); /* changing its pointers */
SamplesP[ tid ] = Samples; /* and restoring them later */
SampleIndexP[ tid ] = SampleIndex;
SampleCountP[ tid ] = SampleCount;
Samples = old_samples;
SampleIndex = old_sample_index;
SampleCount = old_sample_count;
}
if( SampleIndexP[ tid ] >= Margin ) {
StopAndSave();
}
}
static void readMemory( seg_offset *from, int size, char *to )
{
static TRACEBUF mybuff;
mybuff.pid = Pid;
mybuff.tid = 0; /* NB: callgraph info only supported on thread 0 */
mybuff.segv = from->segment;
mybuff.offv = from->offset + size - 1;
while( size ) {
mybuff.cmd = PT_CMD_READ_MEM_D;
DosPTrace( &mybuff );
size--;
mybuff.offv--;
to[ size ] = mybuff.value;
}
}
static void writeMemory( seg_offset *to, int size, char *from )
{
static TRACEBUF mybuff;
mybuff.pid = Pid;
mybuff.tid = 0; /* NB: callgraph info only supported on thread 0 */
mybuff.segv = to->segment;
mybuff.offv = to->offset + size - 1;
while( size ) {
size--;
mybuff.value = from[ size ];
mybuff.cmd = PT_CMD_WRITE_MEM_D;
DosPTrace( &mybuff );
mybuff.offv--;
}
}
void GetCommArea()
{
if( CommonAddr.segment == 0 ) { /* can't get the common */
Comm.cgraph_top = 0; /* region yet. */
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 {
readMemory( &CommonAddr, sizeof( Comm ), (char *) &Comm );
}
}
void ResetCommArea()
{
if( CommonAddr.segment != 0 ) { /* reset common variables */
Comm.pop_no = 0;
Comm.push_no = 0;
CommonAddr.offset += 9;
writeMemory( &CommonAddr, 4, (char *) &Comm.pop_no );
CommonAddr.offset -= 9;
}
}
void GetNextAddr()
{
seg_offset addr;
struct {
unsigned long ptr;
seg cs;
off ip;
} stack_entry;
if( CommonAddr.segment == 0 ) {
CGraphOff = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?