13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Thread Library
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ---------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Win32 implementation of thread management.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deThread.h"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if (DE_OS == DE_OS_WIN32 || DE_OS == DE_OS_WINCE)
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
2958da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos#include "deInt32.h"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define VC_EXTRALEAN
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define WIN32_LEAN_AND_MEAN
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <windows.h>
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/* Thread handle equals deThread in this implementation. */
363c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDE_STATIC_ASSERT(sizeof(deThread) >= sizeof(HANDLE));
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef struct ThreadEntry_s
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deThreadFunc	func;
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void*			arg;
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} ThreadEntry;
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int mapPriority (deThreadPriority priority)
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (priority)
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_THREADPRIORITY_LOWEST:	return THREAD_PRIORITY_IDLE;
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_THREADPRIORITY_LOW:		return THREAD_PRIORITY_LOWEST;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_THREADPRIORITY_NORMAL:	return THREAD_PRIORITY_NORMAL;
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_THREADPRIORITY_HIGH:	return THREAD_PRIORITY_ABOVE_NORMAL;
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_THREADPRIORITY_HIGHEST:	return THREAD_PRIORITY_HIGHEST;
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:	DE_ASSERT(DE_FALSE);
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return 0;
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic DWORD __stdcall startThread (LPVOID entryPtr)
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ThreadEntry*	entry	= (ThreadEntry*)entryPtr;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deThreadFunc	func	= entry->func;
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void*			arg		= entry->arg;
633fdee359c9eee4d6c1d823b23f7f64631b5945f8Jarkko Pöyry
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFree(entry);
653fdee359c9eee4d6c1d823b23f7f64631b5945f8Jarkko Pöyry
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	func(arg);
673fdee359c9eee4d6c1d823b23f7f64631b5945f8Jarkko Pöyry
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return 0;
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
713c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeThread deThread_create (deThreadFunc func, void* arg, const deThreadAttributes* attributes)
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ThreadEntry*	entry	= (ThreadEntry*)deMalloc(sizeof(ThreadEntry));
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE			thread	= 0;
753fdee359c9eee4d6c1d823b23f7f64631b5945f8Jarkko Pöyry
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!entry)
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
783fdee359c9eee4d6c1d823b23f7f64631b5945f8Jarkko Pöyry
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	entry->func	= func;
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	entry->arg	= arg;
813fdee359c9eee4d6c1d823b23f7f64631b5945f8Jarkko Pöyry
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	thread = CreateThread(DE_NULL, 0, startThread, entry, 0, DE_NULL);
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!thread)
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFree(entry);
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
883fdee359c9eee4d6c1d823b23f7f64631b5945f8Jarkko Pöyry
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (attributes)
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		SetThreadPriority(thread, mapPriority(attributes->priority));
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (deThread)thread;
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
953c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deThread_join (deThread thread)
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE	handle		= (HANDLE)thread;
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	WaitForSingleObject(handle, INFINITE);
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deThread_destroy (deThread thread)
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	HANDLE	handle		= (HANDLE)thread;
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CloseHandle(handle);
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deSleep (deUint32 milliseconds)
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Sleep((DWORD)milliseconds);
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deYield (void)
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1163fdee359c9eee4d6c1d823b23f7f64631b5945f8Jarkko Pöyry	SwitchToThread();
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11958da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulosstatic SYSTEM_LOGICAL_PROCESSOR_INFORMATION* getWin32ProcessorInfo (deUint32* numBytes)
12058da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos{
12158da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	deUint32								curSize	= (deUint32)sizeof(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)*8;
12258da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	SYSTEM_LOGICAL_PROCESSOR_INFORMATION*	info	= (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)deMalloc(curSize);
12358da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
12458da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	for (;;)
12558da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	{
12658da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		DWORD	inOutLen	= curSize;
12758da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		DWORD	err;
12858da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
12958da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		if (GetLogicalProcessorInformation(info, &inOutLen))
13058da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		{
13158da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos			*numBytes = inOutLen;
13258da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos			return info;
13358da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		}
13458da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		else
13558da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		{
13658da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos			err = GetLastError();
13758da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
13858da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos			if (err == ERROR_INSUFFICIENT_BUFFER)
13958da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos			{
14058da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos				curSize <<= 1;
14158da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos				info = deRealloc(info, curSize);
14258da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos			}
14358da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos			else
14458da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos			{
14558da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos				deFree(info);
14658da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos				return DE_NULL;
14758da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos			}
14858da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		}
14958da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	}
15058da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos}
15158da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
15258da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulostypedef struct ProcessorInfo_s
15358da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos{
15458da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	deUint32	numPhysicalCores;
15558da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	deUint32	numLogicalCores;
15658da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos} ProcessorInfo;
15758da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
15858da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulosvoid parseWin32ProcessorInfo (ProcessorInfo* dst, const SYSTEM_LOGICAL_PROCESSOR_INFORMATION* src, deUint32 numBytes)
15958da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos{
16058da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	const SYSTEM_LOGICAL_PROCESSOR_INFORMATION*	cur		= src;
16158da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
16258da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	deMemset(dst, 0, sizeof(ProcessorInfo));
16358da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
16458da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	while (((const deUint8*)cur - (const deUint8*)src) + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= numBytes)
16558da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	{
16658da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		if (cur->Relationship == RelationProcessorCore)
16758da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		{
16858da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos			dst->numPhysicalCores	+= 1;
16958da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos#if (DE_PTR_SIZE == 8)
17058da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos			dst->numLogicalCores	+= dePop64(cur->ProcessorMask);
17158da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos#else
17258da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos			dst->numLogicalCores	+= dePop32(cur->ProcessorMask);
17358da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos#endif
17458da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		}
17558da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
17658da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		cur++;
17758da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	}
17858da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos}
17958da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
18058da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry HaulosdeBool getProcessorInfo (ProcessorInfo* info)
18158da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos{
18258da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	deUint32								numBytes	= 0;
18358da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	SYSTEM_LOGICAL_PROCESSOR_INFORMATION*	rawInfo		= getWin32ProcessorInfo(&numBytes);
18458da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
18558da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	if (!numBytes)
18658da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		return DE_FALSE;
18758da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
18858da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	parseWin32ProcessorInfo(info, rawInfo, numBytes);
18958da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	deFree(rawInfo);
19058da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
19158da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	return DE_TRUE;
19258da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos}
19358da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
19458da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry HaulosdeUint32 deGetNumTotalPhysicalCores (void)
19558da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos{
19658da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	ProcessorInfo	info;
19758da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
19858da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	if (!getProcessorInfo(&info))
19958da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		return 1u;
20058da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
20158da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	return info.numPhysicalCores;
20258da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos}
20358da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
20458da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry HaulosdeUint32 deGetNumTotalLogicalCores (void)
20558da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos{
20658da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	ProcessorInfo	info;
20758da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
20858da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	if (!getProcessorInfo(&info))
20958da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos		return 1u;
21058da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
21158da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	return info.numLogicalCores;
21258da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos}
21358da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
21458da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry HaulosdeUint32 deGetNumAvailableLogicalCores (void)
21558da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos{
21658da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos	return deGetNumTotalLogicalCores();
21758da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos}
21858da74f0a5e226f1ee74718fb2d5e46b14f12757Pyry Haulos
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* DE_OS */
220