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

📄 prtrace.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//*  * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape Portable Runtime (NSPR). *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//*** prtrace.c -- NSPR Trace Instrumentation**** Implement the API defined in prtrace.h*******/#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)#include <string.h>#include "prtrace.h"#include "prclist.h"#include "prlock.h"#include "prcvar.h"#include "prio.h"#include "prlog.h"#include "prenv.h"#include "prmem.h"#include "prerror.h"#define DEFAULT_TRACE_BUFSIZE ( 1024 * 1024 )#define DEFAULT_BUFFER_SEGMENTS    2/*** Enumerate states in a RName structure*/typedef enum TraceState{    Running = 1,    Suspended = 2} TraceState;/*** Define QName structure*/typedef struct QName{    PRCList link;    PRCList rNameList;    char    name[PRTRACE_NAME_MAX+1];} QName;/*** Define RName structure*/typedef struct RName{    PRCList link;    PRLock  *lock;    QName   *qName;    TraceState state;    char    name[PRTRACE_NAME_MAX+1];    char    desc[PRTRACE_DESC_MAX+1];} RName;/*** The Trace Facility database***/static PRLogModuleInfo *lm;static PRLock      *traceLock;      /* Facility Lock */static PRCList     qNameList;       /* anchor to all QName structures */static TraceState traceState = Running;/*** in-memory trace buffer controls*/static  PRTraceEntry    *tBuf;      /* pointer to buffer */static  PRInt32         bufSize;    /* size of buffer, in bytes, rounded up to sizeof(PRTraceEntry) */static  volatile PRInt32  next;     /* index to next PRTraceEntry */static  PRInt32         last;       /* index of highest numbered trace entry *//*** Real-time buffer capture controls*/static PRInt32 fetchLastSeen = 0;static PRBool  fetchLostData = PR_FALSE;/*** Buffer write-to-file controls*/static  PRLock      *logLock;               /* Sync lock */static  PRCondVar   *logCVar;               /* Sync Condidtion Variable *//*** Inter-thread state communication.** Controling thread writes to logOrder under protection of logCVar** the logging thread reads logOrder and sets logState on Notify.** ** logSegments, logCount, logLostData must be read and written under** protection of logLock, logCVar.** */static  enum LogState{    LogNotRunning,  /* Initial state */    LogReset,       /* Causes logger to re-calc controls */    LogActive,      /* Logging in progress, set only by log thread */    LogSuspend,     /* Suspend Logging */     LogResume,      /* Resume Logging => LogActive */     LogStop         /* Stop the log thread */}   logOrder, logState, localState;         /* controlling state variables */static  PRInt32     logSegments;            /* Number of buffer segments */static  PRInt32     logEntries;             /* number of Trace Entries in the buffer */static  PRInt32     logEntriesPerSegment;   /* number of PRTraceEntries per buffer segment */static  PRInt32     logSegSize;             /* size of buffer segment */static  PRInt32     logCount;               /* number of segments pending output */static  PRInt32     logLostData;            /* number of lost log buffer segments *//*** end Trace Database***//*** _PR_InitializeTrace() -- Initialize the trace facility*/static void NewTraceBuffer( PRInt32 size ){    /*    ** calculate the size of the buffer    ** round down so that each segment has the same number of    ** trace entries    */    logSegments = DEFAULT_BUFFER_SEGMENTS;    logEntries = size / sizeof(PRTraceEntry);    logEntriesPerSegment = logEntries / logSegments;    logEntries = logSegments * logEntriesPerSegment;    bufSize = logEntries * sizeof(PRTraceEntry);    logSegSize = logEntriesPerSegment * sizeof(PRTraceEntry);    PR_ASSERT( bufSize != 0);    PR_LOG( lm, PR_LOG_ERROR,        ("NewTraceBuffer: logSegments: %ld, logEntries: %ld, logEntriesPerSegment: %ld, logSegSize: %ld",            logSegments, logEntries, logEntriesPerSegment, logSegSize ));    tBuf = PR_Malloc( bufSize );    if ( tBuf == NULL )    {        PR_LOG( lm, PR_LOG_ERROR,            ("PRTrace: Failed to get trace buffer"));        PR_ASSERT( 0 );    }     else    {        PR_LOG( lm, PR_LOG_NOTICE,            ("PRTrace: Got trace buffer of size: %ld, at %p", bufSize, tBuf));    }    next = 0;    last = logEntries -1;    logCount = 0;    logLostData = PR_TRUE; /* not really on first call */    logOrder = LogReset;} /* end NewTraceBuffer() *//*** _PR_InitializeTrace() -- Initialize the trace facility*/static void _PR_InitializeTrace( void ){    /* The lock pointer better be null on this call */    PR_ASSERT( traceLock == NULL );    traceLock = PR_NewLock();    PR_ASSERT( traceLock != NULL );    PR_Lock( traceLock );        PR_INIT_CLIST( &qNameList );    lm = PR_NewLogModule("trace");    bufSize = DEFAULT_TRACE_BUFSIZE;    NewTraceBuffer( bufSize );    /* Initialize logging controls */    logLock = PR_NewLock();    logCVar = PR_NewCondVar( logLock );    PR_Unlock( traceLock );    return;    } /* end _PR_InitializeTrace() *//*** Create a Trace Handle*/PR_IMPLEMENT(PRTraceHandle)	PR_CreateTrace(     	const char *qName,          /* QName for this trace handle */	    const char *rName,          /* RName for this trace handle */	    const char *description     /* description for this trace handle */){    QName   *qnp;    RName   *rnp;    PRBool  matchQname = PR_FALSE;    /* Self initialize, if necessary */    if ( traceLock == NULL )        _PR_InitializeTrace();    /* Validate input arguments */    PR_ASSERT( strlen(qName) <= PRTRACE_NAME_MAX );    PR_ASSERT( strlen(rName) <= PRTRACE_NAME_MAX );    PR_ASSERT( strlen(description) <= PRTRACE_DESC_MAX );    PR_LOG( lm, PR_LOG_DEBUG,            ("PRTRACE: CreateTrace: Qname: %s, RName: %s", qName, rName));    /* Lock the Facility */    PR_Lock( traceLock );    /* Do we already have a matching QName? */    if (!PR_CLIST_IS_EMPTY( &qNameList ))    {        qnp = (QName *) PR_LIST_HEAD( &qNameList );        do {            if ( strcmp(qnp->name, qName) == 0)            {                matchQname = PR_TRUE;                break;            }            qnp = (QName *)PR_NEXT_LINK( &qnp->link );        } while( qnp != (QName *)PR_LIST_HEAD( &qNameList ));    }    /*    ** If we did not find a matching QName,    **    allocate one and initialize it.    **    link it onto the qNameList.    **    */    if ( matchQname != PR_TRUE )    {        qnp = PR_NEWZAP( QName );        PR_ASSERT( qnp != NULL );        PR_INIT_CLIST( &qnp->link );         PR_INIT_CLIST( &qnp->rNameList );         strcpy( qnp->name, qName );        PR_APPEND_LINK( &qnp->link, &qNameList );     }    /* Do we already have a matching RName? */    if (!PR_CLIST_IS_EMPTY( &qnp->rNameList ))    {        rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList );        do {            /*            ** No duplicate RNames are allowed within a QName            **            */            PR_ASSERT( strcmp(rnp->name, rName));            rnp = (RName *)PR_NEXT_LINK( &rnp->link );        } while( rnp != (RName *)PR_LIST_HEAD( &qnp->rNameList ));    }    /* Get a new RName structure; initialize its members */    rnp = PR_NEWZAP( RName );    PR_ASSERT( rnp != NULL );    PR_INIT_CLIST( &rnp->link );    strcpy( rnp->name, rName );    strcpy( rnp->desc, description );    rnp->lock = PR_NewLock();    rnp->state = Running;    if ( rnp->lock == NULL )    {        PR_ASSERT(0);    }    PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */        rnp->qName = qnp;                       /* point the RName to the QName */    /* Unlock the Facility */    PR_Unlock( traceLock );    PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Create: QName: %s %p, RName: %s %p\n\t",        qName, qnp, rName, rnp ));    return((PRTraceHandle)rnp);} /* end  PR_CreateTrace() *//****/PR_IMPLEMENT(void) 	PR_DestroyTrace( 		PRTraceHandle handle    /* Handle to be destroyed */){    RName   *rnp = (RName *)handle;    QName   *qnp = rnp->qName;    PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting: QName: %s, RName: %s",         qnp->name, rnp->name));    /* Lock the Facility */    PR_Lock( traceLock );    /*    ** Remove RName from the list of RNames in QName    ** and free RName    */    PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting RName: %s, %p",         rnp->name, rnp));    PR_REMOVE_LINK( &rnp->link );    PR_Free( rnp->lock );    PR_DELETE( rnp );    /*    ** If this is the last RName within QName    **   remove QName from the qNameList and free it    */    if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) )    {        PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting unused QName: %s, %p",             qnp->name, qnp));        PR_REMOVE_LINK( &qnp->link );        PR_DELETE( qnp );    }     /* Unlock the Facility */    PR_Unlock( traceLock );    return;} /* end PR_DestroyTrace()  *//*** Create a TraceEntry in the trace buffer*/PR_IMPLEMENT(void) 	PR_Trace(     	PRTraceHandle handle,       /* use this trace handle */	    PRUint32    userData0,      /* User supplied data word 0 */	    PRUint32    userData1,      /* User supplied data word 1 */	    PRUint32    userData2,      /* User supplied data word 2 */	    PRUint32    userData3,      /* User supplied data word 3 */	    PRUint32    userData4,      /* User supplied data word 4 */	    PRUint32    userData5,      /* User supplied data word 5 */	    PRUint32    userData6,      /* User supplied data word 6 */	    PRUint32    userData7       /* User supplied data word 7 */){    PRTraceEntry   *tep;    PRInt32         mark;    if ( (traceState == Suspended )         || ( ((RName *)handle)->state == Suspended ))         return;    /*    ** Get the next trace entry slot w/ minimum delay    */    PR_Lock( traceLock );    tep = &tBuf[next++];     if ( next > last )        next = 0;    if ( fetchLostData == PR_FALSE && next == fetchLastSeen )        fetchLostData = PR_TRUE;        mark = next;            PR_Unlock( traceLock );    /*    ** We have a trace entry. Fill it in.    */    tep->thread = PR_GetCurrentThread();    tep->handle = handle;    tep->time   = PR_Now();    tep->userData[0] = userData0;    tep->userData[1] = userData1;    tep->userData[2] = userData2;    tep->userData[3] = userData3;    tep->userData[4] = userData4;    tep->userData[5] = userData5;    tep->userData[6] = userData6;    tep->userData[7] = userData7;    /* When buffer segment is full, signal trace log thread to run */    if (( mark % logEntriesPerSegment) == 0 )    {        PR_Lock( logLock );        logCount++;        PR_NotifyCondVar( logCVar );        PR_Unlock( logLock );        /*        ** Gh0D! This is awful!        ** Anyway, to minimize lost trace data segments,        ** I inserted the PR_Sleep(0) to cause a context switch        ** so that the log thread could run.        ** I know, it perturbs the universe and may cause        ** funny things to happen in the optimized builds.        ** Take it out, loose data; leave it in risk Heisenberg.        */        /* PR_Sleep(0); */    }    return;} /* end PR_Trace() *//****/PR_IMPLEMENT(void) 	PR_SetTraceOption( 	    PRTraceOption command,  /* One of the enumerated values */	    void *value             /* command value or NULL */){    RName * rnp;    switch ( command )    {        case PRTraceBufSize :            PR_Lock( traceLock );            PR_Free( tBuf );            bufSize = *(PRInt32 *)value;            NewTraceBuffer( bufSize );            PR_Unlock( traceLock );            PR_LOG( lm, PR_LOG_DEBUG,                ("PRSetTraceOption: PRTraceBufSize: %ld", bufSize));            break;                case PRTraceEnable :            rnp = *(RName **)value;            rnp->state = Running;            PR_LOG( lm, PR_LOG_DEBUG,                ("PRSetTraceOption: PRTraceEnable: %p", rnp));            break;

⌨️ 快捷键说明

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