commands/spinlock/spinlock.cpp
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/spinlock/spinlock.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,146 @@
+// spinlock.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>
+#include <fshell/ioutils.h>
+#include <HAL.H>
+
+using namespace IoUtils;
+
+class CCmdSpinlock : public CMemoryAccessCommandBase
+	{
+public:
+	static CCommandBase* NewLC();
+	~CCmdSpinlock();
+private:
+	CCmdSpinlock();
+private: // From CCommandBase.
+	virtual const TDesC& Name() const;
+	virtual void DoRunL();
+	virtual void ArgumentsL(RCommandArgumentList& aArguments);
+	virtual void OptionsL(RCommandOptionList& aOptions);
+private:
+	TInt iStartIn;
+	TInt iDuration;
+	TInt iLoad;
+	TInt iPriority;
+	volatile TInt iCounter;
+	};
+
+
+CCommandBase* CCmdSpinlock::NewLC()
+	{
+	CCmdSpinlock* self = new(ELeave) CCmdSpinlock();
+	CleanupStack::PushL(self);
+	self->BaseConstructL();
+	return self;
+	}
+
+CCmdSpinlock::~CCmdSpinlock()
+	{
+	}
+
+CCmdSpinlock::CCmdSpinlock()
+	{
+	}
+
+const TDesC& CCmdSpinlock::Name() const
+	{
+	_LIT(KName, "spinlock");
+	return KName;
+	}
+
+void CCmdSpinlock::ArgumentsL(RCommandArgumentList& aArguments)
+	{
+	aArguments.AppendIntL(iLoad, _L("load"));
+	}
+
+void CCmdSpinlock::OptionsL(RCommandOptionList& aOptions)
+	{
+	aOptions.AppendIntL(iStartIn, _L("start-after"));
+	aOptions.AppendIntL(iDuration, _L("duration"));
+	aOptions.AppendIntL(iPriority, _L("priority"));
+	}
+
+EXE_BOILER_PLATE(CCmdSpinlock)
+
+void CCmdSpinlock::DoRunL()
+	{
+	if (iPriority)
+		{
+#ifdef FSHELL_MEMORY_ACCESS_SUPPORT
+		LoadMemoryAccessL();
+
+		RThread me;
+		CleanupClosePushL(me);
+		LeaveIfErr(me.Open(me.Id()), _L("Couldn't open myself (!?!)"));
+		LeaveIfErr(iMemAccess.SetThreadPriority(me, iPriority), _L("Couldn't set priority"));
+		CleanupStack::PopAndDestroy(&me);
+#else
+		PrintWarning(_L("--priority is not supported if memoryaccess is not available."));
+#endif
+		}
+
+	if (iStartIn)
+		{
+		Printf(_L("Starting in %d seconds...\r\n"), iStartIn);
+		User::After(iStartIn * 1000000);
+		}
+
+	if (iDuration)
+		{
+		Printf(_L("Starting to spin for %d seconds... (Press CTRL-C to exit earlier)\r\n"), iDuration);
+		}
+	else
+		{
+		Printf(_L("Starting to spin... (Press CTRL-C to exit)\r\n"));
+		}
+
+	// We have ~300,000 cycles per millisecond to play with. We will do some amount of work then wait a millisecond.
+	// This is pretty arbitrary.
+
+	TInt tickPeriod;
+	HAL::Get(HAL::ENanoTickPeriod, tickPeriod);
+
+	TInt endTime; // in nkern ticks
+	if (iDuration)
+		{
+		endTime = User::NTickCount() + (iDuration * 1000000)/tickPeriod;
+		}
+	else
+		{
+		endTime = KMaxTInt;
+		}
+
+	if (iLoad)
+		{
+		//TODO this loop needs sorting out. The User::After is a bit broken.
+		TInt n = iLoad * 1000;
+		while (User::NTickCount() < (TUint)endTime)
+			{
+			for (iCounter = 0; iCounter < n; iCounter++)
+				{
+				// Let's do an exec call just for fun
+				UserSvr::DebugMask(0);
+				}
+
+			User::After(1000); // Wait 1 ms
+			}
+		}
+	else
+		{
+		// Just spin
+		while (User::NTickCount() < (TUint)endTime)
+			{
+			}
+		}
+	}