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 + -
显示快捷键?