debugsrv/runmodedebug/rmdriver/src/d_debug_agent.cpp
author hgs
Fri, 08 Oct 2010 14:56:39 +0300
changeset 56 aa2539c91954
parent 42 0ff24a8f6ca2
permissions -rw-r--r--
201041
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
42
hgs
parents:
diff changeset
     1
// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
hgs
parents:
diff changeset
     2
// All rights reserved.
hgs
parents:
diff changeset
     3
// This component and the accompanying materials are made available
56
hgs
parents: 42
diff changeset
     4
// under the terms of "Eclipse Public License v1.0"
42
hgs
parents:
diff changeset
     5
// which accompanies this distribution, and is available
hgs
parents:
diff changeset
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
hgs
parents:
diff changeset
     7
//
hgs
parents:
diff changeset
     8
// Initial Contributors:
hgs
parents:
diff changeset
     9
// Nokia Corporation - initial contribution.
hgs
parents:
diff changeset
    10
//
hgs
parents:
diff changeset
    11
// Contributors:
hgs
parents:
diff changeset
    12
//
hgs
parents:
diff changeset
    13
// Description:
hgs
parents:
diff changeset
    14
// Purpose: Kernel-side tracking of debug agent information associated
hgs
parents:
diff changeset
    15
// with each process being debugged.
hgs
parents:
diff changeset
    16
// 
hgs
parents:
diff changeset
    17
//
hgs
parents:
diff changeset
    18
hgs
parents:
diff changeset
    19
#include <e32def.h>
hgs
parents:
diff changeset
    20
#include <e32def_private.h>
hgs
parents:
diff changeset
    21
#include <e32cmn.h>
hgs
parents:
diff changeset
    22
#include <e32cmn_private.h>
hgs
parents:
diff changeset
    23
#include <kernel/kernel.h> 
hgs
parents:
diff changeset
    24
#include <kernel/kern_priv.h>
hgs
parents:
diff changeset
    25
#include <nk_trace.h>
hgs
parents:
diff changeset
    26
#include <arm.h>
hgs
parents:
diff changeset
    27
hgs
parents:
diff changeset
    28
#include "d_process_tracker.h"
hgs
parents:
diff changeset
    29
#include "debug_logging.h"
hgs
parents:
diff changeset
    30
hgs
parents:
diff changeset
    31
#include "d_debug_agent.h"
hgs
parents:
diff changeset
    32
#include "debug_utils.h"
hgs
parents:
diff changeset
    33
hgs
parents:
diff changeset
    34
#include "d_debug_agent.inl"
hgs
parents:
diff changeset
    35
hgs
parents:
diff changeset
    36
using namespace Debug;
hgs
parents:
diff changeset
    37
hgs
parents:
diff changeset
    38
// ctor
hgs
parents:
diff changeset
    39
DDebugAgent::DDebugAgent(TUint64 aId) :
hgs
parents:
diff changeset
    40
	iId(aId),
hgs
parents:
diff changeset
    41
	iRequestGetEventStatus(NULL),
hgs
parents:
diff changeset
    42
	iClientThread(0),
hgs
parents:
diff changeset
    43
	iEventQueue(KNumberOfEventsToQueue, 0),
hgs
parents:
diff changeset
    44
	iHead(0),
hgs
parents:
diff changeset
    45
	iTail(0),
hgs
parents:
diff changeset
    46
	iEventQueueLock(NULL),
hgs
parents:
diff changeset
    47
	iFreeSlots(KNumberOfEventsToQueue),
hgs
parents:
diff changeset
    48
	iIgnoringTrace(EFalse),
hgs
parents:
diff changeset
    49
	iEventBalance(0)
hgs
parents:
diff changeset
    50
	{
hgs
parents:
diff changeset
    51
	LOG_MSG2("DDebugAgent::DDebugAgent(), this=0x%x ", this);
hgs
parents:
diff changeset
    52
hgs
parents:
diff changeset
    53
	// Initialize all the Event Actions to Ignore
hgs
parents:
diff changeset
    54
	for(TInt i=0; i<EEventsLast; i++)
hgs
parents:
diff changeset
    55
		{
hgs
parents:
diff changeset
    56
		iEventActions[i] = EActionIgnore;
hgs
parents:
diff changeset
    57
		}
hgs
parents:
diff changeset
    58
	}
hgs
parents:
diff changeset
    59
hgs
parents:
diff changeset
    60
DDebugAgent* DDebugAgent::New(TUint64 aId)
hgs
parents:
diff changeset
    61
	{
hgs
parents:
diff changeset
    62
	LOG_MSG2("DDebugAgent::New(id=0x%lx)", aId);
hgs
parents:
diff changeset
    63
	DDebugAgent* agent = new DDebugAgent(aId);
hgs
parents:
diff changeset
    64
	if(agent == NULL)
hgs
parents:
diff changeset
    65
		{
hgs
parents:
diff changeset
    66
		return (NULL);
hgs
parents:
diff changeset
    67
		}
hgs
parents:
diff changeset
    68
	if(KErrNone != agent->Construct())
hgs
parents:
diff changeset
    69
		{
hgs
parents:
diff changeset
    70
		delete agent;
hgs
parents:
diff changeset
    71
		return (NULL);
hgs
parents:
diff changeset
    72
		}
hgs
parents:
diff changeset
    73
hgs
parents:
diff changeset
    74
	// Use a semaphore to serialise access
hgs
parents:
diff changeset
    75
	TInt err = Kern::SemaphoreCreate(agent->iEventQueueLock, _L("RM_DebugAgentQueueLock"), 1 /* Initial count */);
hgs
parents:
diff changeset
    76
	if (err != KErrNone)
hgs
parents:
diff changeset
    77
		return NULL;
hgs
parents:
diff changeset
    78
hgs
parents:
diff changeset
    79
	return agent;
hgs
parents:
diff changeset
    80
	}
hgs
parents:
diff changeset
    81
hgs
parents:
diff changeset
    82
/** Standard contructor.
hgs
parents:
diff changeset
    83
 * Fills event queue with empty events
hgs
parents:
diff changeset
    84
 * @return : standard system error code
hgs
parents:
diff changeset
    85
 */
hgs
parents:
diff changeset
    86
TInt DDebugAgent::Construct()
hgs
parents:
diff changeset
    87
	{
hgs
parents:
diff changeset
    88
	// Empty the event queue
hgs
parents:
diff changeset
    89
	TDriverEventInfo emptyEvent;
hgs
parents:
diff changeset
    90
	TInt err = KErrNone;
hgs
parents:
diff changeset
    91
hgs
parents:
diff changeset
    92
	for (TInt i=0; i<KNumberOfEventsToQueue; i++)
hgs
parents:
diff changeset
    93
		{
hgs
parents:
diff changeset
    94
		err = iEventQueue.Append(emptyEvent);
hgs
parents:
diff changeset
    95
		if (err != KErrNone)
hgs
parents:
diff changeset
    96
			{
hgs
parents:
diff changeset
    97
			LOG_MSG("Error appending blank event entry");
hgs
parents:
diff changeset
    98
			return err;
hgs
parents:
diff changeset
    99
			}
hgs
parents:
diff changeset
   100
		}
hgs
parents:
diff changeset
   101
hgs
parents:
diff changeset
   102
	err = Kern::CreateClientDataRequest(iRequestGetEventStatus);
hgs
parents:
diff changeset
   103
	if(err != KErrNone)
hgs
parents:
diff changeset
   104
		{
hgs
parents:
diff changeset
   105
		LOG_MSG("Error creating TClientDataRequest");
hgs
parents:
diff changeset
   106
		return err;
hgs
parents:
diff changeset
   107
		}
hgs
parents:
diff changeset
   108
hgs
parents:
diff changeset
   109
	LOG_MSG2("DDebugAgent::Construct() iRequestGetEventStatus=0x%08x", iRequestGetEventStatus);
hgs
parents:
diff changeset
   110
hgs
parents:
diff changeset
   111
	return err;
hgs
parents:
diff changeset
   112
	}
hgs
parents:
diff changeset
   113
hgs
parents:
diff changeset
   114
// dtor
hgs
parents:
diff changeset
   115
DDebugAgent::~DDebugAgent()
hgs
parents:
diff changeset
   116
	{
hgs
parents:
diff changeset
   117
	iEventQueue.Reset();
hgs
parents:
diff changeset
   118
hgs
parents:
diff changeset
   119
	if (iEventQueueLock)
hgs
parents:
diff changeset
   120
		iEventQueueLock->Close(NULL);
hgs
parents:
diff changeset
   121
	
hgs
parents:
diff changeset
   122
	if(iRequestGetEventStatus)
hgs
parents:
diff changeset
   123
		Kern::DestroyClientRequest(iRequestGetEventStatus);
hgs
parents:
diff changeset
   124
	
hgs
parents:
diff changeset
   125
	}
hgs
parents:
diff changeset
   126
hgs
parents:
diff changeset
   127
// Associate an action with a particular kernel event
hgs
parents:
diff changeset
   128
TInt DDebugAgent::SetEventAction(TEventType aEvent, TKernelEventAction aEventAction)
hgs
parents:
diff changeset
   129
	{
hgs
parents:
diff changeset
   130
	// Valid Event?
hgs
parents:
diff changeset
   131
	if (aEvent >= EEventsLast)
hgs
parents:
diff changeset
   132
		{
hgs
parents:
diff changeset
   133
		LOG_MSG2("DDebugAgent::EventAction: Bad Event number %d",aEvent);
hgs
parents:
diff changeset
   134
		return KErrArgument;
hgs
parents:
diff changeset
   135
		}
hgs
parents:
diff changeset
   136
hgs
parents:
diff changeset
   137
	iEventActions[aEvent] = aEventAction;
hgs
parents:
diff changeset
   138
hgs
parents:
diff changeset
   139
	return KErrNone;
hgs
parents:
diff changeset
   140
	}
hgs
parents:
diff changeset
   141
hgs
parents:
diff changeset
   142
/** Get the aEventAction associated with aEvent
hgs
parents:
diff changeset
   143
 *
hgs
parents:
diff changeset
   144
 * @return : aEventAction (always +ve), or KErrArgument.
hgs
parents:
diff changeset
   145
 */
hgs
parents:
diff changeset
   146
TInt DDebugAgent::EventAction(TEventType aEvent)
hgs
parents:
diff changeset
   147
	{
hgs
parents:
diff changeset
   148
	// Validate the Event id
hgs
parents:
diff changeset
   149
	if (aEvent >= EEventsLast)
hgs
parents:
diff changeset
   150
		{
hgs
parents:
diff changeset
   151
		LOG_MSG2("DDebugAgent::EventAction: Bad Event number %d",aEvent);
hgs
parents:
diff changeset
   152
		return KErrArgument;
hgs
parents:
diff changeset
   153
		}
hgs
parents:
diff changeset
   154
hgs
parents:
diff changeset
   155
	// Return the action associated with this event
hgs
parents:
diff changeset
   156
	return iEventActions[aEvent];
hgs
parents:
diff changeset
   157
	}
hgs
parents:
diff changeset
   158
hgs
parents:
diff changeset
   159
/** Obtain the details of the latest kernel event (if it exists) and place the details in aEventInfo
hgs
parents:
diff changeset
   160
 * If there is no event in the queue for this process+agent combination, store the details
hgs
parents:
diff changeset
   161
 * so that it can be notified later when an event actually occurs.
hgs
parents:
diff changeset
   162
 * 
hgs
parents:
diff changeset
   163
 * @param aAsyncGetValueRequest - TClientDataRequest object used for pinning user memory
hgs
parents:
diff changeset
   164
 * @param aClientThread - The ThreadId of the requesting user-side process. In this case the DSS.
hgs
parents:
diff changeset
   165
 */
hgs
parents:
diff changeset
   166
void DDebugAgent::GetEvent(TClientDataRequest<TEventInfo>* aAsyncGetValueRequest, DThread* aClientThread)
hgs
parents:
diff changeset
   167
	{
hgs
parents:
diff changeset
   168
	LockEventQueue();
hgs
parents:
diff changeset
   169
hgs
parents:
diff changeset
   170
	iRequestGetEventStatus->Reset();
hgs
parents:
diff changeset
   171
	TInt err = iRequestGetEventStatus->SetStatus( aAsyncGetValueRequest->StatusPtr() );
hgs
parents:
diff changeset
   172
	if (err != KErrNone)
hgs
parents:
diff changeset
   173
		{
hgs
parents:
diff changeset
   174
		LOG_MSG2("Error :iRequestGetEventStatus->SetStatus ret %d", err);
hgs
parents:
diff changeset
   175
		UnlockEventQueue();
hgs
parents:
diff changeset
   176
		return;
hgs
parents:
diff changeset
   177
		}
hgs
parents:
diff changeset
   178
	
hgs
parents:
diff changeset
   179
	iRequestGetEventStatus->SetDestPtr( aAsyncGetValueRequest->DestPtr() );
hgs
parents:
diff changeset
   180
hgs
parents:
diff changeset
   181
	iEventBalance++;
hgs
parents:
diff changeset
   182
	
hgs
parents:
diff changeset
   183
	LOG_MSG5("DDebugAgent::GetEvent: this=0x%08x, iRequestGetEventStatus=0x%08x, iEventBalance=%d, destPrt=0x%08x", 
hgs
parents:
diff changeset
   184
		this, iRequestGetEventStatus, iEventBalance, aAsyncGetValueRequest->DestPtr() );
hgs
parents:
diff changeset
   185
	
hgs
parents:
diff changeset
   186
	iClientThread = aClientThread;
hgs
parents:
diff changeset
   187
	
hgs
parents:
diff changeset
   188
	if (BufferEmpty())
hgs
parents:
diff changeset
   189
		{
hgs
parents:
diff changeset
   190
		LOG_MSG2("Event buffer empty, iEventBalance=%d", iEventBalance);		
hgs
parents:
diff changeset
   191
		UnlockEventQueue();
hgs
parents:
diff changeset
   192
		return;
hgs
parents:
diff changeset
   193
		}
hgs
parents:
diff changeset
   194
hgs
parents:
diff changeset
   195
	LOG_MSG5("Event already available at queue pos (tail)=%d, evType=%d, threadId=0x%x, actionTaken=%d", 
hgs
parents:
diff changeset
   196
	        iTail,	iEventQueue[iTail].iEventType,	
hgs
parents:
diff changeset
   197
	        iEventQueue[iTail].iThreadId, iEventQueue[iTail].iActionTaken );
hgs
parents:
diff changeset
   198
	
hgs
parents:
diff changeset
   199
	// returning the event to the client
hgs
parents:
diff changeset
   200
	err = iEventQueue[iTail].WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
hgs
parents:
diff changeset
   201
	if (err != KErrNone)
hgs
parents:
diff changeset
   202
		{
hgs
parents:
diff changeset
   203
		LOG_MSG2("Error writing event info: %d", err);
hgs
parents:
diff changeset
   204
		UnlockEventQueue();
hgs
parents:
diff changeset
   205
		return;
hgs
parents:
diff changeset
   206
		}
hgs
parents:
diff changeset
   207
hgs
parents:
diff changeset
   208
	// signal the DSS thread
hgs
parents:
diff changeset
   209
	Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
hgs
parents:
diff changeset
   210
	iEventBalance--;
hgs
parents:
diff changeset
   211
hgs
parents:
diff changeset
   212
	iEventQueue[iTail].Reset();
hgs
parents:
diff changeset
   213
hgs
parents:
diff changeset
   214
	// move to the next slot
hgs
parents:
diff changeset
   215
	IncrementTailPosition();
hgs
parents:
diff changeset
   216
hgs
parents:
diff changeset
   217
	UnlockEventQueue();
hgs
parents:
diff changeset
   218
	}
hgs
parents:
diff changeset
   219
hgs
parents:
diff changeset
   220
/**
hgs
parents:
diff changeset
   221
 * Stop waiting for an event to occur. This means events will be placed 
hgs
parents:
diff changeset
   222
 * in the iEventQueue (by setting iEventBalance to 0) until GetEvent is called. 
hgs
parents:
diff changeset
   223
 */ 
hgs
parents:
diff changeset
   224
TInt DDebugAgent::CancelGetEvent(void)
hgs
parents:
diff changeset
   225
	{
hgs
parents:
diff changeset
   226
	LOG_MSG2("DDebugAgent::CancelGetEvent. iEventBalance=%d. > QueueRequestComplete", iEventBalance);
hgs
parents:
diff changeset
   227
	Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrCancel);
hgs
parents:
diff changeset
   228
	iEventBalance=0;
hgs
parents:
diff changeset
   229
	iClientThread = 0;
hgs
parents:
diff changeset
   230
	return KErrNone;
hgs
parents:
diff changeset
   231
	}
hgs
parents:
diff changeset
   232
hgs
parents:
diff changeset
   233
/** Signal a kernel event to the user-side DSS when it occurs, or queue it for later
hgs
parents:
diff changeset
   234
 * if the user-side has not called GetEvent (see above).
hgs
parents:
diff changeset
   235
 * 
hgs
parents:
diff changeset
   236
 * @param aEventInfo - the details of the event to queue.
hgs
parents:
diff changeset
   237
 */
hgs
parents:
diff changeset
   238
void DDebugAgent::NotifyEvent(const TDriverEventInfo& aEventInfo)
hgs
parents:
diff changeset
   239
	{
hgs
parents:
diff changeset
   240
hgs
parents:
diff changeset
   241
	if(aEventInfo.iEventType >= EEventsLast)
hgs
parents:
diff changeset
   242
		{
hgs
parents:
diff changeset
   243
		LOG_MSG3("DDebugAgent::NotifyEvent(),iEventType %d, this=0x%x. Ignoring since > EEventsLast", aEventInfo.iEventType, this);
hgs
parents:
diff changeset
   244
		return;
hgs
parents:
diff changeset
   245
		}
hgs
parents:
diff changeset
   246
hgs
parents:
diff changeset
   247
	LockEventQueue();
hgs
parents:
diff changeset
   248
hgs
parents:
diff changeset
   249
	DThread* currentThread = &Kern::CurrentThread();
hgs
parents:
diff changeset
   250
	
hgs
parents:
diff changeset
   251
hgs
parents:
diff changeset
   252
	TKernelEventAction action = iEventActions[aEventInfo.iEventType];
hgs
parents:
diff changeset
   253
hgs
parents:
diff changeset
   254
	if (aEventInfo.iProcessId == Id() &&
hgs
parents:
diff changeset
   255
		(aEventInfo.iEventType == EEventsSwExc || aEventInfo.iEventType == EEventsHwExc ||	aEventInfo.iEventType == EEventsKillThread))
hgs
parents:
diff changeset
   256
		{
hgs
parents:
diff changeset
   257
hgs
parents:
diff changeset
   258
		// It might be nice not to deliver *any* events about the debug agent to the agent itself, but this is a bit too drastic a change to make.
hgs
parents:
diff changeset
   259
		// There's a risk it might completely break TRK or similar, and at a more practical level it would require major rewriting of the t_rmdebug2
hgs
parents:
diff changeset
   260
		// tests.
hgs
parents:
diff changeset
   261
		//
hgs
parents:
diff changeset
   262
		// So instead, we only don't suspend&deliver events about the debug agent IF it's a thread crash event AND the thread is process
hgs
parents:
diff changeset
   263
		// critical/permanent AND (in the case of a critical thread) it's an abnormal exit. We're not worrying (yet) about the case where the entire
hgs
parents:
diff changeset
   264
		// process is set as system critical
hgs
parents:
diff changeset
   265
		// This fixes the original problem with CDS's worker thread crashing, and doesn't wreck the t_rmdebug2 tests.
hgs
parents:
diff changeset
   266
hgs
parents:
diff changeset
   267
		TBool problematic = (
hgs
parents:
diff changeset
   268
			(aEventInfo.iThreadFlags & (KThreadFlagProcessCritical|KThreadFlagSystemCritical) && (aEventInfo.iEventType != EEventsKillThread || aEventInfo.iExitType != EExitKill)) // process or system critical, and either an exception (not a EEventsKillThread) or a non EExitKill exit
hgs
parents:
diff changeset
   269
			|| (aEventInfo.iThreadFlags & (KThreadFlagProcessPermanent|KThreadFlagSystemPermanent))
hgs
parents:
diff changeset
   270
			);
hgs
parents:
diff changeset
   271
hgs
parents:
diff changeset
   272
		if (problematic)
hgs
parents:
diff changeset
   273
			{
hgs
parents:
diff changeset
   274
			LOG_MSG("Agent is dying - no further events will be delivered to it");
hgs
parents:
diff changeset
   275
			iAgentDying = ETrue;
hgs
parents:
diff changeset
   276
			}
hgs
parents:
diff changeset
   277
hgs
parents:
diff changeset
   278
		}
hgs
parents:
diff changeset
   279
hgs
parents:
diff changeset
   280
	if (iAgentDying && action == EActionSuspend)
hgs
parents:
diff changeset
   281
		{
hgs
parents:
diff changeset
   282
		LOG_MSG("Not delivering this event or suspending the thread because agent is dying");
hgs
parents:
diff changeset
   283
		action = EActionIgnore;
hgs
parents:
diff changeset
   284
		}
hgs
parents:
diff changeset
   285
hgs
parents:
diff changeset
   286
	switch (action)
hgs
parents:
diff changeset
   287
		{
hgs
parents:
diff changeset
   288
		case EActionSuspend:
hgs
parents:
diff changeset
   289
			{
hgs
parents:
diff changeset
   290
			LOG_MSG5("DDebugAgent::NotifyEvent(), Suspend thread, iEventType %d, this=0x%x currThrd=0x%08x, iEventBalance=%d",
hgs
parents:
diff changeset
   291
				aEventInfo.iEventType, this, currentThread, iEventBalance );
hgs
parents:
diff changeset
   292
hgs
parents:
diff changeset
   293
			switch(aEventInfo.iEventType)
hgs
parents:
diff changeset
   294
				{
hgs
parents:
diff changeset
   295
				case EEventsAddLibrary:
hgs
parents:
diff changeset
   296
				case EEventsRemoveLibrary:
hgs
parents:
diff changeset
   297
					// TomS: Anybody want to explain what is going on here??
hgs
parents:
diff changeset
   298
					currentThread = DebugUtils::OpenThreadHandle(aEventInfo.iThreadId);
hgs
parents:
diff changeset
   299
					if(currentThread)
hgs
parents:
diff changeset
   300
						{
hgs
parents:
diff changeset
   301
						currentThread->Close(NULL);
hgs
parents:
diff changeset
   302
						}
hgs
parents:
diff changeset
   303
					break;
hgs
parents:
diff changeset
   304
				default:
hgs
parents:
diff changeset
   305
					break;
hgs
parents:
diff changeset
   306
				}
hgs
parents:
diff changeset
   307
			
hgs
parents:
diff changeset
   308
			// Do not call suspend for breakpoints, since the breakpoint code that runs when deciding if an exception
hgs
parents:
diff changeset
   309
			// is a breakpoint will itself suspend the thread 
hgs
parents:
diff changeset
   310
			if( (aEventInfo.iEventType != EEventsBreakPoint) && (aEventInfo.iEventType != EEventsProcessBreakPoint) )
hgs
parents:
diff changeset
   311
			    {
hgs
parents:
diff changeset
   312
                TInt err = TheDProcessTracker.SuspendThread(currentThread, aEventInfo.FreezeOnSuspend());
hgs
parents:
diff changeset
   313
                if((err != KErrNone) && (err != KErrAlreadyExists))
hgs
parents:
diff changeset
   314
                    {
hgs
parents:
diff changeset
   315
                    // Is there anything we can do in the future to deal with this error having happened?
hgs
parents:
diff changeset
   316
                    LOG_MSG2("DDebugAgent::NotifyEvent() Problem while suspending thread: %d", err);
hgs
parents:
diff changeset
   317
                    }
hgs
parents:
diff changeset
   318
			    }
hgs
parents:
diff changeset
   319
hgs
parents:
diff changeset
   320
			// now drop through to the continue case, which typically notifies
hgs
parents:
diff changeset
   321
			// the debug agent of the event
hgs
parents:
diff changeset
   322
			}
hgs
parents:
diff changeset
   323
		case EActionContinue:
hgs
parents:
diff changeset
   324
			{
hgs
parents:
diff changeset
   325
			if( action == EActionContinue )
hgs
parents:
diff changeset
   326
				{
hgs
parents:
diff changeset
   327
				LOG_MSG5("DDebugAgent::NotifyEvent(), Action continue, iEventType %d, this=0x%x currThrd=0x%08x, iEventBalance=%d",
hgs
parents:
diff changeset
   328
					aEventInfo.iEventType, this, currentThread, iEventBalance );
hgs
parents:
diff changeset
   329
				}
hgs
parents:
diff changeset
   330
hgs
parents:
diff changeset
   331
			// Queue this event
hgs
parents:
diff changeset
   332
			TDriverEventInfo eventInfo = aEventInfo;
hgs
parents:
diff changeset
   333
			eventInfo.iActionTaken = action;
hgs
parents:
diff changeset
   334
			QueueEvent(eventInfo);
hgs
parents:
diff changeset
   335
hgs
parents:
diff changeset
   336
			// Tell the user about the oldest event in the queue
hgs
parents:
diff changeset
   337
			if ( iClientThread )
hgs
parents:
diff changeset
   338
				{
hgs
parents:
diff changeset
   339
				if( iRequestGetEventStatus && (iEventBalance > 0) )
hgs
parents:
diff changeset
   340
					{
hgs
parents:
diff changeset
   341
					// Fill the event data
hgs
parents:
diff changeset
   342
					TInt err = iEventQueue[iTail].WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
hgs
parents:
diff changeset
   343
					if (err != KErrNone)
hgs
parents:
diff changeset
   344
						{
hgs
parents:
diff changeset
   345
						LOG_MSG2("Error writing event info: %d", err);
hgs
parents:
diff changeset
   346
						}
hgs
parents:
diff changeset
   347
hgs
parents:
diff changeset
   348
					// signal the debugger thread 
hgs
parents:
diff changeset
   349
					LOG_MSG4("> QueueRequestComplete iRequestGetEventStatus=0x%08x, iEventBalance=%d, iTail=%d",
hgs
parents:
diff changeset
   350
						iRequestGetEventStatus->iStatus, iEventBalance, iTail );
hgs
parents:
diff changeset
   351
					Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
hgs
parents:
diff changeset
   352
hgs
parents:
diff changeset
   353
					iEventBalance--;
hgs
parents:
diff changeset
   354
hgs
parents:
diff changeset
   355
					iEventQueue[iTail].Reset();
hgs
parents:
diff changeset
   356
hgs
parents:
diff changeset
   357
					// move to the next slot
hgs
parents:
diff changeset
   358
					IncrementTailPosition();
hgs
parents:
diff changeset
   359
					}
hgs
parents:
diff changeset
   360
				else
hgs
parents:
diff changeset
   361
					{
hgs
parents:
diff changeset
   362
					if( !iRequestGetEventStatus )
hgs
parents:
diff changeset
   363
						{
hgs
parents:
diff changeset
   364
						LOG_MSG("iRequestGetEventStatus is NULL so not signalling client" );
hgs
parents:
diff changeset
   365
						}
hgs
parents:
diff changeset
   366
					else
hgs
parents:
diff changeset
   367
						{
hgs
parents:
diff changeset
   368
						LOG_MSG2("Queued event. iEventBalance=%d (unbalanced event requests vs notifications)", 
hgs
parents:
diff changeset
   369
							iEventBalance );
hgs
parents:
diff changeset
   370
						}
hgs
parents:
diff changeset
   371
					}
hgs
parents:
diff changeset
   372
				}
hgs
parents:
diff changeset
   373
			else
hgs
parents:
diff changeset
   374
				{
hgs
parents:
diff changeset
   375
				 LOG_MSG("DDebugAgent::NotifyEvent() : Not informing client since its thread is NULL");
hgs
parents:
diff changeset
   376
				}
hgs
parents:
diff changeset
   377
			break;
hgs
parents:
diff changeset
   378
			}
hgs
parents:
diff changeset
   379
		case EActionIgnore:
hgs
parents:
diff changeset
   380
		default:
hgs
parents:
diff changeset
   381
			// Ignore everything we don't understand.
hgs
parents:
diff changeset
   382
			break;
hgs
parents:
diff changeset
   383
		}
hgs
parents:
diff changeset
   384
hgs
parents:
diff changeset
   385
	UnlockEventQueue();
hgs
parents:
diff changeset
   386
hgs
parents:
diff changeset
   387
	}
hgs
parents:
diff changeset
   388
hgs
parents:
diff changeset
   389
// Used to identify which Debug Agent this DDebugAgent is associated with.
hgs
parents:
diff changeset
   390
TUint64 DDebugAgent::Id(void)
hgs
parents:
diff changeset
   391
	{
hgs
parents:
diff changeset
   392
	return iId;
hgs
parents:
diff changeset
   393
	}
hgs
parents:
diff changeset
   394
hgs
parents:
diff changeset
   395
/**
hgs
parents:
diff changeset
   396
 * Used to add an event to the event queue for this debug agent if event 
hgs
parents:
diff changeset
   397
 * queue is not at critical level. If it is at critical and it is trace event, 
hgs
parents:
diff changeset
   398
 * we start ignoring trace events and insert a lost trace event.
hgs
parents:
diff changeset
   399
 * If the buffer cannot store an event, only insert a buffer full event.
hgs
parents:
diff changeset
   400
 * @see EEventsBufferFull
hgs
parents:
diff changeset
   401
 * @see EEventsUserTracesLost
hgs
parents:
diff changeset
   402
 * @see TDriverEventInfo
hgs
parents:
diff changeset
   403
 * @see iEventQueue
hgs
parents:
diff changeset
   404
 */
hgs
parents:
diff changeset
   405
void DDebugAgent::QueueEvent(const TDriverEventInfo& aEventInfo)
hgs
parents:
diff changeset
   406
	{
hgs
parents:
diff changeset
   407
	// Have we caught the tail?
hgs
parents:
diff changeset
   408
	if(BufferFull())
hgs
parents:
diff changeset
   409
		{
hgs
parents:
diff changeset
   410
		LOG_MSG("DDebugAgent::QueueEvent : BufferFull. Not queueing");
hgs
parents:
diff changeset
   411
		return;
hgs
parents:
diff changeset
   412
		}
hgs
parents:
diff changeset
   413
hgs
parents:
diff changeset
   414
	// Assert if we think there is space but the slot is not marked empty
hgs
parents:
diff changeset
   415
	__NK_ASSERT_DEBUG(iEventQueue[iHead].iEventType == EEventsUnknown);
hgs
parents:
diff changeset
   416
hgs
parents:
diff changeset
   417
	const TBool bufferAtCritical = BufferAtCriticalLevel();
hgs
parents:
diff changeset
   418
hgs
parents:
diff changeset
   419
	if(!bufferAtCritical)
hgs
parents:
diff changeset
   420
		{
hgs
parents:
diff changeset
   421
		//reset the iIgnoringTrace flag as we are not at 
hgs
parents:
diff changeset
   422
		//critical level and can store event
hgs
parents:
diff changeset
   423
		iIgnoringTrace = EFalse; 
hgs
parents:
diff changeset
   424
		
hgs
parents:
diff changeset
   425
		// Insert the event into the ring buffer at iHead
hgs
parents:
diff changeset
   426
		iEventQueue[iHead] = aEventInfo;
hgs
parents:
diff changeset
   427
		IncrementHeadPosition();
hgs
parents:
diff changeset
   428
		}
hgs
parents:
diff changeset
   429
	else if(bufferAtCritical && BufferCanStoreEvent())
hgs
parents:
diff changeset
   430
		{
hgs
parents:
diff changeset
   431
		LOG_MSG("DDebugAgent::QueueEvent : BufferCritical");
hgs
parents:
diff changeset
   432
		if(aEventInfo.iEventType == EEventsUserTrace)
hgs
parents:
diff changeset
   433
			{
hgs
parents:
diff changeset
   434
			if(!iIgnoringTrace)
hgs
parents:
diff changeset
   435
				{
hgs
parents:
diff changeset
   436
				//if this is the first time we are ignoring trace events, 
hgs
parents:
diff changeset
   437
				//we need to issue a EEventsUserTracesLost event
hgs
parents:
diff changeset
   438
				iEventQueue[iHead].Reset();
hgs
parents:
diff changeset
   439
				iEventQueue[iHead].iEventType = EEventsUserTracesLost;
hgs
parents:
diff changeset
   440
				IncrementHeadPosition();
hgs
parents:
diff changeset
   441
hgs
parents:
diff changeset
   442
				iIgnoringTrace = ETrue;
hgs
parents:
diff changeset
   443
				}
hgs
parents:
diff changeset
   444
			else
hgs
parents:
diff changeset
   445
				{
hgs
parents:
diff changeset
   446
				//otherwise, ignore this event
hgs
parents:
diff changeset
   447
				LOG_MSG("DDebugAgent::QueueEvent : Ignore EEventsUserTrace event");
hgs
parents:
diff changeset
   448
				}
hgs
parents:
diff changeset
   449
			}
hgs
parents:
diff changeset
   450
		else
hgs
parents:
diff changeset
   451
			{
hgs
parents:
diff changeset
   452
			// Store the event since its not a trace event
hgs
parents:
diff changeset
   453
			iEventQueue[iHead] = aEventInfo;
hgs
parents:
diff changeset
   454
			IncrementHeadPosition();
hgs
parents:
diff changeset
   455
			}
hgs
parents:
diff changeset
   456
		}
hgs
parents:
diff changeset
   457
	else
hgs
parents:
diff changeset
   458
		{
hgs
parents:
diff changeset
   459
		//At critical level and cannot store new events, so 
hgs
parents:
diff changeset
   460
		//only one space left. Store a EEventsBufferFull event
hgs
parents:
diff changeset
   461
		LOG_MSG("DDebugAgent::QueueEvent : Event Buffer Full, ignoring event");
hgs
parents:
diff changeset
   462
		iEventQueue[iHead].Reset();
hgs
parents:
diff changeset
   463
		iEventQueue[iHead].iEventType = EEventsBufferFull;
hgs
parents:
diff changeset
   464
		IncrementHeadPosition();
hgs
parents:
diff changeset
   465
		}
hgs
parents:
diff changeset
   466
	}
hgs
parents:
diff changeset
   467
hgs
parents:
diff changeset
   468
// End of file - d_debug_agent.cpp