sl@0: // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\thread\smpsafe.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: IMPORT_C void DoNothingA(); sl@0: IMPORT_C void DoNothingB(); sl@0: IMPORT_C void DoNothingC(); sl@0: IMPORT_C void DoNothingD(); sl@0: IMPORT_C void DoNothingE(); sl@0: sl@0: #ifdef MAKE_DLL sl@0: sl@0: #ifdef PROVIDE_A sl@0: EXPORT_C void DoNothingA() {} sl@0: #endif sl@0: sl@0: #ifdef PROVIDE_B sl@0: EXPORT_C void DoNothingB() { DoNothingA(); } sl@0: #endif sl@0: sl@0: #ifdef PROVIDE_C sl@0: EXPORT_C void DoNothingC() { DoNothingD(); DoNothingE(); } sl@0: #endif sl@0: sl@0: #ifdef PROVIDE_D sl@0: EXPORT_C void DoNothingD() { DoNothingC(); } sl@0: #endif sl@0: sl@0: #ifdef PROVIDE_E sl@0: EXPORT_C void DoNothingE() { DoNothingC(); } sl@0: #endif sl@0: sl@0: #else // !MAKE_DLL sl@0: sl@0: volatile TInt Affinity; sl@0: RSemaphore Start; sl@0: RSemaphore Stop; sl@0: sl@0: const TInt KLoopTries = 100; sl@0: sl@0: // This gets run in a low priority thread. Each time around the loop it waits to be told to go, sl@0: // then sets Affinity to 0, then tells the other thread it's done. If we're actually locked to sl@0: // the same processor as the main thread, however, then we won't get to run until the other thread sl@0: // waits for the Stop semaphore, and thus Affinity will not get set to 0 until the other thread sl@0: // checked it already. sl@0: TInt AffinitySlave(TAny*) sl@0: { sl@0: for (TInt i = KLoopTries; i>0; --i) sl@0: { sl@0: Start.Wait(); sl@0: Affinity = 0; sl@0: Stop.Signal(); sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CheckAffinity() sl@0: { sl@0: RThread t; sl@0: TInt r = t.Create(_L("AffinitySlave"), AffinitySlave, KDefaultStackSize, NULL, NULL); sl@0: if (r != KErrNone) sl@0: return r; sl@0: sl@0: Start.CreateLocal(0); sl@0: Stop.CreateLocal(0); sl@0: sl@0: TRequestStatus s; sl@0: t.Logon(s); sl@0: t.SetPriority(EPriorityLess); sl@0: t.Resume(); sl@0: sl@0: TInt a = 1; sl@0: for (TInt i = KLoopTries; i>0; --i) sl@0: { sl@0: Affinity = 1; // assume we are locked to a single cpu sl@0: Start.Signal(); // tell the other thread to run sl@0: TUint32 target = User::NTickCount() + 10; sl@0: while (User::NTickCount() < target) sl@0: { sl@0: // spin, waiting to see if the other thread actually *does* run sl@0: } sl@0: a = Affinity; sl@0: if (a == 0) sl@0: break; sl@0: Stop.Wait(); // We didn't see it this time, but try again in case of scheduling fluke sl@0: } sl@0: sl@0: t.Kill(0); sl@0: User::WaitForRequest(s); sl@0: t.Close(); sl@0: sl@0: return a; sl@0: } sl@0: sl@0: #ifndef OMIT_MAIN sl@0: GLDEF_C TInt E32Main() sl@0: { sl@0: #ifdef USE_A sl@0: DoNothingA(); sl@0: #endif sl@0: #ifdef USE_B sl@0: DoNothingB(); sl@0: #endif sl@0: return CheckAffinity(); sl@0: } sl@0: #endif // OMIT_MAIN sl@0: sl@0: #endif