/** * Given a thread ID, return a handle to the corresponding DThread. If the returned * pointer is non-NULL, it is the responsibility of the caller to close the handle. * * @pre caller must be in thread critical section * @post if a non-NULL value is returned then a handle to the thread has been * opened on the callers behalf * @param aThreadId ID of the thread to return a handle for * @return a DThread* to the appropriate thread, or NULL if a handle could not be * opened to the specified thread */ DThread* DebugUtils::OpenThreadHandle(TUint64 aThreadId) { __ASSERT_CRITICAL; LOG_MSG2("DebugUtils::OpenThreadHandle(0x%lx)", aThreadId); DObjectCon& threads = *Kern::Containers()[EThread]; // Get containing holding threads threads.Wait(); // Obtain the container mutex so the list does get changed under us DThread* thread = Kern::ThreadFromId(aThreadId); // Open a handle to the thread so that it doesn't exit while we are processing if (thread) { // if opening a handle fails then set thread to NULL if(KErrNone != thread->Open()) { LOG_MSG2("\tCould not open handle to thread %d", (TUint32)aThreadId); thread = NULL; } } else { LOG_MSG2("\tThread with ID %d is NULL", (TUint32)aThreadId); } threads.Signal(); // Release the container mutex return thread; }
// // The implementation of RBMDriver::SetAbsPriority() call. // TInt DBMLChannel::SetAbsPriority(TInt aThreadHandle, TInt aNewPrio, TInt* aOldPrio) { NKern::LockSystem(); // // Under the system lock find the DThread object and increment its ref-count (i.e Open()) // DThread* thr = (DThread*) Kern::ObjectFromHandle(&Kern::CurrentThread(), aThreadHandle, EThread); TInt r; if (!thr) { r = EBadHandle; } else { r = thr->Open(); } // // Now it's safe to release the system lock and to work with the object. // NKern::ThreadEnterCS(); NKern::UnlockSystem(); if (r != KErrNone) { NKern::ThreadLeaveCS(); return r; } *aOldPrio = thr->iDefaultPriority; Kern::SetThreadPriority(aNewPrio, thr); // // Work is done - close the object. // thr->Close(NULL); NKern::ThreadLeaveCS(); return KErrNone; }
void DPowerManager::RequestWakeupEventNotification(TRequestStatus* aStatus) { // called by ExecHandler __KTRACE_OPT(KPOWER,Kern::Printf("PowerManger::RequestWakeupEventNotification()")); Lock(); // we aquire this lock to avoid new requests while in PowerDown NKern::LockSystem(); if (iClient || iRequest->SetStatus(aStatus) != KErrNone) Kern::RequestComplete(aStatus, KErrInUse); else { iClient = TheCurrentThread; iClient->Open(); } NKern::UnlockSystem(); Unlock(); __KTRACE_OPT(KPOWER,Kern::Printf("<PowerManger::RequestWakeupEventNotification()")); }
/** * Opens a reference to the first thread of the given process. Returns NULL if * there are no threads remaining in the process or if the thread couldn't be opened. * * @pre Caller must be in thread context, in critical section, no fast mutexes held. * @post if result is non-NULL caller is responsible for closing the handle * @param aProcess The process whose first thread is to be opened * @return an Open()ed pointer to the first thread in the process, or NULL. */ DThread* DebugUtils::OpenFirstThreadForProcess(DProcess* aProcess) { __ASSERT_CRITICAL; // Copied from memspy's DMemSpyDriverOSAdaptionDProcess::OpenFirstThread() // It appears that the system lock needs to be held while manipulating the iThreadQ DThread* result = NULL; NKern::LockSystem(); // We don't use DProcess::FirstThread() as that doesn't appear to do any checking of whether the list is empty, ie if there are no threads at all SDblQueLink* threadLink = aProcess->iThreadQ.First(); if (threadLink != NULL && threadLink != &aProcess->iThreadQ.iA) { result = _LOFF(threadLink,DThread,iProcessLink); if (result->Open() != KErrNone) { result = NULL; } } NKern::UnlockSystem(); return result; }
/** Handle the requests for this channel. @param aFunction The operation the LDD should perform. @param a1 The first argument for the operation. @param a2 The second argument for the operation. @return KErrNone on success or one of the system wide error codes. */ TInt DDefragChannel::Request(TInt aFunction, TAny* a1, TAny* a2) { TInt r = KErrNone; NKern::ThreadEnterCS(); Kern::SemaphoreWait(*iDefragSemaphore); if (!iDefragDfcFree && aFunction != RDefragChannel::EControlGeneralDefragDfcComplete) {// Only allow a single defrag operation at a time. r = KErrInUse; goto exit; } switch (aFunction) { case RDefragChannel::EControlGeneralDefragDfc: // Queue a defrag operation so that on completion it queues a // DFC on this driver. iRequestThread = &Kern::CurrentThread(); iRequestThread->Open(); // Open a reference on this channel to stop the destructor running before // the defrag request has completed. Open(); r = iCompleteReq->SetStatus((TRequestStatus*)a1); if (r == KErrNone) r = iDefragReq.DefragRam(&iDefragCompleteDfc, KDefragRamThreadPriority); if (r != KErrNone) {// defrag operation didn't start so close all openned handles AsyncClose(); iRequestThread->AsyncClose(); iRequestThread = NULL; } else iDefragDfcFree = EFalse; break; case RDefragChannel::EControlGeneralDefragDfcComplete: if (iRequestThread != NULL) {// The defrag dfc hasn't completed so this shouldn't have been invoked. r = KErrGeneral; } else { iDefragDfcFree = ETrue; } break; case RDefragChannel::EControlGeneralDefragSem: {// Queue a defrag operation so that it will signal a fast mutex once // it has completed. NFastSemaphore sem; NKern::FSSetOwner(&sem, 0); r = iDefragReq.DefragRam(&sem, KDefragRamThreadPriority); if (r != KErrNone) {// Error occurred attempting to queue the defrag operation. break; } // Defrag operation has now been queued so wait for it to finish. // Could do some extra kernel side work here before waiting on the // semaphore. NKern::FSWait(&sem); r = iDefragReq.Result(); } break; case RDefragChannel::EControlGeneralDefrag: // Synchronously perform a defrag. { r = iDefragReq.DefragRam(KDefragRamThreadPriority); } break; case RDefragChannel::EControlAllocLowestZone: // Allocate from the lowest preference zone r = DoAllocLowestZone(); break; case RDefragChannel::EControlClaimLowestZone: // Claims the lowest preference zone r = DoClaimLowestZone(); break; case RDefragChannel::EControlCloseChunk: // Have finished with the chunk so close it then free the RAM mapped by it r = DoChunkClose(); TRACE( if (r != KErrNone) {Kern::Printf("ChunkClose returns %d", r);}); break; default: r=KErrNotSupported; break; }