Logo Search packages:      
Sourcecode: u++ version File versions

uProfiler.h

//                              -*- Mode: C++ -*- 
// 
// uC++ Version 5.0.1, Copyright (C) Robert Denda 1997
// 
// uProfiler.cc -- 
// 
// Author           : Robert Denda
// Created On       : Tue Jul 16 16:45:16 1996
// Last Modified By : Peter A. Buhr
// Last Modified On : Thu Aug 26 00:06:41 2004
// Update Count     : 646
//
// This  library is free  software; you  can redistribute  it and/or  modify it
// under the terms of the GNU Lesser General Public License as published by the
// Free Software  Foundation; either  version 2.1 of  the License, or  (at your
// option) any later version.
// 
// This library is distributed in the  hope that it will be useful, but WITHOUT
// ANY  WARRANTY;  without even  the  implied  warranty  of MERCHANTABILITY  or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
// for more details.
// 
// You should  have received a  copy of the  GNU Lesser General  Public License
// along  with this library.
// 

#ifndef __U_PROFILER_H__
#define __U_PROFILER_H__

#include <uC++.h>


class uProfileAnalyze;                          // forward declarations
class uSymbolTable;
class uCallGraphInfo;
class uProfileSampler;
class uExecutionMonitor;
class uExecutionMonitorNode;
class uMemoryInfoEntry;


// The maximum number of metrics that are allowed to request memory allocation in the uC++ kernel
#define U_MAX_METRICS 8


//######################### uCreateMetricFunctions #########################


struct uCreateMetricFunctions : public uSeqable {
    char *className;
    void *createWidgetFunction;                         // address of function to create metric startup widget in Profiler startup window
    void *createMonitorFunction;

    uCreateMetricFunctions(char *name);
    ~uCreateMetricFunctions();
}; // uCreateMetricFunctions 


//######################### uProfileEvent #########################


class uProfileEvent : public uSeqable {
    friend uTask uProfiler;                     // only profiler can access member routines
    friend class uProfileMonitorSet;
    
    uExecutionMonitorNode &monitor;
    uTime time;
  public:    
    uProfileEvent( uExecutionMonitorNode &monitor );
}; // uProfileEvent


//######################### uProfileMonitorSet #########################


class uProfileMonitorSet : private uSequence<uProfileEvent> {
  public:
    void OrderedInsert( uProfileEvent *np );
    uProfileEvent *Head();
    uProfileEvent *Succ( uProfileEvent *e );
    void Remove( uProfileEvent *e );
    void Reorder( uProfileEvent *np );
}; // uProfileMonitorSet


//######################### uProfiler ##########################


uTask uProfiler {
    friend uTask uProcessorTask;
    friend class uProcessor;
    friend uCoroutine uProcessorKernel;                          
    friend class uProfilerBoot;
    friend class uSymbolTable;
    friend class uProfilerStartWidget;
    friend class uExecutionMonitor;
    friend class uMemoryExecutionMonitor;               // access: uGetMetricMemoryIndex()
    friend class uCGMonitor;                    // activate uProfiler hooks in distributed monitoring mode
    friend class uESMonitor;                    // activate uProfiler hooks in distributed monitoring mode
    friend class uPOTMonitor;                   // activate uProfiler hooks in distributed monitoring mode
    friend class uMemMonitor;                   // activate uProfiler hooks in distributed monitoring mode
    friend class uHWMonitor;                            // activate uProfiler hooks in distributed monitoring mode
    friend class uHWFunctionMonitor;                    // activate uProfiler hooks in distributed monitoring mode
    friend class uProfileSampler;               // access: addFuncCallInfo, memory allocation hooks
    friend class uProfileAnalyze;               // access: symbolTable, InfoList
    friend void __cyg_profile_func_enter( void *pcCurrentFunction, void *pcCallingFunction );
    friend void __cyg_profile_func_exit( void *pcCurrentFunction, void *pcCallingFunction );
    friend class uSigHandlerModule;             // access: uProfilerInstance
    friend class uCoroutineMain;                // access: uProfilerInstance
    friend class uMachContext;                        // access: uProfilerInstance
    friend class uBaseCoroutine;                // access: uProfilerInstance
    friend class uBaseTask;                     // access: uProfilerInstance
    friend class uSerial;                       // access: uProfilerInstance
    friend class uSerialConstructor;                  // access: uProfilerInstance
    friend class uSerialDestructor;             // access: uProfilerInstance    
    friend class uSerialMember;                       // access: uProfilerInstance
    friend class uCondition;                    // access: uProfilerInstance                    
    friend class uCoroutineConstructor;               // access: uProfilerInstance
    friend class uCoroutineDestructor;                // access: uProfilerInstance
    friend class uTaskConstructor;              // access: uProfilerInstance
    friend class uTaskDestructor;               // access: uProfilerInstance
    friend class uTaskMain;                     // access: uProfilerInstance
    friend class uHeapManager;                        // access: uProfilerInstance
    friend class uSpinLock;                             // access: uProfilerInstance
    friend class uCondLock;                             // access: uProfilerInstance
    friend class uOwnerLock;                            // access: uProfilerInstance
    friend class uEventList;                            // access: uProfilerInstance
    friend void uExit( int retcode );                 // access: uProfilerInstance

    static uProfiler *uProfilerInstance;        // pointer to profiler

    uSequence<uCreateMetricFunctions> *metricList;      // list of metrics, used to create the profiler's startup window
    unsigned int numMetrics;
    int numMemoryMetrics;                       // current index into the metric memory array

    uProfileMonitorSet monitorSet;              // list of poll events for samplers 
    uCluster           cluster;                       // own cluster
    uProcessor         processor;               // own processor
    uSymbolTable      *symbolTable;             // symbol table of the executable
    uClock            &processorClock;                // clock used to get current time
    bool               finish;                        // end of gathering data

    char              *filename;                // name of executable

    uCondition delay;                           // TEMPORARY: don't even ask

    // communication 
    const uBaseTask     *taskToProcess;
    uBaseTask::uTaskState taskState;
    const uBaseCoroutine *coroutineToProcess;
    const uBaseCoroutine *coroutineFromProcess;
    const uProcessor    *processorToProcess;
    const uCluster      *cluster1;
    const uCluster      *cluster2;
    const uSerial *serial;
    const char          *objectName;
    const uCondition    *condition;
    void          *currentFunction;
    void          *callingFunction;
    void          *firstArg;
    uTime               contextSwTime;                // used to reduced the number of calls to uGetTime(), which is expensive
    void                *memAddress;
    size_t              memSizeRequested, memSizeAllocated;
    
    // monitoring modules
    mutable uSequence<uExecutionMonitorNode> &MonitorList;                    // list of all selected profiling monitors 
    mutable uSequence<uExecutionMonitorNode> &RegisterTaskMonitorList;        // list of monitors to be informed upon task registration
    mutable uSequence<uExecutionMonitorNode> &DeregisterTaskMonitorList;      // list of monitors to be informed upon task deregistration
    mutable uSequence<uExecutionMonitorNode> &RegisterTaskStartExecutionMonitorList; // list of monitors to be infor. upon task registration
    mutable uSequence<uExecutionMonitorNode> &RegisterTaskEndExecutionMonitorList;   // list of monitors to be infor. upon task registration
    mutable uSequence<uExecutionMonitorNode> &RegisterProcessorMonitorList;   // list of monitors to be informed upon processor registr.
    mutable uSequence<uExecutionMonitorNode> &DeregisterProcessorMonitorList; // list of monitors to be informed upon processor dereg.
    mutable uSequence<uExecutionMonitorNode> &MigrateTaskMonitorList;         // list of monitors to be informed upon task migration
    mutable uSequence<uExecutionMonitorNode> &MigrateProcessorMonitorList;    // list of monitors to be informed upon processor migration
    mutable uSequence<uExecutionMonitorNode> &RegisterFunctionEntryMonitorList;     // list of monitors to be informed upon routine entry
    mutable uSequence<uExecutionMonitorNode> &RegisterFunctionExitMonitorList;  // list of monitors to be informed upon routine exit
    mutable uSequence<uExecutionMonitorNode> &RegisterMutexFunctionEntryTryMonitorList;   // list of monitors to be informed upon mutex routine entry petition
    mutable uSequence<uExecutionMonitorNode> &RegisterMutexFunctionEntryDoneMonitorList; // list of monitors to be informed upon mutex routine entry 
    mutable uSequence<uExecutionMonitorNode> &RegisterMutexFunctionExitMonitorList; // list of monitors informed upon mutex routine exit
    mutable uSequence<uExecutionMonitorNode> &RegisterMonitorMonitorList;     // list of monitors to be informed upon monitor creation
    mutable uSequence<uExecutionMonitorNode> &DeregisterMonitorMonitorList;   // list of monitors to be informed upon monitor creation    
    mutable uSequence<uExecutionMonitorNode> &RegisterAcceptStartMonitorList; // list of monitors to be informed upon accept start
    mutable uSequence<uExecutionMonitorNode> &RegisterAcceptEndMonitorList;   // list of monitors to be informed upon accept end
    mutable uSequence<uExecutionMonitorNode> &RegisterWaitMonitorList;        // list of monitors to be informed upon wait on condition
    mutable uSequence<uExecutionMonitorNode> &RegisterReadyMonitorList;       // list of monitors to be informed upon wake up after wait on condition
    mutable uSequence<uExecutionMonitorNode> &RegisterSignalMonitorList;      // list of monitors to be informed upon signal on condition
    mutable uSequence<uExecutionMonitorNode> &RegisterCoroutineMonitorList;   // list of monitors to be informed upon coroutine creation
    mutable uSequence<uExecutionMonitorNode> &DeregisterCoroutineMonitorList; // list of monitors to be informed upon coroutine deletion
    mutable uSequence<uExecutionMonitorNode> &RegisterCoroutineBlockMonitorList;  // list of monitors to be informed on coroutine inactivate
    mutable uSequence<uExecutionMonitorNode> &RegisterCoroutineUnblockMonitorList; // list of monitors to be informed on coroutine activate
    mutable uSequence<uExecutionMonitorNode> &RegisterTaskExecStateMonitorList; // list of monitors to be informed on change of task state
    mutable uSequence<uExecutionMonitorNode> &RegisterSetNameMonitorList;       //  monitors to be inf. on task/coroutine change of name
    mutable uSequence<uExecutionMonitorNode> &RegisterMemoryAllocateMonitorList;
    mutable uSequence<uExecutionMonitorNode> &RegisterMemoryDeallocateMonitorList;
    mutable uSequence<uExecutionMonitorNode> &PollMonitorList;                // list of monitors to be periodically polled
       
    // built in monitoring modules 
    mutable uSequence<uExecutionMonitorNode> &BuiltInRegisterTaskBlockMonitorList; // list of monitors to be informed upon task block
    mutable uSequence<uExecutionMonitorNode> &BuiltInRegisterTaskUnblockMonitorList; // list of monitors to be informed upon task unblock
    mutable uSequence<uExecutionMonitorNode> &BuiltInRegisterFunctionEntryMonitorList;
    mutable uSequence<uExecutionMonitorNode> &BuiltInRegisterFunctionExitMonitorList;
     
    void main();
    void CheckMetricList( void );               // make sure all required info for creating metrics is provided

    // functions for handling dynamic memory allocation in uC++ kernel
    int  uGetMetricMemoryIndex();                                       // get an index into the metric memory array
    void uPreallocateMetricMemory( void **, const uBaseTask & ) const;  // preallocate required metric memory for current task in provided array
    void uPostallocateMetricMemory( const uBaseTask & ) const;          // postallocate required metric memory for current task
    void uSetMetricMemoryPointers( void **, const uBaseTask & ) const;  // force profiler to use provided array for memory management
    void uResetMetricMemoryPointers( const uBaseTask & ) const;         // allow profiler to resume using its native array for memory management

    void AddToMonitorList( uExecutionMonitor *mon ) const;

    uMutex void RegisterTaskMutex( uBaseTask &task, uSerial &serial, const uBaseTask &parent );
    uMutex void DeregisterTaskMutex( uBaseTask &task );
    uMutex void RegisterTaskStartExecutionMutex( const uBaseTask &task );
    uMutex void RegisterTaskEndExecutionMutex( const uBaseTask &task );
    uMutex void MigrateTaskMutex( const uBaseTask &task, const uCluster &fromCluster, const uCluster &toCluster );
    uMutex void RegisterProcessorMutex( const uProcessor &processor );
    uMutex void DeregisterProcessorMutex( const uProcessor &processor );
    uMutex void MigrateProcessorMutex( const uProcessor &processor, const uCluster &fromCluster, const uCluster &toCluster );
    uMutex void RegisterFunctionEntryMutex( uBaseTask *task, void *pcCallingFunction, void *pcCurrentFunction, void *pcFirstArg );
    uMutex void RegisterFunctionExitMutex( uBaseTask *task, void *pcCallingFunction, void *pcCurrentFunction, void *pcFirstArg );
    uMutex void RegisterMutexFunctionEntryTryMutex( const uSerial &serial, const uBaseTask &task );
    uMutex void RegisterMutexFunctionEntryDoneMutex( const uSerial &serial, const uBaseTask &task );    
    uMutex void RegisterMutexFunctionExitMutex( const uSerial &serial, const uBaseTask &task );
    uMutex void RegisterMonitorMutex( uSerial &serial, const char *name, uBaseTask &task );
    uMutex void DeregisterMonitorMutex( const uSerial &serial, const uBaseTask &task );    
    uMutex void RegisterAcceptStartMutex( const uSerial &serial, const uBaseTask &task );
    uMutex void RegisterAcceptEndMutex( const uSerial &serial, const uBaseTask &task );
    uMutex void RegisterWaitMutex( const uCondition &condition, const uBaseTask &task, const uSerial &serial );
    uMutex void RegisterReadyMutex( const uCondition &condition, const uBaseTask &task, const uSerial &serial );    
    uMutex void RegisterSignalMutex( const uCondition &condition, const uBaseTask &task, const uSerial &serial );    
    uMutex void RegisterCoroutineMutex( uBaseCoroutine &coroutine, uSerial &serial );
    uMutex void DeregisterCoroutineMutex( uBaseCoroutine &coroutine );
    uMutex void RegisterCoroutineBlockMutex( const uBaseTask &task, uBaseCoroutine &coroutine );
    uMutex void RegisterCoroutineUnblockMutex( const uBaseTask &task );
    uMutex void RegisterTaskExecStateMutex( uBaseTask &task, uBaseTask::uTaskState state, void *function );
    uMutex void RegisterSetNameMutex( const uBaseCoroutine &coroutine, const char *name );
    uMutex void RegisterMemoryAllocateMutex( void *address, size_t size, size_t size, const uBaseTask &task );
    uMutex void RegisterMemoryDeallocateMutex( void *address, size_t size, const uBaseTask &task );
     
    uMutex void Finish();
  public:
    uProfiler( char *filename );
    ~uProfiler();

    uNoMutex const uSymbolTable *GetSymbolTable() const;
    uNoMutex const uProfileAnalyze *GetAnalyzer() const;
    uNoMutex uCluster &GetCluster() const { return const_cast<uCluster &>( cluster ); }

    uTime WakeUp();

    uNoMutex void RegisterTask( uBaseTask &task, uSerial &serial, const uBaseTask &parent );
    uNoMutex void DeregisterTask( uBaseTask &task );
    uNoMutex void RegisterTaskStartExecution( const uBaseTask &task );
    uNoMutex void RegisterTaskEndExecution( const uBaseTask &task );
    uNoMutex void RegisterProcessor( const uProcessor &processor );
    uNoMutex void DeregisterProcessor( const uProcessor &processor );
    uNoMutex void MigrateTask( const uBaseTask &task, const uCluster &fromCluster, const uCluster &toCluster );
    uNoMutex void MigrateProcessor( const uProcessor &processor, const uCluster &fromCluster, const uCluster &toCluster );
    uNoMutex void RegisterFunctionEntry( uBaseTask *task, void *pcCallingFunction, void *pcCurrentFunction, void *pcFirstArg );
    uNoMutex void RegisterFunctionExit( uBaseTask *task, void *pcCallingFunction, void *pcCurrentFunction, void *pcFirstArg  );
    uNoMutex void RegisterMutexFunctionEntryTry( const uSerial &serial, const uBaseTask &task );
    uNoMutex void RegisterMutexFunctionEntryDone( uSerial &serial, uBaseTask &task );
    uNoMutex void RegisterMutexFunctionExit( const uSerial &serial, const uBaseTask &task );
    uNoMutex void RegisterMonitor( uSerial &serial, const char *name, uBaseTask &task );
    uNoMutex void DeregisterMonitor( const uSerial &serial, const uBaseTask &task );
    uNoMutex void RegisterAcceptStart( const uSerial &serial, const uBaseTask &task );
    uNoMutex void RegisterAcceptEnd( const uSerial &serial, const uBaseTask &task );
    uNoMutex void RegisterWait( const uCondition &condition, const uBaseTask &task, const uSerial &serial );
    uNoMutex void RegisterReady( const uCondition &condition, const uBaseTask &task, const uSerial &serial );
    uNoMutex void RegisterSignal( const uCondition &condition, const uBaseTask &task, const uSerial &serial );
    uNoMutex void RegisterCoroutine( uBaseCoroutine &coroutine, uSerial &serial );
    uNoMutex void DeregisterCoroutine( uBaseCoroutine &coroutine );
    uNoMutex void RegisterCoroutineBlock( uBaseTask &task, uBaseCoroutine &coroutine );
    uNoMutex void RegisterCoroutineUnblock( uBaseTask &task );
    uNoMutex void RegisterTaskExecState( uBaseTask &task, uBaseTask::uTaskState state );
    uNoMutex void RegisterSetName( const uBaseCoroutine &coroutine, const char *name );
    uNoMutex uMemoryInfoEntry *RegisterMemoryAllocate( void *address, size_t size, size_t size );
    uNoMutex void RegisterMemoryDeallocate( void *address, size_t size, uMemoryInfoEntry *entry );
    uNoMutex void Poll();

    // built-in modules (do not have corresponding mutex members => cannot be used by user metrics)
    uNoMutex void BuiltInRegisterTaskBlock( uBaseTask &task );    // not allowed to block ( hook inside context switch routine )
    uNoMutex void BuiltInRegisterTaskUnblock( uBaseTask &task ); // not allowed to block  ( hook inside context switch routine )
    uNoMutex void BuiltInRegisterFunctionEntry();
    uNoMutex void BuiltInRegisterFunctionExit();
    uNoMutex void BuiltInRegisterProcessor( const uProcessor & );    // not allowed to block (hook inside uC++ kernel)
    uNoMutex void BuiltInDeregisterProcessor( const uProcessor & );  // not allowed to block (hook inside uC++ kernel)
    uNoMutex void BuiltInRegisterTaskStartSpin( const uBaseTask & ); // not allowed to block
    uNoMutex void BuiltInRegisterTaskStopSpin( const uBaseTask & );  // not allowed to block

    // routine pointers to member routines in uProfiler

    static void (* uProfiler_RegisterTask)(uProfiler *, const uBaseTask &, const uSerial &, const uBaseTask & );
    static void (* uProfiler_DeregisterTask)(uProfiler *, const uBaseTask &);
    static void (* uProfiler_RegisterTaskStartExecution)(uProfiler *, const uBaseTask & );
    static void (* uProfiler_RegisterTaskEndExecution)(uProfiler *, const uBaseTask & );
    static void (* uProfiler_RegisterProcessor)(uProfiler *, const uProcessor &);
    static void (* uProfiler_DeregisterProcessor)(uProfiler *, const uProcessor &);
    static void (* uProfiler_RegisterTaskMigrate)(uProfiler *, const uBaseTask &, const uCluster &, const uCluster &);
    static void (* uProfiler_RegisterProcessorMigrate)(uProfiler *, const uProcessor &, const uCluster &, const uCluster &);
    static void (* uProfiler_RegisterFunctionEntry)(uProfiler *, uBaseTask *, unsigned int, unsigned int, unsigned int );
    static void (* uProfiler_RegisterFunctionExit)(uProfiler *, uBaseTask *);
    static void (* uProfiler_RegisterMutexFunctionEntryTry)(uProfiler *, const uSerial &, const uBaseTask &);
    static void (* uProfiler_RegisterMutexFunctionEntryDone)(uProfiler *, const uSerial &, const uBaseTask &);    
    static void (* uProfiler_RegisterMutexFunctionExit)(uProfiler *, const uSerial &, const uBaseTask &);
    static void (* uProfiler_RegisterMonitor)(uProfiler *, const uSerial &, const char *, const uBaseTask &);
    static void (* uProfiler_DeregisterMonitor)(uProfiler *, const uSerial &, const uBaseTask &);
    static void (* uProfiler_RegisterAcceptStart)(uProfiler *, const uSerial &, const uBaseTask &);
    static void (* uProfiler_RegisterAcceptEnd)(uProfiler *, const uSerial &, const uBaseTask &);    
    static void (* uProfiler_RegisterWait)(uProfiler *, const uCondition &, const uBaseTask &, const uSerial &);
    static void (* uProfiler_RegisterReady)(uProfiler *, const uCondition &, const uBaseTask &, const uSerial &);
    static void (* uProfiler_RegisterSignal)(uProfiler *, const uCondition &, const uBaseTask &, const uSerial &);
    static void (* uProfiler_RegisterCoroutine)(uProfiler *, const uBaseCoroutine &, const uSerial &);
    static void (* uProfiler_DeregisterCoroutine)(uProfiler *, const uBaseCoroutine &);
    static void (* uProfiler_RegisterCoroutineBlock)(uProfiler *, const uBaseTask &, const uBaseCoroutine &);    
    static void (* uProfiler_RegisterCoroutineUnblock)(uProfiler *, const uBaseTask &);
    static void (* uProfiler_RegisterTaskExecState)(uProfiler *, const uBaseTask &, uBaseTask::uTaskState );
    static void (* uProfiler_Poll)(uProfiler *);
    static void (* uProfiler_RegisterSetName)(uProfiler *, const uBaseCoroutine &, const char *);
    static uMemoryInfoEntry *(* uProfiler_RegisterMemoryAllocate)(uProfiler *, void *, size_t, size_t );
    static void (* uProfiler_RegisterMemoryDeallocate)(uProfiler *, void *, size_t, uMemoryInfoEntry * );
    
    static void (* uProfiler_RegisterCluster)(uProfiler *, const uCluster &);
    static void (* uProfiler_DeregisterCluster)(uProfiler *, const uCluster &);

    // hooks for built in metrics (cannot be used by user metrics because they do not notify execution monitors)

    static void (* uProfiler_BuiltInRegisterTaskBlock)(uProfiler *, const uBaseTask &);
    static void (* uProfiler_BuiltInRegisterTaskUnblock)(uProfiler *, const uBaseTask &);
    static void (* uProfiler_BuiltInRegisterFunctionEntry)(uProfiler *);
    static void (* uProfiler_BuiltInRegisterFunctionExit)(uProfiler *);
    static void (* uProfiler_BuiltInRegisterProcessor)(uProfiler *, const uProcessor &);
    static void (* uProfiler_BuiltInDeregisterProcessor)(uProfiler *, const uProcessor &);
    static void (* uProfiler_BuiltInRegisterTaskStartSpin)(uProfiler *, const uBaseTask &);
    static void (* uProfiler_BuiltInRegisterTaskStopSpin)(uProfiler *, const uBaseTask &);

    // dynamic memory allocation in uC++ kernel

    static void (* uProfiler_PreallocateMetricMemory)(uProfiler *, void **, const uBaseTask &);
    static void (* uProfiler_PostallocateMetricMemory)(uProfiler *, const uBaseTask &);
    static void (* uProfiler_SetMetricMemoryPointers)(uProfiler *, void **, const uBaseTask &);
    static void (* uProfiler_ResetMetricMemoryPointers)(uProfiler *, const uBaseTask &);

    // debugging hook
    static void (* uProfiler_printCallStack)(uProfileSampler * );
}; // uProfiler


#endif // __U_PROFILER_H__


// Local variables: //
// compile-command: "gmake install" //
// End: //

Generated by  Doxygen 1.6.0   Back to index