os/security/cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4/cryptojobs.cpp
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
/*
sl@0
     2
* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
*
sl@0
    16
*/
sl@0
    17
sl@0
    18
sl@0
    19
/**
sl@0
    20
 @file
sl@0
    21
 @internalComponent
sl@0
    22
 @released
sl@0
    23
*/
sl@0
    24
#include <kernel/kern_priv.h>
sl@0
    25
#include "cryptojobs.h"
sl@0
    26
sl@0
    27
EXPORT_C TraceFunction * &TraceFunction::HeadRef()
sl@0
    28
	{
sl@0
    29
	static TraceFunction *sHead = 0;
sl@0
    30
	return sHead;
sl@0
    31
	}
sl@0
    32
sl@0
    33
sl@0
    34
sl@0
    35
EXPORT_C DCryptoJobScheduler::DCryptoJobScheduler()
sl@0
    36
	{
sl@0
    37
	TRACE_FUNCTION("DCryptoJobScheduler");
sl@0
    38
	}
sl@0
    39
sl@0
    40
EXPORT_C DCryptoJobScheduler::~DCryptoJobScheduler()
sl@0
    41
	{
sl@0
    42
	TRACE_FUNCTION("~DCryptoJobScheduler");
sl@0
    43
	// At this point the LDD channels and PDD factory/chans should
sl@0
    44
	// have already been deleted...
sl@0
    45
	}
sl@0
    46
sl@0
    47
sl@0
    48
EXPORT_C void DCryptoJobScheduler::ScheduleJob(CryptoJob *aJob)
sl@0
    49
	{
sl@0
    50
	TRACE_FUNCTION("ScheduleJob");
sl@0
    51
	if(aJob->iInJobList)
sl@0
    52
		{
sl@0
    53
		// Already in a job list
sl@0
    54
		// If it is the current job and it is not running then try and schedule it
sl@0
    55
		// It was probably stalled waiting for the user to read and/or write data.
sl@0
    56
		if((aJob == iJobList) && (aJob->iState != CryptoJob::ERunning))
sl@0
    57
			{
sl@0
    58
			// Job is not running, and is first in list, so schedule
sl@0
    59
			// it without rescheduling the first job (which is us!)
sl@0
    60
			Schedule(EFalse);
sl@0
    61
			return;
sl@0
    62
			}
sl@0
    63
		// Attempt to reschedule current job, ie if it is not running
sl@0
    64
		// save its state and try running a different job.
sl@0
    65
		Schedule(ETrue);
sl@0
    66
		return;
sl@0
    67
		}
sl@0
    68
sl@0
    69
	// Not in list, so add it
sl@0
    70
	aJob->iJobScheduler = this;
sl@0
    71
	aJob->iNext = 0;
sl@0
    72
	if(aJob->iState == CryptoJob::ECreated)
sl@0
    73
		{
sl@0
    74
		aJob->iState = CryptoJob::EReadyForFirstRun;
sl@0
    75
		}
sl@0
    76
	if(iJobList == 0)
sl@0
    77
		{
sl@0
    78
		// Only job
sl@0
    79
		iJobList = aJob;
sl@0
    80
		aJob->iInJobList = ETrue;
sl@0
    81
		}
sl@0
    82
	else
sl@0
    83
		{
sl@0
    84
		// Insert as second on list.
sl@0
    85
		// 
sl@0
    86
		// This quick and easy to do because it does not require a
sl@0
    87
		// re-schedule or a full list walk. It is slightly unfair to
sl@0
    88
		// existing jobs, but usually there will only be the head job
sl@0
    89
		// anyway.
sl@0
    90
		CryptoJob *p = iJobList->iNext;
sl@0
    91
		iJobList->iNext = aJob;
sl@0
    92
		aJob->iNext = p;
sl@0
    93
		aJob->iInJobList = ETrue;
sl@0
    94
		}
sl@0
    95
	
sl@0
    96
	// Attempt re-schedule
sl@0
    97
	Schedule(ETrue);
sl@0
    98
	}
sl@0
    99
sl@0
   100
EXPORT_C void DCryptoJobScheduler::DeScheduleJob(CryptoJob *aJob)
sl@0
   101
	{
sl@0
   102
	TRACE_FUNCTION("DeScheduleJob");
sl@0
   103
	if((aJob->iState == CryptoJob::EReady) || (aJob->iState == CryptoJob::ERunning))
sl@0
   104
		{
sl@0
   105
		aJob->DoReleaseHw();
sl@0
   106
		}
sl@0
   107
	
sl@0
   108
	aJob->iState = CryptoJob::ECreated;
sl@0
   109
	
sl@0
   110
	// Hunt for and remove job from queue.
sl@0
   111
	// This is a linear search, BUT the list length is probably one...
sl@0
   112
	// Try and set pp to point to the pointer to the job we are removing
sl@0
   113
	CryptoJob **pp = &iJobList; 
sl@0
   114
	while(*pp != aJob && *pp)
sl@0
   115
		{
sl@0
   116
		pp = &((*pp)->iNext);
sl@0
   117
		}
sl@0
   118
	if(*pp == aJob)
sl@0
   119
		{
sl@0
   120
		*pp = (*pp)->iNext;
sl@0
   121
		aJob->iNext = 0;
sl@0
   122
		aJob->iJobScheduler = 0;
sl@0
   123
		aJob->iInJobList = EFalse;
sl@0
   124
		}
sl@0
   125
	}
sl@0
   126
sl@0
   127
sl@0
   128
sl@0
   129
EXPORT_C void DCryptoJobScheduler::SliceComplete(CryptoJob *aJob, TInt aStatus)
sl@0
   130
	{
sl@0
   131
	TRACE_FUNCTION("SliceComplete");
sl@0
   132
	// Need start next slice or swap to another job and start it
sl@0
   133
	if(aJob != iJobList)
sl@0
   134
		{
sl@0
   135
		Kern::Printf("DCryptoJobScheduler::SliceComplete - not running job 0x%x=0x%x",
sl@0
   136
					 aJob, iJobList);
sl@0
   137
		return;
sl@0
   138
		}
sl@0
   139
	
sl@0
   140
	if(aStatus != KErrNone)
sl@0
   141
		{
sl@0
   142
		JobComplete(aJob, aStatus);
sl@0
   143
		return;
sl@0
   144
		}
sl@0
   145
sl@0
   146
	Schedule(ETrue); // Change jobs and run top one
sl@0
   147
	return;
sl@0
   148
	}
sl@0
   149
sl@0
   150
sl@0
   151
EXPORT_C void DCryptoJobScheduler::JobComplete(CryptoJob *aJob, TInt aStatus)
sl@0
   152
	{
sl@0
   153
	TRACE_FUNCTION("JobComplete");
sl@0
   154
	if(aJob != iJobList)
sl@0
   155
		{
sl@0
   156
		Kern::Printf("DCryptoJobScheduler::JobComplete - not running job 0x%x=0x%x",
sl@0
   157
					 aJob, iJobList);
sl@0
   158
		return;
sl@0
   159
		}
sl@0
   160
sl@0
   161
	// Pop job and update state
sl@0
   162
	DeScheduleJob(aJob);
sl@0
   163
	
sl@0
   164
	aJob->iCallbacks->JobComplete(aStatus);
sl@0
   165
sl@0
   166
	Schedule(EFalse); // Run top job
sl@0
   167
	}
sl@0
   168
sl@0
   169
void DCryptoJobScheduler::Schedule(TBool aReschedule)
sl@0
   170
	{
sl@0
   171
	TRACE_FUNCTION("Schedule");
sl@0
   172
	if(iJobList == 0)
sl@0
   173
		{
sl@0
   174
		return;
sl@0
   175
		}
sl@0
   176
sl@0
   177
	if(iJobList->iState == CryptoJob::ERunning)
sl@0
   178
		{
sl@0
   179
		// h/w busy so can not do anything now.
sl@0
   180
		return;
sl@0
   181
		}
sl@0
   182
	
sl@0
   183
	if((iJobList->iNext == 0) && (iJobList->iState == CryptoJob::EStalled))
sl@0
   184
		{
sl@0
   185
		// Only one job in list and its stalled. Leave it on the h/w
sl@0
   186
		// as an optimisation.
sl@0
   187
		return;
sl@0
   188
		}
sl@0
   189
sl@0
   190
	if(iJobList->iNext)
sl@0
   191
		{
sl@0
   192
		// More than one job in list.
sl@0
   193
		// If top job is stalled, or reschedule is requested then swap jobs
sl@0
   194
		// Only the top job can ever be marked as EStalled.
sl@0
   195
		// (Only running job can stall and new jobs get inserted second in the list)
sl@0
   196
		TBool stalledJob = (iJobList->iState == CryptoJob::EStalled);
sl@0
   197
		if(stalledJob || aReschedule)
sl@0
   198
			{
sl@0
   199
			//
sl@0
   200
			// Pop current job from front of list
sl@0
   201
			//
sl@0
   202
			CryptoJob *oldJob = iJobList;
sl@0
   203
			iJobList = iJobList->iNext;
sl@0
   204
			oldJob->iNext = 0;
sl@0
   205
			if(oldJob->DoSaveState())
sl@0
   206
				{
sl@0
   207
				// State was saved
sl@0
   208
				oldJob->iState = CryptoJob::EReadySavedState;
sl@0
   209
				}
sl@0
   210
			else
sl@0
   211
				{
sl@0
   212
				// No state was saved
sl@0
   213
				oldJob->iState = CryptoJob::EReadyNoSavedState;
sl@0
   214
				}
sl@0
   215
			if(stalledJob)
sl@0
   216
				{
sl@0
   217
				oldJob->iInJobList = EFalse;
sl@0
   218
				}
sl@0
   219
			else
sl@0
   220
				{
sl@0
   221
				//
sl@0
   222
				// Append oldJob to end of list
sl@0
   223
				//
sl@0
   224
				// Find ptr to last job
sl@0
   225
				CryptoJob **pp = &iJobList;
sl@0
   226
				while(*pp)
sl@0
   227
					{
sl@0
   228
					pp = &(*pp)->iNext;
sl@0
   229
					}
sl@0
   230
				// Append
sl@0
   231
				*pp = oldJob;
sl@0
   232
				}
sl@0
   233
			}
sl@0
   234
		}
sl@0
   235
	
sl@0
   236
	//
sl@0
   237
	// Run new job
sl@0
   238
	//
sl@0
   239
	CryptoJob *firstJob = iJobList;
sl@0
   240
sl@0
   241
	switch(firstJob->iState)
sl@0
   242
		{
sl@0
   243
		case CryptoJob::EReady:
sl@0
   244
			firstJob->DoSlice(EFalse);
sl@0
   245
			break;
sl@0
   246
sl@0
   247
		case CryptoJob::EReadyForFirstRun:
sl@0
   248
			firstJob->iState = CryptoJob::EReady;
sl@0
   249
			firstJob->DoSlice(ETrue);
sl@0
   250
			break;
sl@0
   251
sl@0
   252
		case CryptoJob::EReadyNoSavedState:
sl@0
   253
			firstJob->iState = CryptoJob::EReady;
sl@0
   254
			firstJob->DoSlice(EFalse);
sl@0
   255
			break;
sl@0
   256
sl@0
   257
		case CryptoJob::EReadySavedState:
sl@0
   258
			firstJob->iState = CryptoJob::EReady;
sl@0
   259
			firstJob->DoRestoreState();
sl@0
   260
			firstJob->DoSlice(EFalse);
sl@0
   261
			break;
sl@0
   262
			
sl@0
   263
		case CryptoJob::ECreated:
sl@0
   264
		case CryptoJob::EStalled:
sl@0
   265
		default:
sl@0
   266
			Kern::Printf("DCryptoJobScheduler::Schedule bad state %d", iJobList->iState);
sl@0
   267
			DeScheduleJob(firstJob); // Abort/remove from list
sl@0
   268
			Schedule(EFalse);
sl@0
   269
			return;
sl@0
   270
		}
sl@0
   271
sl@0
   272
	return;
sl@0
   273
	}
sl@0
   274
sl@0
   275
sl@0
   276
EXPORT_C CryptoJob::CryptoJob()
sl@0
   277
	: iState(ECreated),
sl@0
   278
	  iJobScheduler(0),
sl@0
   279
	  iCallbacks(0),
sl@0
   280
	  iNext(0),
sl@0
   281
	  iInJobList(EFalse)
sl@0
   282
	{
sl@0
   283
	TRACE_FUNCTION("CryptoJob");
sl@0
   284
	}
sl@0
   285
sl@0
   286
EXPORT_C CryptoJob::~CryptoJob()
sl@0
   287
	{
sl@0
   288
	TRACE_FUNCTION("~CryptoJob");
sl@0
   289
	// Do not call DeScheduleJob from here because it will crash....  The
sl@0
   290
	// derived class destructor has already run and the object is now
sl@0
   291
	// considered to be of type CryptoJob (not the derived class) so
sl@0
   292
	// most virtual functions are pure virtual and calling them will
sl@0
   293
	// cause a crash.
sl@0
   294
	}
sl@0
   295
sl@0
   296
EXPORT_C void CryptoJob::Stalled()
sl@0
   297
	{
sl@0
   298
	TRACE_FUNCTION("Stalled");
sl@0
   299
	iState = EStalled;
sl@0
   300
	iJobScheduler->SliceComplete(this, KErrNone);	
sl@0
   301
	}
sl@0
   302
sl@0
   303
EXPORT_C void CryptoJob::Resume()
sl@0
   304
	{
sl@0
   305
	TRACE_FUNCTION("Resume");
sl@0
   306
	if(iState == EStalled)
sl@0
   307
		{
sl@0
   308
		iState = EReady;
sl@0
   309
		}
sl@0
   310
	iJobScheduler->ScheduleJob(this);	
sl@0
   311
	}
sl@0
   312
sl@0
   313
EXPORT_C void CryptoJob::DeScheduleJob()
sl@0
   314
	{
sl@0
   315
	TRACE_FUNCTION("DeScheduleJob");
sl@0
   316
	if(iJobScheduler)
sl@0
   317
		{
sl@0
   318
		iJobScheduler->DeScheduleJob(this);
sl@0
   319
		}
sl@0
   320
	}
sl@0
   321
sl@0
   322
EXPORT_C void CryptoJob::SetRunning(TBool aRunning)
sl@0
   323
	{
sl@0
   324
	TRACE_FUNCTION("SetRunning");
sl@0
   325
	if(aRunning)
sl@0
   326
		{
sl@0
   327
		if((iState != EReady) && (iState != ERunning))
sl@0
   328
			{
sl@0
   329
			Kern::Printf("CryptoJob::SetRunning(%d) iState is %d this=%x", aRunning, iState, this);
sl@0
   330
			Kern::Fault("CryptoJob", 42);
sl@0
   331
			}
sl@0
   332
		iState = ERunning;
sl@0
   333
		}
sl@0
   334
	else
sl@0
   335
		{
sl@0
   336
		if((iState != ERunning) && (iState != EReady))
sl@0
   337
			{
sl@0
   338
			Kern::Printf("CryptoJob::SetRunning(%d) iState is %d this=%x", aRunning, iState, this);
sl@0
   339
			Kern::Fault("CryptoJob", 43);
sl@0
   340
			}
sl@0
   341
		iState = EReady;
sl@0
   342
		}
sl@0
   343
	}
sl@0
   344
sl@0
   345
EXPORT_C CryptoJob::CryptoJobState CryptoJob::State() const
sl@0
   346
	{
sl@0
   347
	TRACE_FUNCTION("State");
sl@0
   348
	return iState;
sl@0
   349
	}
sl@0
   350
sl@0
   351
sl@0
   352
// End of file
sl@0
   353