eglglobals.c revision d8407755
13464ebd5Sriastradh/************************************************************************** 23464ebd5Sriastradh * 3af69d88dSmrg * Copyright 2008 VMware, Inc. 43464ebd5Sriastradh * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com> 53464ebd5Sriastradh * Copyright 2010-2011 LunarG, Inc. 63464ebd5Sriastradh * All Rights Reserved. 73464ebd5Sriastradh * 83464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a 93464ebd5Sriastradh * copy of this software and associated documentation files (the 103464ebd5Sriastradh * "Software"), to deal in the Software without restriction, including 113464ebd5Sriastradh * without limitation the rights to use, copy, modify, merge, publish, 123464ebd5Sriastradh * distribute, sub license, and/or sell copies of the Software, and to 133464ebd5Sriastradh * permit persons to whom the Software is furnished to do so, subject to 143464ebd5Sriastradh * the following conditions: 153464ebd5Sriastradh * 163464ebd5Sriastradh * The above copyright notice and this permission notice (including the 173464ebd5Sriastradh * next paragraph) shall be included in all copies or substantial portions 183464ebd5Sriastradh * of the Software. 193464ebd5Sriastradh * 203464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 213464ebd5Sriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 223464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 233464ebd5Sriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 243464ebd5Sriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 253464ebd5Sriastradh * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 263464ebd5Sriastradh * DEALINGS IN THE SOFTWARE. 273464ebd5Sriastradh * 283464ebd5Sriastradh **************************************************************************/ 293464ebd5Sriastradh 303464ebd5Sriastradh 314a49301eSmrg#include <stdlib.h> 327e995a2eSmrg#include <stdio.h> 337e995a2eSmrg#include <string.h> 344a49301eSmrg#include <assert.h> 357e995a2eSmrg#include "c11/threads.h" 367e995a2eSmrg 374a49301eSmrg#include "eglglobals.h" 387e995a2eSmrg#include "egldevice.h" 39cdc920a0Smrg#include "egldisplay.h" 404a49301eSmrg#include "egldriver.h" 417e995a2eSmrg#include "egllog.h" 427e995a2eSmrg 43d8407755Smaya#include "util/macros.h" 44d8407755Smaya 457e995a2eSmrg#ifdef HAVE_MINCORE 467e995a2eSmrg#include <unistd.h> 477e995a2eSmrg#include <sys/mman.h> 487e995a2eSmrg#endif 494a49301eSmrg 504a49301eSmrg 517e995a2eSmrgstatic mtx_t _eglGlobalMutex = _MTX_INITIALIZER_NP; 52af69d88dSmrg 534a49301eSmrgstruct _egl_global _eglGlobal = 544a49301eSmrg{ 557e995a2eSmrg .Mutex = &_eglGlobalMutex, 567e995a2eSmrg .DisplayList = NULL, 577e995a2eSmrg .DeviceList = &_eglSoftwareDevice, 587e995a2eSmrg .NumAtExitCalls = 3, 597e995a2eSmrg .AtExitCalls = { 604a49301eSmrg /* default AtExitCalls, called in reverse order */ 617e995a2eSmrg _eglFiniDevice, /* always called last */ 627e995a2eSmrg _eglUnloadDrivers, 637e995a2eSmrg _eglFiniDisplay, 64af69d88dSmrg }, 65af69d88dSmrg 667e995a2eSmrg .ClientOnlyExtensionString = 67af69d88dSmrg "EGL_EXT_client_extensions" 687e995a2eSmrg " EGL_EXT_device_base" 697e995a2eSmrg " EGL_EXT_device_enumeration" 707e995a2eSmrg " EGL_EXT_device_query" 71af69d88dSmrg " EGL_EXT_platform_base" 727e995a2eSmrg " EGL_KHR_client_get_all_proc_addresses" 737e995a2eSmrg " EGL_KHR_debug", 747e995a2eSmrg 757e995a2eSmrg .PlatformExtensionString = 767e995a2eSmrg#ifdef HAVE_WAYLAND_PLATFORM 77af69d88dSmrg " EGL_EXT_platform_wayland" 787e995a2eSmrg#endif 797e995a2eSmrg#ifdef HAVE_X11_PLATFORM 807e995a2eSmrg " EGL_EXT_platform_x11" 817e995a2eSmrg#endif 827e995a2eSmrg#ifdef HAVE_DRM_PLATFORM 83af69d88dSmrg " EGL_MESA_platform_gbm" 847e995a2eSmrg#endif 857e995a2eSmrg#ifdef HAVE_SURFACELESS_PLATFORM 867e995a2eSmrg " EGL_MESA_platform_surfaceless" 877e995a2eSmrg#endif 887e995a2eSmrg "", 897e995a2eSmrg 907e995a2eSmrg .ClientExtensionString = NULL, 917e995a2eSmrg 927e995a2eSmrg .debugCallback = NULL, 937e995a2eSmrg .debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR, 944a49301eSmrg}; 954a49301eSmrg 96d63b28c1Smartinstatic EGLBoolean registered = EGL_FALSE; 974a49301eSmrg 98d63b28c1Smartinstatic void __attribute__((__destructor__)) 994a49301eSmrg_eglAtExit(void) 1004a49301eSmrg{ 1014a49301eSmrg EGLint i; 102d63b28c1Smartin 103d63b28c1Smartin if (!registered) 1047e995a2eSmrg return; 105d63b28c1Smartin 1064a49301eSmrg for (i = _eglGlobal.NumAtExitCalls - 1; i >= 0; i--) 1074a49301eSmrg _eglGlobal.AtExitCalls[i](); 1084a49301eSmrg} 1094a49301eSmrg 1104a49301eSmrg 1114a49301eSmrgvoid 1124a49301eSmrg_eglAddAtExitCall(void (*func)(void)) 1134a49301eSmrg{ 1144a49301eSmrg if (func) { 1157e995a2eSmrg static EGLBoolean registered = EGL_FALSE; 1164a49301eSmrg 1177e995a2eSmrg mtx_lock(_eglGlobal.Mutex); 1184a49301eSmrg 119d63b28c1Smartin registered = EGL_TRUE; 1204a49301eSmrg 1214a49301eSmrg assert(_eglGlobal.NumAtExitCalls < ARRAY_SIZE(_eglGlobal.AtExitCalls)); 1224a49301eSmrg _eglGlobal.AtExitCalls[_eglGlobal.NumAtExitCalls++] = func; 1234a49301eSmrg 1247e995a2eSmrg mtx_unlock(_eglGlobal.Mutex); 1257e995a2eSmrg } 1267e995a2eSmrg} 1277e995a2eSmrg 1287e995a2eSmrgconst char * 1297e995a2eSmrg_eglGetClientExtensionString(void) 1307e995a2eSmrg{ 1317e995a2eSmrg const char *ret; 1327e995a2eSmrg 1337e995a2eSmrg mtx_lock(_eglGlobal.Mutex); 1347e995a2eSmrg 1357e995a2eSmrg if (_eglGlobal.ClientExtensionString == NULL) { 1367e995a2eSmrg size_t clientLen = strlen(_eglGlobal.ClientOnlyExtensionString); 1377e995a2eSmrg size_t platformLen = strlen(_eglGlobal.PlatformExtensionString); 1387e995a2eSmrg 1397e995a2eSmrg _eglGlobal.ClientExtensionString = (char *) malloc(clientLen + platformLen + 1); 1407e995a2eSmrg if (_eglGlobal.ClientExtensionString != NULL) { 1417e995a2eSmrg char *ptr = _eglGlobal.ClientExtensionString; 1427e995a2eSmrg 1437e995a2eSmrg memcpy(ptr, _eglGlobal.ClientOnlyExtensionString, clientLen); 1447e995a2eSmrg ptr += clientLen; 1457e995a2eSmrg 1467e995a2eSmrg if (platformLen > 0) { 1477e995a2eSmrg // Note that if PlatformExtensionString is not empty, then it will 1487e995a2eSmrg // already have a leading space. 1497e995a2eSmrg assert(_eglGlobal.PlatformExtensionString[0] == ' '); 1507e995a2eSmrg memcpy(ptr, _eglGlobal.PlatformExtensionString, platformLen); 1517e995a2eSmrg ptr += platformLen; 1527e995a2eSmrg } 1537e995a2eSmrg *ptr = '\0'; 1547e995a2eSmrg } 1554a49301eSmrg } 1567e995a2eSmrg ret = _eglGlobal.ClientExtensionString; 1577e995a2eSmrg 1587e995a2eSmrg mtx_unlock(_eglGlobal.Mutex); 1597e995a2eSmrg return ret; 1607e995a2eSmrg} 1617e995a2eSmrg 1627e995a2eSmrgEGLBoolean 1637e995a2eSmrg_eglPointerIsDereferencable(void *p) 1647e995a2eSmrg{ 1657e995a2eSmrg#ifdef HAVE_MINCORE 1667e995a2eSmrg uintptr_t addr = (uintptr_t) p; 16766d8f6e3Schristos#ifdef __linux__ 16866d8f6e3Schristos unsigned 16966d8f6e3Schristos#endif 17066d8f6e3Schristos char valid = 0; 1717e995a2eSmrg const long page_size = getpagesize(); 1727e995a2eSmrg 1737e995a2eSmrg if (p == NULL) 1747e995a2eSmrg return EGL_FALSE; 1757e995a2eSmrg 1767e995a2eSmrg /* align addr to page_size */ 1777e995a2eSmrg addr &= ~(page_size - 1); 1787e995a2eSmrg 1797e995a2eSmrg if (mincore((void *) addr, page_size, &valid) < 0) { 1807e995a2eSmrg _eglLog(_EGL_DEBUG, "mincore failed: %m"); 1817e995a2eSmrg return EGL_FALSE; 1827e995a2eSmrg } 1837e995a2eSmrg 1847e995a2eSmrg /* mincore() returns 0 on success, and -1 on failure. The last parameter 1857e995a2eSmrg * is a vector of bytes with one entry for each page queried. mincore 1867e995a2eSmrg * returns page residency information in the first bit of each byte in the 1877e995a2eSmrg * vector. 1887e995a2eSmrg * 1897e995a2eSmrg * Residency doesn't actually matter when determining whether a pointer is 1907e995a2eSmrg * dereferenceable, so the output vector can be ignored. What matters is 1917e995a2eSmrg * whether mincore succeeds. See: 1927e995a2eSmrg * 1937e995a2eSmrg * http://man7.org/linux/man-pages/man2/mincore.2.html 1947e995a2eSmrg */ 1957e995a2eSmrg return EGL_TRUE; 1967e995a2eSmrg#else 1977e995a2eSmrg return p != NULL; 1987e995a2eSmrg#endif 1994a49301eSmrg} 200