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 44 static int mapPriority (deThreadPriority priority) 45 { 46 switch (priority) 47 { 48 case DE_THREADPRIORITY_LOWEST: return THREAD_PRIORITY_IDLE; 49 case DE_THREADPRIORITY_LOW: return THREAD_PRIORITY_LOWEST; 50 case DE_THREADPRIORITY_NORMAL: return THREAD_PRIORITY_NORMAL; 51 case DE_THREADPRIORITY_HIGH: return THREAD_PRIORITY_ABOVE_NORMAL; 52 case DE_THREADPRIORITY_HIGHEST: return THREAD_PRIORITY_HIGHEST; 53 default: DE_ASSERT(DE_FALSE); 54 } 55 return 0; 56 } 57 58 static DWORD __stdcall startThread (LPVOID entryPtr) 59 { 60 ThreadEntry* entry = (ThreadEntry*)entryPtr; 61 deThreadFunc func = entry->func; 62 void* arg = entry->arg; 63 64 deFree(entry); 65 66 func(arg); 67 68 return 0; 69 } 70 71 deThread deThread_create (deThreadFunc func, void* arg, const deThreadAttributes* attributes) 72 { 73 ThreadEntry* entry = (ThreadEntry*)deMalloc(sizeof(ThreadEntry)); 74 HANDLE thread = 0; 75 76 if (!entry) 77 return 0; 78 79 entry->func = func; 80 entry->arg = arg; 81 82 thread = CreateThread(DE_NULL, 0, startThread, entry, 0, DE_NULL); 83 if (!thread) 84 { 85 deFree(entry); 86 return 0; 87 } 88 89 if (attributes) 90 SetThreadPriority(thread, mapPriority(attributes->priority)); 91 92 return (deThread)thread; 93 } 94 95 deBool deThread_join (deThread thread) 96 { 97 HANDLE handle = (HANDLE)thread; 98 WaitForSingleObject(handle, INFINITE); 99 100 return DE_TRUE; 101 } 102 103 void deThread_destroy (deThread thread) 104 { 105 HANDLE handle = (HANDLE)thread; 106 CloseHandle(handle); 107 } 108 109 void deSleep (deUint32 milliseconds) 110 { 111 Sleep((DWORD)milliseconds); 112 } 113 114 void deYield (void) 115 { 116 SwitchToThread(); 117 } 118 119 static SYSTEM_LOGICAL_PROCESSOR_INFORMATION* getWin32ProcessorInfo (deUint32* numBytes) 120 { 121 deUint32 curSize = (deUint32)sizeof(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)*8; 122 SYSTEM_LOGICAL_PROCESSOR_INFORMATION* info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)deMalloc(curSize); 123 124 for (;;) 125 { 126 DWORD inOutLen = curSize; 127 DWORD err; 128 129 if (GetLogicalProcessorInformation(info, &inOutLen)) 130 { 131 *numBytes = inOutLen; 132 return info; 133 } 134 else 135 { 136 err = GetLastError(); 137 138 if (err == ERROR_INSUFFICIENT_BUFFER) 139 { 140 curSize <<= 1; 141 info = deRealloc(info, curSize); 142 } 143 else 144 { 145 deFree(info); 146 return DE_NULL; 147 } 148 } 149 } 150 } 151 152 typedef struct ProcessorInfo_s 153 { 154 deUint32 numPhysicalCores; 155 deUint32 numLogicalCores; 156 } ProcessorInfo; 157 158 void parseWin32ProcessorInfo (ProcessorInfo* dst, const SYSTEM_LOGICAL_PROCESSOR_INFORMATION* src, deUint32 numBytes) 159 { 160 const SYSTEM_LOGICAL_PROCESSOR_INFORMATION* cur = src; 161 162 deMemset(dst, 0, sizeof(ProcessorInfo)); 163 164 while (((const deUint8*)cur - (const deUint8*)src) + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= numBytes) 165 { 166 if (cur->Relationship == RelationProcessorCore) 167 { 168 dst->numPhysicalCores += 1; 169 #if (DE_PTR_SIZE == 8) 170 dst->numLogicalCores += dePop64(cur->ProcessorMask); 171 #else 172 dst->numLogicalCores += dePop32(cur->ProcessorMask); 173 #endif 174 } 175 176 cur++; 177 } 178 } 179 180 deBool getProcessorInfo (ProcessorInfo* info) 181 { 182 deUint32 numBytes = 0; 183 SYSTEM_LOGICAL_PROCESSOR_INFORMATION* rawInfo = getWin32ProcessorInfo(&numBytes); 184 185 if (!numBytes) 186 return DE_FALSE; 187 188 parseWin32ProcessorInfo(info, rawInfo, numBytes); 189 deFree(rawInfo); 190 191 return DE_TRUE; 192 } 193 194 deUint32 deGetNumTotalPhysicalCores (void) 195 { 196 ProcessorInfo info; 197 198 if (!getProcessorInfo(&info)) 199 return 1u; 200 201 return info.numPhysicalCores; 202 } 203 204 deUint32 deGetNumTotalLogicalCores (void) 205 { 206 ProcessorInfo info; 207 208 if (!getProcessorInfo(&info)) 209 return 1u; 210 211 return info.numLogicalCores; 212 } 213 214 deUint32 deGetNumAvailableLogicalCores (void) 215 { 216 return deGetNumTotalLogicalCores(); 217 } 218 219 #endif /* DE_OS */ 220