/**************************************************************************1*2* Copyright 2008 VMware, Inc.3* Copyright 2009-2010 Chia-I Wu <[email protected]>4* Copyright 2010-2011 LunarG, Inc.5* All Rights Reserved.6*7* Permission is hereby granted, free of charge, to any person obtaining a8* copy of this software and associated documentation files (the9* "Software"), to deal in the Software without restriction, including10* without limitation the rights to use, copy, modify, merge, publish,11* distribute, sub license, and/or sell copies of the Software, and to12* permit persons to whom the Software is furnished to do so, subject to13* the following conditions:14*15* The above copyright notice and this permission notice (including the16* next paragraph) shall be included in all copies or substantial portions17* of the Software.18*19* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR20* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,21* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL22* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER23* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING24* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER25* DEALINGS IN THE SOFTWARE.26*27**************************************************************************/282930#include <stdlib.h>31#include <stdio.h>32#include <string.h>33#include <assert.h>34#include "c11/threads.h"3536#include "eglglobals.h"37#include "egldevice.h"38#include "egldisplay.h"3940#include "util/macros.h"4142#ifdef HAVE_MINCORE43#include <unistd.h>44#include <sys/mman.h>45#endif464748static mtx_t _eglGlobalMutex = _MTX_INITIALIZER_NP;4950struct _egl_global _eglGlobal =51{52.Mutex = &_eglGlobalMutex,53.DisplayList = NULL,54.DeviceList = &_eglSoftwareDevice,55.NumAtExitCalls = 2,56.AtExitCalls = {57/* default AtExitCalls, called in reverse order */58_eglFiniDevice, /* always called last */59_eglFiniDisplay,60},6162#if USE_LIBGLVND63.ClientOnlyExtensionString =64#else65.ClientExtensionString =66#endif67"EGL_EXT_client_extensions"68" EGL_EXT_device_base"69" EGL_EXT_device_enumeration"70" EGL_EXT_device_query"71" EGL_EXT_platform_base"72" EGL_KHR_client_get_all_proc_addresses"73" EGL_KHR_debug"7475#if USE_LIBGLVND76,77.PlatformExtensionString =78#else79" "80#endif8182"EGL_EXT_platform_device"83#ifdef HAVE_WAYLAND_PLATFORM84" EGL_EXT_platform_wayland"85" EGL_KHR_platform_wayland"86#endif87#ifdef HAVE_X11_PLATFORM88" EGL_EXT_platform_x11"89" EGL_KHR_platform_x11"90#endif91#ifdef HAVE_XCB_PLATFORM92" EGL_MESA_platform_xcb"93#endif94#ifdef HAVE_DRM_PLATFORM95" EGL_MESA_platform_gbm"96" EGL_KHR_platform_gbm"97#endif98" EGL_MESA_platform_surfaceless"99"",100101.debugCallback = NULL,102.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR,103};104105106static void107_eglAtExit(void)108{109EGLint i;110for (i = _eglGlobal.NumAtExitCalls - 1; i >= 0; i--)111_eglGlobal.AtExitCalls[i]();112}113114115void116_eglAddAtExitCall(void (*func)(void))117{118if (func) {119static EGLBoolean registered = EGL_FALSE;120121mtx_lock(_eglGlobal.Mutex);122123if (!registered) {124atexit(_eglAtExit);125registered = EGL_TRUE;126}127128assert(_eglGlobal.NumAtExitCalls < ARRAY_SIZE(_eglGlobal.AtExitCalls));129_eglGlobal.AtExitCalls[_eglGlobal.NumAtExitCalls++] = func;130131mtx_unlock(_eglGlobal.Mutex);132}133}134135EGLBoolean136_eglPointerIsDereferencable(void *p)137{138uintptr_t addr = (uintptr_t) p;139const long page_size = getpagesize();140#ifdef HAVE_MINCORE141unsigned char valid = 0;142143if (p == NULL)144return EGL_FALSE;145146/* align addr to page_size */147addr &= ~(page_size - 1);148149/* mincore expects &valid to be unsigned char* on Linux but char* on BSD:150* we cast pointers to void, to fix type mismatch warnings in all systems151*/152if (mincore((void *) addr, page_size, (void*)&valid) < 0) {153return EGL_FALSE;154}155156/* mincore() returns 0 on success, and -1 on failure. The last parameter157* is a vector of bytes with one entry for each page queried. mincore158* returns page residency information in the first bit of each byte in the159* vector.160*161* Residency doesn't actually matter when determining whether a pointer is162* dereferenceable, so the output vector can be ignored. What matters is163* whether mincore succeeds. See:164*165* http://man7.org/linux/man-pages/man2/mincore.2.html166*/167return EGL_TRUE;168#else169// Without mincore(), we just assume that the first page is unmapped.170return addr >= page_size;171#endif172}173174175