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