AnubisProcess.h 10.5 KB

#ifndef __CM_ANUBIS_PROCESS_H__
#define __CM_ANUBIS_PROCESS_H__



/* see vm.cpp for explanations of this: */ 
#define NO_BIG_SWITCH
#define WITH_STATIC_MEMBERS   



#include "AnubisSupport.h"
#include "CMList.h"
#include "vm.h"
#include "bytecode.h"   
#include "Profiling.h"   
#include "../../../third_dev/sqlite3/sqlite3.h"   
#include "perf.h"   

BEGIN_NAMESPACE(CM);
//class AnubisAllocator;

class AnubisProcess
{
  public:

    enum anbStatus
    {
      machine_not_used,
      running,
      waiting_for_event,
      waiting_for_condition,
      waiting_for_completion,
      finished,
      need_bigger_stack,
      need_bigger_locked_files_stack,
      need_more_memory,
      invalid_instruction,
      invalid_IP
    };

    enum WorkSort
    {
      computing,
      deleting,
      equaling,
      serializing,
      unserializing
    };

    AnubisProcess(void);
    virtual ~AnubisProcess();

    /** 
     * CreateProcess constructor
     * @param starting_point where to begin within code
     * @param byte_code code to execute
     * @param code_size 
     * @param allocator
     * @return Return the process id of new created process, otherwise -1 for error
     */
    int Create(U8 * starting_IP, U8 priority, AnubisAllocator *allocator);

    /** 
     * Set the pid of the process. usually is the process list who decide the pid of the 
     * process
     * @param pid  process unique id
     */
    void SetPid(U32 pid);
    void SetStatus(anbStatus);

    U32 GetPid(void);
    anbStatus GetStatus(void);
    const struct timeval&	GetStartingTime(void) const { return m_starting_time; }
    //U32	GetStartingPoint(void) const { return m_starting_point; }
    int	GetStepCounter(void) const { return m_steps; }
    U8  *GetIP(void);
    U32 *GetSP(void);
    U8  *GetCodeBegin(void);
    U32  GetWorkSort(void);
    U32 *GetSPBegin(void);
    U32 *GetSPEnd(void);
    U32 GetMainRegister() const				{ return m_R; }
    U32 GetIndexRegister() const				{ return m_I; }
    bool IsUnserialFailed() const				{ return m_unserial_failed; }
    bool IsDUCNonEmpty() const				{ return m_duc_non_empty; }
    U8 GetPriority() const				{ return m_priority; }
    void  SetSP(U32 * sp);
    U8* GetSerializationBuffer() const	{ return m_serial_buf; }
    U32 GetSerializationSize() const	{ return m_serial_size; }
    U32 GetSerializationNext() const	{ return m_serial_next; }

    AnubisAllocator *GetAllocator(void);
    struct timeval * GetAlarm(void);
    void PushOnSP(U32 value);
    int RunMachine(int steps);

    // Stack function
    void EnlargeStack(void);
    //  void EnlargeLockedFilesStack(void);


    // Profiling functions
    static ArrayTemplate<FunctionSummary*> & GetFunctionsList() { return m_functions; }
    static FunctionSummary * GetFunction(const String & name, int32 label, bool createIfMissing = true);
    static FunctionSummary * GetFunction(int32 label);
    FunctionCall * CurrentFunction() const		{ return m_current_function; }

    // Performance functions
    const bigtime_t & GetPerfSum() const { return m_perf_time_sum; }
    void PerfSumTime(bigtime_t t) { m_perf_time_sum += t; }
    void ResetPerfSum() { m_perf_time_sum = 0; }
    U32 GetAverageLoad1() const { return (U32)(m_perf_1 * 100) >> FSHIFT; }	
    U32 GetAverageLoad5() const { return (U32)(m_perf_5 * 100) >> FSHIFT; }	
    U32 GetAverageLoad15() const { return (U32)(m_perf_15 * 100) >> FSHIFT; }	

  private:
    bool MakeSQLite3Result(sqlite3_stmt * stmt, int error_code);

  protected:
  private:
    U32 m_pid;                           /* process unique id */
    anbStatus m_status;                  /* current status of this process */ 
    U32 m_work_sort;                     /* what it is currently doing */ 
    int m_steps;                         /* must be signed (((m_steps--) <= 0) in 'vm.cpp') */ 
    U32 m_R;                             /* main register of the machine */ 
    U32 m_I;                             /* index register of the machine */
    struct timeval m_starting_time;      /* keep trace of starting time for debugging purpose.*/
    //U32 m_starting_point;                /* keep trace of starting point for debugging purpose.*/
    U8* m_IP;                            /* instruction pointer */ 
    U8* m_previous_IP;                   /* previous value of instruction pointer */ 
    U32 * m_SP_begin;                    /* address of process stack */ 
    U32 * m_SP;                          /* stack pointer */ 
    U32 * m_SP_end;                      /* end of process stack */ 
    /* the two fields below droped since version 1.13. They are incompatible with the loading
       of several modules, because the same process may execute code from different modules. 
       (the same is true of 'm_starting_point' above) */
    //U8 * m_code_begin;                   /* address of code */ 
    //U8 * m_code_end;                     /* end of code */ 
    AnubisAllocator *m_allocator;               /* memory allocator */ 
    U32 m_DUC1;                          /* datum under construction 1 */ 
    U32 m_DUC2;                          /* datum under construction 2 */ 
    U32 m_DUC3;                          /* datum under construction 3 */ 
    double m_DUC1d;                      /* datum under construction double 1 */ 
    struct timeval m_alarm; 
    pid_t m_child;                       /* used by the 'execute' primitive */    
    U8 * m_serial_buf;                   /* serialization buffer */
    U32 m_serial_size;                   /* current size of buffer */ 
    U32 m_serial_next;                   /* current next free position */ 
    unsigned int m_unserial_failed:1;    /* flag for unserialization control */ 

    unsigned int m_duc_non_empty:1;      /* flag for control of DUC1 DUC2 and DUC3 */ 
    //  U32 m_locked_files_stack_size;       /* current size of locked files stack */ 
    //  U32 m_locked_files_SP;               /* locked files stack pointer */ 
    //  U32 * m_locked_files;                /* stack of locked files (vm strings) */
    U8    m_priority;                    // current priority of the process
#ifdef instruction_count
    U32 m_i_count[256];                  /* one counter for each instruction */
#endif   
    FunctionCall	*	m_current_function;		// used by profiling instructions (begin_op and end_op)
    static ArrayTemplate<FunctionSummary*> m_functions;

    // performance
    bigtime_t			m_perf_time_sum;
  public:
    U32 m_perf_1;
    U32 m_perf_5;
    U32 m_perf_15;


#ifdef NO_BIG_SWITCH   

    /* Declaration of all instructions of the VM as member functions. 

       ci_ is used for 'computing'
       si_ is used for 'serializing' 
       ui_ is used for 'unserializing'

       'normal_instructions_list'    and    'pseudo_instructions_list'    are    #defined    in
       'anubis_dev/include/bytecode.h'. */    

#ifdef WITH_STATIC_MEMBERS   
    /* member functions are static and the process is passed explicitly */ 
#define STKW static
#define EARG AnubisProcess *
#else   
    /* member functions are instance functions and the process is implicit */ 
#define STKW
#define EARG void
#endif   

    /* computing */ 
#define item(n) STKW void ci_##n(EARG); 
    common_instructions_list
      normal_instructions_list
      pseudo_instructions_list
#undef item   
      STKW void ci_dummy(EARG); 

    /* serializing */ 
#define item(n) STKW void serialize_##n(EARG); 
    common_instructions_list
      normal_instructions_list
      pseudo_instructions_list
#undef item   
      STKW void serialize_dummy(EARG); 

    /* unserializing */ 
#define item(n) STKW void ui_##n(EARG); 
    common_instructions_list
      normal_instructions_list
      pseudo_instructions_list
#undef item   
      STKW void ui_dummy(EARG); 

    /* The macros which are needed for declaring the above functions in .cpp files: */ 
#ifdef NO_BIG_SWITCH   
#ifdef WITH_STATIC_MEMBERS
#define MAM(m) (this_one->m)
#define ci_decl(n) void AnubisProcess::ci_##n(AnubisProcess *this_one)
#define si_decl(n) void AnubisProcess::serialize_##n(AnubisProcess *this_one)
#define ui_decl(n) void AnubisProcess::ui_##n(AnubisProcess *this_one)
#else   
#define MAM(m) (m)   
#define ci_decl(n) void AnubisProcess::ci_##n(void)   
#define si_decl(n) void AnubisProcess::serialize_##n(void)
#define ui_decl(n) void AnubisProcess::ui_##n(void)   
#endif      
#endif   




    /* the tables of functions */ 
#ifdef WITH_STATIC_MEMBERS   
    static void (*(ci_ftable[]))(AnubisProcess *); 
    static void (*(si_ftable[]))(AnubisProcess *); 
    static void (*(ui_ftable[]))(AnubisProcess *); 
#else
    void (*(ci_ftable[]))(void); 
    void (*(si_ftable[]))(void); 
    void (*(ui_ftable[]))(void); 
#endif

#endif /* NO_BIG_SWITCH */    
};



#ifdef NO_BIG_SWITCH 
#ifdef debug_vm   
#define trace if (debugging ||\
    (start_end_debug &&\
     (start_debug<=relative_IP((MAM(m_IP)))) &&\
     ((U32)(relative_IP(MAM(m_IP)))<=end_debug))) {\
  int i = *(MAM(m_IP));\
  LOGINFO("\n\nstack: ");\
  { U32 *p;\
    for (p = MAM(m_SP)-1; p >= MAM(m_SP_begin) && p >= MAM(m_SP)-6; p--)\
    LOGINFO("%.8x ",*p); }\
  LOGINFO("\n%d %s steps=%d IP=%d SP=%.3d R=%.8x I=%.3d" \
      " uf=%d sbuf=%d snxt=%d ssiz=%d mem=%d\n",\
      MAM(m_pid), ShortString((CM::AnubisProcess::WorkSort)MAM(m_work_sort)),\
      MAM(m_steps),relative_IP(MAM(m_IP)),MAM(m_SP)-MAM(m_SP_begin),MAM(m_R),MAM(m_I),\
      (U32)(MAM(m_unserial_failed)),\
      (U32)(MAM(m_serial_buf)),MAM(m_serial_next),MAM(m_serial_size),\
      memory_in_use);\
  LOGINFO("   %16s (%.3d) %.3d %.3d %.3d %.3d %.3d %.3d %.3d %.3d %.3d %.3d %.3d %.3d",\
      instr_name(i,get16(1)),i,\
      get8(1),get8(2),get8(3),get8(4),get8(5),get8(6),get8(7),get8(8),\
      get8(9),get8(10),get8(11),get8(12));\
  fflush(stdout); }
#else
#define trace
#endif   
#endif   








class AnubisProcessList : public List
{
  public:
    virtual ~AnubisProcessList();
    static AnubisProcessList* GetInstance();
    AnubisProcess * GetProcessAt(U32);
    AnubisProcess * GetProcessByID(U32);
    AnubisProcess * CreateAnubisProcess(U8 * starting_IP, U8 priority, AnubisAllocator* allocator);
    void DeleteProcess(U32 pid);
    AnubisProcess * GetRunningProcess() const { return _runningProcess; }
    void SetRunningProcess(AnubisProcess * current) { _runningProcess = current; }
  protected:
  private:
    AnubisProcessList();

    U32 _pidCounter; 
    AnubisProcess * _runningProcess;
    static AnubisProcessList* _instance; // instance du singleton

};

#define TheAnubisProcessList CM::AnubisProcessList::GetInstance()


END_NAMESPACE(CM);

extern "C" const char * ShortString(CM::AnubisProcess::WorkSort ws);

#endif // __CM_PROCESS_H__