⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 htrace.cpp

📁 A Windows CE API Inecptor Tools
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    }    ULONG l_lTextAreaSize = 
        s_Impl.m_BufferPointers.m_dwTextAreaSize;
    if(!l_lTextAreaSize)
    {        return false;
    }    ULONG * l_pdwBytesWritten = &s_Impl.
        m_BufferPointers.m_pGlobalFooter->m_dwNumBytesWritten;
    if(s_Impl.m_BufferPointers.m_pGlobalFooter->m_dwFrozen)
    {        return false;
    }    char* l_pszTextArea = (char*)s_Impl.m_BufferPointers.m_pTextArea;

    if((ULONG)l_iLenBytes > l_lTextAreaSize)
       l_iLenBytes = l_lTextAreaSize;

    //To ensure thread safety, we access the m_iWriteTo 
    //variable only from the single atomic operation
    ULONG l_dwWriteAt = InterlockedExchangeAdd
        ((long*)l_pdwBytesWritten,l_iLenBytes);

    if(l_dwWriteAt + l_iLenBytes > s_Impl.m_BufferPointers.
        m_pGlobalFooter->m_dwStopAfterThreshold)
    {
        s_Impl.m_BufferPointers.m_pGlobalFooter->m_dwFrozen = 1;
        return false;
    }


    //Now we reserved a space in the buffer,which other threads
    //will not touch, unless the buffer is filled too fast. In 
    //that case we will have meaningless garbage in the buffer.

    //Wrap around (circular buffer):
    l_dwWriteAt %= l_lTextAreaSize;

    if(l_dwWriteAt + l_iLenBytes <= l_lTextAreaSize)
    {
       memcpy(l_pszTextArea + l_dwWriteAt, p_pszString, l_iLenBytes);
    }
    else
    {
        ULONG l_dwWriteAtTheTail = l_lTextAreaSize - l_dwWriteAt;

        memcpy(l_pszTextArea + l_dwWriteAt, p_pszString, 
            l_dwWriteAtTheTail);

        ULONG l_dwWriteAtTheBeginning = 
            l_iLenBytes -l_dwWriteAtTheTail;

        memcpy(l_pszTextArea, p_pszString + l_dwWriteAtTheTail,
            l_dwWriteAtTheBeginning);
    }
    return true;
}//bool AddToTraceBuffer

#if defined(WINAPP) //{
/*-------------------------------------------------------------
   FUNCTION: CreateOpenFileMapping
   PURPOSE:  Create file mapping for use as a shared memory 
    buffer by WIN32 applications
-------------------------------------------------------------*/
HANDLE CreateOpenFileMapping
(
    LPCTSTR p_pszMemMapFilePath, 
    int     p_iFileSize,
    bool   *p_pbReturnIsCreated
)
{
    *p_pbReturnIsCreated = false;

#if !defined(_WIN32_WCE)
    HANDLE l_hFileMapping = OpenFileMapping(
        FILE_MAP_ALL_ACCESS, FALSE, g_szMemMapFileName);
    if(l_hFileMapping)
        return l_hFileMapping;
    HANDLE l_hFileHandle = CreateFile(p_pszMemMapFilePath, 
        GENERIC_READ | GENERIC_WRITE, 
        FILE_SHARE_WRITE | FILE_SHARE_READ, 0,
        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
#else
    HANDLE l_hFileHandle = CreateFileForMapping(p_pszMemMapFilePath, 
        GENERIC_READ | GENERIC_WRITE, 
        FILE_SHARE_WRITE | FILE_SHARE_READ, 0,
        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
#endif
    if(GetLastError() != ERROR_SHARING_VIOLATION)
    {
        *p_pbReturnIsCreated = true;
        if(l_hFileHandle == INVALID_HANDLE_VALUE) 
        {
            HTRACE(TG_Error, 
                _T("ERROR: Cannot open file %s for mapping (%s)"), 
                 p_pszMemMapFilePath, ERR_EXPL(GetLastError()));
            return NULL;
        }//if(l_hFileHandle ==  INVALID_HANDLE_VALUE)
    }
    HANDLE l_hFileMapping = CreateFileMapping(l_hFileHandle, 
        NULL, PAGE_READWRITE, 0, p_iFileSize, g_szMemMapFileName);
    CloseHandle(l_hFileHandle);
    if(!l_hFileMapping)
    {//May be somebody else created it?
#if !defined(_WIN32_WCE)
        l_hFileMapping = OpenFileMapping(
            FILE_MAP_ALL_ACCESS, FALSE, 
            g_szMemMapFileName);
#endif
        if(!l_hFileMapping)
        {
            HTRACE(TG_Error, 
                _T("Failed to create file mapping(%s)"),
                ERR_EXPL(GetLastError()));
            return false;
        }
    }
    return l_hFileMapping;
}//HANDLE CreateNewFileMapping

/*-------------------------------------------------------------
   FUNCTION: TraceImpl::CreateAndMapFile
   PURPOSE:  Open an existing memory mapped file or create new
    one for use as shared memory buffer by WIN32 applications
-------------------------------------------------------------*/
bool TraceImpl::CreateAndMapFile
(
    LPCTSTR       p_pszMemMapFilePath, 
    int           p_iFileSize
)
{
    if(m_BufferPointers.m_pGlobalHeader)
        return false;
    TCHAR l_szFileName[260];
    if(p_pszMemMapFilePath == NULL || 
        !_tcschr(p_pszMemMapFilePath, '\\'))
    {
#if defined(_WIN32_WCE)
        //Just put it in the root
        int l_iLen = 1;
        l_szFileName[0] = '\\';
#else
        //No directory specified. Try to create the file in the
        //current directory
        GetCurrentDirectory(
            sizeof(l_szFileName)/sizeof(l_szFileName[0]), 
            l_szFileName);
        int l_iLen = strlen(l_szFileName);
        if(l_iLen > 0 && l_szFileName[l_iLen-1] != '\\')
            l_szFileName[l_iLen++] = '\\';
#endif
        if(p_pszMemMapFilePath)
            _tcscpy(l_szFileName + l_iLen, p_pszMemMapFilePath);
        else
            _tcscpy(l_szFileName + l_iLen, g_szMemMapFileName);
        p_pszMemMapFilePath = l_szFileName;
    }

    bool l_bFileCreated = false;
    if(!m_hFileMapping) 
    {
        if(p_iFileSize <= 0)
           p_iFileSize = g_iDefaultMemMapFileSize;
        p_iFileSize += TRACE_BUFFER_EXTRA_SIZE;

        m_hFileMapping = CreateOpenFileMapping(p_pszMemMapFilePath, 
            p_iFileSize, &l_bFileCreated);
    }//if(!m_hFileMapping)

    GlobalTraceBufferHeader * l_pBufferHeader = 
        (GlobalTraceBufferHeader * ) 
        MapViewOfFile(m_hFileMapping, FILE_MAP_ALL_ACCESS, 
        0,0,0);
    if(!l_pBufferHeader)
    {
        return false;
    }
    if(l_bFileCreated) 
    {
        memset(l_pBufferHeader, 0, p_iFileSize);
        int l_iSizeTextArea = 
            p_iFileSize - TRACE_BUFFER_EXTRA_SIZE;

        l_pBufferHeader->m_dwSignature = 
            TRACE_BUFFER_SIGNATURE;
        SetTextAreaSizeHex(l_pBufferHeader->m_cSizeTextArea, 
            l_iSizeTextArea);    }    AssignTraceBufferPtr(l_pBufferHeader);    if(l_bFileCreated)    {        m_BufferPointers.m_pGlobalFooter->m_dwStopAfterThreshold =             (ULONG)-1;        m_BufferPointers.m_pGlobalFooter->m_dwFrozen = 0;     }

    m_bBufferMapped = true;
    return true;
}//bool TraceImpl::CreateAndMapFile
#endif //#if defined(WINAPP) }

#if defined(__linux__)//{
//First we need to define semaphore routines for linux.
//define _TEST_SEM to trace and test semaphore routines 
//in a console app.
//#define _TEST_SEM
#ifdef _TEST_SEM
#define SEM_TRACE(format, param1, param2, param3) \
    {printf(format, param1, param2, param3);\
    printf("Press Enter key to continue\n");\
    getchar();}
#else
#define SEM_TRACE(format, param1, param2, param3)
#endif
static bool DoSemOp(int p_iSemID, int p_iNum, 
                    int p_iIncDec, bool p_bUndoable)
{
    SEM_TRACE("Before calling semop %d #%d Inc %d\n", 
        p_iSemID, p_iNum, p_iIncDec);
    sembuf l_SemBuf;
    l_SemBuf.sem_num = p_iNum;
    l_SemBuf.sem_op = p_iIncDec;
    l_SemBuf.sem_flg = p_bUndoable? SEM_UNDO : 0;
    if(semop(p_iSemID, &l_SemBuf, 1) != 0)
    {
        SEM_TRACE("semop failed. %s\n",
            strerror(errno),0,0);
        HTRACE(TG_Error, "semop failed. %s\n",
            strerror(errno));
        return false;
    }
    SEM_TRACE("After calling semop %d #%d Inc %d\n", 
        p_iSemID, p_iNum, p_iIncDec);
    return true;
}

//We will use a semaphore to achieve InterlockedIncrement/
//InterlockedDecrement behavior between processes. We cannot 
//use regular InterlockedIncrement on a shared memory variable 
//because a process may be killed as a result of a crash or by 
//quitting debugging session, which will leave the shared 
//variable in incremented state forever. Increment of a 
//semaphore, on the other hand, is automatically undone
//by the OS on the process death if SEM_UNDO flag is set.
//The problem with semaphores is that IPC semaphore API is too
//inflexible: it does not allow to increment the semaphore 
//value and get the previous value in the same atomic 
//operation. Therefore, we need to use two operations: 
//semctl(GETVAL) and semop(+1) and protect these operations 
//by a second semaphore to make them atomic. Despite using 
//2 semaphores, this function is not blocking: it may wait
//for the second semaphore very briefly until the another 
//process exits from it's call to 
//InterlockedExchangeAddUsingSemaphore.
static bool InterlockedExchangeAddUsingSemaphore
(
    int   p_iSemKey, 
    int & p_riSemID,
    int   p_iAdd, 
    int & p_riReturnPreviousValue
)
{
    bool l_bResult = true;
    bool l_bCreatedNew = false;
    if(p_riSemID <= 0)
    {
        //Need to create the semaphore.
        //We create a set of 2 semaphores: first is the 
        //interlocked counter. The second is to protect 
        //the modification of the first one.
        int l_iSemID = semget(p_iSemKey,2,
            IPC_CREAT|IPC_EXCL|0660);
        if(l_iSemID < 0)
        {
            SEM_TRACE(
               "Failed to create exclusive semaphore"
                 " %d. %s\n",
                p_iSemKey, strerror(errno), 0);
                //This is not an error
        
            //OK, get it non-exclusively
            l_iSemID = semget(p_iSemKey, 2, 
                IPC_CREAT|0660);
            if(l_iSemID < 0)
            {
                HTRACE(TG_Error, 
                    "Failed to get semaphore %d. %s\n",
                    p_iSemKey, strerror(errno));
                return false;
            }
            SEM_TRACE("Opened semaphore key %d id %d\n", 
                p_iSemKey, l_iSemID, 0);
            //wait and acquire the second semaphore
            if(!DoSemOp(l_iSemID,1,-1, true))
                return false;
        }
        else
        {
            //We just created the semaphores. Both of them 
            //should have value 0, which means that other 
            //processes will be blocked on the second
            //semaphore until we release it below.
            l_bCreatedNew = true;
            SEM_TRACE(
                "Exclusively created semaphore key %d id %d\n",
                p_iSemKey, l_iSemID, 0);            
        }
        p_riSemID = l_iSemID;    
    }//if(p_riSemID <= 0)
    else
    {
        //wait and acquire the second semaphore
        if(!DoSemOp(p_riSemID,1,-1, true))
            return false;
    }
    p_riReturnPreviousValue = semctl(p_riSemID, 0, GETVAL);
    SEM_TRACE("semctl(%d,0,GETVAL) returned %d"
        " going to increment by %d\n",
        p_riSemID, p_riReturnPreviousValue, p_iAdd);
    if(p_riReturnPreviousValue < 0)
    {
        HTRACE(TG_Error, 
            "ERROR: semctl(%d, GETVAL) failed. %s\n",
            p_riSemID, strerror(errno));
        l_bResult = false;
    }
    else if(p_riReturnPreviousValue + p_iAdd < 0)
    {
        HTRACE(TG_Error, 
            "ERROR: InterlockedExchangeAddUsingSemaphore"
            " called with semaphore value %d and add = %d."
            " Result will be negative", 
            p_riReturnPreviousValue, p_iAdd);
        l_bResult = false;
    }
    else
    {
        //increase/decrease value of the first semaphore.
        if(!DoSemOp(p_riSemID,0,p_iAdd, true))
            l_bResult = false;
    }
    //Release second semaphore.
    //We should use non-undoable release if we just created 
    //the semaphore, because it should be left in released 
    //state after the process terminates.
    if(!DoSemOp(p_riSemID,1,+1, l_bCreatedNew? false : true))
        return false;
    return l_bResult;
}//bool InterlockedExchangeAddUsingSemaphore

bool PrepareMemMapFile
(
    int   p_iMemMapFile,
    const char * p_pszMemMapFilePath,
    int   p_iTextAreaSize,
    bool  p_bInitialize,
    int * p_piReturnTotalSize,
    GlobalTraceBufferHeader ** p_ppReturnHeader
)
{
    int l_iTotalFileSize = 
        p_iTextAreaSize + TRACE_BUFFER_EXTRA_SIZE;
    if(p_bInitialize)
    {   //We are the first process, which created the 
        //file and must initialize it.
        //First, make sure the file is long enough
        int l_iSize = lseek(p_iMemMapFile, 0, SEEK_END);
        if(l_iSize < l_iTotalFileSize)
        {
            if(lseek(p_iMemMapFile,l_iTotalFileSize-1,SEEK_SET)
                != l_iTotalFileSize-1)
            {
                HTRACE(TG_Error, 
                    "ERROR: lseek(%s, %d) failed: %s",
                    p_pszMemMapFilePath, l_iTotalFileSize-1,
                    strerror(errno));
                return false;
            }
            if(write(p_iMemMapFile, "", 1) < 0)
            {
                HTRACE(TG_Error, 
                    "ERROR: write of 1 byte to %s failed: %s",
                    p_pszMemMapFilePath, strerror(errno));
                return false;
            }
        }
        else if(l_iSize > l_iTotalFileSize)
        {
            if(ftruncate(p_iMemMapFile, l_iTotalFileSize) < 0)
            {
                HTRACE(TG_Error, "ERROR: ftruncate failed. %s",
                    strerror(errno));
                return false;
            }
        }
        l_iSize = lseek(p_iMemMapFile, 0, SEEK_END);
    }//if(p_bInitialize)
    else
    {   //The file is already in u

⌨️ 快捷键说明

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