--- a/kerneltest/e32test/thread/smpsafe.cpp Wed Dec 23 11:43:31 2009 +0000
+++ b/kerneltest/e32test/thread/smpsafe.cpp Thu Jan 07 13:38:45 2010 +0200
@@ -49,41 +49,62 @@
#else // !MAKE_DLL
-TInt Affinity;
+volatile TInt Affinity;
+RSemaphore Start;
+RSemaphore Stop;
+
+const TInt KLoopTries = 100;
+// This gets run in a low priority thread. Each time around the loop it waits to be told to go,
+// then sets Affinity to 0, then tells the other thread it's done. If we're actually locked to
+// the same processor as the main thread, however, then we won't get to run until the other thread
+// waits for the Stop semaphore, and thus Affinity will not get set to 0 until the other thread
+// checked it already.
TInt AffinitySlave(TAny*)
{
- for (;;)
+ for (TInt i = KLoopTries; i>0; --i)
{
- __e32_atomic_store_rel32(&Affinity, 0); // we can't be locked if this runs
- User::AfterHighRes(1);
+ Start.Wait();
+ Affinity = 0;
+ Stop.Signal();
}
+ return KErrNone;
}
TInt CheckAffinity()
{
- __e32_atomic_store_rel32(&Affinity, 1); // assume we are locked to a single cpu
-
RThread t;
TInt r = t.Create(_L("AffinitySlave"), AffinitySlave, KDefaultStackSize, NULL, NULL);
if (r != KErrNone)
return r;
+ Start.CreateLocal(0);
+ Stop.CreateLocal(0);
+
TRequestStatus s;
t.Logon(s);
t.SetPriority(EPriorityLess);
t.Resume();
- TUint32 target = User::NTickCount() + 10;
- while (User::NTickCount() < target) {}
-
- r = __e32_atomic_load_acq32(&Affinity);
+ for (TInt i = KLoopTries; i>0; --i)
+ {
+ Affinity = 1; // assume we are locked to a single cpu
+ Start.Signal(); // tell the other thread to run
+ TUint32 target = User::NTickCount() + 10;
+ while (User::NTickCount() < target)
+ {
+ // spin, waiting to see if the other thread actually *does* run
+ }
+ if (Affinity == 0)
+ break;
+ Stop.Wait(); // We didn't see it this time, but try again in case of scheduling fluke
+ }
t.Kill(0);
User::WaitForRequest(s);
t.Close();
- return r;
+ return Affinity;
}
#ifndef OMIT_MAIN