commands/setpriority/setpriority.cpp
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // setpriority.cpp
       
     2 // 
       
     3 // Copyright (c) 2008 - 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "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 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 #include <fshell/memoryaccesscmd.h>
       
    14 
       
    15 using namespace IoUtils;
       
    16 
       
    17 class CCmdSetpriority;
       
    18 class CNewThreadNotifier : public CActive
       
    19 	{
       
    20 public:
       
    21 	CNewThreadNotifier(CCmdSetpriority& aCmd, RMemoryAccess& aMemAccess);
       
    22 	void Start();
       
    23 	~CNewThreadNotifier();
       
    24 	void DoCancel();
       
    25 	void RunL();
       
    26 
       
    27 private:
       
    28 	CCmdSetpriority& iCmd;
       
    29 	RMemoryAccess& iMemAccess;
       
    30 	};
       
    31 
       
    32 class CCmdSetpriority : public CMemoryAccessCommandBase
       
    33 	{
       
    34 public:
       
    35 	static CCommandBase* NewLC();
       
    36 	~CCmdSetpriority();
       
    37 	void NewThread(TInt aHandle);
       
    38 private:
       
    39 	CCmdSetpriority();
       
    40 private: // From CCommandBase.
       
    41 	virtual const TDesC& Name() const;
       
    42 	virtual void DoRunL();
       
    43 	virtual void ArgumentsL(RCommandArgumentList& aArguments);
       
    44 	virtual void OptionsL(RCommandOptionList& aOptions);
       
    45 private:
       
    46 	RArray<TUint> iTids;
       
    47 	RArray<TUint> iPids;
       
    48 	TInt iPriority;
       
    49 	HBufC* iName;
       
    50 	TProcessKernelInfo iProcInfo;
       
    51 	TThreadKernelInfo iThreadInfo;
       
    52 	CNewThreadNotifier* iNotifier;
       
    53 	};
       
    54 
       
    55 
       
    56 CCommandBase* CCmdSetpriority::NewLC()
       
    57 	{
       
    58 	CCmdSetpriority* self = new(ELeave) CCmdSetpriority();
       
    59 	CleanupStack::PushL(self);
       
    60 	self->BaseConstructL();
       
    61 	return self;
       
    62 	}
       
    63 
       
    64 CCmdSetpriority::~CCmdSetpriority()
       
    65 	{
       
    66 	delete iNotifier;
       
    67 	delete iName;
       
    68 	iTids.Close();
       
    69 	iPids.Close();
       
    70 	}
       
    71 
       
    72 CCmdSetpriority::CCmdSetpriority()
       
    73 	: CMemoryAccessCommandBase(EManualComplete)
       
    74 	{
       
    75 	}
       
    76 
       
    77 const TDesC& CCmdSetpriority::Name() const
       
    78 	{
       
    79 	_LIT(KName, "setpriority");
       
    80 	return KName;
       
    81 	}
       
    82 
       
    83 void CCmdSetpriority::ArgumentsL(RCommandArgumentList& aArguments)
       
    84 	{
       
    85 	aArguments.AppendIntL(iPriority, _L("priority"));
       
    86 	}
       
    87 
       
    88 void CCmdSetpriority::OptionsL(RCommandOptionList& aOptions)
       
    89 	{
       
    90 	aOptions.AppendStringL(iName, _L("match"));
       
    91 	aOptions.AppendUintL(iPids, _L("pid"));
       
    92 	aOptions.AppendUintL(iTids, _L("tid"));
       
    93 	}
       
    94 
       
    95 
       
    96 EXE_BOILER_PLATE(CCmdSetpriority)
       
    97 
       
    98 void CCmdSetpriority::DoRunL()
       
    99 	{
       
   100 	LoadMemoryAccessL();
       
   101 	TInt err = KErrNone;
       
   102 
       
   103 	// Fix up priorities that we had to make different to kernel cos fshell can't handle negative arguments
       
   104 	// See enum TThrdPriority in kern_priv.h for the meaning of these negative numbers
       
   105 	switch(iPriority)
       
   106 		{
       
   107 		case 101: iPriority = -8; break;
       
   108 		case 102: iPriority = -7; break;
       
   109 		case 103: iPriority = -6; break;
       
   110 		case 104: iPriority = -5; break;
       
   111 		case 105: iPriority = -4; break;
       
   112 		case 106: iPriority = -3; break;
       
   113 		case 107: iPriority = -2; break;
       
   114 		default:
       
   115 			break;
       
   116 		}
       
   117 
       
   118 	if (iName)
       
   119 		{
       
   120 		TPtrC8 name8 = iName->Des().Collapse();
       
   121 		LeaveIfErr(iMemAccess.SetPriorityOverride(iPriority, name8), _L("Couldn't set priority override"));
       
   122 		iNotifier = new(ELeave) CNewThreadNotifier(*this, iMemAccess);
       
   123 		iNotifier->Start();
       
   124 		return;
       
   125 		}
       
   126 	
       
   127 	if (iTids.Count() && iPids.Count())
       
   128 		{
       
   129 		LeaveIfErr(KErrArgument, _L("You cannot specify both --tid and --pid - a single priority cannot be valid for thread and process."));
       
   130 		}
       
   131 
       
   132 	for (TInt i = 0; i < iTids.Count(); i++)
       
   133 		{
       
   134 		TUint id = iTids[i];
       
   135 		RThread thread;
       
   136 		err = iMemAccess.RThreadForceOpen(thread, id);
       
   137 		if (!err) err = iMemAccess.SetThreadPriority(thread, iPriority);
       
   138 		if (err) PrintError(err, _L("Couldn't set priority for thread %u"), id);
       
   139 		thread.Close();
       
   140 		}
       
   141 	
       
   142 	for (TInt i = 0; i < iPids.Count(); i++)
       
   143 		{
       
   144 		TUint id = iPids[i];
       
   145 		// Get KProcessFlagPriorityControl flag
       
   146 		RProcess process;
       
   147 		err = process.Open(id);
       
   148 		LeaveIfErr(err, _L("Couldn't open process with ID %u"), id);
       
   149 
       
   150 		TBool priorityControlAllowed = EFalse;
       
   151 		TPckg<TProcessKernelInfo> pkg(iProcInfo);
       
   152 		err = iMemAccess.GetObjectInfoByHandle(EProcess, RThread().Id(), process.Handle(), pkg);
       
   153 		if (err)
       
   154 			{
       
   155 			PrintWarning(_L("Couldn't get priority control flag setting (%d)\r\n"), err);
       
   156 			}
       
   157 		else
       
   158 			{
       
   159 			if (iProcInfo.iFlags & KProcessFlagPriorityControl) priorityControlAllowed = ETrue;
       
   160 			}
       
   161 
       
   162 		if (!priorityControlAllowed)
       
   163 			{
       
   164 			PrintError(KErrAccessDenied, _L("This process does not allow setting of its priority"));
       
   165 			}
       
   166 		else if (iPriority != EPriorityBackground && iPriority != EPriorityForeground)
       
   167 			{
       
   168 			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."));
       
   169 			}
       
   170 		process.SetPriority((TProcessPriority)iPriority);
       
   171 		process.Close();
       
   172 		}
       
   173 	Complete(KErrNone);
       
   174 	}
       
   175 
       
   176 void CCmdSetpriority::NewThread(TInt aHandle)
       
   177 	{
       
   178 	if (aHandle == KErrNotSupported)
       
   179 		{
       
   180 		PrintError(KErrNotSupported, _L("Kernel was not compiled with __DEBUGGER_SUPPORT__, can't get thread creation notifications."));
       
   181 		Complete(aHandle);
       
   182 		}
       
   183 	else if (aHandle < 0)
       
   184 		{
       
   185 		PrintError(aHandle, _L("Failed to get new thread notification, or couldn't open handle to thread."));
       
   186 		Complete(aHandle);
       
   187 		}
       
   188 	else
       
   189 		{
       
   190 		RThread thread;
       
   191 		thread.SetHandle(aHandle);
       
   192 		TFullName name(thread.FullName());
       
   193 		TInt priority = 0;
       
   194 		TPckg<TThreadKernelInfo> pkg(iThreadInfo);
       
   195 		TInt err = iMemAccess.GetObjectInfoByHandle(EThread, RThread().Id(), aHandle, pkg);
       
   196 		if (!err)
       
   197 			{
       
   198 			priority = iThreadInfo.iThreadPriority;
       
   199 			}
       
   200 
       
   201 		TUint tid = thread.Id();
       
   202 		Printf(_L("New thread id %u name %S priority adjusted to %d\r\n"), tid, &name, priority);
       
   203 		thread.Close();
       
   204 		}
       
   205 	}
       
   206 
       
   207 CNewThreadNotifier::CNewThreadNotifier(CCmdSetpriority& aCmd, RMemoryAccess& aMemAccess)
       
   208 	: CActive(CActive::EPriorityStandard), iCmd(aCmd), iMemAccess(aMemAccess)
       
   209 	{
       
   210 	CActiveScheduler::Add(this);
       
   211 	}
       
   212 
       
   213 CNewThreadNotifier::~CNewThreadNotifier()
       
   214 	{
       
   215 	Cancel();
       
   216 	}
       
   217 
       
   218 void CNewThreadNotifier::DoCancel()
       
   219 	{
       
   220 	iMemAccess.CancelNotifyThreadCreation();
       
   221 	}
       
   222 
       
   223 void CNewThreadNotifier::RunL()
       
   224 	{
       
   225 	TInt stat = iStatus.Int();
       
   226 	if (stat >= 0)
       
   227 		{
       
   228 		Start();
       
   229 		}
       
   230 	iCmd.NewThread(stat);
       
   231 	}
       
   232 
       
   233 void CNewThreadNotifier::Start()
       
   234 	{
       
   235 	if (!IsActive())
       
   236 		{
       
   237 		iMemAccess.NotifyThreadCreation(iStatus);
       
   238 		SetActive();
       
   239 		}
       
   240 	}