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