Home | History | Annotate | Download | only in win32
      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