First public contribution.
2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
24 #include <kernel/kern_priv.h>
25 #include "cryptojobs.h"
27 EXPORT_C TraceFunction * &TraceFunction::HeadRef()
29 static TraceFunction *sHead = 0;
35 EXPORT_C DCryptoJobScheduler::DCryptoJobScheduler()
37 TRACE_FUNCTION("DCryptoJobScheduler");
40 EXPORT_C DCryptoJobScheduler::~DCryptoJobScheduler()
42 TRACE_FUNCTION("~DCryptoJobScheduler");
43 // At this point the LDD channels and PDD factory/chans should
44 // have already been deleted...
48 EXPORT_C void DCryptoJobScheduler::ScheduleJob(CryptoJob *aJob)
50 TRACE_FUNCTION("ScheduleJob");
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))
58 // Job is not running, and is first in list, so schedule
59 // it without rescheduling the first job (which is us!)
63 // Attempt to reschedule current job, ie if it is not running
64 // save its state and try running a different job.
69 // Not in list, so add it
70 aJob->iJobScheduler = this;
72 if(aJob->iState == CryptoJob::ECreated)
74 aJob->iState = CryptoJob::EReadyForFirstRun;
80 aJob->iInJobList = ETrue;
84 // Insert as second on list.
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
90 CryptoJob *p = iJobList->iNext;
91 iJobList->iNext = aJob;
93 aJob->iInJobList = ETrue;
96 // Attempt re-schedule
100 EXPORT_C void DCryptoJobScheduler::DeScheduleJob(CryptoJob *aJob)
102 TRACE_FUNCTION("DeScheduleJob");
103 if((aJob->iState == CryptoJob::EReady) || (aJob->iState == CryptoJob::ERunning))
108 aJob->iState = CryptoJob::ECreated;
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)
116 pp = &((*pp)->iNext);
122 aJob->iJobScheduler = 0;
123 aJob->iInJobList = EFalse;
129 EXPORT_C void DCryptoJobScheduler::SliceComplete(CryptoJob *aJob, TInt aStatus)
131 TRACE_FUNCTION("SliceComplete");
132 // Need start next slice or swap to another job and start it
135 Kern::Printf("DCryptoJobScheduler::SliceComplete - not running job 0x%x=0x%x",
140 if(aStatus != KErrNone)
142 JobComplete(aJob, aStatus);
146 Schedule(ETrue); // Change jobs and run top one
151 EXPORT_C void DCryptoJobScheduler::JobComplete(CryptoJob *aJob, TInt aStatus)
153 TRACE_FUNCTION("JobComplete");
156 Kern::Printf("DCryptoJobScheduler::JobComplete - not running job 0x%x=0x%x",
161 // Pop job and update state
164 aJob->iCallbacks->JobComplete(aStatus);
166 Schedule(EFalse); // Run top job
169 void DCryptoJobScheduler::Schedule(TBool aReschedule)
171 TRACE_FUNCTION("Schedule");
177 if(iJobList->iState == CryptoJob::ERunning)
179 // h/w busy so can not do anything now.
183 if((iJobList->iNext == 0) && (iJobList->iState == CryptoJob::EStalled))
185 // Only one job in list and its stalled. Leave it on the h/w
186 // as an optimisation.
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)
200 // Pop current job from front of list
202 CryptoJob *oldJob = iJobList;
203 iJobList = iJobList->iNext;
205 if(oldJob->DoSaveState())
208 oldJob->iState = CryptoJob::EReadySavedState;
212 // No state was saved
213 oldJob->iState = CryptoJob::EReadyNoSavedState;
217 oldJob->iInJobList = EFalse;
222 // Append oldJob to end of list
224 // Find ptr to last job
225 CryptoJob **pp = &iJobList;
239 CryptoJob *firstJob = iJobList;
241 switch(firstJob->iState)
243 case CryptoJob::EReady:
244 firstJob->DoSlice(EFalse);
247 case CryptoJob::EReadyForFirstRun:
248 firstJob->iState = CryptoJob::EReady;
249 firstJob->DoSlice(ETrue);
252 case CryptoJob::EReadyNoSavedState:
253 firstJob->iState = CryptoJob::EReady;
254 firstJob->DoSlice(EFalse);
257 case CryptoJob::EReadySavedState:
258 firstJob->iState = CryptoJob::EReady;
259 firstJob->DoRestoreState();
260 firstJob->DoSlice(EFalse);
263 case CryptoJob::ECreated:
264 case CryptoJob::EStalled:
266 Kern::Printf("DCryptoJobScheduler::Schedule bad state %d", iJobList->iState);
267 DeScheduleJob(firstJob); // Abort/remove from list
276 EXPORT_C CryptoJob::CryptoJob()
283 TRACE_FUNCTION("CryptoJob");
286 EXPORT_C CryptoJob::~CryptoJob()
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
296 EXPORT_C void CryptoJob::Stalled()
298 TRACE_FUNCTION("Stalled");
300 iJobScheduler->SliceComplete(this, KErrNone);
303 EXPORT_C void CryptoJob::Resume()
305 TRACE_FUNCTION("Resume");
306 if(iState == EStalled)
310 iJobScheduler->ScheduleJob(this);
313 EXPORT_C void CryptoJob::DeScheduleJob()
315 TRACE_FUNCTION("DeScheduleJob");
318 iJobScheduler->DeScheduleJob(this);
322 EXPORT_C void CryptoJob::SetRunning(TBool aRunning)
324 TRACE_FUNCTION("SetRunning");
327 if((iState != EReady) && (iState != ERunning))
329 Kern::Printf("CryptoJob::SetRunning(%d) iState is %d this=%x", aRunning, iState, this);
330 Kern::Fault("CryptoJob", 42);
336 if((iState != ERunning) && (iState != EReady))
338 Kern::Printf("CryptoJob::SetRunning(%d) iState is %d this=%x", aRunning, iState, this);
339 Kern::Fault("CryptoJob", 43);
345 EXPORT_C CryptoJob::CryptoJobState CryptoJob::State() const
347 TRACE_FUNCTION("State");