xref: /aosp_15_r20/external/deqp/framework/delibs/dethread/win32/deThreadWin32.c (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Thread Library
3  * ---------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Win32 implementation of thread management.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "deThread.h"
25 
26 #if (DE_OS == DE_OS_WIN32 || DE_OS == DE_OS_WINCE)
27 
28 #include "deMemory.h"
29 #include "deInt32.h"
30 
31 #define VC_EXTRALEAN
32 #define WIN32_LEAN_AND_MEAN
33 #include <windows.h>
34 
35 /* Thread handle equals deThread in this implementation. */
36 DE_STATIC_ASSERT(sizeof(deThread) >= sizeof(HANDLE));
37 
38 typedef struct ThreadEntry_s
39 {
40     deThreadFunc func;
41     void *arg;
42 } ThreadEntry;
43 
mapPriority(deThreadPriority priority)44 static int mapPriority(deThreadPriority priority)
45 {
46     switch (priority)
47     {
48     case DE_THREADPRIORITY_LOWEST:
49         return THREAD_PRIORITY_IDLE;
50     case DE_THREADPRIORITY_LOW:
51         return THREAD_PRIORITY_LOWEST;
52     case DE_THREADPRIORITY_NORMAL:
53         return THREAD_PRIORITY_NORMAL;
54     case DE_THREADPRIORITY_HIGH:
55         return THREAD_PRIORITY_ABOVE_NORMAL;
56     case DE_THREADPRIORITY_HIGHEST:
57         return THREAD_PRIORITY_HIGHEST;
58     default:
59         DE_ASSERT(false);
60     }
61     return 0;
62 }
63 
startThread(LPVOID entryPtr)64 static DWORD __stdcall startThread(LPVOID entryPtr)
65 {
66     ThreadEntry *entry = (ThreadEntry *)entryPtr;
67     deThreadFunc func  = entry->func;
68     void *arg          = entry->arg;
69 
70     deFree(entry);
71 
72     func(arg);
73 
74     return 0;
75 }
76 
deThread_create(deThreadFunc func,void * arg,const deThreadAttributes * attributes)77 deThread deThread_create(deThreadFunc func, void *arg, const deThreadAttributes *attributes)
78 {
79     ThreadEntry *entry = (ThreadEntry *)deMalloc(sizeof(ThreadEntry));
80     HANDLE thread      = 0;
81 
82     if (!entry)
83         return 0;
84 
85     entry->func = func;
86     entry->arg  = arg;
87 
88     thread = CreateThread(DE_NULL, 0, startThread, entry, 0, DE_NULL);
89     if (!thread)
90     {
91         deFree(entry);
92         return 0;
93     }
94 
95     if (attributes)
96         SetThreadPriority(thread, mapPriority(attributes->priority));
97 
98     return (deThread)thread;
99 }
100 
deThread_join(deThread thread)101 bool deThread_join(deThread thread)
102 {
103     HANDLE handle = (HANDLE)thread;
104     WaitForSingleObject(handle, INFINITE);
105 
106     return true;
107 }
108 
deThread_destroy(deThread thread)109 void deThread_destroy(deThread thread)
110 {
111     HANDLE handle = (HANDLE)thread;
112     CloseHandle(handle);
113 }
114 
deSleep(uint32_t milliseconds)115 void deSleep(uint32_t milliseconds)
116 {
117     Sleep((DWORD)milliseconds);
118 }
119 
deYield(void)120 void deYield(void)
121 {
122     SwitchToThread();
123 }
124 
getWin32ProcessorInfo(uint32_t * numBytes)125 static SYSTEM_LOGICAL_PROCESSOR_INFORMATION *getWin32ProcessorInfo(uint32_t *numBytes)
126 {
127     uint32_t curSize                           = (uint32_t)sizeof(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION) * 8;
128     SYSTEM_LOGICAL_PROCESSOR_INFORMATION *info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION *)deMalloc(curSize);
129 
130     for (;;)
131     {
132         DWORD inOutLen = curSize;
133         DWORD err;
134 
135         if (GetLogicalProcessorInformation(info, &inOutLen))
136         {
137             *numBytes = inOutLen;
138             return info;
139         }
140         else
141         {
142             err = GetLastError();
143 
144             if (err == ERROR_INSUFFICIENT_BUFFER)
145             {
146                 curSize <<= 1;
147                 info = deRealloc(info, curSize);
148             }
149             else
150             {
151                 deFree(info);
152                 return DE_NULL;
153             }
154         }
155     }
156 }
157 
158 typedef struct ProcessorInfo_s
159 {
160     uint32_t numPhysicalCores;
161     uint32_t numLogicalCores;
162 } ProcessorInfo;
163 
parseWin32ProcessorInfo(ProcessorInfo * dst,const SYSTEM_LOGICAL_PROCESSOR_INFORMATION * src,uint32_t numBytes)164 void parseWin32ProcessorInfo(ProcessorInfo *dst, const SYSTEM_LOGICAL_PROCESSOR_INFORMATION *src, uint32_t numBytes)
165 {
166     const SYSTEM_LOGICAL_PROCESSOR_INFORMATION *cur = src;
167 
168     deMemset(dst, 0, sizeof(ProcessorInfo));
169 
170     while (((const uint8_t *)cur - (const uint8_t *)src) + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= numBytes)
171     {
172         if (cur->Relationship == RelationProcessorCore)
173         {
174             dst->numPhysicalCores += 1;
175 #if (DE_PTR_SIZE == 8)
176             dst->numLogicalCores += dePop64(cur->ProcessorMask);
177 #else
178             dst->numLogicalCores += dePop32(cur->ProcessorMask);
179 #endif
180         }
181 
182         cur++;
183     }
184 }
185 
getProcessorInfo(ProcessorInfo * info)186 bool getProcessorInfo(ProcessorInfo *info)
187 {
188     uint32_t numBytes                             = 0;
189     SYSTEM_LOGICAL_PROCESSOR_INFORMATION *rawInfo = getWin32ProcessorInfo(&numBytes);
190 
191     if (!numBytes)
192         return false;
193 
194     parseWin32ProcessorInfo(info, rawInfo, numBytes);
195     deFree(rawInfo);
196 
197     return true;
198 }
199 
deGetNumTotalPhysicalCores(void)200 uint32_t deGetNumTotalPhysicalCores(void)
201 {
202     ProcessorInfo info;
203 
204     if (!getProcessorInfo(&info))
205         return 1u;
206 
207     return info.numPhysicalCores;
208 }
209 
deGetNumTotalLogicalCores(void)210 uint32_t deGetNumTotalLogicalCores(void)
211 {
212     ProcessorInfo info;
213 
214     if (!getProcessorInfo(&info))
215         return 1u;
216 
217     return info.numLogicalCores;
218 }
219 
deGetNumAvailableLogicalCores(void)220 uint32_t deGetNumAvailableLogicalCores(void)
221 {
222     return deGetNumTotalLogicalCores();
223 }
224 
225 #endif /* DE_OS */
226