diff -r 000000000000 -r 7f656887cf89 commands/setpriority/setpriority.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commands/setpriority/setpriority.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,240 @@ +// setpriority.cpp +// +// Copyright (c) 2008 - 2010 Accenture. All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Accenture - Initial contribution +// + +#include + +using namespace IoUtils; + +class CCmdSetpriority; +class CNewThreadNotifier : public CActive + { +public: + CNewThreadNotifier(CCmdSetpriority& aCmd, RMemoryAccess& aMemAccess); + void Start(); + ~CNewThreadNotifier(); + void DoCancel(); + void RunL(); + +private: + CCmdSetpriority& iCmd; + RMemoryAccess& iMemAccess; + }; + +class CCmdSetpriority : public CMemoryAccessCommandBase + { +public: + static CCommandBase* NewLC(); + ~CCmdSetpriority(); + void NewThread(TInt aHandle); +private: + CCmdSetpriority(); +private: // From CCommandBase. + virtual const TDesC& Name() const; + virtual void DoRunL(); + virtual void ArgumentsL(RCommandArgumentList& aArguments); + virtual void OptionsL(RCommandOptionList& aOptions); +private: + RArray iTids; + RArray iPids; + TInt iPriority; + HBufC* iName; + TProcessKernelInfo iProcInfo; + TThreadKernelInfo iThreadInfo; + CNewThreadNotifier* iNotifier; + }; + + +CCommandBase* CCmdSetpriority::NewLC() + { + CCmdSetpriority* self = new(ELeave) CCmdSetpriority(); + CleanupStack::PushL(self); + self->BaseConstructL(); + return self; + } + +CCmdSetpriority::~CCmdSetpriority() + { + delete iNotifier; + delete iName; + iTids.Close(); + iPids.Close(); + } + +CCmdSetpriority::CCmdSetpriority() + : CMemoryAccessCommandBase(EManualComplete) + { + } + +const TDesC& CCmdSetpriority::Name() const + { + _LIT(KName, "setpriority"); + return KName; + } + +void CCmdSetpriority::ArgumentsL(RCommandArgumentList& aArguments) + { + aArguments.AppendIntL(iPriority, _L("priority")); + } + +void CCmdSetpriority::OptionsL(RCommandOptionList& aOptions) + { + aOptions.AppendStringL(iName, _L("match")); + aOptions.AppendUintL(iPids, _L("pid")); + aOptions.AppendUintL(iTids, _L("tid")); + } + + +EXE_BOILER_PLATE(CCmdSetpriority) + +void CCmdSetpriority::DoRunL() + { + LoadMemoryAccessL(); + TInt err = KErrNone; + + // Fix up priorities that we had to make different to kernel cos fshell can't handle negative arguments + // See enum TThrdPriority in kern_priv.h for the meaning of these negative numbers + switch(iPriority) + { + case 101: iPriority = -8; break; + case 102: iPriority = -7; break; + case 103: iPriority = -6; break; + case 104: iPriority = -5; break; + case 105: iPriority = -4; break; + case 106: iPriority = -3; break; + case 107: iPriority = -2; break; + default: + break; + } + + if (iName) + { + TPtrC8 name8 = iName->Des().Collapse(); + LeaveIfErr(iMemAccess.SetPriorityOverride(iPriority, name8), _L("Couldn't set priority override")); + iNotifier = new(ELeave) CNewThreadNotifier(*this, iMemAccess); + iNotifier->Start(); + return; + } + + if (iTids.Count() && iPids.Count()) + { + LeaveIfErr(KErrArgument, _L("You cannot specify both --tid and --pid - a single priority cannot be valid for thread and process.")); + } + + for (TInt i = 0; i < iTids.Count(); i++) + { + TUint id = iTids[i]; + RThread thread; + err = iMemAccess.RThreadForceOpen(thread, id); + if (!err) err = iMemAccess.SetThreadPriority(thread, iPriority); + if (err) PrintError(err, _L("Couldn't set priority for thread %u"), id); + thread.Close(); + } + + for (TInt i = 0; i < iPids.Count(); i++) + { + TUint id = iPids[i]; + // Get KProcessFlagPriorityControl flag + RProcess process; + err = process.Open(id); + LeaveIfErr(err, _L("Couldn't open process with ID %u"), id); + + TBool priorityControlAllowed = EFalse; + TPckg pkg(iProcInfo); + err = iMemAccess.GetObjectInfoByHandle(EProcess, RThread().Id(), process.Handle(), pkg); + if (err) + { + PrintWarning(_L("Couldn't get priority control flag setting (%d)\r\n"), err); + } + else + { + if (iProcInfo.iFlags & KProcessFlagPriorityControl) priorityControlAllowed = ETrue; + } + + if (!priorityControlAllowed) + { + PrintError(KErrAccessDenied, _L("This process does not allow setting of its priority")); + } + else if (iPriority != EPriorityBackground && iPriority != EPriorityForeground) + { + PrintError(KErrAccessDenied, _L("The kernel will ignore requests to set a process priority that isn't Background (250) or Foreground (350). I can't see how to get round this even using memory access. Sorry.")); + } + process.SetPriority((TProcessPriority)iPriority); + process.Close(); + } + Complete(KErrNone); + } + +void CCmdSetpriority::NewThread(TInt aHandle) + { + if (aHandle == KErrNotSupported) + { + PrintError(KErrNotSupported, _L("Kernel was not compiled with __DEBUGGER_SUPPORT__, can't get thread creation notifications.")); + Complete(aHandle); + } + else if (aHandle < 0) + { + PrintError(aHandle, _L("Failed to get new thread notification, or couldn't open handle to thread.")); + Complete(aHandle); + } + else + { + RThread thread; + thread.SetHandle(aHandle); + TFullName name(thread.FullName()); + TInt priority = 0; + TPckg pkg(iThreadInfo); + TInt err = iMemAccess.GetObjectInfoByHandle(EThread, RThread().Id(), aHandle, pkg); + if (!err) + { + priority = iThreadInfo.iThreadPriority; + } + + TUint tid = thread.Id(); + Printf(_L("New thread id %u name %S priority adjusted to %d\r\n"), tid, &name, priority); + thread.Close(); + } + } + +CNewThreadNotifier::CNewThreadNotifier(CCmdSetpriority& aCmd, RMemoryAccess& aMemAccess) + : CActive(CActive::EPriorityStandard), iCmd(aCmd), iMemAccess(aMemAccess) + { + CActiveScheduler::Add(this); + } + +CNewThreadNotifier::~CNewThreadNotifier() + { + Cancel(); + } + +void CNewThreadNotifier::DoCancel() + { + iMemAccess.CancelNotifyThreadCreation(); + } + +void CNewThreadNotifier::RunL() + { + TInt stat = iStatus.Int(); + if (stat >= 0) + { + Start(); + } + iCmd.NewThread(stat); + } + +void CNewThreadNotifier::Start() + { + if (!IsActive()) + { + iMemAccess.NotifyThreadCreation(iStatus); + SetActive(); + } + }