os/kernelhwsrv/kernel/eka/include/nkernsmp/dfcs.h
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32\include\nkernsmp\dfcs.h
sl@0
    15
// 
sl@0
    16
// WARNING: This file contains some APIs which are internal and are subject
sl@0
    17
//          to change without notice. Such APIs should therefore not be used
sl@0
    18
//          outside the Kernel and Hardware Services package.
sl@0
    19
//
sl@0
    20
sl@0
    21
#ifndef __DFCS_H__
sl@0
    22
#define __DFCS_H__
sl@0
    23
sl@0
    24
#include <nklib.h>
sl@0
    25
#include <nk_event.h>
sl@0
    26
sl@0
    27
class NTimer;
sl@0
    28
class NThreadBase;
sl@0
    29
class NThread;
sl@0
    30
class NFastSemaphore;
sl@0
    31
class NFastMutex;
sl@0
    32
class TSubScheduler;
sl@0
    33
class TCancelIPI;
sl@0
    34
sl@0
    35
/********************************************
sl@0
    36
 * Delayed function call queue
sl@0
    37
 ********************************************/
sl@0
    38
sl@0
    39
/**
sl@0
    40
@publishedPartner
sl@0
    41
@released
sl@0
    42
sl@0
    43
The number of DFC priorities the system has, which range from 0
sl@0
    44
to KNumDfcPriorities - 1.
sl@0
    45
*/
sl@0
    46
const TInt KNumDfcPriorities=8;
sl@0
    47
sl@0
    48
/**
sl@0
    49
@publishedPartner
sl@0
    50
@released
sl@0
    51
sl@0
    52
The highest priority level for a DFC, which is equal to KNumDfcPriorities + 1.
sl@0
    53
*/
sl@0
    54
const TInt KMaxDfcPriority=KNumDfcPriorities-1;
sl@0
    55
sl@0
    56
class TDfc;
sl@0
    57
/**
sl@0
    58
@publishedPartner
sl@0
    59
@prototype
sl@0
    60
sl@0
    61
Defines a DFC queue.
sl@0
    62
sl@0
    63
Each DFC queue is associated with a thread.
sl@0
    64
sl@0
    65
@see TDfc
sl@0
    66
*/
sl@0
    67
class TDfcQue : public TPriList<TDfc,KNumDfcPriorities>
sl@0
    68
	{
sl@0
    69
public:
sl@0
    70
	IMPORT_C TDfcQue();
sl@0
    71
sl@0
    72
	inline TBool IsEmpty();		/**< @internalComponent */
sl@0
    73
	static void ThreadFunction(TAny* aDfcQ);
sl@0
    74
public:
sl@0
    75
	NThreadBase* iThread;		/**< @internalComponent */
sl@0
    76
	};
sl@0
    77
sl@0
    78
/**
sl@0
    79
@internalComponent
sl@0
    80
*/
sl@0
    81
inline TBool TDfcQue::IsEmpty()
sl@0
    82
	{ return (iPresent[0]==0); }
sl@0
    83
sl@0
    84
/********************************************
sl@0
    85
 * Delayed function call
sl@0
    86
 ********************************************/
sl@0
    87
sl@0
    88
/**
sl@0
    89
@publishedPartner
sl@0
    90
@released
sl@0
    91
sl@0
    92
The function type that can be set to run as a DFC or IDFC.
sl@0
    93
sl@0
    94
@see TDfc
sl@0
    95
*/
sl@0
    96
typedef NEventFn TDfcFn;
sl@0
    97
sl@0
    98
/**
sl@0
    99
@publishedPartner
sl@0
   100
@prototype
sl@0
   101
sl@0
   102
Defines a Deferred Function Call (DFC) or Immediate Deferred Function Call (IDFC).
sl@0
   103
sl@0
   104
A DFC is a kernel object that specifies a function to be run in a thread,
sl@0
   105
which is processing a DFC queue. A DFC is added to a DFC queue that is 
sl@0
   106
associated with a given thread, where it is cooperatively scheduled with other
sl@0
   107
DFCs on that queue.  Queued DFCs are run in order of their priority, followed
sl@0
   108
by the order they where queued.  When the DFC gets to run, the function is run
sl@0
   109
kernel side, and no other DFC in this queue will get to run until it 
sl@0
   110
completes. A DFC can be queued from any context.
sl@0
   111
sl@0
   112
An IDFC is run as soon as the scheduler is next run, which is during the IRQ
sl@0
   113
postamble if queued from an ISR; when the currently-running IDFC completes if
sl@0
   114
queued from an IDFC; or when the kernel is next unlocked if queued from thread
sl@0
   115
context.  Unlike a DFC, the IDFC is not run from a thread context, and its
sl@0
   116
execution time must be much smaller.  For these reasons, IDFCs are rarely used
sl@0
   117
directly, but are used for implementation of the kernel and RTOS personality
sl@0
   118
layers.  An important use of IDFCs is in the implementation of queuing DFCs from
sl@0
   119
an ISR context.  IDFCs are run with interrupts enabled but the kernel locked.
sl@0
   120
*/
sl@0
   121
class TDfc : public NEventHandler
sl@0
   122
	{
sl@0
   123
	// iPriority<KNumDfcPriorities => DFC, otherwise IDFC
sl@0
   124
	//
sl@0
   125
	// iHState2	= 0 normally
sl@0
   126
	//			= Bit n is set if CPU n is waiting to cancel this DFC
sl@0
   127
	// iHState1	= 0 if not on any list
sl@0
   128
	//			= 100nnnnn if on CPU n endogenous IDFC/DFC queue
sl@0
   129
	//			= 101nnnnn if on CPU n exogenous IDFC queue
sl@0
   130
	//			= 110nnnnn if running on CPU n
sl@0
   131
	//			= 111nnnnn if running on CPU n and a second execution is also pending (Add() was called while running)
sl@0
   132
	//			= 011nnnnn if running on CPU n and a second idle queue is also pending (QueueOnIdle() was called while running)
sl@0
   133
	//			= 0010000g if idle DFC generation g (could be either on idle queue or CPU endogenous IDFC/DFC queue)
sl@0
   134
	//			= 00000001 if on final DFC queue
sl@0
   135
	// iHState1 and iHState2 are accessed together as a single 16 bit iDfcState
sl@0
   136
	//
sl@0
   137
	// iHState0 is set to 0 when a DFC/IDFC is added to a CPUs endogenous IDFC
sl@0
   138
	// queue or to the idle queue. It is set to 1 if and when BeginTiedEvent()
sl@0
   139
	// is subsequently called (thus only for tied IDFCs).
sl@0
   140
	//
sl@0
   141
	// For IDFC iHType = EEventHandlerIDFC
sl@0
   142
	// For DFC iHType = priority (0 to 7) and iTied points to TDfcQue (since DFCs can't be tied)
sl@0
   143
	//
sl@0
   144
public:
sl@0
   145
	IMPORT_C TDfc(TDfcFn aFunction, TAny* aPtr);									// create IDFC
sl@0
   146
	IMPORT_C TDfc(NSchedulable* aTied, TDfcFn aFunction, TAny* aPtr);				// create IDFC tied to a thread or group
sl@0
   147
	IMPORT_C TDfc(TDfcFn aFunction, TAny* aPtr, TInt aPriority);					// create DFC, queue to be set later
sl@0
   148
	IMPORT_C TDfc(TDfcFn aFunction, TAny* aPtr, TDfcQue* aDfcQ, TInt aPriority);	// create DFC
sl@0
   149
	IMPORT_C ~TDfc();
sl@0
   150
	IMPORT_C TBool Add();						// call from ISR or IDFC or thread with kernel locked
sl@0
   151
	IMPORT_C TBool Cancel();					// call from anywhere except ISR
sl@0
   152
	IMPORT_C TBool Enque();						// call from thread
sl@0
   153
	IMPORT_C TBool Enque(NFastMutex* aMutex);	// call from thread, signal fast mutex (anti-thrash)
sl@0
   154
	IMPORT_C TBool DoEnque();					// call from IDFC or thread with kernel locked
sl@0
   155
	IMPORT_C TBool RawAdd();					// same as Add() but without checks for 'correct' usage or other instrumentation
sl@0
   156
	IMPORT_C TBool QueueOnIdle();				// queue the DFC to be run when the system goes idle
sl@0
   157
	IMPORT_C TInt SetTied(NSchedulable* aTied);	// tie an IDFC to a thread or group
sl@0
   158
	IMPORT_C NThreadBase* Thread();				// thread on which DFC runs, NULL for IDFC
sl@0
   159
public:
sl@0
   160
	inline TBool Queued();
sl@0
   161
	inline TBool IsIDFC();
sl@0
   162
	inline TBool IsDFC();
sl@0
   163
	inline void SetDfcQ(TDfcQue* aDfcQ);
sl@0
   164
	inline void SetFunction(TDfcFn aDfcFn);
sl@0
   165
	inline void SetPriority(TInt aPriority);			/**< @internalComponent */
sl@0
   166
private:
sl@0
   167
	inline TBool IsValid();								/**< @internalComponent */
sl@0
   168
private:
sl@0
   169
	TUint32 AddStateChange();							/**< @internalComponent */
sl@0
   170
	TUint32 MoveToFinalQStateChange();					/**< @internalComponent */
sl@0
   171
	TUint32 TransferIDFCStateChange(TInt aCpu);			/**< @internalComponent */
sl@0
   172
	TUint32 RunIDFCStateChange();						/**< @internalComponent */
sl@0
   173
	TUint32 EndIDFCStateChange(TSubScheduler*);			/**< @internalComponent */
sl@0
   174
	TUint32 EndIDFCStateChange2();						/**< @internalComponent */
sl@0
   175
	TUint32 CancelInitialStateChange();					/**< @internalComponent */
sl@0
   176
	TUint32 CancelFinalStateChange();					/**< @internalComponent */
sl@0
   177
	TUint32 QueueOnIdleStateChange();					/**< @internalComponent */
sl@0
   178
	void ResetState();									/**< @internalComponent */
sl@0
   179
sl@0
   180
	friend class TSubScheduler;
sl@0
   181
	friend class TCancelIPI;
sl@0
   182
	friend class TDfcQue;
sl@0
   183
	friend class NTimer;
sl@0
   184
	};
sl@0
   185
sl@0
   186
/**
sl@0
   187
@publishedPartner
sl@0
   188
@prototype
sl@0
   189
sl@0
   190
Used to find out if the DFC/IDFC is queued on either the pending or final DFC queue.
sl@0
   191
sl@0
   192
@return TRUE if the DFC/IDFC is queued, otherwise FALSE.
sl@0
   193
sl@0
   194
*/
sl@0
   195
inline TBool TDfc::Queued()
sl@0
   196
	{ TUint32 state = i8816.iHState16; return state && (state&0xE0)!=0xC0; }
sl@0
   197
sl@0
   198
/**
sl@0
   199
@publishedPartner
sl@0
   200
@prototype
sl@0
   201
sl@0
   202
Determines if the object represents an IDFC rather than a DFC.
sl@0
   203
sl@0
   204
@return TRUE if this represents an IDFC, otherwise FALSE.
sl@0
   205
*/
sl@0
   206
inline TBool TDfc::IsIDFC()
sl@0
   207
	{ return iHType == EEventHandlerIDFC; }
sl@0
   208
sl@0
   209
/**
sl@0
   210
@publishedPartner
sl@0
   211
@prototype
sl@0
   212
sl@0
   213
Determines if the object represents a DFC rather than an IDFC.
sl@0
   214
sl@0
   215
@return TRUE if this represents a DFC, otherwise FALSE.
sl@0
   216
*/
sl@0
   217
inline TBool TDfc::IsDFC()
sl@0
   218
	{ return iHType < KNumDfcPriorities; }
sl@0
   219
sl@0
   220
sl@0
   221
/**
sl@0
   222
@publishedPartner
sl@0
   223
@prototype
sl@0
   224
sl@0
   225
Sets the DFC queue that the DFC is to added to and executed by.
sl@0
   226
sl@0
   227
Note that this function should only be used in the initialisation of the DFC, 
sl@0
   228
when it is not on any queue.  This function does not move the DFC from one 
sl@0
   229
queue to another.
sl@0
   230
sl@0
   231
@param aDfcQ
sl@0
   232
sl@0
   233
	The DFC queue that the DFC is to be added to and executed by.
sl@0
   234
sl@0
   235
*/
sl@0
   236
inline void TDfc::SetDfcQ(TDfcQue* aDfcQ)
sl@0
   237
	{ iDfcQ = aDfcQ; }
sl@0
   238
sl@0
   239
/**
sl@0
   240
@publishedPartner
sl@0
   241
@prototype
sl@0
   242
sl@0
   243
Sets the function that is run when the DFC/IDFC is scheduled.
sl@0
   244
sl@0
   245
@param aDfcFn
sl@0
   246
sl@0
   247
	The function that the DFC/IDFC runs when it is scheduled.
sl@0
   248
sl@0
   249
*/
sl@0
   250
inline void TDfc::SetFunction(TDfcFn aDfcFn)
sl@0
   251
	{ iFn = aDfcFn; }
sl@0
   252
sl@0
   253
/**
sl@0
   254
@internalComponent
sl@0
   255
*/
sl@0
   256
inline void TDfc::SetPriority(TInt aPriority)
sl@0
   257
	{ iHState = (TUint8)aPriority; }
sl@0
   258
sl@0
   259
#ifdef __INCLUDE_TDFC_DEFINES__
sl@0
   260
/**
sl@0
   261
@internalComponent
sl@0
   262
*/
sl@0
   263
#define	iDfcState		(i8816.iHState16)
sl@0
   264
sl@0
   265
/**
sl@0
   266
@internalComponent
sl@0
   267
*/
sl@0
   268
#define DFC_STATE(p)	((p)->i8816.iHState16)
sl@0
   269
#endif
sl@0
   270
sl@0
   271
sl@0
   272
/********************************************
sl@0
   273
 * Kernel-side asynchronous request,
sl@0
   274
 * based on DFC queueing
sl@0
   275
 ********************************************/
sl@0
   276
sl@0
   277
/**
sl@0
   278
@internalComponent
sl@0
   279
*/
sl@0
   280
class TAsyncRequest : protected TDfc
sl@0
   281
	{
sl@0
   282
public:
sl@0
   283
	IMPORT_C void Send(TDfc* aCompletionDfc);
sl@0
   284
	IMPORT_C void Send(NFastSemaphore* aCompletionSemaphore);
sl@0
   285
	IMPORT_C TInt SendReceive();
sl@0
   286
	IMPORT_C void Cancel();
sl@0
   287
	IMPORT_C void Complete(TInt aResult);
sl@0
   288
	inline TBool PollForCancel()
sl@0
   289
		{ return iCancel; }
sl@0
   290
protected:
sl@0
   291
	IMPORT_C TAsyncRequest(TDfcFn aFunction, TDfcQue* aDfcQ, TInt aPriority);
sl@0
   292
protected:
sl@0
   293
	TAny*	iCompletionObject;
sl@0
   294
	volatile TBool	iCancel;
sl@0
   295
	TInt	iResult;
sl@0
   296
	};
sl@0
   297
sl@0
   298
sl@0
   299
#endif