kernel/eka/drivers/debug/rmdebug/d_debug_agent.cpp
branchRCL_3
changeset 21 e7d2d738d3c2
parent 0 a41df078684a
equal deleted inserted replaced
20:597aaf25e343 21:e7d2d738d3c2
    29 #include "debug_logging.h"
    29 #include "debug_logging.h"
    30 
    30 
    31 #include "d_debug_agent.h"
    31 #include "d_debug_agent.h"
    32 #include "debug_utils.h"
    32 #include "debug_utils.h"
    33 
    33 
       
    34 #include "d_debug_agent.inl"
       
    35 
    34 using namespace Debug;
    36 using namespace Debug;
    35 
    37 
    36 #define NUMBER_OF_EVENTS_TO_QUEUE 100
       
    37 #define CRITICAL_BUFFER_SIZE (NUMBER_OF_EVENTS_TO_QUEUE - 50)
       
    38 
       
    39 // ctor
    38 // ctor
    40 DDebugAgent::DDebugAgent(TUint64 aId)
    39 DDebugAgent::DDebugAgent(TUint64 aId) :
    41 : iId(aId),
    40 	iId(aId),
    42   iEventInfo(NULL),
    41 	iRequestGetEventStatus(NULL),
    43   iEventQueue(NUMBER_OF_EVENTS_TO_QUEUE, 0),
    42 	iClientThread(0),
    44   iRequestGetEventStatus(NULL),
    43 	iEventQueue(KNumberOfEventsToQueue, 0),
    45   iClientThread(0),
    44 	iHead(0),
    46   iHead(0),
    45 	iTail(0),
    47   iTail(0),
    46 	iEventQueueLock(NULL),
    48   iIgnoringTrace(EFalse)
    47 	iFreeSlots(KNumberOfEventsToQueue),
    49 	{
    48 	iIgnoringTrace(EFalse),
    50 	LOG_MSG("DDebugAgent::DDebugAgent() ");
    49 	iEventBalance(0)
       
    50 	{
       
    51 	LOG_MSG2("DDebugAgent::DDebugAgent(), this=0x%x ", this);
    51 
    52 
    52 	// Initialize all the Event Actions to Ignore
    53 	// Initialize all the Event Actions to Ignore
    53 	for(TInt i=0; i<EEventsLast; i++)
    54 	for(TInt i=0; i<EEventsLast; i++)
    54 		{
    55 		{
    55 		iEventActions[i] = EActionIgnore;
    56 		iEventActions[i] = EActionIgnore;
    67 	if(KErrNone != agent->Construct())
    68 	if(KErrNone != agent->Construct())
    68 		{
    69 		{
    69 		delete agent;
    70 		delete agent;
    70 		return (NULL);
    71 		return (NULL);
    71 		}
    72 		}
       
    73 
       
    74 	// Use a semaphore to serialise access
       
    75 	TInt err = Kern::SemaphoreCreate(agent->iEventQueueLock, _L("RM_DebugAgentQueueLock"), 1 /* Initial count */);
       
    76 	if (err != KErrNone)
       
    77 		return NULL;
       
    78 
    72 	return agent;
    79 	return agent;
    73 	}
    80 	}
    74 
    81 
       
    82 /** Standard contructor.
       
    83  * Fills event queue with empty events
       
    84  * @return : standard system error code
       
    85  */
    75 TInt DDebugAgent::Construct()
    86 TInt DDebugAgent::Construct()
    76 	{
    87 	{
    77 	// Empty the event queue
    88 	// Empty the event queue
    78 	LOG_MSG("DDebugAgent::Construct()");
    89 	LOG_MSG("DDebugAgent::Construct()");
    79 	TDriverEventInfo emptyEvent;
    90 	TDriverEventInfo emptyEvent;
    80 
    91 	TInt err = KErrNone;
    81 	for (TInt i=0; i<NUMBER_OF_EVENTS_TO_QUEUE; i++)
    92 
    82 		{
    93 	for (TInt i=0; i<KNumberOfEventsToQueue; i++)
    83 		TInt err = iEventQueue.Append(emptyEvent);
    94 		{
    84 		if (KErrNone != err)
    95 		err = iEventQueue.Append(emptyEvent);
       
    96 		if (err != KErrNone)
    85 			{
    97 			{
    86 			LOG_MSG("Error appending blank event entry");
    98 			LOG_MSG("Error appending blank event entry");
    87 			return err;
    99 			return err;
    88 			}
   100 			}
    89 		}
   101 		}
    90 	return KErrNone;
   102 
    91 	}
   103 	err = Kern::CreateClientDataRequest(iRequestGetEventStatus);
    92 
   104 	if(err != KErrNone)
       
   105 		{
       
   106 		LOG_MSG("Error creating TClientDataRequest");
       
   107 		return err;
       
   108 		}
       
   109 
       
   110 	LOG_MSG2("DDebugAgent::Construct() iRequestGetEventStatus=0x%08x", iRequestGetEventStatus);
       
   111 
       
   112 	return err;
       
   113 	}
    93 
   114 
    94 // dtor
   115 // dtor
    95 DDebugAgent::~DDebugAgent()
   116 DDebugAgent::~DDebugAgent()
    96 	{
   117 	{
    97 	iEventQueue.Reset();
   118 	iEventQueue.Reset();
       
   119 
       
   120 	if (iEventQueueLock)
       
   121 		iEventQueueLock->Close(NULL);
       
   122 	
       
   123 	if(iRequestGetEventStatus)
       
   124 		Kern::DestroyClientRequest(iRequestGetEventStatus);
       
   125 	
    98 	}
   126 	}
    99 
   127 
   100 // Associate an action with a particular kernel event
   128 // Associate an action with a particular kernel event
   101 TInt DDebugAgent::SetEventAction(TEventType aEvent, TKernelEventAction aEventAction)
   129 TInt DDebugAgent::SetEventAction(TEventType aEvent, TKernelEventAction aEventAction)
   102 	{
   130 	{
   110 	iEventActions[aEvent] = aEventAction;
   138 	iEventActions[aEvent] = aEventAction;
   111 
   139 
   112 	return KErrNone;
   140 	return KErrNone;
   113 	}
   141 	}
   114 
   142 
   115 /* Get the aEventAction associated with aEvent
   143 /** Get the aEventAction associated with aEvent
   116  *
   144  *
   117  * Returns : aEventAction (always +ve), or KErrArgument.
   145  * @return : aEventAction (always +ve), or KErrArgument.
   118  */
   146  */
   119 TInt DDebugAgent::EventAction(TEventType aEvent)
   147 TInt DDebugAgent::EventAction(TEventType aEvent)
   120 	{
   148 	{
   121 	// Validate the Event id
   149 	// Validate the Event id
   122 	if (aEvent >= EEventsLast)
   150 	if (aEvent >= EEventsLast)
   127 
   155 
   128 	// Return the action associated with this event
   156 	// Return the action associated with this event
   129 	return iEventActions[aEvent];
   157 	return iEventActions[aEvent];
   130 	}
   158 	}
   131 
   159 
   132 // Obtain the details of the latest kernel event (if it exists) and place the details in aEventInfo
   160 /** Obtain the details of the latest kernel event (if it exists) and place the details in aEventInfo
   133 // If there is no event in the queue for this process+agent combination, store the details
   161  * If there is no event in the queue for this process+agent combination, store the details
   134 // so that it can be notified later when an event actually occurs.
   162  * so that it can be notified later when an event actually occurs.
   135 //
   163  * 
   136 // @param aAsyncGetValueRequest - TClientDataRequest object used for pinning user memory
   164  * @param aAsyncGetValueRequest - TClientDataRequest object used for pinning user memory
   137 // @param aEventInfo - Address of TEventInfo structure to place event data when available
   165  * @param aClientThread - The ThreadId of the requesting user-side process. In this case the DSS.
   138 // @param aClientThread - The ThreadId of the requesting user-side process. In this case the DSS.
   166  */
   139 void DDebugAgent::GetEvent(TClientDataRequest<TEventInfo>* aAsyncGetValueRequest, TEventInfo* aEventInfo, DThread* aClientThread)
   167 void DDebugAgent::GetEvent(TClientDataRequest<TEventInfo>* aAsyncGetValueRequest, DThread* aClientThread)
   140 	{
   168 	{
       
   169 	LockEventQueue();
       
   170 
       
   171 	iRequestGetEventStatus->Reset();
       
   172 	TInt err = iRequestGetEventStatus->SetStatus( aAsyncGetValueRequest->StatusPtr() );
       
   173 	if (err != KErrNone)
       
   174 		{
       
   175 		LOG_MSG2("Error :iRequestGetEventStatus->SetStatus ret %d", err);
       
   176 		return;
       
   177 		}
       
   178 	
       
   179 	iRequestGetEventStatus->SetDestPtr( aAsyncGetValueRequest->DestPtr() );
       
   180 
       
   181 	iEventBalance++;
       
   182 	
       
   183 	LOG_MSG4("DDebugAgent::GetEvent: this=0x%08x, iRequestGetEventStatus=0x%08x, iEventBalance=%d", 
       
   184 		this, iRequestGetEventStatus, iEventBalance );
       
   185 	
   141 	iClientThread = aClientThread;
   186 	iClientThread = aClientThread;
   142 
   187 	
   143 	if (BufferEmpty())
   188 	if (BufferEmpty())
   144 		{
   189 		{
   145 		LOG_MSG("no events available");
   190 		LOG_MSG2("Event buffer empty, iEventBalance=%d", iEventBalance);		
   146 
   191 		UnlockEventQueue();
   147 		// store the pointer so we can modify it later
       
   148 		iEventInfo = (TEventInfo *)aEventInfo;
       
   149 		iRequestGetEventStatus = aAsyncGetValueRequest;
       
   150 		return;
   192 		return;
   151 		}
   193 		}
   152 
   194 
   153 	LOG_MSG("Event available");
   195 	LOG_MSG2("Event already available at queue pos=%d", iTail);
   154 
   196 
   155 	// returning the event to the client
   197 	// returning the event to the client
   156 	TInt err = iEventQueue[iTail].WriteEventToClientThread(aAsyncGetValueRequest,iClientThread);
   198 	err = iEventQueue[iTail].WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
   157 	if (KErrNone != err)
   199 	if (err != KErrNone)
   158 		{
   200 		{
   159 		LOG_MSG2("Error writing event info: %d", err);
   201 		LOG_MSG2("Error writing event info: %d", err);
       
   202 		UnlockEventQueue();
   160 		return;
   203 		return;
   161 		}
   204 		}
   162 
   205 
   163 	// signal the DSS thread
   206 	// signal the DSS thread
   164 	Kern::QueueRequestComplete(iClientThread, aAsyncGetValueRequest, KErrNone);
   207 	Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
       
   208 	iEventBalance--;
   165 
   209 
   166 	iEventQueue[iTail].Reset();
   210 	iEventQueue[iTail].Reset();
   167 
   211 
   168 	// move to the next slot
   212 	// move to the next slot
   169 	IncrementPosition(iTail);
   213 	IncrementTailPosition();
   170 	}
   214 
   171 
   215 	UnlockEventQueue();
   172 // Stop waiting for an event to occur. This means events will be placed in the iEventQueue
   216 	}
   173 // until GetEvent is called.
   217 
       
   218 /**
       
   219  * Stop waiting for an event to occur. This means events will be placed 
       
   220  * in the iEventQueue (by setting iEventBalance to 0) until GetEvent is called. 
       
   221  */ 
   174 TInt DDebugAgent::CancelGetEvent(void)
   222 TInt DDebugAgent::CancelGetEvent(void)
   175 	{
   223 	{
       
   224 	LOG_MSG2("DDebugAgent::CancelGetEvent. iEventBalance=%d. > QueueRequestComplete", iEventBalance);
   176 	Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrCancel);
   225 	Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrCancel);
   177 	iEventInfo = NULL;
   226 	iEventBalance=0;
   178     iRequestGetEventStatus = 0;
       
   179 	iClientThread = 0;
   227 	iClientThread = 0;
   180 
       
   181 	return KErrNone;
   228 	return KErrNone;
   182 	}
   229 	}
   183 
   230 
   184 // Signal a kernel event to the user-side DSS when it occurs, or queue it for later
   231 /** Signal a kernel event to the user-side DSS when it occurs, or queue it for later
   185 // if the user-side has not called GetEvent (see above).
   232  * if the user-side has not called GetEvent (see above).
   186 //
   233  * 
   187 // @param aEventInfo - the details of the event to queue.
   234  * @param aEventInfo - the details of the event to queue.
       
   235  */
   188 void DDebugAgent::NotifyEvent(const TDriverEventInfo& aEventInfo)
   236 void DDebugAgent::NotifyEvent(const TDriverEventInfo& aEventInfo)
   189 	{
   237 	{
   190 	LOG_MSG("DDebugAgent::NotifyEvent()");
       
   191 	// Action depends on the TKernelEvent type in aEventInfo.iType
       
   192 	
       
   193 	// Added to fix the pass by value issue seen in Coverity.  
       
   194 	// Function is changed to pass by reference but temp object is explicitly created.
       
   195 	TDriverEventInfo eventInfo = aEventInfo;
       
   196 
   238 
   197 	if(aEventInfo.iEventType >= EEventsLast)
   239 	if(aEventInfo.iEventType >= EEventsLast)
   198 		{
   240 		{
   199 		// unknown event type so return
   241 		LOG_MSG3("DDebugAgent::NotifyEvent(),iEventType %d, this=0x%x. Ignoring since > EEventsLast", aEventInfo.iEventType, this);
   200 		return;
   242 		return;
   201 		}
   243 		}
   202 
   244 
   203 	TKernelEventAction action = iEventActions[eventInfo.iEventType];
   245 	LockEventQueue();
       
   246 
       
   247 	DThread* currentThread = &Kern::CurrentThread();
       
   248 	
       
   249 	LOG_MSG5("DDebugAgent::NotifyEvent(), iEventType %d, this=0x%x currThrd=0x%08x, iEventBalance=%d",
       
   250 		aEventInfo.iEventType, this, currentThread, iEventBalance );
       
   251 	TKernelEventAction action = iEventActions[aEventInfo.iEventType];
   204 
   252 
   205 	switch (action)
   253 	switch (action)
   206 		{
   254 		{
   207 		case EActionSuspend:
   255 		case EActionSuspend:
   208 			{
   256 			{
   209 			LOG_MSG("DDebugAgent::NotifyEvent() Suspend thread");
   257 			LOG_MSG("DDebugAgent::NotifyEvent() Suspend thread");
   210 			DThread* currentThread = &Kern::CurrentThread();
   258 
   211 			switch(eventInfo.iEventType)
   259 			switch(aEventInfo.iEventType)
   212 				{
   260 				{
   213 				case EEventsAddLibrary:
   261 				case EEventsAddLibrary:
   214 				case EEventsRemoveLibrary:
   262 				case EEventsRemoveLibrary:
   215 					currentThread = DebugUtils::OpenThreadHandle(eventInfo.iThreadId);
   263 					currentThread = DebugUtils::OpenThreadHandle(aEventInfo.iThreadId);
   216 					if(currentThread)
   264 					if(currentThread)
   217 						{
   265 						{
   218 						currentThread->Close(NULL);
   266 						currentThread->Close(NULL);
   219 						}
   267 						}
   220 					break;
   268 					break;
   221 				default:
   269 				default:
   222 					break;
   270 					break;
   223 				}
   271 				}
   224 			TInt err = TheDProcessTracker.SuspendThread(currentThread, eventInfo.FreezeOnSuspend());
   272 			TInt err = TheDProcessTracker.SuspendThread(currentThread, aEventInfo.FreezeOnSuspend());
   225 			if(!( (err == KErrNone) || (err == KErrAlreadyExists) ))
   273 			if((err != KErrNone) && (err != KErrAlreadyExists))
   226 				{
   274 				{
   227 				// Is there anything we can do in the future to deal with this error having happened?
   275 				// Is there anything we can do in the future to deal with this error having happened?
   228 				LOG_MSG2("DDebugAgent::NotifyEvent() Problem while suspending thread: %d", err);
   276 				LOG_MSG2("DDebugAgent::NotifyEvent() Problem while suspending thread: %d", err);
   229 				}
   277 				}
   230 
   278 
   231 			// now drop through to the continue case, which typically notifies
   279 			// now drop through to the continue case, which typically notifies
   232 			// the debug agent of the event
   280 			// the debug agent of the event
   233 			}
   281 			}
   234 		case EActionContinue:
   282 		case EActionContinue:
   235 			LOG_MSG("DDebugAgent::NotifyEvent() Continue");
       
   236 
       
   237 			// Tell the user about this event
       
   238 			if (iEventInfo && iClientThread)
       
   239 			{
   283 			{
   240 				LOG_MSG("Completing event\r\n");
   284 			// Queue this event
   241 
   285 			QueueEvent(aEventInfo);
   242 				// returning the event to the client
   286 
   243 				TInt err = eventInfo.WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
   287 			// Tell the user about the oldest event in the queue
   244 				if (KErrNone != err)
   288 			if ( iClientThread )
   245 				{
   289 				{
   246 					LOG_MSG2("Error writing event info: %d", err);
   290 				if( iRequestGetEventStatus && (iEventBalance > 0) )
   247 				}
   291 					{
   248 
   292 					// Fill the event data
   249 				// clear this since we've completed the request
   293 					TInt err = iEventQueue[iTail].WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
   250 				iEventInfo = NULL;
   294 					if (err != KErrNone)
   251 
   295 						{
   252 				// signal the debugger thread
   296 						LOG_MSG2("Error writing event info: %d", err);
   253 				Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
   297 						}
       
   298 
       
   299 					// signal the debugger thread 
       
   300 					LOG_MSG4("> QueueRequestComplete iRequestGetEventStatus=0x%08x, iEventBalance=%d, iTail=%d",
       
   301 						iRequestGetEventStatus->iStatus, iEventBalance, iTail );
       
   302 					Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
       
   303 
       
   304 					iEventBalance--;
       
   305 
       
   306 					iEventQueue[iTail].Reset();
       
   307 
       
   308 					// move to the next slot
       
   309 					IncrementTailPosition();
       
   310 					}
       
   311 				else
       
   312 					{
       
   313 					if( !iRequestGetEventStatus )
       
   314 						{
       
   315 						LOG_MSG("iRequestGetEventStatus is NULL so not signalling client" );
       
   316 						}
       
   317 					else
       
   318 						{
       
   319 						LOG_MSG2("Queued event. iEventBalance=%d (unbalanced event requests vs notifications)", 
       
   320 							iEventBalance );
       
   321 						}
       
   322 					}
       
   323 				}
       
   324 			else
       
   325 				{
       
   326 				 LOG_MSG("DDebugAgent::NotifyEvent() : Not informing client since its thread is NULL");
       
   327 				}
       
   328 			break;
   254 			}
   329 			}
   255 			else
       
   256 			{
       
   257 				LOG_MSG("Queuing event\r\n");
       
   258 
       
   259 				QueueEvent(eventInfo);
       
   260 
       
   261 			}
       
   262 			break;
       
   263 
       
   264 		case EActionIgnore:
   330 		case EActionIgnore:
   265 		default:
   331 		default:
   266 			LOG_MSG("DDebugAgent::NotifyEvent() fallen through to default case");
   332 			LOG_EVENT_MSG("DDebugAgent::NotifyEvent() fallen through to default case");
   267 			// Ignore everything we don't understand.
   333 			// Ignore everything we don't understand.
   268 			return;
   334 
   269 		}
   335 		}
       
   336 
       
   337 	UnlockEventQueue();
   270 
   338 
   271 	}
   339 	}
   272 
   340 
   273 // Used to identify which Debug Agent this DDebugAgent is associated with.
   341 // Used to identify which Debug Agent this DDebugAgent is associated with.
   274 TUint64 DDebugAgent::Id(void)
   342 TUint64 DDebugAgent::Id(void)
   275 	{
   343 	{
   276 	return iId;
   344 	return iId;
   277 	}
   345 	}
   278 
   346 
   279 // Used to add an event to the event queue for this debug agent
   347 /**
   280 void DDebugAgent::QueueEvent(TDriverEventInfo& aEventInfo)
   348  * Used to add an event to the event queue for this debug agent if event 
       
   349  * queue is not at critical level. If it is at critical and it is trace event, 
       
   350  * we start ignoring trace events and insert a lost trace event.
       
   351  * If the buffer cannot store an event, only insert a buffer full event.
       
   352  * @see EEventsBufferFull
       
   353  * @see EEventsUserTracesLost
       
   354  * @see TDriverEventInfo
       
   355  * @see iEventQueue
       
   356  */
       
   357 void DDebugAgent::QueueEvent(const TDriverEventInfo& aEventInfo)
   281 	{
   358 	{
   282 	// Have we caught the tail?
   359 	// Have we caught the tail?
   283 	if(BufferFull())
   360 	if(BufferFull())
   284 		{
   361 		{
       
   362 		LOG_MSG("DDebugAgent::QueueEvent : BufferFull. Not queueing");
   285 		return;
   363 		return;
   286 		}
   364 		}
   287 	
   365 
   288 	//check to see if we wish to ignore this event - we dump trace events as they are lower priority than the other events
   366 	// Assert if we think there is space but the slot is not marked empty
   289 	if(BufferAtCriticalLevel())
   367 	__NK_ASSERT_DEBUG(iEventQueue[iHead].iEventType == EEventsUnknown);
   290 		{
   368 
       
   369 	const TBool bufferAtCritical = BufferAtCriticalLevel();
       
   370 
       
   371 	if(!bufferAtCritical)
       
   372 		{
       
   373 		//reset the iIgnoringTrace flag as we are not at 
       
   374 		//critical level and can store event
       
   375 		iIgnoringTrace = EFalse; 
       
   376 		
       
   377 		// Insert the event into the ring buffer at iHead
       
   378 		iEventQueue[iHead] = aEventInfo;
       
   379 		IncrementHeadPosition();
       
   380 		}
       
   381 	else if(bufferAtCritical && BufferCanStoreEvent())
       
   382 		{
       
   383 		LOG_MSG("DDebugAgent::QueueEvent : BufferCritical");
   291 		if(aEventInfo.iEventType == EEventsUserTrace)
   384 		if(aEventInfo.iEventType == EEventsUserTrace)
   292 			{
   385 			{
   293 			if(!iIgnoringTrace)
   386 			if(!iIgnoringTrace)
   294 				{
   387 				{
   295 				//if this is the first time we are ignoring trace events, we need to issue a EEventsUserTracesLost event
   388 				//if this is the first time we are ignoring trace events, 
   296 				aEventInfo.Reset();
   389 				//we need to issue a EEventsUserTracesLost event
   297 				aEventInfo.iEventType = EEventsUserTracesLost;
   390 				iEventQueue[iHead].Reset();
   298 				
   391 				iEventQueue[iHead].iEventType = EEventsUserTracesLost;
       
   392 				IncrementHeadPosition();
       
   393 
   299 				iIgnoringTrace = ETrue;
   394 				iIgnoringTrace = ETrue;
   300 				}
   395 				}
   301 			else
   396 			else
   302 				{
   397 				{
   303 				//otherwise, ignore this event
   398 				//otherwise, ignore this event
   304 				return;
   399 				LOG_MSG("DDebugAgent::QueueEvent : Ignore EEventsUserTrace event");
   305 				}
   400 				}
   306 			}
   401 			}
       
   402 		else
       
   403 			{
       
   404 			// Store the event since its not a trace event
       
   405 			iEventQueue[iHead] = aEventInfo;
       
   406 			IncrementHeadPosition();
       
   407 			}
   307 		}
   408 		}
   308 	else
   409 	else
   309 		{
   410 		{
   310 		//reset the iIgnoringTrace flag as we are not at critical level
   411 		//At critical level and cannot store new events, so 
   311 		iIgnoringTrace = EFalse; 
   412 		//only one space left. Store a EEventsBufferFull event
   312 		}	
   413 		LOG_MSG("DDebugAgent::QueueEvent : Event Buffer Full, ignoring event");
   313 
   414 		iEventQueue[iHead].Reset();
   314 	// only one space left so store a EEventsBufferFull event
   415 		iEventQueue[iHead].iEventType = EEventsBufferFull;
   315 	if(!BufferCanStoreEvent())
   416 		IncrementHeadPosition();
   316 		{
   417 		}
   317 		aEventInfo.Reset();
   418 	}
   318 		aEventInfo.iEventType = EEventsBufferFull;
   419 
   319 		}
   420 // End of file - d_debug_agent.cpp
   320 
       
   321 	__NK_ASSERT_DEBUG(iEventQueue[iHead].iEventType == EEventsUnknown); // we think there is space but the slot is not marked empty
       
   322 
       
   323 	// Insert the event into the ring buffer at iHead
       
   324 	iEventQueue[iHead] = aEventInfo;
       
   325 	IncrementPosition(iHead);
       
   326 	}
       
   327 
       
   328 // Checks whether the event queue is empty
       
   329 TBool DDebugAgent::BufferEmpty() const
       
   330 	{
       
   331 	return (NumberOfEmptySlots() == NUMBER_OF_EVENTS_TO_QUEUE);
       
   332 	}
       
   333 
       
   334 // Checks whether the event queue is full
       
   335 TBool DDebugAgent::BufferFull() const
       
   336 	{
       
   337 	return (NumberOfEmptySlots() == 0);
       
   338 	}
       
   339 
       
   340 // Checks whether there is room in the event queue to store an event (i.e. at least two free slots)
       
   341 TBool DDebugAgent::BufferCanStoreEvent() const
       
   342 	{
       
   343 	return (NumberOfEmptySlots() > 1);
       
   344 	}
       
   345 
       
   346 //This looks to see if the buffer is close to being full and should only accept higher priority debug events (user trace is the only low priority event) 
       
   347 TBool DDebugAgent::BufferAtCriticalLevel() const
       
   348 	{
       
   349 	return (NumberOfEmptySlots() < NUMBER_OF_EVENTS_TO_QUEUE - CRITICAL_BUFFER_SIZE);
       
   350 	}
       
   351 
       
   352 // increments aPosition, wrapping at NUMBER_OF_EVENTS_TO_QUEUE if necessary
       
   353 void DDebugAgent::IncrementPosition(TInt& aPosition)
       
   354 	{
       
   355 	aPosition = (aPosition + 1) % NUMBER_OF_EVENTS_TO_QUEUE;
       
   356 	}
       
   357 
       
   358 // finds the number of empty slots in the event queue
       
   359 TInt DDebugAgent::NumberOfEmptySlots() const
       
   360 	{
       
   361 	if(iHead < iTail)
       
   362 		{
       
   363 		return (iTail - iHead) - 1;
       
   364 		}
       
   365 	// iHead >= iTail
       
   366 	return NUMBER_OF_EVENTS_TO_QUEUE - (iHead - iTail);
       
   367 	}
       
   368