1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /*============================================================ |
6 | ** |
7 | ** Source : test.c |
8 | ** |
9 | ** Purpose: Test for InterlockedCompareExchange() function using multiple threads |
10 | ** |
11 | ** |
12 | **=========================================================*/ |
13 | |
14 | |
15 | |
16 | #include <palsuite.h> |
17 | |
18 | #define MAX_THREADS 10 |
19 | #define REPEAT_COUNT 10 |
20 | |
21 | //Global Variable Declaration |
22 | LONG g_Total = 0; |
23 | LONG Lock=0; |
24 | |
25 | |
26 | void ModifyGlobalResource(void); |
27 | void AcquireLock(PLONG pLock); |
28 | void ReleaseLock(PLONG pLock); |
29 | |
30 | |
31 | |
32 | //Main entry point of the program |
33 | int __cdecl main(int argc, char *argv[]) { |
34 | |
35 | int i = 0; |
36 | DWORD dwThreadID=0; |
37 | LONG totalOperations = 0; |
38 | |
39 | HANDLE hThread[MAX_THREADS]; |
40 | |
41 | /* |
42 | * Initialize the PAL and return FAILURE if this fails |
43 | */ |
44 | |
45 | if(0 != (PAL_Initialize(argc, argv))) |
46 | { |
47 | return FAIL; |
48 | } |
49 | |
50 | |
51 | totalOperations = MAX_THREADS * REPEAT_COUNT; |
52 | |
53 | |
54 | //Create MAX_THREADS threads that will operate on the global counter |
55 | for (i=0;i<MAX_THREADS;i++) |
56 | { |
57 | hThread[i] = CreateThread( |
58 | NULL, // default security attributes |
59 | 0, // use default stack size |
60 | (LPTHREAD_START_ROUTINE) ModifyGlobalResource, // thread function |
61 | NULL, // argument to thread function |
62 | 0, // use default creation flags |
63 | &dwThreadID); // returns the thread identifier |
64 | |
65 | // Check the return value for success. |
66 | |
67 | if (hThread[i] == NULL) |
68 | { |
69 | Fail("ERROR: Was not able to create thread\n" |
70 | "GetLastError returned %d\n" , GetLastError()); |
71 | } |
72 | |
73 | } |
74 | |
75 | |
76 | //Wait for all threads to finish |
77 | for (i=0;i<MAX_THREADS;i++) |
78 | { |
79 | |
80 | if (WAIT_OBJECT_0 != WaitForSingleObject (hThread[i], INFINITE)) |
81 | { |
82 | Fail ("Main: Wait for Single Object failed. Failing test.\n" |
83 | "GetLastError returned %d\n" , GetLastError()); |
84 | } |
85 | |
86 | } |
87 | |
88 | |
89 | if (0!= g_Total) |
90 | { |
91 | Fail("Test Failed \n" ); |
92 | } |
93 | |
94 | Trace("Global Counter Value at the end of the test %d \n" , g_Total); |
95 | |
96 | /* |
97 | * Terminate PAL |
98 | */ |
99 | |
100 | PAL_Terminate(); |
101 | return PASS; |
102 | } |
103 | |
104 | |
105 | void ModifyGlobalResource(void) |
106 | { |
107 | |
108 | int i =0; |
109 | |
110 | for (i=0;i<REPEAT_COUNT;i++) |
111 | { |
112 | |
113 | /* |
114 | Acquire Lock Provides Synchronization Around g_Total global variable |
115 | */ |
116 | |
117 | AcquireLock(&Lock); |
118 | |
119 | /* |
120 | The following set of operations is guaranteed to be atomic by virtue of the fact |
121 | that InterLockedCompareExchange was able to guarantee that the compare |
122 | and exchange operation on pLock was thread safe. If the same set of code was |
123 | executed without using InterlockedCompareExchange the code would fail most of |
124 | time. |
125 | |
126 | */ |
127 | g_Total++; |
128 | Sleep(100); |
129 | g_Total--; |
130 | if (0!=g_Total) |
131 | { |
132 | Fail("Test Failed beacuse g_Total was not protected \n" ); |
133 | } |
134 | |
135 | |
136 | /* |
137 | Acquire Lock releases the lock around g_Total Global variable |
138 | */ |
139 | |
140 | ReleaseLock(&Lock); |
141 | } |
142 | |
143 | |
144 | } |
145 | |
146 | |
147 | void AcquireLock(PLONG pLock) |
148 | { |
149 | //Spin Lock implemented with the help of InterlockedCompareExchange |
150 | |
151 | |
152 | while(1) |
153 | { |
154 | if (InterlockedCompareExchange(pLock,1,0)==0) |
155 | break; |
156 | } |
157 | |
158 | } |
159 | |
160 | |
161 | void ReleaseLock(PLONG pLock) |
162 | { |
163 | |
164 | |
165 | MemoryBarrier(); |
166 | *pLock = 0; |
167 | } |
168 | |
169 | |