kernel/eka/drivers/debug/rmdebug/d_debug_agent.cpp
changeset 245 647ab20fee2e
parent 244 a77889bee936
child 252 0a40b8675b23
--- a/kernel/eka/drivers/debug/rmdebug/d_debug_agent.cpp	Thu Aug 12 11:55:14 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,420 +0,0 @@
-// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of the License "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-// Purpose: Kernel-side tracking of debug agent information associated
-// with each process being debugged.
-// 
-//
-
-#include <e32def.h>
-#include <e32def_private.h>
-#include <e32cmn.h>
-#include <e32cmn_private.h>
-#include <kernel/kernel.h> 
-#include <kernel/kern_priv.h>
-#include <nk_trace.h>
-#include <arm.h>
-
-#include "d_process_tracker.h"
-#include "debug_logging.h"
-
-#include "d_debug_agent.h"
-#include "debug_utils.h"
-
-#include "d_debug_agent.inl"
-
-using namespace Debug;
-
-// ctor
-DDebugAgent::DDebugAgent(TUint64 aId) :
-	iId(aId),
-	iRequestGetEventStatus(NULL),
-	iClientThread(0),
-	iEventQueue(KNumberOfEventsToQueue, 0),
-	iHead(0),
-	iTail(0),
-	iEventQueueLock(NULL),
-	iFreeSlots(KNumberOfEventsToQueue),
-	iIgnoringTrace(EFalse),
-	iEventBalance(0)
-	{
-	LOG_MSG2("DDebugAgent::DDebugAgent(), this=0x%x ", this);
-
-	// Initialize all the Event Actions to Ignore
-	for(TInt i=0; i<EEventsLast; i++)
-		{
-		iEventActions[i] = EActionIgnore;
-		}
-	}
-
-DDebugAgent* DDebugAgent::New(TUint64 aId)
-	{
-	LOG_MSG("DDebugAgent::New()");
-	DDebugAgent* agent = new DDebugAgent(aId);
-	if(agent == NULL)
-		{
-		return (NULL);
-		}
-	if(KErrNone != agent->Construct())
-		{
-		delete agent;
-		return (NULL);
-		}
-
-	// Use a semaphore to serialise access
-	TInt err = Kern::SemaphoreCreate(agent->iEventQueueLock, _L("RM_DebugAgentQueueLock"), 1 /* Initial count */);
-	if (err != KErrNone)
-		return NULL;
-
-	return agent;
-	}
-
-/** Standard contructor.
- * Fills event queue with empty events
- * @return : standard system error code
- */
-TInt DDebugAgent::Construct()
-	{
-	// Empty the event queue
-	LOG_MSG("DDebugAgent::Construct()");
-	TDriverEventInfo emptyEvent;
-	TInt err = KErrNone;
-
-	for (TInt i=0; i<KNumberOfEventsToQueue; i++)
-		{
-		err = iEventQueue.Append(emptyEvent);
-		if (err != KErrNone)
-			{
-			LOG_MSG("Error appending blank event entry");
-			return err;
-			}
-		}
-
-	err = Kern::CreateClientDataRequest(iRequestGetEventStatus);
-	if(err != KErrNone)
-		{
-		LOG_MSG("Error creating TClientDataRequest");
-		return err;
-		}
-
-	LOG_MSG2("DDebugAgent::Construct() iRequestGetEventStatus=0x%08x", iRequestGetEventStatus);
-
-	return err;
-	}
-
-// dtor
-DDebugAgent::~DDebugAgent()
-	{
-	iEventQueue.Reset();
-
-	if (iEventQueueLock)
-		iEventQueueLock->Close(NULL);
-	
-	if(iRequestGetEventStatus)
-		Kern::DestroyClientRequest(iRequestGetEventStatus);
-	
-	}
-
-// Associate an action with a particular kernel event
-TInt DDebugAgent::SetEventAction(TEventType aEvent, TKernelEventAction aEventAction)
-	{
-	// Valid Event?
-	if (aEvent >= EEventsLast)
-		{
-		LOG_MSG2("DDebugAgent::EventAction: Bad Event number %d",aEvent);
-		return KErrArgument;
-		}
-
-	iEventActions[aEvent] = aEventAction;
-
-	return KErrNone;
-	}
-
-/** Get the aEventAction associated with aEvent
- *
- * @return : aEventAction (always +ve), or KErrArgument.
- */
-TInt DDebugAgent::EventAction(TEventType aEvent)
-	{
-	// Validate the Event id
-	if (aEvent >= EEventsLast)
-		{
-		LOG_MSG2("DDebugAgent::EventAction: Bad Event number %d",aEvent);
-		return KErrArgument;
-		}
-
-	// Return the action associated with this event
-	return iEventActions[aEvent];
-	}
-
-/** Obtain the details of the latest kernel event (if it exists) and place the details in aEventInfo
- * If there is no event in the queue for this process+agent combination, store the details
- * so that it can be notified later when an event actually occurs.
- * 
- * @param aAsyncGetValueRequest - TClientDataRequest object used for pinning user memory
- * @param aClientThread - The ThreadId of the requesting user-side process. In this case the DSS.
- */
-void DDebugAgent::GetEvent(TClientDataRequest<TEventInfo>* aAsyncGetValueRequest, DThread* aClientThread)
-	{
-	LockEventQueue();
-
-	iRequestGetEventStatus->Reset();
-	TInt err = iRequestGetEventStatus->SetStatus( aAsyncGetValueRequest->StatusPtr() );
-	if (err != KErrNone)
-		{
-		LOG_MSG2("Error :iRequestGetEventStatus->SetStatus ret %d", err);
-		return;
-		}
-	
-	iRequestGetEventStatus->SetDestPtr( aAsyncGetValueRequest->DestPtr() );
-
-	iEventBalance++;
-	
-	LOG_MSG4("DDebugAgent::GetEvent: this=0x%08x, iRequestGetEventStatus=0x%08x, iEventBalance=%d", 
-		this, iRequestGetEventStatus, iEventBalance );
-	
-	iClientThread = aClientThread;
-	
-	if (BufferEmpty())
-		{
-		LOG_MSG2("Event buffer empty, iEventBalance=%d", iEventBalance);		
-		UnlockEventQueue();
-		return;
-		}
-
-	LOG_MSG2("Event already available at queue pos=%d", iTail);
-
-	// returning the event to the client
-	err = iEventQueue[iTail].WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
-	if (err != KErrNone)
-		{
-		LOG_MSG2("Error writing event info: %d", err);
-		UnlockEventQueue();
-		return;
-		}
-
-	// signal the DSS thread
-	Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
-	iEventBalance--;
-
-	iEventQueue[iTail].Reset();
-
-	// move to the next slot
-	IncrementTailPosition();
-
-	UnlockEventQueue();
-	}
-
-/**
- * Stop waiting for an event to occur. This means events will be placed 
- * in the iEventQueue (by setting iEventBalance to 0) until GetEvent is called. 
- */ 
-TInt DDebugAgent::CancelGetEvent(void)
-	{
-	LOG_MSG2("DDebugAgent::CancelGetEvent. iEventBalance=%d. > QueueRequestComplete", iEventBalance);
-	Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrCancel);
-	iEventBalance=0;
-	iClientThread = 0;
-	return KErrNone;
-	}
-
-/** Signal a kernel event to the user-side DSS when it occurs, or queue it for later
- * if the user-side has not called GetEvent (see above).
- * 
- * @param aEventInfo - the details of the event to queue.
- */
-void DDebugAgent::NotifyEvent(const TDriverEventInfo& aEventInfo)
-	{
-
-	if(aEventInfo.iEventType >= EEventsLast)
-		{
-		LOG_MSG3("DDebugAgent::NotifyEvent(),iEventType %d, this=0x%x. Ignoring since > EEventsLast", aEventInfo.iEventType, this);
-		return;
-		}
-
-	LockEventQueue();
-
-	DThread* currentThread = &Kern::CurrentThread();
-	
-	LOG_MSG5("DDebugAgent::NotifyEvent(), iEventType %d, this=0x%x currThrd=0x%08x, iEventBalance=%d",
-		aEventInfo.iEventType, this, currentThread, iEventBalance );
-	TKernelEventAction action = iEventActions[aEventInfo.iEventType];
-
-	switch (action)
-		{
-		case EActionSuspend:
-			{
-			LOG_MSG("DDebugAgent::NotifyEvent() Suspend thread");
-
-			switch(aEventInfo.iEventType)
-				{
-				case EEventsAddLibrary:
-				case EEventsRemoveLibrary:
-					currentThread = DebugUtils::OpenThreadHandle(aEventInfo.iThreadId);
-					if(currentThread)
-						{
-						currentThread->Close(NULL);
-						}
-					break;
-				default:
-					break;
-				}
-			TInt err = TheDProcessTracker.SuspendThread(currentThread, aEventInfo.FreezeOnSuspend());
-			if((err != KErrNone) && (err != KErrAlreadyExists))
-				{
-				// Is there anything we can do in the future to deal with this error having happened?
-				LOG_MSG2("DDebugAgent::NotifyEvent() Problem while suspending thread: %d", err);
-				}
-
-			// now drop through to the continue case, which typically notifies
-			// the debug agent of the event
-			}
-		case EActionContinue:
-			{
-			// Queue this event
-			QueueEvent(aEventInfo);
-
-			// Tell the user about the oldest event in the queue
-			if ( iClientThread )
-				{
-				if( iRequestGetEventStatus && (iEventBalance > 0) )
-					{
-					// Fill the event data
-					TInt err = iEventQueue[iTail].WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
-					if (err != KErrNone)
-						{
-						LOG_MSG2("Error writing event info: %d", err);
-						}
-
-					// signal the debugger thread 
-					LOG_MSG4("> QueueRequestComplete iRequestGetEventStatus=0x%08x, iEventBalance=%d, iTail=%d",
-						iRequestGetEventStatus->iStatus, iEventBalance, iTail );
-					Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
-
-					iEventBalance--;
-
-					iEventQueue[iTail].Reset();
-
-					// move to the next slot
-					IncrementTailPosition();
-					}
-				else
-					{
-					if( !iRequestGetEventStatus )
-						{
-						LOG_MSG("iRequestGetEventStatus is NULL so not signalling client" );
-						}
-					else
-						{
-						LOG_MSG2("Queued event. iEventBalance=%d (unbalanced event requests vs notifications)", 
-							iEventBalance );
-						}
-					}
-				}
-			else
-				{
-				 LOG_MSG("DDebugAgent::NotifyEvent() : Not informing client since its thread is NULL");
-				}
-			break;
-			}
-		case EActionIgnore:
-		default:
-			LOG_EVENT_MSG("DDebugAgent::NotifyEvent() fallen through to default case");
-			// Ignore everything we don't understand.
-
-		}
-
-	UnlockEventQueue();
-
-	}
-
-// Used to identify which Debug Agent this DDebugAgent is associated with.
-TUint64 DDebugAgent::Id(void)
-	{
-	return iId;
-	}
-
-/**
- * Used to add an event to the event queue for this debug agent if event 
- * queue is not at critical level. If it is at critical and it is trace event, 
- * we start ignoring trace events and insert a lost trace event.
- * If the buffer cannot store an event, only insert a buffer full event.
- * @see EEventsBufferFull
- * @see EEventsUserTracesLost
- * @see TDriverEventInfo
- * @see iEventQueue
- */
-void DDebugAgent::QueueEvent(const TDriverEventInfo& aEventInfo)
-	{
-	// Have we caught the tail?
-	if(BufferFull())
-		{
-		LOG_MSG("DDebugAgent::QueueEvent : BufferFull. Not queueing");
-		return;
-		}
-
-	// Assert if we think there is space but the slot is not marked empty
-	__NK_ASSERT_DEBUG(iEventQueue[iHead].iEventType == EEventsUnknown);
-
-	const TBool bufferAtCritical = BufferAtCriticalLevel();
-
-	if(!bufferAtCritical)
-		{
-		//reset the iIgnoringTrace flag as we are not at 
-		//critical level and can store event
-		iIgnoringTrace = EFalse; 
-		
-		// Insert the event into the ring buffer at iHead
-		iEventQueue[iHead] = aEventInfo;
-		IncrementHeadPosition();
-		}
-	else if(bufferAtCritical && BufferCanStoreEvent())
-		{
-		LOG_MSG("DDebugAgent::QueueEvent : BufferCritical");
-		if(aEventInfo.iEventType == EEventsUserTrace)
-			{
-			if(!iIgnoringTrace)
-				{
-				//if this is the first time we are ignoring trace events, 
-				//we need to issue a EEventsUserTracesLost event
-				iEventQueue[iHead].Reset();
-				iEventQueue[iHead].iEventType = EEventsUserTracesLost;
-				IncrementHeadPosition();
-
-				iIgnoringTrace = ETrue;
-				}
-			else
-				{
-				//otherwise, ignore this event
-				LOG_MSG("DDebugAgent::QueueEvent : Ignore EEventsUserTrace event");
-				}
-			}
-		else
-			{
-			// Store the event since its not a trace event
-			iEventQueue[iHead] = aEventInfo;
-			IncrementHeadPosition();
-			}
-		}
-	else
-		{
-		//At critical level and cannot store new events, so 
-		//only one space left. Store a EEventsBufferFull event
-		LOG_MSG("DDebugAgent::QueueEvent : Event Buffer Full, ignoring event");
-		iEventQueue[iHead].Reset();
-		iEventQueue[iHead].iEventType = EEventsBufferFull;
-		IncrementHeadPosition();
-		}
-	}
-
-// End of file - d_debug_agent.cpp