1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Thread Library
3e5c31af7Sopenharmony_ci * ---------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Unix implementation of thread management.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "deThread.h"
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#if (DE_OS == DE_OS_UNIX || DE_OS == DE_OS_OSX || DE_OS == DE_OS_ANDROID || DE_OS == DE_OS_SYMBIAN || DE_OS == DE_OS_IOS || DE_OS == DE_OS_QNX || DE_OS == DE_OS_FUCHSIA)
27e5c31af7Sopenharmony_ci
28e5c31af7Sopenharmony_ci#include "deMemory.h"
29e5c31af7Sopenharmony_ci#include "deInt32.h"
30e5c31af7Sopenharmony_ci
31e5c31af7Sopenharmony_ci#if !defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE < 500)
32e5c31af7Sopenharmony_ci#	error "You are using too old posix API!"
33e5c31af7Sopenharmony_ci#endif
34e5c31af7Sopenharmony_ci
35e5c31af7Sopenharmony_ci#include <unistd.h>
36e5c31af7Sopenharmony_ci#include <pthread.h>
37e5c31af7Sopenharmony_ci#include <sched.h>
38e5c31af7Sopenharmony_ci#if (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_ANDROID)
39e5c31af7Sopenharmony_ci#	include <sys/syscall.h>
40e5c31af7Sopenharmony_ci#endif
41e5c31af7Sopenharmony_ci
42e5c31af7Sopenharmony_ci#if (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS)
43e5c31af7Sopenharmony_ci#	if !defined(_SC_NPROCESSORS_CONF)
44e5c31af7Sopenharmony_ci#		define _SC_NPROCESSORS_CONF 57
45e5c31af7Sopenharmony_ci#	endif
46e5c31af7Sopenharmony_ci#	if !defined(_SC_NPROCESSORS_ONLN)
47e5c31af7Sopenharmony_ci#		define _SC_NPROCESSORS_ONLN 58
48e5c31af7Sopenharmony_ci#	endif
49e5c31af7Sopenharmony_ci#endif
50e5c31af7Sopenharmony_ci
51e5c31af7Sopenharmony_citypedef struct Thread_s
52e5c31af7Sopenharmony_ci{
53e5c31af7Sopenharmony_ci	pthread_t		thread;
54e5c31af7Sopenharmony_ci	deThreadFunc	func;
55e5c31af7Sopenharmony_ci	void*			arg;
56e5c31af7Sopenharmony_ci} Thread;
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_ciDE_STATIC_ASSERT(sizeof(deThread) >= sizeof(Thread*));
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_cistatic void* startThread (void* entryPtr)
61e5c31af7Sopenharmony_ci{
62e5c31af7Sopenharmony_ci	Thread*			thread	= (Thread*)entryPtr;
63e5c31af7Sopenharmony_ci	deThreadFunc	func	= thread->func;
64e5c31af7Sopenharmony_ci	void*			arg		= thread->arg;
65e5c31af7Sopenharmony_ci
66e5c31af7Sopenharmony_ci	/* Start actual thread. */
67e5c31af7Sopenharmony_ci	func(arg);
68e5c31af7Sopenharmony_ci
69e5c31af7Sopenharmony_ci	return DE_NULL;
70e5c31af7Sopenharmony_ci}
71e5c31af7Sopenharmony_ci
72e5c31af7Sopenharmony_cideThread deThread_create (deThreadFunc func, void* arg, const deThreadAttributes* attributes)
73e5c31af7Sopenharmony_ci{
74e5c31af7Sopenharmony_ci	pthread_attr_t	attr;
75e5c31af7Sopenharmony_ci	Thread*			thread	= (Thread*)deCalloc(sizeof(Thread));
76e5c31af7Sopenharmony_ci
77e5c31af7Sopenharmony_ci	if (!thread)
78e5c31af7Sopenharmony_ci		return 0;
79e5c31af7Sopenharmony_ci
80e5c31af7Sopenharmony_ci	thread->func	= func;
81e5c31af7Sopenharmony_ci	thread->arg		= arg;
82e5c31af7Sopenharmony_ci
83e5c31af7Sopenharmony_ci	if (pthread_attr_init(&attr) != 0)
84e5c31af7Sopenharmony_ci	{
85e5c31af7Sopenharmony_ci		deFree(thread);
86e5c31af7Sopenharmony_ci		return 0;
87e5c31af7Sopenharmony_ci	}
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_ci	/* \todo [2009-11-12 pyry] Map attributes. */
90e5c31af7Sopenharmony_ci	DE_UNREF(attributes);
91e5c31af7Sopenharmony_ci
92e5c31af7Sopenharmony_ci	if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) != 0)
93e5c31af7Sopenharmony_ci	{
94e5c31af7Sopenharmony_ci		pthread_attr_destroy(&attr);
95e5c31af7Sopenharmony_ci		deFree(thread);
96e5c31af7Sopenharmony_ci		return 0;
97e5c31af7Sopenharmony_ci	}
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_ci	if (pthread_create(&thread->thread, &attr, startThread, thread) != 0)
100e5c31af7Sopenharmony_ci	{
101e5c31af7Sopenharmony_ci		pthread_attr_destroy(&attr);
102e5c31af7Sopenharmony_ci		deFree(thread);
103e5c31af7Sopenharmony_ci		return 0;
104e5c31af7Sopenharmony_ci	}
105e5c31af7Sopenharmony_ci	DE_ASSERT(thread->thread);
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci	pthread_attr_destroy(&attr);
108e5c31af7Sopenharmony_ci
109e5c31af7Sopenharmony_ci	return (deThread)thread;
110e5c31af7Sopenharmony_ci}
111e5c31af7Sopenharmony_ci
112e5c31af7Sopenharmony_cideBool deThread_join (deThread threadptr)
113e5c31af7Sopenharmony_ci{
114e5c31af7Sopenharmony_ci	Thread*		thread	= (Thread*)threadptr;
115e5c31af7Sopenharmony_ci	int			ret;
116e5c31af7Sopenharmony_ci
117e5c31af7Sopenharmony_ci	DE_ASSERT(thread->thread);
118e5c31af7Sopenharmony_ci	ret = pthread_join(thread->thread, DE_NULL);
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ci	/* If join fails for some reason, at least mark as detached. */
121e5c31af7Sopenharmony_ci	if (ret != 0)
122e5c31af7Sopenharmony_ci		pthread_detach(thread->thread);
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_ci	/* Thread is no longer valid as far as we are concerned. */
125e5c31af7Sopenharmony_ci	thread->thread = 0;
126e5c31af7Sopenharmony_ci
127e5c31af7Sopenharmony_ci	return (ret == 0);
128e5c31af7Sopenharmony_ci}
129e5c31af7Sopenharmony_ci
130e5c31af7Sopenharmony_civoid deThread_destroy (deThread threadptr)
131e5c31af7Sopenharmony_ci{
132e5c31af7Sopenharmony_ci	Thread* thread = (Thread*)threadptr;
133e5c31af7Sopenharmony_ci
134e5c31af7Sopenharmony_ci	if (thread->thread)
135e5c31af7Sopenharmony_ci	{
136e5c31af7Sopenharmony_ci		/* Not joined, detach. */
137e5c31af7Sopenharmony_ci		int ret = pthread_detach(thread->thread);
138e5c31af7Sopenharmony_ci		DE_ASSERT(ret == 0);
139e5c31af7Sopenharmony_ci		DE_UNREF(ret);
140e5c31af7Sopenharmony_ci	}
141e5c31af7Sopenharmony_ci
142e5c31af7Sopenharmony_ci	deFree(thread);
143e5c31af7Sopenharmony_ci}
144e5c31af7Sopenharmony_ci
145e5c31af7Sopenharmony_civoid deSleep (deUint32 milliseconds)
146e5c31af7Sopenharmony_ci{
147e5c31af7Sopenharmony_ci	/* Maximum value for usleep is 10^6. */
148e5c31af7Sopenharmony_ci	deUint32 seconds = milliseconds / 1000;
149e5c31af7Sopenharmony_ci
150e5c31af7Sopenharmony_ci	milliseconds = milliseconds - seconds * 1000;
151e5c31af7Sopenharmony_ci
152e5c31af7Sopenharmony_ci	if (seconds > 0)
153e5c31af7Sopenharmony_ci		sleep(seconds);
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_ci	usleep((useconds_t)milliseconds * (useconds_t)1000);
156e5c31af7Sopenharmony_ci}
157e5c31af7Sopenharmony_ci
158e5c31af7Sopenharmony_civoid deYield (void)
159e5c31af7Sopenharmony_ci{
160e5c31af7Sopenharmony_ci	sched_yield();
161e5c31af7Sopenharmony_ci}
162e5c31af7Sopenharmony_ci
163e5c31af7Sopenharmony_ci#if (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_ANDROID)
164e5c31af7Sopenharmony_ci
165e5c31af7Sopenharmony_cideUint32 deGetNumAvailableLogicalCores (void)
166e5c31af7Sopenharmony_ci{
167e5c31af7Sopenharmony_ci#if !defined(__FreeBSD__)
168e5c31af7Sopenharmony_ci	unsigned long		mask		= 0;
169e5c31af7Sopenharmony_ci	const unsigned int	maskSize	= sizeof(mask);
170e5c31af7Sopenharmony_ci	long				ret;
171e5c31af7Sopenharmony_ci
172e5c31af7Sopenharmony_ci	deMemset(&mask, 0, sizeof(mask));
173e5c31af7Sopenharmony_ci
174e5c31af7Sopenharmony_ci	ret = syscall(__NR_sched_getaffinity, 0, maskSize, &mask);
175e5c31af7Sopenharmony_ci
176e5c31af7Sopenharmony_ci	if (ret > 0)
177e5c31af7Sopenharmony_ci	{
178e5c31af7Sopenharmony_ci		return (deUint32)dePop64(mask);
179e5c31af7Sopenharmony_ci	}
180e5c31af7Sopenharmony_ci	else
181e5c31af7Sopenharmony_ci	{
182e5c31af7Sopenharmony_ci#endif
183e5c31af7Sopenharmony_ci#if defined(_SC_NPROCESSORS_ONLN)
184e5c31af7Sopenharmony_ci		const long count = sysconf(_SC_NPROCESSORS_ONLN);
185e5c31af7Sopenharmony_ci
186e5c31af7Sopenharmony_ci		if (count <= 0)
187e5c31af7Sopenharmony_ci			return 1;
188e5c31af7Sopenharmony_ci		else
189e5c31af7Sopenharmony_ci			return (deUint32)count;
190e5c31af7Sopenharmony_ci#else
191e5c31af7Sopenharmony_ci		return 1;
192e5c31af7Sopenharmony_ci#endif
193e5c31af7Sopenharmony_ci
194e5c31af7Sopenharmony_ci#if !defined(__FreeBSD__)
195e5c31af7Sopenharmony_ci	}
196e5c31af7Sopenharmony_ci#endif
197e5c31af7Sopenharmony_ci}
198e5c31af7Sopenharmony_ci
199e5c31af7Sopenharmony_ci#else
200e5c31af7Sopenharmony_ci
201e5c31af7Sopenharmony_cideUint32 deGetNumAvailableLogicalCores (void)
202e5c31af7Sopenharmony_ci{
203e5c31af7Sopenharmony_ci#if defined(_SC_NPROCESSORS_ONLN)
204e5c31af7Sopenharmony_ci	const long count = sysconf(_SC_NPROCESSORS_ONLN);
205e5c31af7Sopenharmony_ci
206e5c31af7Sopenharmony_ci	if (count <= 0)
207e5c31af7Sopenharmony_ci		return 1;
208e5c31af7Sopenharmony_ci	else
209e5c31af7Sopenharmony_ci		return (deUint32)count;
210e5c31af7Sopenharmony_ci#else
211e5c31af7Sopenharmony_ci	return 1;
212e5c31af7Sopenharmony_ci#endif
213e5c31af7Sopenharmony_ci}
214e5c31af7Sopenharmony_ci
215e5c31af7Sopenharmony_ci#endif
216e5c31af7Sopenharmony_ci
217e5c31af7Sopenharmony_cideUint32 deGetNumTotalLogicalCores (void)
218e5c31af7Sopenharmony_ci{
219e5c31af7Sopenharmony_ci#if defined(_SC_NPROCESSORS_CONF)
220e5c31af7Sopenharmony_ci	const long count = sysconf(_SC_NPROCESSORS_CONF);
221e5c31af7Sopenharmony_ci
222e5c31af7Sopenharmony_ci	if (count <= 0)
223e5c31af7Sopenharmony_ci		return 1;
224e5c31af7Sopenharmony_ci	else
225e5c31af7Sopenharmony_ci		return (deUint32)count;
226e5c31af7Sopenharmony_ci#else
227e5c31af7Sopenharmony_ci	return 1;
228e5c31af7Sopenharmony_ci#endif
229e5c31af7Sopenharmony_ci}
230e5c31af7Sopenharmony_ci
231e5c31af7Sopenharmony_cideUint32 deGetNumTotalPhysicalCores (void)
232e5c31af7Sopenharmony_ci{
233e5c31af7Sopenharmony_ci	/* \todo [2015-04-09 pyry] Parse /proc/cpuinfo perhaps? */
234e5c31af7Sopenharmony_ci	return deGetNumTotalLogicalCores();
235e5c31af7Sopenharmony_ci}
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_ci#endif /* DE_OS */
238