--- /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 <fshell/memoryaccesscmd.h>
+
+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<TUint> iTids;
+ RArray<TUint> 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<TProcessKernelInfo> 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<TThreadKernelInfo> 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();
+ }
+ }