kernel/eka/nkern/win32/ncsched.cpp
author hgs
Mon, 27 Sep 2010 10:52:00 +0100
changeset 273 6a75fa55495f
parent 90 947f0dc9f7a8
permissions -rw-r--r--
201037_09
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
     1
// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
     2
// All rights reserved.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
     3
// This component and the accompanying materials are made available
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
     4
// under the terms of the License "Eclipse Public License v1.0"
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
     5
// which accompanies this distribution, and is available
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
     7
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
     8
// Initial Contributors:
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
     9
// Nokia Corporation - initial contribution.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    10
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    11
// Contributors:
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    12
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    13
// Description:
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    14
// e32\nkern\win32\ncsched.cpp
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    15
//
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    16
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    17
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    18
// NThreadBase member data
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    19
#define __INCLUDE_NTHREADBASE_DEFINES__
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    20
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    21
#include <e32cmn.h>
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    22
#include <e32cmn_private.h>
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    23
#include "nk_priv.h"
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    24
#include <emulator.h>
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    25
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    26
#ifdef	__EMI_SUPPORT__
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    27
extern void EMI_AddTaskSwitchEvent(TAny* aPrevious, TAny* aNext);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    28
extern void EMI_CheckDfcTag(TAny* aNext);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    29
#endif
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    30
typedef void (*ProcessHandler)(TAny* aAddressSpace);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    31
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    32
static NThreadBase* SelectThread(TScheduler& aS)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    33
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    34
// Select the next thread to run.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    35
// This is the heart of the rescheduling algorithm.
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    36
// This should be essentially the same as the EPOC32 version!
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    37
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    38
	{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    39
	NThreadBase* t = static_cast<NThreadBase*>(aS.First());
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    40
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    41
#ifdef	_DEBUG
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    42
	__NK_ASSERT_DEBUG(t);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    43
	if (t->iHeldFastMutex)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    44
		{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    45
		__KTRACE_OPT(KSCHED2, DEBUGPRINT("Resched init->%T, Holding %M", t, t->iHeldFastMutex));
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    46
		}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    47
	else
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    48
		{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    49
		__KTRACE_OPT(KSCHED2, DEBUGPRINT("Resched init->%T", t));
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    50
		}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    51
#endif	// _DEBUG
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    52
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    53
	if (t->iTime == 0 && !t->Alone())
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    54
		{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    55
		// round robin
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    56
		// get here if thread's timeslice has expired and there is another
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    57
		// thread ready at the same priority
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    58
		if (t->iHeldFastMutex)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    59
			{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    60
			// round-robin deferred due to fast mutex held
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    61
			t->iHeldFastMutex->iWaiting = 1;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    62
			return t;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    63
			}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    64
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    65
		t->iTime = t->iTimeslice;		// reset old thread time slice
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    66
		t = static_cast<NThreadBase*>(t->iNext);					// next thread
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    67
		aS.iQueue[t->iPriority] = t;		// make it first in list
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    68
		__KTRACE_OPT(KSCHED2, DEBUGPRINT("RoundRobin->%T", t));
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    69
		}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    70
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    71
	if (t->iHeldFastMutex)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    72
		{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    73
		if (t->iHeldFastMutex == &aS.iLock)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    74
			{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    75
			// thread holds system lock: use it
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    76
			return t;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    77
			}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    78
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    79
		if ((t->i_ThrdAttr & KThreadAttImplicitSystemLock) != 0 && aS.iLock.iHoldingThread)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    80
			t->iHeldFastMutex->iWaiting = 1;
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    81
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    82
		__NK_ASSERT_DEBUG((t->i_ThrdAttr & KThreadAttAddressSpace) == 0);
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    83
		/*
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    84
		Check for an address space change. Not implemented for Win32, but useful as
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    85
		documentaiton of the algorithm.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    86
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    87
		if ((t->i_ThrdAttr & KThreadAttAddressSpace) != 0 && t->iAddressSpace != aS.iAddressSpace)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    88
			t->iHeldFastMutex->iWaiting = 1;
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    89
		*/
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    90
		}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    91
	else if (t->iWaitFastMutex && t->iWaitFastMutex->iHoldingThread)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    92
		{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
    93
		__KTRACE_OPT(KSCHED2, DEBUGPRINT("Resched inter->%T, Blocked on %M", t->iWaitFastMutex->iHoldingThread, t->iWaitFastMutex));
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    94
		t = t->iWaitFastMutex->iHoldingThread;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    95
		}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    96
	else if (t->i_ThrdAttr & KThreadAttImplicitSystemLock)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    97
		{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    98
		// implicit system lock required
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
    99
		if (aS.iLock.iHoldingThread)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   100
			{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   101
			// system lock held, switch to that thread
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   102
			t = aS.iLock.iHoldingThread;
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   103
			__KTRACE_OPT(KSCHED2, DEBUGPRINT("Resched inter->%T (IMP SYS)", t));
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   104
			t->iHeldFastMutex->iWaiting = 1;	// aS.iLock.iWaiting = 1;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   105
			return t;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   106
			}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   107
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   108
		__NK_ASSERT_DEBUG((t->i_ThrdAttr & KThreadAttAddressSpace) == 0);
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   109
		/*
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   110
		Check for an address space change. Not implemented for Win32, but useful as
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   111
		documentaiton of the algorithm.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   112
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   113
		if ((t->i_ThrdAttr & KThreadAttAddressSpace) != 0 || t->iAddressSpace != aS.iAddressSpace)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   114
			{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   115
			// what do we do now?
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   116
			__NK_ASSERT_DEBUG(FALSE);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   117
			}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   118
		*/
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   119
		}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   120
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   121
	return t;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   122
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   123
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   124
// from NThread
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   125
#undef i_ThrdAttr
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   126
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   127
// From here on it's all emulator (i.e. Win32) specific; there isn't any EPOC32 equivalent for most of it.
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   128
//
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   129
// The emulator uses one Win32 thread for each Symbian thread; these are the ones scheduled by the Symbian
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   130
// nanokernel in the algorithm above. Only one such thread will be running at a time; the others will be
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   131
// waiting on their individual scheduler locks, thus simulating a single-threaded architecture.
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   132
//
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   133
// In addition, there are some more Win32 threads used to handle timers, interrupts and the like. These
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   134
// are not under control of the Symbian scheduler. They are given higher priority than the Symbian threads,
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   135
// so they can run preemptively under control of the Win32 scheduler. However, they must call functions
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   136
// from the Win32Interrupt class before using any Symbian OS calls, so that the current Symbian thread can
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   137
// be suspended during the 'virtual interrupt'.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   138
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   139
static DWORD TlsIndex = TLS_OUT_OF_INDEXES;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   140
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   141
void SchedulerInit(NThread& aInit)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   142
//
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   143
// Initialise the win32 nKern scheduler
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   144
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   145
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   146
	DWORD procaffin, sysaffin;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   147
	if (GetProcessAffinityMask(GetCurrentProcess(), &procaffin, &sysaffin))
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   148
		{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   149
		DWORD cpu;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   150
		switch (Win32SingleCpu)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   151
			{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   152
		default:
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   153
			// bind the emulator to a nominated CPU on the host PC
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   154
			cpu = (1 << Win32SingleCpu);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   155
			if (!(sysaffin & cpu))
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   156
				cpu = procaffin;	// CPU selection invalid
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   157
			break;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   158
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   159
		case NThread::ECpuSingle:
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   160
			// bind the emulator to a single CPU on the host PC, pick one
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   161
			cpu = procaffin ^ (procaffin & (procaffin - 1));
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   162
			break;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   163
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   164
		case NThread::ECpuAll:
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   165
			// run the emulator on all CPUs on the host PC
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   166
			cpu = sysaffin;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   167
			break;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   168
			}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   169
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   170
		SetProcessAffinityMask(GetCurrentProcess(), cpu);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   171
		}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   172
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   173
	// identify whether we can use the atomic SignalObjectAndWait API in Win32 for rescheduling
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   174
	Win32AtomicSOAW = (SignalObjectAndWait(aInit.iScheduleLock, aInit.iScheduleLock, INFINITE, FALSE) == WAIT_OBJECT_0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   175
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   176
	// allocate the TLS used for thread identification, and set it for the init thread
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   177
	TlsIndex = TlsAlloc();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   178
	__NK_ASSERT_ALWAYS(TlsIndex != TLS_OUT_OF_INDEXES);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   179
	SchedulerRegister(aInit);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   180
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   181
	Win32FindNonPreemptibleFunctions();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   182
	Interrupt.Init();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   183
	}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   184
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   185
void SchedulerRegister(NThread& aSelf)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   186
	{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   187
	TlsSetValue(TlsIndex, &aSelf);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   188
	}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   189
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   190
inline NThread* RunningThread()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   191
// Returns the NThread actually running
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   192
	{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   193
	if (TlsIndex == TLS_OUT_OF_INDEXES)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   194
		return NULL;				// not yet initialised
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   195
	else
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   196
		return static_cast<NThread*>(TlsGetValue(TlsIndex));
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   197
	}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   198
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   199
inline TBool IsScheduledThread()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   200
// True if the NThread actually running is the scheduled one (not an interrupt thread or similar)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   201
	{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   202
	return RunningThread() == TheScheduler.iCurrentThread;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   203
	}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   204
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   205
inline NThread& CheckedCurrentThread()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   206
// Returns the NThread actually running, checking that it's the scheduled one (not an interrupt thread or similar)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   207
	{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   208
	NThread* t = RunningThread();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   209
	__NK_ASSERT_ALWAYS(t == TheScheduler.iCurrentThread);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   210
	return *t;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   211
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   212
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   213
static void ThreadExit(NThread& aCurrent, NThread& aNext)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   214
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   215
// The final context switch of a thread.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   216
// Wake up the next thread and then destroy this one's Win32 resources.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   217
//
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   218
// Return without terminating if we need to immediately reschedule again
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   219
// because we had to unlock the kernel but there are DFCs pending.
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   220
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   221
	{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   222
	// the thread is dead
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   223
	// extract win32 handles from dying NThread object before rescheduling
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   224
	HANDLE sl = aCurrent.iScheduleLock;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   225
	HANDLE th = aCurrent.iWinThread;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   226
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   227
	// wake up the next thread
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   228
	if (aNext.WakeUp())
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   229
		return;			// need to re-reschedule in this thread
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   230
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   231
	// we are now a vanilla win32 thread, nKern no longer knows about us
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   232
	// release resources and exit cleanly
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   233
	CloseHandle(sl);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   234
	CloseHandle(th);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   235
	ExitThread(0);		// does not return
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   236
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   237
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   238
#ifdef	MONITOR_THREAD_CPU_TIME
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   239
static inline void UpdateThreadCpuTime(NThread& aCurrent, NThread& aNext)
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   240
	{
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   241
	TUint32 timestamp = NKern::FastCounter();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   242
	if (aCurrent.iLastStartTime)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   243
		aCurrent.iTotalCpuTime += timestamp - aCurrent.iLastStartTime;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   244
	aNext.iLastStartTime = timestamp;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   245
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   246
#else
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   247
static inline void UpdateThreadCpuTime(NThread& /*aCurrent*/, NThread& /*aNext*/)
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   248
	{
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   249
	}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   250
#endif	// MONITOR_THREAD_CPU_TIME
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   251
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   252
static void SwitchThreads(NThread& aCurrent, NThread& aNext)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   253
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   254
// The fundamental context switch - wake up the next thread and wait for reschedule
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   255
// trivially is aNext.WakeUp(), Wait(aCurrent.iScheduleLock), but we may be able to
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   256
// optimise the signal-and-wait
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   257
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   258
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   259
	__NK_ASSERT_ALWAYS(InterruptsStatus(ETrue));
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   260
	UpdateThreadCpuTime(aCurrent, aNext);
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   261
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   262
	if (aCurrent.iNState == NThread::EDead)
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   263
		{
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   264
		ThreadExit(aCurrent, aNext);
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   265
		// Yes, this is reachable!
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   266
		}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   267
	else if (Win32AtomicSOAW && aNext.iWakeup == NThread::ERelease)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   268
		{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   269
		// special case optimization for normally scheduled threads using atomic Win32 primitive
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   270
		TheScheduler.iCurrentThread = &aNext;
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   271
		CheckedSignalObjectAndWait(aNext.iScheduleLock, aCurrent.iScheduleLock);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   272
		}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   273
	else if (aNext.WakeUp())
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   274
		{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   275
		// We didn't wake the target thread; instead we need to re-reschedule in this thread
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   276
		__NK_ASSERT_ALWAYS(InterruptsStatus(EFalse));
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   277
		return;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   278
		}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   279
	else
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   280
		{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   281
		// Target thread woken, now wait to be rescheduled
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   282
		CheckedWaitForSingleObject(aCurrent.iScheduleLock);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   283
		}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   284
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   285
	__NK_ASSERT_ALWAYS(InterruptsStatus(ETrue));
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   286
	}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   287
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   288
void TScheduler::Reschedule()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   289
//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   290
// Enter with kernel locked, exit with kernel unlocked, interrupts disabled.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   291
// If the thread is dead do not return, but terminate the thread.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   292
//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   293
	{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   294
	__NK_ASSERT_ALWAYS(TheScheduler.iKernCSLocked == 1);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   295
	NThread& me = *static_cast<NThread*>(TheScheduler.iCurrentThread);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   296
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   297
	for (;;)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   298
		{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   299
		NKern::DisableAllInterrupts();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   300
		if (TheScheduler.iDfcPendingFlag)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   301
			TheScheduler.QueueDfcs();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   302
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   303
		// Exit from this loop when further rescheduling is no longer needed
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   304
		if (!TheScheduler.iRescheduleNeededFlag)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   305
			break;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   306
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   307
		// Choose the next thread to run, using the Symbian scheduler
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   308
		TheScheduler.iRescheduleNeededFlag = FALSE;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   309
		NKern::EnableAllInterrupts();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   310
		NThread* t = static_cast<NThread*>(SelectThread(TheScheduler));
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   311
		__KTRACE_OPT(KSCHED, DEBUGPRINT("Reschedule->%T (%08x%08x)", t, TheScheduler.iPresent[1], TheScheduler.iPresent[0]));
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   312
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   313
#ifdef	__EMI_SUPPORT__
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   314
		EMI_AddTaskSwitchEvent(&me, t);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   315
		EMI_CheckDfcTag(t);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   316
#endif
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   317
#ifdef	BTRACE_CPU_USAGE
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   318
		if (TheScheduler.iCpuUsageFilter)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   319
			TheScheduler.iBTraceHandler(BTRACE_HEADER_C(4, BTrace::ECpuUsage, BTrace::ENewThreadContext), 0, (TUint32)t, 0, 0, 0, 0, 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   320
#endif
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   321
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   322
		// SwitchThreads() can return immediately, if it turns out that another reschedule is
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   323
		// necessary; otherwise, this thread will be descheduled in favour of the one selected
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   324
		// above, and SwitchThreads() will only return when this thread is next selected
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   325
		SwitchThreads(me, *t);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   326
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   327
		// When we start again, we should check for being forced to exit; otherwise go round the
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   328
		// loop again to see whether another reschedule is called for (e.g. if there are new DFCs).
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   329
		NThread::TDivert divertToExit = me.iDivertFn;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   330
		me.iDivertFn = NULL;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   331
		if (divertToExit)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   332
			divertToExit();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   333
		}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   334
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   335
	// interrupts are disabled, the kernel is still locked
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   336
	if (TheScheduler.iProcessHandler)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   337
		(*ProcessHandler(TheScheduler.iProcessHandler))(me.iAddressSpace);		// thread will need to have its static data updated
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   338
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   339
	__NK_ASSERT_ALWAYS(TheScheduler.iKernCSLocked == 1);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   340
	TheScheduler.iKernCSLocked = 0;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   341
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   342
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   343
void TScheduler::YieldTo(NThreadBase*)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   344
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   345
// Directed context switch to the nominated thread.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   346
// Enter with kernel locked, exit with kernel unlocked but interrupts disabled.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   347
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   348
	{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   349
	RescheduleNeeded();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   350
	TScheduler::Reschedule();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   351
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   352
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   353
TBool NThread::WakeUp()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   354
//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   355
// Wake up the thread. What to do depends on whether it was preempted or voluntarily
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   356
// rescheduled.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   357
//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   358
// On entry, the kernel is locked, and interrupts may be enabled or disabled.
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   359
//
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   360
// The return value is TRUE if the caller should immediately reschedule again because we
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   361
// needed to unlock the kernel in order to resume the thread but there were DFCs pending.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   362
// In this case, the thread is not woken, the kernel remains locked, and the return is
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   363
// made with interrupts disabled (whether or not they were on entry).
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   364
//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   365
// Otherise, the target thread is woken up (in any of several different ways), and the
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   366
// the return value is FALSE. In that case the interrupt status is unchanged; and the
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   367
// kernel may or not still be locked.
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   368
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   369
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   370
	__NK_ASSERT_ALWAYS(TheScheduler.iKernCSLocked > 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   371
	__NK_ASSERT_ALWAYS(RunningThread() != this);		// Can't wake self!
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   372
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   373
	switch (iWakeup)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   374
		{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   375
	default:
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   376
		FAULT();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   377
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   378
	case EIdle:
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   379
		// The thread is waiting on its scheduler lock, in Idle()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   380
		__NK_ASSERT_ALWAYS(TheScheduler.iCurrentThread == this);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   381
		CheckedSetEvent(iScheduleLock);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   382
		break;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   383
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   384
	case ERelease:
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   385
		// The thread is waiting on its scheduler lock
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   386
		TheScheduler.iCurrentThread = this;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   387
		CheckedSetEvent(iScheduleLock);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   388
		break;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   389
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   390
	case EResumeLocked:
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   391
		// The thread is Win32 suspended and must be resumed.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   392
		//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   393
		// A newly created thread does not need the kernel unlocked so we can
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   394
		// just resume it; OTOH it will need to have its static data updated ...
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   395
		//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   396
		__KTRACE_OPT(KSCHED, DEBUGPRINT("Win32ResumeLocked->%T", this));
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   397
		iWakeup = ERelease;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   398
		TheScheduler.iCurrentThread = this;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   399
		if (TheScheduler.iProcessHandler)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   400
			(*ProcessHandler(TheScheduler.iProcessHandler))(iAddressSpace);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   401
		CheckedResumeThread(iWinThread);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   402
		break;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   403
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   404
	case EResumeDiverted:
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   405
		// The thread is Win32 suspended and must be resumed.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   406
		//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   407
		// It does not need the kernel unlocked, but does have a diversion pending. We
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   408
		// know it's safe to divert the thread here because we called IsSafeToPreempt()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   409
		// when we suspended it - otherwise the diversion could get lost.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   410
		//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   411
		__KTRACE_OPT(KSCHED, DEBUGPRINT("Win32Resume->%T (Resuming diverted thread)", this));
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   412
		iWakeup = ERelease;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   413
		TheScheduler.iCurrentThread = this;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   414
		ApplyDiversion();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   415
		CheckedResumeThread(iWinThread, ETrue);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   416
		break;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   417
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   418
	case EResume:
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   419
		// The thread is Win32 suspended and must be resumed.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   420
		//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   421
		// The complication here is that we have to unlock the kernel on behalf of the
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   422
		// pre-empted thread. Before doing so, we have to check whether there are DFCs
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   423
		// or a reschedule pending; if so, we don't unlock the kernel or wake the target
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   424
		// thread, but instead return TRUE, so that our caller (usually SwitchThreads()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   425
		// above) knows to return and go round the TScheduler::Reschedule() loop again.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   426
		//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   427
		TInt irq = NKern::DisableAllInterrupts();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   428
		if (TheScheduler.iRescheduleNeededFlag || TheScheduler.iDfcPendingFlag)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   429
			{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   430
			__KTRACE_OPT(KSCHED, DEBUGPRINT("Win32Resume->%T preempted", this));
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   431
			TheScheduler.iRescheduleNeededFlag = TRUE;	// ensure we do the reschedule
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   432
			return TRUE;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   433
			}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   434
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   435
		// Otherwise we mark the thread as not-preempted, unlock the kernel, restore
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   436
		// interrupts, and resume the thread.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   437
		__KTRACE_OPT(KSCHED, DEBUGPRINT("Win32Resume->%T", this));
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   438
		iWakeup = ERelease;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   439
		TheScheduler.iCurrentThread = this;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   440
		if (TheScheduler.iProcessHandler)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   441
			(*ProcessHandler(TheScheduler.iProcessHandler))(iAddressSpace); // threads resumed after interrupt or locks need to have static data updated
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   442
		TheScheduler.iKernCSLocked = 0;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   443
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   444
		// If there are callbacks waiting, and the thread is in user mode, divert it to
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   445
		// pick up its callbacks (we know this is safe because we called IsSafeToPreempt()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   446
		// when we suspended it - otherwise the diversion could get lost.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   447
		if (iUserModeCallbacks != NULL && !iInKernel)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   448
			{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   449
			TheScheduler.iKernCSLocked = 1;					// prevent further pre-emption
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   450
			ApplyDiversion();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   451
			}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   452
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   453
		// If pre-emption occurs before the thread is resumed, it is the new thread that
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   454
		// is pre-empted, not the running thread, so we are guaranteed to be able to call
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   455
		// ResumeThread. If pre-emption occurs, and we are rescheduled to run before that
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   456
		// occurs, we will once again be running with the kernel locked and the other
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   457
		// thread will have been re-suspended by Win32: so all is well.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   458
		//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   459
		NKern::RestoreInterrupts(irq);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   460
		CheckedResumeThread(iWinThread);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   461
		break;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   462
		}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   463
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   464
	return FALSE;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   465
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   466
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   467
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   468
/**	Put the emulator into 'idle'.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   469
	This is called by the idle thread when there is nothing else to do.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   470
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   471
	@internalTechnology
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   472
 */
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   473
EXPORT_C void NThread::Idle()
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   474
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   475
// Rather than spin, we go to sleep on the schedule lock. Preemption detects
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   476
// this state (Win32Idling) and pokes the event rather than diverting the thread.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   477
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   478
// enter and exit with kernel locked
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   479
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   480
	{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   481
	NThread& me = *static_cast<NThread*>(TheScheduler.iCurrentThread);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   482
	me.iWakeup = EIdle;
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   483
	CheckedWaitForSingleObject(me.iScheduleLock);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   484
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   485
	// something happened, and we've been prodded by an interrupt
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   486
	// the kernel was locked by the interrupt, and now reschedule
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   487
	me.iWakeup = ERelease;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   488
	TScheduler::Reschedule();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   489
	NKern::EnableAllInterrupts();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   490
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   491
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   492
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   493
void EnterKernel(TBool aDiversion)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   494
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   495
	NThread& t = CheckedCurrentThread();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   496
	volatile TInt& inKernel = t.iInKernel;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   497
	__NK_ASSERT_DEBUG(inKernel >= 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   498
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   499
	// This code has to be re-entrant, because a thread that's in the process
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   500
	// of entering the kernel may be preempted; then if it isn't yet marked
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   501
	// as 'in the kernel' it can be diverted through EnterKernel()/LeaveKernel()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   502
	// in order to execute user-mode callbacks.  However this is all in the
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   503
	// same thread context, so it doesn't need any special synchronisation.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   504
	// The moment of 'entering' the kernel is deemed to occur when the new value
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   505
	// of iInKernel is written back to the NThread object.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   506
	if (inKernel++ == 0)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   507
		{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   508
		// preamble when coming from userspace
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   509
		__NK_ASSERT_ALWAYS(InterruptsStatus(ETrue));
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   510
		__NK_ASSERT_ALWAYS(t.iHeldFastMutex == 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   511
		if (aDiversion)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   512
			{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   513
			// Forced entry, to make thread exit or run user-mode callbacks
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   514
			// If exiting, iCsCount will have been set to 1 to prevent preemption
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   515
			// Otherwise it must be 0, as in the non-diversion case
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   516
			__NK_ASSERT_ALWAYS(t.iCsCount <= 1);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   517
			__NK_ASSERT_ALWAYS(TheScheduler.iKernCSLocked == 1);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   518
			}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   519
		else
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   520
			{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   521
			__NK_ASSERT_ALWAYS(t.iCsCount == 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   522
			__NK_ASSERT_ALWAYS(TheScheduler.iKernCSLocked == 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   523
			}
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   524
		}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   525
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   526
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   527
void LeaveKernel()
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   528
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   529
	NThread& t = CheckedCurrentThread();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   530
	volatile TInt& inKernel = t.iInKernel;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   531
	__NK_ASSERT_DEBUG(inKernel > 0);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   532
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   533
	// This code has to be re-entrant, because a thread that's in the process
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   534
	// of leaving the kernel may be preempted; then if it isn't still marked
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   535
	// as 'in the kernel' it can be diverted through EnterKernel()/LeaveKernel()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   536
	// in order to execute user-mode callbacks.  However this is all in the
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   537
	// same thread context, so it doesn't need any special synchronisation.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   538
	// The moment of 'leaving' the kernel is deemed to occur when the new value
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   539
	// of iInKernel is written back to the NThread object.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   540
	if (inKernel == 1)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   541
		{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   542
		// postamble when about to return to userspace
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   543
		__NK_ASSERT_ALWAYS(t.iCsCount == 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   544
		__NK_ASSERT_ALWAYS(t.iHeldFastMutex == 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   545
		__NK_ASSERT_ALWAYS(TheScheduler.iKernCSLocked == 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   546
		NKern::DisableAllInterrupts();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   547
		t.CallUserModeCallbacks();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   548
		NKern::EnableAllInterrupts();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   549
		}
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   550
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   551
	inKernel -= 1;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   552
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   553
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   554
/**	Locks the kernel and returns a pointer to the current thread
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   555
	Increments iKernCSLocked, thereby deferring IDFCs and preemption.
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   556
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   557
    @pre    Call either in a thread or an IDFC context.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   558
    @pre    Do not call from an ISR.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   559
	@pre	Do not call from bare Win32 threads.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   560
 */
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   561
EXPORT_C NThread* NKern::LockC()
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   562
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   563
	CHECK_PRECONDITIONS(MASK_NOT_ISR, "NKern::LockC");
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   564
	__ASSERT_WITH_MESSAGE_ALWAYS(IsScheduledThread(), "Do not call from bare Win32 threads", "NKern::LockC");	// check that we are a scheduled thread
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   565
	++TheScheduler.iKernCSLocked;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   566
	return (NThread*)TheScheduler.iCurrentThread;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   567
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   568
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   569
/**	Locks the kernel.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   570
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   571
	Increments iKernCSLocked, thereby deferring IDFCs and preemption.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   572
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   573
    @pre    Call either in a thread or an IDFC context.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   574
    @pre    Do not call from an ISR.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   575
	@pre	Do not call from bare Win32 threads.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   576
 */
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   577
EXPORT_C void NKern::Lock()
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   578
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   579
	CHECK_PRECONDITIONS(MASK_NOT_ISR, "NKern::Lock");
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   580
	__ASSERT_WITH_MESSAGE_ALWAYS(IsScheduledThread(), "Do not call from bare Win32 threads", "NKern::Lock");	// check that we are a scheduled thread
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   581
	++TheScheduler.iKernCSLocked;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   582
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   583
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   584
/**	Unlocks the kernel.
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   585
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   586
	Decrements iKernCSLocked; if it would become zero and IDFCs or a reschedule are
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   587
	pending, calls the scheduler to process them.
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   588
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   589
    @pre    Call either in a thread or an IDFC context.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   590
    @pre    Do not call from an ISR.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   591
	@pre	Do not call from bare Win32 threads.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   592
 */
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   593
EXPORT_C void NKern::Unlock()
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   594
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   595
	// check that the caller is the scheduled thread
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   596
	__ASSERT_WITH_MESSAGE_DEBUG(IsScheduledThread(), "Do not call from bare Win32 threads", "NKern::Unlock");
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   597
	CHECK_PRECONDITIONS(MASK_NOT_ISR, "NKern::Unlock");
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   598
	__NK_ASSERT_ALWAYS(TheScheduler.iKernCSLocked > 0);	// Can't unlock if it isn't locked!
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   599
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   600
	// Rather than decrementing the lock before testing the flags, and then
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   601
	// re-incrementing it in order to call Reschedule() -- which would
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   602
	// leave a window for preemption -- we can test the flags first, and then
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   603
	// see whether the lock count is 1 ...
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   604
	if ((TheScheduler.iRescheduleNeededFlag || TheScheduler.iDfcPendingFlag) &&
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   605
			TheScheduler.iKernCSLocked == 1)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   606
		{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   607
		// Reschedule() returns with the kernel unlocked, but interrupts disabled
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   608
		TScheduler::Reschedule();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   609
		NKern::EnableAllInterrupts();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   610
		}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   611
	else
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   612
		{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   613
		// All other cases - just decrement the lock count
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   614
		TheScheduler.iKernCSLocked -= 1;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   615
		}
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   616
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   617
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   618
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   619
/**	Allows IDFCs and rescheduling if they are pending.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   620
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   621
	If IDFCs or a reschedule are pending and iKernCSLocked is exactly equal to 1
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   622
	calls the scheduler to process the IDFCs and possibly reschedule.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   623
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   624
	@return	Nonzero if a reschedule actually occurred, zero if not.
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   625
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   626
    @pre    Call either in a thread or an IDFC context.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   627
    @pre    Do not call from an ISR.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   628
	@pre	Do not call from bare Win32 threads.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   629
 */
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   630
EXPORT_C TInt NKern::PreemptionPoint()
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   631
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   632
	// check that the caller is the scheduled thread
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   633
	__ASSERT_WITH_MESSAGE_DEBUG(IsScheduledThread(), "Do not call from bare Win32 threads", "NKern::PreemptionPoint");
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   634
	CHECK_PRECONDITIONS(MASK_NOT_ISR, "NKern::PreemptionPoint");
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   635
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   636
	if ((TheScheduler.iRescheduleNeededFlag || TheScheduler.iDfcPendingFlag) &&
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   637
			TheScheduler.iKernCSLocked == 1)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   638
		{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   639
		// Reschedule() returns with the kernel unlocked, but interrupts disabled
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   640
		TScheduler::Reschedule();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   641
		TheScheduler.iKernCSLocked = 1;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   642
		NKern::EnableAllInterrupts();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   643
		return TRUE;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   644
		}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   645
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   646
	return FALSE;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   647
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   648
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   649
/**	Return the current processor context type
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   650
	(thread, IDFC, interrupt or escaped thread)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   651
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   652
	@return	A value from NKern::TContext enumeration (including EEscaped)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   653
	@pre	Any context
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   654
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   655
	@see	NKern::TContext
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   656
 */
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   657
EXPORT_C TInt NKern::CurrentContext()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   658
	{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   659
	NThread* t = RunningThread();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   660
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   661
	if (!t)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   662
		return NKern::EInterrupt;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   663
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   664
	if (TheScheduler.iInIDFC)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   665
		return NKern::EIDFC;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   666
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   667
	if (t->iWakeup == NThread::EEscaped)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   668
		return NKern::EEscaped;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   669
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   670
	__NK_ASSERT_ALWAYS(NKern::Crashed() || t == TheScheduler.iCurrentThread);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   671
	return NKern::EThread;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   672
	}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   673
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   674
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   675
/**	Disable normal 'interrupts'.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   676
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   677
	@param	aLevel Ignored
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   678
    @pre    Call in a Symbian (thread, IDFC, ISR) context.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   679
	@pre	Do not call from bare Win32 threads.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   680
	@return	Cookie to be passed into RestoreInterrupts()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   681
 */
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   682
EXPORT_C TInt NKern::DisableInterrupts(TInt /*aLevel*/)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   683
	{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   684
	return Interrupt.MaskInterrupts(EFalse);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   685
	}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   686
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   687
/** Restore interrupt mask to state preceding a DisableInterrupts() call
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   688
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   689
	@param	aLevel Cookie returned by Disable(All)Interrupts()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   690
    @pre    Call in a Symbian (thread, IDFC, ISR) context.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   691
	@pre	Do not call from bare Win32 threads.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   692
 */
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   693
EXPORT_C void NKern::RestoreInterrupts(TInt aLevel)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   694
	{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   695
	Interrupt.RestoreInterruptMask(aLevel);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   696
	}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   697
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   698
/**	Disable all maskable 'interrupts'.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   699
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   700
    @pre    Call in a Symbian (thread, IDFC, ISR) context.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   701
	@pre	Do not call from bare Win32 threads.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   702
	@return	Cookie to be passed into RestoreInterrupts()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   703
 */
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   704
EXPORT_C TInt NKern::DisableAllInterrupts()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   705
	{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   706
	return Interrupt.MaskInterrupts(EFalse);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   707
	}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   708
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   709
/**	Enable all maskable 'interrupts'
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   710
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   711
	@internalComponent
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   712
    @pre    Call in a Symbian (thread, IDFC, ISR) context.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   713
	@pre	Do not call from bare Win32 threads.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   714
 */
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   715
EXPORT_C void NKern::EnableAllInterrupts()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   716
	{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   717
	Interrupt.RestoreInterruptMask(0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   718
	}
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   719
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   720
/**	Mark the start of an 'interrupt' in the Win32 emulator.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   721
	This must be called in interrupt threads before using any other kernel APIs,
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   722
	and should be paired with a call to EndOfInterrupt().
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   723
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   724
	@pre	Win32 'interrupt' thread context
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   725
 */
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   726
EXPORT_C void StartOfInterrupt()
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   727
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   728
	// check that the caller is not a scheduled thread
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   729
	__ASSERT_WITH_MESSAGE_DEBUG(!IsScheduledThread(), "Win32 'interrupt' thread context", "StartOfInterrupt");
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   730
	Interrupt.BeginInterrupt();
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   731
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   732
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   733
/**	Mark the end of an 'interrupt' in the Win32 emulator.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   734
	This checks to see if we need to reschedule.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   735
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   736
	@pre	Win32 'interrupt' thread context
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   737
 */
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   738
EXPORT_C void EndOfInterrupt()
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   739
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   740
	// check that the caller is not a scheduled thread
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   741
	__ASSERT_WITH_MESSAGE_DEBUG(!IsScheduledThread(), "Win32 'interrupt' thread context", "EndOfInterrupt");
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   742
	Interrupt.EndInterrupt();
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   743
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   744
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   745
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   746
// The Win32Interrupt class manages virtual interrupts from Win32 event threads
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   747
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   748
void Win32Interrupt::Init()
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   749
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   750
	InitializeCriticalSection(&iCS);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   751
	iQ = CreateSemaphoreA(NULL, 0, KMaxTInt, NULL);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   752
	__NK_ASSERT_ALWAYS(iQ);
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   753
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   754
	// create the NThread which exists solely to service reschedules for interrupts
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   755
	// this makes the End() much simpler as it merely needs to kick this thread
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   756
	SNThreadCreateInfo ni;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   757
	memclr(&ni, sizeof(ni));
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   758
	ni.iFunction = &SchedulerThreadFunction;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   759
	ni.iTimeslice = -1;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   760
	ni.iPriority = 1;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   761
	NKern::ThreadCreate(&iScheduler, ni);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   762
	NKern::Lock();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   763
	TScheduler::YieldTo(&iScheduler);
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   764
	RestoreInterruptMask(0);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   765
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   766
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   767
void Win32Interrupt::BeginInterrupt()
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   768
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   769
	__NK_ASSERT_ALWAYS(!IsScheduledThread());				// check that we aren't a scheduled thread
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   770
	MaskInterrupts(ETrue);									// suspend scheduled thread and set mask
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   771
#ifdef	BTRACE_CPU_USAGE
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   772
	BTrace0(BTrace::ECpuUsage, BTrace::EIrqStart);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   773
#endif
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   774
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   775
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   776
void Win32Interrupt::EndInterrupt()
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   777
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   778
	NThread* pC = iInterrupted;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   779
	iInterrupted = 0;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   780
	__NK_ASSERT_ALWAYS(pC == TheScheduler.iCurrentThread);	// unchanged since BeginInterrupt()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   781
	__NK_ASSERT_ALWAYS(!IsScheduledThread());				// check that we aren't a scheduled thread
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   782
	__NK_ASSERT_ALWAYS(iOwner == GetCurrentThreadId());		// check we are the interrupting thread
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   783
	__NK_ASSERT_ALWAYS(InterruptsStatus(EFalse));
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   784
	__NK_ASSERT_ALWAYS(iLevel == 1);						// DSG: is this correct?
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   785
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   786
	if (TheScheduler.iKernCSLocked)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   787
		{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   788
		// No rescheduling allowed; just resume the interrupted thread
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   789
		NKern::EnableAllInterrupts();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   790
		CheckedResumeThread(pC->iWinThread);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   791
		return;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   792
		}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   793
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   794
	__NK_ASSERT_ALWAYS(iLevel == 1);						// DSG: is this correct?
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   795
	__NK_ASSERT_ALWAYS(TheScheduler.iKernCSLocked == 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   796
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   797
	TBool diversionUnsafe = EFalse;							// Optimistic assumption until checked
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   798
	if (TheScheduler.iRescheduleNeededFlag || TheScheduler.iDfcPendingFlag)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   799
		{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   800
		switch (pC->iWakeup)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   801
			{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   802
		default:
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   803
			FAULT();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   804
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   805
		case NThread::EIdle:
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   806
			// wake up the Idle thread, it will always reschedule immediately
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   807
			TheScheduler.iKernCSLocked = 1;					// prevent further pre-emption
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   808
			if (pC->WakeUp())
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   809
				FAULT();									// this can't happen
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   810
			NKern::EnableAllInterrupts();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   811
			CheckedResumeThread(pC->iWinThread);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   812
			return;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   813
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   814
		case NThread::ERelease:
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   815
			if (pC->IsSafeToPreempt())
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   816
				{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   817
				// pre-empt the current thread and poke the 'scheduler' thread
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   818
				UpdateThreadCpuTime(*pC, iScheduler);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   819
				pC->iWakeup = NThread::EResume;				// how to wake this thread later
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   820
				TheScheduler.iKernCSLocked = 1;				// prevent further pre-emption
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   821
				RescheduleNeeded();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   822
				NKern::EnableAllInterrupts();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   823
				if (iScheduler.WakeUp())
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   824
					FAULT();								// this can't happen
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   825
				return;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   826
				}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   827
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   828
			diversionUnsafe = ETrue;						// don't consider diverting
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   829
			break;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   830
			}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   831
		}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   832
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   833
#ifdef	BTRACE_CPU_USAGE
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   834
	// no thread reschedle, so emit trace...
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   835
	BTrace0(BTrace::ECpuUsage, BTrace::EIrqEnd);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   836
#endif
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   837
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   838
	// If there are callbacks waiting, and the thread is in user mode, and it's at a
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   839
	// point where it can safely be preempted, then divert it to pick up its callbacks
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   840
	if (pC->iUserModeCallbacks != NULL && !pC->iInKernel && !diversionUnsafe)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   841
		if (pC->IsSafeToPreempt())
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   842
			{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   843
			TheScheduler.iKernCSLocked = 1;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   844
			pC->ApplyDiversion();
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   845
			}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   846
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   847
	NKern::EnableAllInterrupts();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   848
	CheckedResumeThread(pC->iWinThread);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   849
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   850
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   851
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   852
TInt Win32Interrupt::MaskInterrupts(TBool aPreempt)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   853
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   854
	if (!iQ)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   855
		return 0;									// interrupt scheme not enabled yet
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   856
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   857
	EnterCriticalSection(&iCS); 					// Win32 critical section, not a Symbian one
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   858
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   859
	DWORD id = GetCurrentThreadId();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   860
	if (iOwner == id)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   861
		{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   862
		// The easiest case: we already own the mask, so just increment the level.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   863
		// The requirement for rescheduling on exit is unaffected.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   864
		__NK_ASSERT_ALWAYS(!aPreempt);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   865
		TInt r = iLevel++;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   866
		LeaveCriticalSection(&iCS);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   867
		return r;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   868
		}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   869
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   870
	if (!iOwner && !aPreempt)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   871
		{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   872
		// Another easy case; we've been called from a Symbian thread, and there's
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   873
		// no contention, so we can just take ownership of the interrupt mask. No
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   874
		// rescheduling is required on exit (but this may change) ...
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   875
		__NK_ASSERT_ALWAYS(iLevel == 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   876
		TInt r = iLevel++;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   877
		iOwner = id;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   878
		iRescheduleOnExit = EFalse;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   879
		LeaveCriticalSection(&iCS);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   880
		return r;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   881
		}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   882
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   883
	if (iOwner)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   884
		{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   885
		// Someone else owns it; if we've been called from an interrupt thread,
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   886
		// this could be another interrupt thread or a Symbian thread. If we're
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   887
		// being called from a Symbian thread, the owner must be another Symbian
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   888
		// thread, because a Symbian thread can't preempt an interrupt thread.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   889
		//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   890
		// In either case, we can increment the count of waiters, then wait for the
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   891
		// curent holder to release it. Note that another (interrupt) thread could
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   892
		// also do this, and then the order in which they get to run is undefined.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   893
		iWaiting += 1;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   894
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   895
		do
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   896
			{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   897
			__NK_ASSERT_ALWAYS(iWaiting > 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   898
			LeaveCriticalSection(&iCS);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   899
			CheckedWaitForSingleObject(iQ);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   900
			EnterCriticalSection(&iCS);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   901
			__NK_ASSERT_ALWAYS(iWaiting > 0);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   902
			}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   903
		while (iOwner);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   904
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   905
		iWaiting -= 1;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   906
		iRescheduleOnExit = IsScheduledThread() && (TheScheduler.iRescheduleNeededFlag || TheScheduler.iDfcPendingFlag);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   907
		}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   908
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   909
	// Nobody now controls the interrupt mask ...
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   910
	__NK_ASSERT_ALWAYS(iOwner == 0 && iLevel == 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   911
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   912
	if (aPreempt)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   913
		{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   914
		// ... but in this case, we've been called from an interrupt thread and
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   915
		// a Symbian thread may still be running -- yes, even though all emulator
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   916
		// threads are normally bound to a single CPU!
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   917
		//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   918
		// To ensure that such a thread doesn't see an inconsistent state, we
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   919
		// have to suspend it before we actually take ownership, as it could
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   920
		// examine the interrupt state at any time, without taking any locks.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   921
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   922
		__NK_ASSERT_ALWAYS(iInterrupted == 0);		// we haven't done this already
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   923
		NThread* pC;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   924
		for (;;)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   925
			{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   926
			pC = static_cast<NThread*>(TheScheduler.iCurrentThread);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   927
			CheckedSuspendThread(pC->iWinThread);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   928
			if (pC == TheScheduler.iCurrentThread)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   929
				break;								// no change of thread, so ok to proceed
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   930
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   931
			// We suspended the thread while doing a (Symbian) context switch!
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   932
			// The scheduler state might be inconsistent if we left it like that,
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   933
			// so instead we'll resume it, then try again ...
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   934
			CheckedResumeThread(pC->iWinThread);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   935
			}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   936
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   937
		__NK_ASSERT_ALWAYS(iInterrupted == 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   938
		iInterrupted = pC;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   939
		}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   940
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   941
	// Now we can assert ownership of the interrupt mask.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   942
	__NK_ASSERT_ALWAYS(iOwner == 0 && iLevel == 0);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   943
	TInt r = iLevel++;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   944
	iOwner = id;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   945
	LeaveCriticalSection(&iCS);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   946
	return r;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   947
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   948
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   949
void Win32Interrupt::RestoreInterruptMask(TInt aLevel)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   950
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   951
	if (!iQ)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   952
		return;										// interrupt scheme not enabled yet
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   953
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   954
	DWORD id = GetCurrentThreadId();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   955
	EnterCriticalSection(&iCS); 					// Win32 critical section, not a Symbian one
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   956
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   957
	for (;;)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   958
		{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   959
		__NK_ASSERT_ALWAYS(id == iOwner);			// only the current owner may do this
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   960
		TInt count = iLevel - aLevel;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   961
		if (count <= 0)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   962
			break;									// already restored to that level
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   963
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   964
		iLevel = aLevel;							// update the recursion level first
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   965
		if (aLevel > 0)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   966
			{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   967
			// The easiest case: we're still holding ownership, so there's nothing to do
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   968
			break;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   969
			}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   970
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   971
		iOwner = 0;									// give up ownership
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   972
		if (iWaiting)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   973
			{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   974
			// Someone else is waiting for control of the interrupt mask.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   975
			// They may preempt us as soon as we exit the critical section
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   976
			// (at the end of this function)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   977
			CheckedReleaseSemaphore(iQ);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   978
			break;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   979
			}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   980
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   981
		// Lock fully released, no-one waiting, so see whether we need to reschedule
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   982
		if (TheScheduler.iKernCSLocked || !iRescheduleOnExit)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   983
			break;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   984
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   985
		// Interrupt mask fully unlocked, but reschedule required ...
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   986
		TheScheduler.iKernCSLocked = 1;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   987
		LeaveCriticalSection(&iCS);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   988
		TScheduler::Reschedule();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   989
		EnterCriticalSection(&iCS);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   990
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   991
		// Note: TScheduler::Reschedule() above calls MaskInterrupts() -- which changes
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   992
		// the state of most of our member data. It returns with the kernel unlocked,
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   993
		// but interrupts still disabled. Hence we will have reacquired ownership of the
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   994
		// interrupt mask, and must release it again.  Instead of going recursive with a
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   995
		// call to EnableAllInterrupts() we iterate; we'll get out of this loop eventually,
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   996
		// because iRescheduleOnExit is updated by MaskInterrupts() ...
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
   997
		aLevel = 0;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   998
		}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
   999
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1000
	LeaveCriticalSection(&iCS);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1001
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1002
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1003
void Win32Interrupt::ForceReschedule()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1004
	{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1005
	RescheduleNeeded();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1006
	if (iScheduler.WakeUp())
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1007
		FAULT();											// this can't happen
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1008
	}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1009
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1010
void Win32Interrupt::SchedulerThreadFunction(TAny*)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1011
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1012
// The entry-point for the interrupt-rescheduler thread.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1013
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1014
// This spends its whole life going around the TScheduler::Reschedule() loop
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1015
// selecting another thread to run.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1016
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1017
	{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1018
	TheScheduler.iKernCSLocked = 1;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1019
	RescheduleNeeded();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1020
	TScheduler::Reschedule();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1021
	FAULT();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1022
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1023
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1024
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1025
//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1026
// We need a global lock in the emulator to avoid scheduling reentrancy problems with the host
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1027
// in particular, some host API calls acquire host mutexes, preempting such services results
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1028
// in suspension of those threads which can cause deadlock if another thread requires that host
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1029
// mutex.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1030
//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1031
// Because thread dreaction and code loading also require the same underlying mutex (used
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1032
// by NT to protect DLL entrypoint calling), this would be rather complex with a fast mutex.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1033
// For now, keep it simple and use the preemption lock. Note that this means that the
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1034
// MS timer DFC may be significantly delayed when loading large DLL trees, for example.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1035
//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1036
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1037
void SchedulerLock()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1038
//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1039
// Acquire the global lock. May be called before scheduler running, so handle that case
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1040
//
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1041
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1042
	if (TheScheduler.iCurrentThread)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1043
		{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1044
		EnterKernel();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1045
		NKern::Lock();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1046
		}
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1047
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1048
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1049
void SchedulerUnlock()
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1050
//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1051
// Release the global lock. May be called before scheduler running, so handle that case
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1052
//
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1053
	{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1054
	if (TheScheduler.iCurrentThread)
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1055
		{
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1056
		NKern::Unlock();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1057
		LeaveKernel();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1058
		}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1059
	}
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1060
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1061
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1062
// This function allows a thread to escape from the Symbian scheduling domain to
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1063
// become an ordinary Win32 thread for a while, in cases where it is necessary
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1064
// to use Win32 APIs that are incompatible with the Symbian threading model.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1065
// AFAICS this is not currently used!
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1066
void SchedulerEscape()
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1067
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1068
	NThread& me = CheckedCurrentThread();
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1069
	EnterKernel();
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1070
	__NK_ASSERT_ALWAYS(TheScheduler.iKernCSLocked == 0);	// Can't call Escape() with the Emulator/kernel already locked
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1071
	NKern::ThreadEnterCS();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1072
	NKern::Lock();
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1073
	me.iNState = NThreadBase::EBlocked;
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1074
	TheScheduler.Remove(&me);
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1075
	me.iWakeup = NThread::EEscaped;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1076
	SetThreadPriority(me.iWinThread, THREAD_PRIORITY_ABOVE_NORMAL);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1077
	Interrupt.ForceReschedule();
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1078
	// This schedules some other thread so we can carry on outside the scheduler domain.
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1079
	// It will change the value of iCurrentThread to ensure the 'escaped' invariants are set
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1080
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1081
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1082
void ReenterDfc(TAny* aPtr)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1083
	{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1084
	NThread& me = *static_cast<NThread*>(aPtr);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1085
	me.iWakeup = NThread::ERelease;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1086
	me.CheckSuspendThenReady();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1087
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1088
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1089
void SchedulerReenter()
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1090
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1091
	NThread* me = RunningThread();
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1092
	__NK_ASSERT_ALWAYS(me);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1093
	__NK_ASSERT_ALWAYS(me->iWakeup == NThread::EEscaped);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1094
	TDfc idfc(&ReenterDfc, me);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1095
	StartOfInterrupt();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1096
	idfc.Add();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1097
	EndOfInterrupt();
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1098
	SetThreadPriority(me->iWinThread, THREAD_PRIORITY_NORMAL);
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1099
	CheckedWaitForSingleObject(me->iScheduleLock);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1100
	// when released, the kernel is locked and handed over to us
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1101
	// need to complete the reschedule protocol in this thread now
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1102
	TScheduler::Reschedule();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1103
	NKern::EnableAllInterrupts();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1104
	NKern::ThreadLeaveCS();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1105
	LeaveKernel();
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1106
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1107
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1108
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1109
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1110
// We use SuspendThread and ResumeThread to preempt threads.  This can cause
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1111
// deadlock if the thread is using windows synchronisation primitives (eg
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1112
// critical sections).  This isn't too much of a problem most of the time,
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1113
// because threads generally use the symbian environment rather than the native
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1114
// windows APIs.  However exceptions are an issue - they can happen at any time,
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1115
// and cause execution of native windows code over which we have no control.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1116
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1117
// To work around this we examine the call stack to see if the thread is inside
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1118
// one of the windows exception handling functions.  If so, preemption is
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1119
// deferred.
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1120
//
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1121
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1122
#include <winnt.h>
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1123
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1124
// Uncomment the following line to turn on tracing when we examine the call stack
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1125
// #define DUMP_STACK_BACKTRACE
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1126
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1127
#ifdef	DUMP_STACK_BACKTRACE
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1128
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1129
#include <psapi.h>
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1130
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1131
typedef BOOL (WINAPI GMIFunc)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO lpmodinfo, DWORD cb);
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1132
typedef BOOL (WINAPI EPMFunc)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1133
typedef DWORD (WINAPI GMBNFunc)(HANDLE hProcess, HMODULE hModule, LPSTR lpBaseName, DWORD nSize);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1134
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1135
void PrintAllModuleInfo()
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1136
	{
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1137
	HMODULE psapiLibrary = LoadLibraryA("psapi.dll");
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1138
	__NK_ASSERT_ALWAYS(psapiLibrary != NULL);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1139
	EPMFunc* epmFunc = (EPMFunc*)GetProcAddress(psapiLibrary, "EnumProcessModules");
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1140
	__NK_ASSERT_ALWAYS(epmFunc != NULL);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1141
	GMIFunc* gmiFunc = (GMIFunc*)GetProcAddress(psapiLibrary, "GetModuleInformation");
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1142
	__NK_ASSERT_ALWAYS(gmiFunc != NULL);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1143
	GMBNFunc* gmbnFunc = (GMBNFunc*)GetProcAddress(psapiLibrary, "GetModuleBaseNameA");
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1144
	__NK_ASSERT_ALWAYS(gmbnFunc != NULL);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1145
	const TInt maxModules = 256;
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1146
	HMODULE modules[maxModules];
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1147
	DWORD spaceNeeded;
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1148
	BOOL r = epmFunc(GetCurrentProcess(), modules, sizeof(HMODULE) * maxModules, &spaceNeeded);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1149
	__NK_ASSERT_ALWAYS(r);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1150
	__NK_ASSERT_ALWAYS(spaceNeeded <= sizeof(HMODULE) * maxModules);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1151
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1152
	for (TUint i = 0 ; i < spaceNeeded / sizeof(HMODULE) ; ++i)
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1153
		{
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1154
		HMODULE library = modules[i];
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1155
		const TUint maxNameLen = 64;
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1156
		char name[maxNameLen];
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1157
		WORD len = gmbnFunc(GetCurrentProcess(), library, name, sizeof(name));
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1158
		__NK_ASSERT_ALWAYS(len > 0 && len < maxNameLen);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1159
		MODULEINFO info;
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1160
		r = gmiFunc(GetCurrentProcess(), library, &info, sizeof(info));
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1161
		__NK_ASSERT_ALWAYS(r);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1162
		DEBUGPRINT("Module %s found at %08x to %08x", name, (TUint)info.lpBaseOfDll, (TUint)info.lpBaseOfDll + info.SizeOfImage);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1163
		}
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1164
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1165
	r = FreeLibrary(psapiLibrary);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1166
	__NK_ASSERT_ALWAYS(r);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1167
	}
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1168
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1169
#endif	// DUMP_STACK_BACKTRACE
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1170
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1171
const TInt KWin32NonPreemptibleFunctionCount = 2;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1172
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1173
struct TWin32FunctionInfo
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1174
	{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1175
	TUint iStartAddr;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1176
	TUint iLength;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1177
	};
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1178
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1179
static TWin32FunctionInfo Win32NonPreemptibleFunctions[KWin32NonPreemptibleFunctionCount];
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1180
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1181
HMODULE GetFirstLoadedModuleHandleA(const char* aModuleName1, const char* aModuleName2)
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1182
	{
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1183
	HMODULE result = GetModuleHandleA(aModuleName1);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1184
	return result ? result : GetModuleHandleA(aModuleName2);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1185
	}
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1186
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1187
TWin32FunctionInfo Win32FindExportedFunction(const char* aFunctionName, ...)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1188
	{
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1189
	va_list arg;
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1190
	va_start(arg, aFunctionName);
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1191
	HMODULE library = NULL;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1192
	const char* libname;
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1193
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1194
	// Loop through arguments until we find a library we can get a handle to.  List of library names
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1195
	// is NULL-terminated.
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1196
	while ((libname = va_arg(arg, const char*)) != NULL)
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1197
		{
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1198
		library = GetModuleHandleA(libname);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1199
		if (library != NULL)
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1200
			break;
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1201
		}
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1202
	va_end(arg);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1203
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1204
	// Make sure we did get a valid library
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1205
	__NK_ASSERT_ALWAYS(library != NULL);
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1206
	
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1207
	// Find the start address of the function
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1208
	TUint start = (TUint)GetProcAddress(library, aFunctionName);
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1209
	__NK_ASSERT_ALWAYS(start != 0);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1210
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1211
	// Now have to check all other exports to find the end of the function
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1212
	TUint end = ~0u;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1213
	for (TInt i = 1; ; ++i)
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1214
		{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1215
		TUint addr = (TUint)GetProcAddress(library, MAKEINTRESOURCEA(i));
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1216
		if (!addr)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1217
			break;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1218
		if (addr > start && addr < end)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1219
			end = addr;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1220
		}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1221
	__NK_ASSERT_ALWAYS(end != ~0u);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1222
	TWin32FunctionInfo result = { start, end - start };
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1223
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1224
#ifdef	DUMP_STACK_BACKTRACE
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1225
	DEBUGPRINT("Function %s found at %08x to %08x", aFunctionName, start, end);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1226
#endif
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1227
	
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1228
	return result;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1229
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1230
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1231
void Win32FindNonPreemptibleFunctions()
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1232
	{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1233
#ifdef	DUMP_STACK_BACKTRACE
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1234
	PrintAllModuleInfo();
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1235
#endif
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1236
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1237
	TUint i = 0;
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1238
	Win32NonPreemptibleFunctions[i++] = Win32FindExportedFunction("RaiseException", "kernelbase.dll", "kernel32.dll", NULL);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1239
	Win32NonPreemptibleFunctions[i++] = Win32FindExportedFunction("KiUserExceptionDispatcher", "ntdll.dll", NULL);
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1240
	__NK_ASSERT_ALWAYS(i == KWin32NonPreemptibleFunctionCount);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1241
	}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1242
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1243
TBool Win32IsThreadInNonPreemptibleFunction(HANDLE aWinThread, TLinAddr aStackTop)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1244
	{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1245
	const TInt KMaxSearchDepth = 16;		 // 12 max observed while handling exceptions
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1246
	const TInt KMaxStackSize = 1024 * 1024;  // Default reserved stack size on windows
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1247
	const TInt KMaxFrameSize = 4096;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1248
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1249
	CONTEXT c;
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1250
	c.ContextFlags = CONTEXT_CONTROL;
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1251
	CheckedGetThreadContext(aWinThread, &c);
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1252
	TUint eip = c.Eip;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1253
	TUint ebp = c.Ebp;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1254
	TUint lastEbp = c.Esp;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1255
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1256
#ifdef	DUMP_STACK_BACKTRACE
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1257
	DEBUGPRINT("Stack backtrace for thread %x", aWinThread);
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1258
#endif
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1259
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1260
	// Walk the call stack
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1261
	for (TInt i = 0 ; i < KMaxSearchDepth ; ++i)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1262
		{
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1263
#ifdef	DUMP_STACK_BACKTRACE
90
947f0dc9f7a8 Revision: 201015
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents: 0
diff changeset
  1264
		DEBUGPRINT("  %08x", eip);
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1265
#endif
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1266
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1267
		for (TInt j = 0 ; j < KWin32NonPreemptibleFunctionCount ; ++j)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1268
			{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1269
			const TWin32FunctionInfo& info = Win32NonPreemptibleFunctions[j];
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1270
			if (TUint(eip - info.iStartAddr) < info.iLength)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1271
				{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1272
				__KTRACE_OPT(KSCHED, DEBUGPRINT("Thread is in non-preemptible function %d at frame %d: eip == %08x", j, i, eip));
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1273
				return TRUE;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1274
				}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1275
			}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1276
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1277
		// Check frame pointer is valid before dereferencing it
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1278
		if (TUint(aStackTop - ebp) > KMaxStackSize || TUint(ebp - lastEbp) > KMaxFrameSize || ebp & 3)
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1279
			break;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1280
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1281
		TUint* frame = (TUint*)ebp;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1282
		lastEbp = ebp;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1283
		ebp = frame[0];
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1284
		eip = frame[1];
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1285
		}
273
6a75fa55495f 201037_09
hgs
parents: 90
diff changeset
  1286
0
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1287
	return FALSE;
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1288
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1289
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1290
TBool NThread::IsSafeToPreempt()
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1291
	{
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1292
	return !Win32IsThreadInNonPreemptibleFunction(iWinThread, iUserStackBase);
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1293
	}
a41df078684a Convert Kernelhwsrv package from SFL to EPL
John Imhofe
parents:
diff changeset
  1294