diff -r 96e5fb8b040d -r 36bfc973b146 kerneltest/e32test/thread/smpsafe.cpp --- a/kerneltest/e32test/thread/smpsafe.cpp Thu Dec 17 09:24:54 2009 +0200 +++ 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