aboutsummaryrefslogtreecommitdiff
path: root/C/Threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'C/Threads.c')
-rw-r--r--C/Threads.c237
1 files changed, 234 insertions, 3 deletions
diff --git a/C/Threads.c b/C/Threads.c
index 464efec..177d1d9 100644
--- a/C/Threads.c
+++ b/C/Threads.c
@@ -1,5 +1,5 @@
1/* Threads.c -- multithreading library 1/* Threads.c -- multithreading library
22024-03-28 : Igor Pavlov : Public domain */ 2: Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -59,6 +59,100 @@ WRes Thread_Wait_Close(CThread *p)
59 return (res != 0 ? res : res2); 59 return (res != 0 ? res : res2);
60} 60}
61 61
62typedef struct MY_PROCESSOR_NUMBER {
63 WORD Group;
64 BYTE Number;
65 BYTE Reserved;
66} MY_PROCESSOR_NUMBER, *MY_PPROCESSOR_NUMBER;
67
68typedef struct MY_GROUP_AFFINITY {
69#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION < 100000)
70 // KAFFINITY is not defined in old mingw
71 ULONG_PTR
72#else
73 KAFFINITY
74#endif
75 Mask;
76 WORD Group;
77 WORD Reserved[3];
78} MY_GROUP_AFFINITY, *MY_PGROUP_AFFINITY;
79
80typedef BOOL (WINAPI *Func_SetThreadGroupAffinity)(
81 HANDLE hThread,
82 CONST MY_GROUP_AFFINITY *GroupAffinity,
83 MY_PGROUP_AFFINITY PreviousGroupAffinity);
84
85typedef BOOL (WINAPI *Func_GetThreadGroupAffinity)(
86 HANDLE hThread,
87 MY_PGROUP_AFFINITY GroupAffinity);
88
89typedef BOOL (WINAPI *Func_GetProcessGroupAffinity)(
90 HANDLE hProcess,
91 PUSHORT GroupCount,
92 PUSHORT GroupArray);
93
94Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
95
96#if 0
97#include <stdio.h>
98#define PRF(x) x
99/*
100--
101 before call of SetThreadGroupAffinity()
102 GetProcessGroupAffinity return one group.
103 after call of SetThreadGroupAffinity():
104 GetProcessGroupAffinity return more than group,
105 if SetThreadGroupAffinity() was to another group.
106--
107 GetProcessAffinityMask MS DOCs:
108 {
109 If the calling process contains threads in multiple groups,
110 the function returns zero for both affinity masks.
111 }
112 but tests in win10 with 2 groups (less than 64 cores total):
113 GetProcessAffinityMask() still returns non-zero affinity masks
114 even after SetThreadGroupAffinity() calls.
115*/
116static void PrintProcess_Info()
117{
118 {
119 const
120 Func_GetProcessGroupAffinity fn_GetProcessGroupAffinity =
121 (Func_GetProcessGroupAffinity) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
122 "GetProcessGroupAffinity");
123 if (fn_GetProcessGroupAffinity)
124 {
125 unsigned i;
126 USHORT GroupCounts[64];
127 USHORT GroupCount = Z7_ARRAY_SIZE(GroupCounts);
128 BOOL boolRes = fn_GetProcessGroupAffinity(GetCurrentProcess(),
129 &GroupCount, GroupCounts);
130 printf("\n====== GetProcessGroupAffinity : "
131 "boolRes=%u GroupCounts = %u :",
132 boolRes, (unsigned)GroupCount);
133 for (i = 0; i < GroupCount; i++)
134 printf(" %u", GroupCounts[i]);
135 printf("\n");
136 }
137 }
138 {
139 DWORD_PTR processAffinityMask, systemAffinityMask;
140 if (GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask))
141 {
142 PRF(printf("\n====== GetProcessAffinityMask : "
143 ": processAffinityMask=%x, systemAffinityMask=%x\n",
144 (UInt32)processAffinityMask, (UInt32)systemAffinityMask);)
145 }
146 else
147 printf("\n==GetProcessAffinityMask FAIL");
148 }
149}
150#else
151#ifndef USE_THREADS_CreateThread
152// #define PRF(x)
153#endif
154#endif
155
62WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) 156WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
63{ 157{
64 /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ 158 /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
@@ -72,7 +166,43 @@ WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
72 166
73 unsigned threadId; 167 unsigned threadId;
74 *p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId)); 168 *p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId));
75 169
170#if 0 // 1 : for debug
171 {
172 DWORD_PTR prevMask;
173 DWORD_PTR affinity = 1 << 0;
174 prevMask = SetThreadAffinityMask(*p, (DWORD_PTR)affinity);
175 prevMask = prevMask;
176 }
177#endif
178#if 0 // 1 : for debug
179 {
180 /* win10: new thread will be created in same group that is assigned to parent thread
181 but affinity mask will contain all allowed threads of that group,
182 even if affinity mask of parent group is not full
183 win11: what group it will be created, if we have set
184 affinity of parent thread with ThreadGroupAffinity?
185 */
186 const
187 Func_GetThreadGroupAffinity fn =
188 (Func_GetThreadGroupAffinity) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
189 "GetThreadGroupAffinity");
190 if (fn)
191 {
192 // BOOL wres2;
193 MY_GROUP_AFFINITY groupAffinity;
194 memset(&groupAffinity, 0, sizeof(groupAffinity));
195 /* wres2 = */ fn(*p, &groupAffinity);
196 PRF(printf("\n==Thread_Create cur = %6u GetThreadGroupAffinity(): "
197 "wres2_BOOL = %u, group=%u mask=%x\n",
198 GetCurrentThreadId(),
199 wres2,
200 groupAffinity.Group,
201 (UInt32)groupAffinity.Mask);)
202 }
203 }
204#endif
205
76 #endif 206 #endif
77 207
78 /* maybe we must use errno here, but probably GetLastError() is also OK. */ 208 /* maybe we must use errno here, but probably GetLastError() is also OK. */
@@ -110,7 +240,84 @@ WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param
110 */ 240 */
111 } 241 }
112 { 242 {
113 DWORD prevSuspendCount = ResumeThread(h); 243 const DWORD prevSuspendCount = ResumeThread(h);
244 /* ResumeThread() returns:
245 0 : was_not_suspended
246 1 : was_resumed
247 -1 : error
248 */
249 if (prevSuspendCount == (DWORD)-1)
250 wres = GetError();
251 }
252 }
253
254 /* maybe we must use errno here, but probably GetLastError() is also OK. */
255 return wres;
256
257 #endif
258}
259
260
261WRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, unsigned group, CAffinityMask affinityMask)
262{
263#ifdef USE_THREADS_CreateThread
264
265 UNUSED_VAR(group)
266 UNUSED_VAR(affinityMask)
267 return Thread_Create(p, func, param);
268
269#else
270
271 /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
272 HANDLE h;
273 WRes wres;
274 unsigned threadId;
275 h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId));
276 *p = h;
277 wres = HandleToWRes(h);
278 if (h)
279 {
280 // PrintProcess_Info();
281 {
282 const
283 Func_SetThreadGroupAffinity fn =
284 (Func_SetThreadGroupAffinity) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
285 "SetThreadGroupAffinity");
286 if (fn)
287 {
288 // WRes wres2;
289 MY_GROUP_AFFINITY groupAffinity, prev_groupAffinity;
290 memset(&groupAffinity, 0, sizeof(groupAffinity));
291 // groupAffinity.Mask must use only bits that supported by current group
292 // (groupAffinity.Mask = 0) means all allowed bits
293 groupAffinity.Mask = affinityMask;
294 groupAffinity.Group = (WORD)group;
295 // wres2 =
296 fn(h, &groupAffinity, &prev_groupAffinity);
297 /*
298 if (groupAffinity.Group == prev_groupAffinity.Group)
299 wres2 = wres2;
300 else
301 wres2 = wres2;
302 if (wres2 == 0)
303 {
304 wres2 = GetError();
305 PRF(printf("\n==SetThreadGroupAffinity error: %u\n", wres2);)
306 }
307 else
308 {
309 PRF(printf("\n==Thread_Create_With_Group::SetThreadGroupAffinity()"
310 " threadId = %6u"
311 " group=%u mask=%x\n",
312 threadId,
313 prev_groupAffinity.Group,
314 (UInt32)prev_groupAffinity.Mask);)
315 }
316 */
317 }
318 }
319 {
320 const DWORD prevSuspendCount = ResumeThread(h);
114 /* ResumeThread() returns: 321 /* ResumeThread() returns:
115 0 : was_not_suspended 322 0 : was_not_suspended
116 1 : was_resumed 323 1 : was_resumed
@@ -297,6 +504,13 @@ WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
297 return Thread_Create_With_CpuSet(p, func, param, NULL); 504 return Thread_Create_With_CpuSet(p, func, param, NULL);
298} 505}
299 506
507/*
508WRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, unsigned group, CAffinityMask affinity)
509{
510 UNUSED_VAR(group)
511 return Thread_Create_With_Affinity(p, func, param, affinity);
512}
513*/
300 514
301WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) 515WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity)
302{ 516{
@@ -577,5 +791,22 @@ WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p)
577 return AutoResetEvent_CreateNotSignaled(p); 791 return AutoResetEvent_CreateNotSignaled(p);
578} 792}
579 793
794void ThreadNextGroup_Init(CThreadNextGroup *p, UInt32 numGroups, UInt32 startGroup)
795{
796 // printf("\n====== ThreadNextGroup_Init numGroups = %x: startGroup=%x\n", numGroups, startGroup);
797 if (numGroups == 0)
798 numGroups = 1;
799 p->NumGroups = numGroups;
800 p->NextGroup = startGroup % numGroups;
801}
802
803
804UInt32 ThreadNextGroup_GetNext(CThreadNextGroup *p)
805{
806 const UInt32 next = p->NextGroup;
807 p->NextGroup = (next + 1) % p->NumGroups;
808 return next;
809}
810
580#undef PRF 811#undef PRF
581#undef Print 812#undef Print