kerneltest/e32test/thread/smpsafe.cpp
changeset 33 0173bcd7697c
parent 0 a41df078684a
child 36 538db54a451d
equal deleted inserted replaced
31:56f325a607ea 33:0173bcd7697c
    47 EXPORT_C void DoNothingE() { DoNothingC(); }
    47 EXPORT_C void DoNothingE() { DoNothingC(); }
    48 #endif
    48 #endif
    49 
    49 
    50 #else // !MAKE_DLL
    50 #else // !MAKE_DLL
    51 
    51 
    52 TInt Affinity;
    52 volatile TInt Affinity;
       
    53 RSemaphore Start;
       
    54 RSemaphore Stop;
    53 
    55 
       
    56 const TInt KLoopTries = 100;
       
    57 
       
    58 // This gets run in a low priority thread. Each time around the loop it waits to be told to go,
       
    59 // then sets Affinity to 0, then tells the other thread it's done. If we're actually locked to
       
    60 // the same processor as the main thread, however, then we won't get to run until the other thread
       
    61 // waits for the Stop semaphore, and thus Affinity will not get set to 0 until the other thread
       
    62 // checked it already.
    54 TInt AffinitySlave(TAny*)
    63 TInt AffinitySlave(TAny*)
    55 	{
    64 	{
    56 	for (;;)
    65 	for (TInt i = KLoopTries; i>0; --i)
    57 		{
    66 		{
    58 		__e32_atomic_store_rel32(&Affinity, 0); // we can't be locked if this runs
    67 		Start.Wait();
    59 		User::AfterHighRes(1);
    68 		Affinity = 0;
       
    69 		Stop.Signal();
    60 		}
    70 		}
       
    71 	return KErrNone;
    61 	}
    72 	}
    62 
    73 
    63 TInt CheckAffinity()
    74 TInt CheckAffinity()
    64 	{
    75 	{
    65 	__e32_atomic_store_rel32(&Affinity, 1); // assume we are locked to a single cpu
       
    66 
       
    67 	RThread t;
    76 	RThread t;
    68 	TInt r = t.Create(_L("AffinitySlave"), AffinitySlave, KDefaultStackSize, NULL, NULL);
    77 	TInt r = t.Create(_L("AffinitySlave"), AffinitySlave, KDefaultStackSize, NULL, NULL);
    69 	if (r != KErrNone)
    78 	if (r != KErrNone)
    70 		return r;
    79 		return r;
       
    80 
       
    81 	Start.CreateLocal(0);
       
    82 	Stop.CreateLocal(0);
    71 
    83 
    72 	TRequestStatus s;
    84 	TRequestStatus s;
    73 	t.Logon(s);
    85 	t.Logon(s);
    74 	t.SetPriority(EPriorityLess);
    86 	t.SetPriority(EPriorityLess);
    75 	t.Resume();
    87 	t.Resume();
    76 
    88 
    77 	TUint32 target = User::NTickCount() + 10;
    89 	for (TInt i = KLoopTries; i>0; --i)
    78 	while (User::NTickCount() < target) {}
    90 		{
    79 
    91 		Affinity = 1; // assume we are locked to a single cpu
    80 	r = __e32_atomic_load_acq32(&Affinity);
    92 		Start.Signal(); // tell the other thread to run
       
    93 		TUint32 target = User::NTickCount() + 10;
       
    94 		while (User::NTickCount() < target)
       
    95 			{
       
    96 			// spin, waiting to see if the other thread actually *does* run
       
    97 			}
       
    98 		if (Affinity == 0)
       
    99 			break;
       
   100 		Stop.Wait(); // We didn't see it this time, but try again in case of scheduling fluke
       
   101 		}
    81 
   102 
    82 	t.Kill(0);
   103 	t.Kill(0);
    83 	User::WaitForRequest(s);
   104 	User::WaitForRequest(s);
    84 	t.Close();
   105 	t.Close();
    85 
   106 
    86 	return r;
   107 	return Affinity;
    87 	}
   108 	}
    88 
   109 
    89 #ifndef OMIT_MAIN
   110 #ifndef OMIT_MAIN
    90 GLDEF_C TInt E32Main()
   111 GLDEF_C TInt E32Main()
    91 	{
   112 	{