sampos22.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 616 行 · 第 1/2 页

C
616
字号
/****************************************************************************
*
*                            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 2.x performance sampling core.
*
****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <string.h>
#include <i86.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "sample.h"
#include "wmsg.h"
#include "smpstuff.h"

#define INCL_32

#define INCL_BASE
#define INCL_DOSDEVICES
#define INCL_DOSMEMMGR
#define INCL_DOSPROCESS
#define INCL_DOSSESMGR
#include "os2.h"

// "Fake" notification codes used internally
#define DBG_N_Breakpoint        -100
#define DBG_N_SStep             -101
#define DBG_N_Signal            -102

#define BUFF_SIZE 2048

static char             UtilBuff[BUFF_SIZE];
static uDB_t            Buff;
static PID              Pid;
static USHORT           InitialCS;
static ULONG            MainMod = 0;
static ULONG            SleepTime;
static unsigned         *SampleIndexP;
static unsigned         *SampleCountP;
static samp_block       * FAR_PTR *SamplesP;
static samp_block       * FAR_PTR *CallGraphP;
static unsigned         MaxThread = 1;
static unsigned         ExceptNum;
static int              NewSession;
static int              sleepProcId = 0;

static seg_offset       CommonAddr;

#define STACK_SIZE 32768

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( void )
{
    SleepTime = 55;
}

void SetTimerRate( char **cmd )
{
    SleepTime = GetNumber( 1, 1000, cmd, 10 );
}

unsigned long TimerRate( void )
{
    return( 1000L * SleepTime );
}

unsigned SafeMargin( void )
{
    return( Ceiling-10 );
}

int VersionCheck( void )
{
    return( TRUE );
}

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, TID 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();
    }
}


void GetCommArea( void )
{
    uDB_t   mybuff;

    if( CommonAddr.segment == 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 {
        mybuff.Pid = Pid;
        mybuff.Tid = 0;         /* callgraph info only supported on thread 0 */
        mybuff.Cmd = DBG_C_ReadMemBuf;
        mybuff.Addr = CommonAddr.offset;
        mybuff.Len = sizeof( Comm );
        mybuff.Buffer = FP_OFF( &Comm );
        DosDebug( &mybuff );
    }
}


void ResetCommArea( void )
{
    uDB_t   mybuff;

    if( CommonAddr.segment != 0 ) {     /* reset common variables */
        Comm.pop_no = 0;
        Comm.push_no = 0;
        mybuff.Pid = Pid;
        mybuff.Tid = 0;         /* callgraph info only supported on thread 0 */
        mybuff.Cmd = DBG_C_WriteMemBuf;
        mybuff.Addr = CommonAddr.offset + 11;
        mybuff.Len = 4;
        mybuff.Buffer = FP_OFF( &Comm.pop_no );
        DosDebug( &mybuff );
    }
}


void GetNextAddr( void )
{
    uDB_t   mybuff;
    struct {
        unsigned long   ptr;
        seg             cs;
        off             ip;
    } stack_entry;

    if( CommonAddr.segment == 0 ) {
        CGraphOff = 0;
        CGraphSeg = 0;
    } else {
        mybuff.Pid = Pid;
        mybuff.Tid = 0;
        mybuff.Cmd = DBG_C_ReadMemBuf;
        mybuff.Addr = Comm.cgraph_top;
        mybuff.Len = sizeof( stack_entry );
        mybuff.Buffer = FP_OFF( &stack_entry );
        DosDebug( &mybuff );
        CGraphOff = stack_entry.ip;
        CGraphSeg = stack_entry.cs;
        Comm.cgraph_top = stack_entry.ptr;
    }
}


void StopProg( void )
{
}


static void CodeLoad( uDB_t FAR_PTR *buff, ULONG mte,
                      char *name, samp_block_kinds kind )
{
    seg_offset  ovl;
    int         i;

    ovl.offset = 0;
    ovl.segment = 0;
    WriteCodeLoad( ovl, name, kind );
    buff->MTE = mte;
    for( i = 1;; ++i ) {
        buff->Cmd = DBG_C_NumToAddr;
        buff->Value = i;
        if( DosDebug( buff ) != 0 ) break;
        if( buff->Cmd != DBG_N_Success ) break;
        /* Assume that all 32-bit apps are running on the CS selector value */
        WriteAddrMap( i, FP_SEG( CodeLoad ), buff->Addr );
    }
}


static void InternalError( char * str )
{
    Output( MsgArray[MSG_SAMPLE_2-ERR_FIRST_MESSAGE] );
    Output( str );
    Output( "\r\n" );
    _exit( -1 );
}


void DebugExecute( uDB_t *buff, ULONG cmd )
{
//    EXCEPTIONREPORTRECORD     ex;
    ULONG                       value;
    ULONG                       stopvalue;
    ULONG                       notify=0;
    char                        name[ BUFF_SIZE ];

    buff->Cmd = cmd;
    value = buff->Value;
    if( cmd == DBG_C_Go ) value = 0;
    stopvalue = XCPT_CONTINUE_EXECUTION;
    if( cmd == DBG_C_Stop ) stopvalue = XCPT_CONTINUE_STOP;

    for( ;; ) {

        buff->Value = value;
        buff->Cmd = cmd;
        if( DosDebug( buff ) ) {
            InternalError( MsgArray[MSG_SAMPLE_7-ERR_FIRST_MESSAGE] );
        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?