• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:	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 
startThread(LPVOID entryPtr)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 
deThread_create(deThreadFunc func,void * arg,const deThreadAttributes * attributes)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 
deThread_join(deThread thread)95 deBool deThread_join (deThread thread)
96 {
97 	HANDLE	handle		= (HANDLE)thread;
98 	WaitForSingleObject(handle, INFINITE);
99 
100 	return DE_TRUE;
101 }
102 
deThread_destroy(deThread thread)103 void deThread_destroy (deThread thread)
104 {
105 	HANDLE	handle		= (HANDLE)thread;
106 	CloseHandle(handle);
107 }
108 
deSleep(deUint32 milliseconds)109 void deSleep (deUint32 milliseconds)
110 {
111 	Sleep((DWORD)milliseconds);
112 }
113 
deYield(void)114 void deYield (void)
115 {
116 	SwitchToThread();
117 }
118 
getWin32ProcessorInfo(deUint32 * numBytes)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 
parseWin32ProcessorInfo(ProcessorInfo * dst,const SYSTEM_LOGICAL_PROCESSOR_INFORMATION * src,deUint32 numBytes)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 
getProcessorInfo(ProcessorInfo * info)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 
deGetNumTotalPhysicalCores(void)194 deUint32 deGetNumTotalPhysicalCores (void)
195 {
196 	ProcessorInfo	info;
197 
198 	if (!getProcessorInfo(&info))
199 		return 1u;
200 
201 	return info.numPhysicalCores;
202 }
203 
deGetNumTotalLogicalCores(void)204 deUint32 deGetNumTotalLogicalCores (void)
205 {
206 	ProcessorInfo	info;
207 
208 	if (!getProcessorInfo(&info))
209 		return 1u;
210 
211 	return info.numLogicalCores;
212 }
213 
deGetNumAvailableLogicalCores(void)214 deUint32 deGetNumAvailableLogicalCores (void)
215 {
216 	return deGetNumTotalLogicalCores();
217 }
218 
219 #endif /* DE_OS */
220