mesa: update to the latest c99/c11 compat headers

No visible API change.

Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
Reviewed-by: Ryan Neph <ryanneph@google.com>
Acked-by: Gert Wollny <gert.wollny@collabora.com>
macos/master
Chia-I Wu 3 years ago
parent c6f193ce32
commit 90ab7ae537
  1. 2
      config.h.meson
  2. 13
      meson.build
  3. 5
      src/gallium/meson.build
  4. 6
      src/mesa/compat/c11/threads.h
  5. 74
      src/mesa/compat/c11/threads_posix.h
  6. 258
      src/mesa/compat/c11/threads_win32.h
  7. 27
      src/mesa/compat/c11_compat.h
  8. 10
      src/mesa/compat/c99_compat.h
  9. 211
      src/mesa/compat/c99_math.h
  10. 2
      src/mesa/compat/no_extern_c.h
  11. 4
      src/mesa/meson.build

@ -1,6 +1,8 @@
#mesondefine VERSION
#mesondefine _GNU_SOURCE
#mesondefine VIRGL_RENDERER_UNSTABLE_APIS
#mesondefine HAVE_FUNC_ATTRIBUTE_WEAK
#mesondefine HAVE_TIMESPEC_GET
#mesondefine HAVE_SYS_UIO_H
#mesondefine HAVE_PTHREAD
#mesondefine HAVE_EPOXY_EGL_H

@ -126,6 +126,19 @@ if cc.has_header('sys/select.h')
conf_data.set('HAVE_SYS_SELECT_H', 1)
endif
supported_function_attributes = cc.get_supported_function_attributes([
'weak'
])
foreach a : supported_function_attributes
conf_data.set('HAVE_FUNC_ATTRIBUTE_@0@'.format(a.to_upper()), 1)
endforeach
foreach f : ['timespec_get']
if cc.has_function(f)
conf_data.set('HAVE_@0@'.format(f.to_upper()), 1)
endif
endforeach
if host_machine.endian() == 'little'
conf_data.set('PIPE_ARCH_LITTLE_ENDIAN', true)
elif host_machine.endian() == 'big'

@ -22,8 +22,6 @@
#
sources_libgallium = [
'include/c99_compat.h',
'include/no_extern_c.h',
'include/pipe/p_config.h',
'include/pipe/p_defines.h',
'include/pipe/p_context.h',
@ -33,9 +31,6 @@ sources_libgallium = [
'include/pipe/p_screen.h',
'include/pipe/p_compiler.h',
'include/pipe/p_video_enums.h',
'include/c11/threads_win32.h',
'include/c11/threads.h',
'include/c11/threads_posix.h',
'auxiliary/util/u_format.h',
'auxiliary/util/u_memory.h',
'auxiliary/util/u_rect.h',

@ -41,12 +41,6 @@
typedef void (*tss_dtor_t)(void*);
typedef int (*thrd_start_t)(void*);
struct xtime {
time_t sec;
long nsec;
};
typedef struct xtime xtime;
/*-------------------- enumeration constants --------------------*/
enum {

@ -132,19 +132,15 @@ cnd_signal(cnd_t *cond)
// 7.25.3.5
static inline int
cnd_timedwait(cnd_t *cond, mtx_t *mtx, const xtime *xt)
cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *abs_time)
{
struct timespec abs_time;
int rt;
assert(mtx != NULL);
assert(cond != NULL);
assert(xt != NULL);
assert(abs_time != NULL);
abs_time.tv_sec = xt->sec;
abs_time.tv_nsec = xt->nsec;
rt = pthread_cond_timedwait(cond, mtx, &abs_time);
rt = pthread_cond_timedwait(cond, mtx, abs_time);
if (rt == ETIMEDOUT)
return thrd_busy;
return (rt == 0) ? thrd_success : thrd_error;
@ -169,6 +165,32 @@ mtx_destroy(mtx_t *mtx)
pthread_mutex_destroy(mtx);
}
/*
* XXX: Workaround when building with -O0 and without pthreads link.
*
* In such cases constant folding and dead code elimination won't be
* available, thus the compiler will always add the pthread_mutexattr*
* functions into the binary. As we try to link, we'll fail as the
* symbols are unresolved.
*
* Ideally we'll enable the optimisations locally, yet that does not
* seem to work.
*
* So the alternative workaround is to annotate the symbols as weak.
* Thus the linker will be happy and things don't clash when building
* with -O1 or greater.
*/
#if defined(HAVE_FUNC_ATTRIBUTE_WEAK) && !defined(__CYGWIN__)
__attribute__((weak))
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
__attribute__((weak))
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);
__attribute__((weak))
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
#endif
// 7.25.4.2
static inline int
mtx_init(mtx_t *mtx, int type)
@ -180,9 +202,14 @@ mtx_init(mtx_t *mtx, int type)
&& type != (mtx_timed|mtx_recursive)
&& type != (mtx_try|mtx_recursive))
return thrd_error;
if ((type & mtx_recursive) == 0) {
pthread_mutex_init(mtx, NULL);
return thrd_success;
}
pthread_mutexattr_init(&attr);
if ((type & mtx_recursive) != 0)
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(mtx, &attr);
pthread_mutexattr_destroy(&attr);
return thrd_success;
@ -204,24 +231,21 @@ thrd_yield(void);
// 7.25.4.4
static inline int
mtx_timedlock(mtx_t *mtx, const xtime *xt)
mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
{
assert(mtx != NULL);
assert(xt != NULL);
assert(ts != NULL);
{
#ifdef EMULATED_THREADS_USE_NATIVE_TIMEDLOCK
struct timespec ts;
int rt;
ts.tv_sec = xt->sec;
ts.tv_nsec = xt->nsec;
rt = pthread_mutex_timedlock(mtx, &ts);
rt = pthread_mutex_timedlock(mtx, ts);
if (rt == 0)
return thrd_success;
return (rt == ETIMEDOUT) ? thrd_busy : thrd_error;
#else
time_t expire = time(NULL);
expire += xt->sec;
expire += ts->tv_sec;
while (mtx_trylock(mtx) != thrd_success) {
time_t now = time(NULL);
if (expire < now)
@ -311,13 +335,10 @@ thrd_join(thrd_t thr, int *res)
// 7.25.5.7
static inline void
thrd_sleep(const xtime *xt)
thrd_sleep(const struct timespec *time_point, struct timespec *remaining)
{
struct timespec req;
assert(xt);
req.tv_sec = xt->sec;
req.tv_nsec = xt->nsec;
nanosleep(&req, NULL);
assert(time_point != NULL);
nanosleep(time_point, remaining);
}
// 7.25.5.8
@ -361,14 +382,15 @@ tss_set(tss_t key, void *val)
/*-------------------- 7.25.7 Time functions --------------------*/
// 7.25.6.1
#ifndef HAVE_TIMESPEC_GET
static inline int
xtime_get(xtime *xt, int base)
timespec_get(struct timespec *ts, int base)
{
if (!xt) return 0;
if (!ts) return 0;
if (base == TIME_UTC) {
xt->sec = time(NULL);
xt->nsec = 0;
clock_gettime(CLOCK_REALTIME, ts);
return base;
}
return 0;
}
#endif

@ -42,23 +42,14 @@ Configuration macro:
(requires WinVista or later)
Otherwise emulate by mtx_trylock() + *busy loop* for WinXP.
EMULATED_THREADS_USE_NATIVE_CV
Use native WindowsAPI condition variable object.
(requires WinVista or later)
Otherwise use emulated implementation for WinXP.
EMULATED_THREADS_TSS_DTOR_SLOTNUM
Max registerable TSS dtor number.
*/
// XXX: Retain XP compatability
#if 0
#if _WIN32_WINNT >= 0x0600
// Prefer native WindowsAPI on newer environment.
#if !defined(__MINGW32__)
#define EMULATED_THREADS_USE_NATIVE_CALL_ONCE
#endif
#define EMULATED_THREADS_USE_NATIVE_CV
#define EMULATED_THREADS_USE_NATIVE_CALL_ONCE
#endif
#endif
#define EMULATED_THREADS_TSS_DTOR_SLOTNUM 64 // see TLS_MINIMUM_AVAILABLE
@ -71,11 +62,11 @@ Configuration macro:
#error EMULATED_THREADS_USE_NATIVE_CALL_ONCE requires _WIN32_WINNT>=0x0600
#endif
#if defined(EMULATED_THREADS_USE_NATIVE_CV) && (_WIN32_WINNT < 0x0600)
#error EMULATED_THREADS_USE_NATIVE_CV requires _WIN32_WINNT>=0x0600
/* Visual Studio 2015 and later */
#ifdef _MSC_VER
#define HAVE_TIMESPEC_GET
#endif
/*---------------------------- macros ----------------------------*/
#ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE
#define ONCE_FLAG_INIT INIT_ONCE_STATIC_INIT
@ -88,18 +79,7 @@ Configuration macro:
#define _MTX_INITIALIZER_NP {(PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0}
/*---------------------------- types ----------------------------*/
typedef struct cnd_t {
#ifdef EMULATED_THREADS_USE_NATIVE_CV
CONDITION_VARIABLE condvar;
#else
int blocked;
int gone;
int to_unblock;
HANDLE sem_queue;
HANDLE sem_gate;
CRITICAL_SECTION monitor;
#endif
} cnd_t;
typedef CONDITION_VARIABLE cnd_t;
typedef HANDLE thrd_t;
@ -146,11 +126,23 @@ static unsigned __stdcall impl_thrd_routine(void *p)
return (unsigned)code;
}
static DWORD impl_xtime2msec(const xtime *xt)
static time_t impl_timespec2msec(const struct timespec *ts)
{
return (DWORD)((xt->sec * 1000U) + (xt->nsec / 1000000L));
return (ts->tv_sec * 1000U) + (ts->tv_nsec / 1000000L);
}
#ifdef HAVE_TIMESPEC_GET
static DWORD impl_abs2relmsec(const struct timespec *abs_time)
{
const time_t abs_ms = impl_timespec2msec(abs_time);
struct timespec now;
timespec_get(&now, TIME_UTC);
const time_t now_ms = impl_timespec2msec(&now);
const DWORD rel_ms = (abs_ms > now_ms) ? (DWORD)(abs_ms - now_ms) : 0;
return rel_ms;
}
#endif
#ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE
struct impl_call_once_param { void (*func)(void); };
static BOOL CALLBACK impl_call_once_callback(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
@ -162,103 +154,6 @@ static BOOL CALLBACK impl_call_once_callback(PINIT_ONCE InitOnce, PVOID Paramete
}
#endif // ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE
#ifndef EMULATED_THREADS_USE_NATIVE_CV
/*
Note:
The implementation of condition variable is ported from Boost.Interprocess
See http://www.boost.org/boost/interprocess/sync/windows/condition.hpp
*/
static void impl_cond_do_signal(cnd_t *cond, int broadcast)
{
int nsignal = 0;
EnterCriticalSection(&cond->monitor);
if (cond->to_unblock != 0) {
if (cond->blocked == 0) {
LeaveCriticalSection(&cond->monitor);
return;
}
if (broadcast) {
cond->to_unblock += nsignal = cond->blocked;
cond->blocked = 0;
} else {
nsignal = 1;
cond->to_unblock++;
cond->blocked--;
}
} else if (cond->blocked > cond->gone) {
WaitForSingleObject(cond->sem_gate, INFINITE);
if (cond->gone != 0) {
cond->blocked -= cond->gone;
cond->gone = 0;
}
if (broadcast) {
nsignal = cond->to_unblock = cond->blocked;
cond->blocked = 0;
} else {
nsignal = cond->to_unblock = 1;
cond->blocked--;
}
}
LeaveCriticalSection(&cond->monitor);
if (0 < nsignal)
ReleaseSemaphore(cond->sem_queue, nsignal, NULL);
}
static int impl_cond_do_wait(cnd_t *cond, mtx_t *mtx, const xtime *xt)
{
int nleft = 0;
int ngone = 0;
int timeout = 0;
DWORD w;
WaitForSingleObject(cond->sem_gate, INFINITE);
cond->blocked++;
ReleaseSemaphore(cond->sem_gate, 1, NULL);
mtx_unlock(mtx);
w = WaitForSingleObject(cond->sem_queue, xt ? impl_xtime2msec(xt) : INFINITE);
timeout = (w == WAIT_TIMEOUT);
EnterCriticalSection(&cond->monitor);
if ((nleft = cond->to_unblock) != 0) {
if (timeout) {
if (cond->blocked != 0) {
cond->blocked--;
} else {
cond->gone++;
}
}
if (--cond->to_unblock == 0) {
if (cond->blocked != 0) {
ReleaseSemaphore(cond->sem_gate, 1, NULL);
nleft = 0;
}
else if ((ngone = cond->gone) != 0) {
cond->gone = 0;
}
}
} else if (++cond->gone == INT_MAX/2) {
WaitForSingleObject(cond->sem_gate, INFINITE);
cond->blocked -= cond->gone;
ReleaseSemaphore(cond->sem_gate, 1, NULL);
cond->gone = 0;
}
LeaveCriticalSection(&cond->monitor);
if (nleft == 1) {
while (ngone--)
WaitForSingleObject(cond->sem_queue, INFINITE);
ReleaseSemaphore(cond->sem_gate, 1, NULL);
}
mtx_lock(mtx);
return timeout ? thrd_busy : thrd_success;
}
#endif // ifndef EMULATED_THREADS_USE_NATIVE_CV
static struct impl_tss_dtor_entry {
tss_t key;
tss_dtor_t dtor;
@ -322,12 +217,8 @@ call_once(once_flag *flag, void (*func)(void))
static inline int
cnd_broadcast(cnd_t *cond)
{
if (!cond) return thrd_error;
#ifdef EMULATED_THREADS_USE_NATIVE_CV
WakeAllConditionVariable(&cond->condvar);
#else
impl_cond_do_signal(cond, 1);
#endif
assert(cond != NULL);
WakeAllConditionVariable(cond);
return thrd_success;
}
@ -335,31 +226,16 @@ cnd_broadcast(cnd_t *cond)
static inline void
cnd_destroy(cnd_t *cond)
{
assert(cond);
#ifdef EMULATED_THREADS_USE_NATIVE_CV
assert(cond != NULL);
// do nothing
#else
CloseHandle(cond->sem_queue);
CloseHandle(cond->sem_gate);
DeleteCriticalSection(&cond->monitor);
#endif
}
// 7.25.3.3
static inline int
cnd_init(cnd_t *cond)
{
if (!cond) return thrd_error;
#ifdef EMULATED_THREADS_USE_NATIVE_CV
InitializeConditionVariable(&cond->condvar);
#else
cond->blocked = 0;
cond->gone = 0;
cond->to_unblock = 0;
cond->sem_queue = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
cond->sem_gate = CreateSemaphore(NULL, 1, 1, NULL);
InitializeCriticalSection(&cond->monitor);
#endif
assert(cond != NULL);
InitializeConditionVariable(cond);
return thrd_success;
}
@ -367,26 +243,25 @@ cnd_init(cnd_t *cond)
static inline int
cnd_signal(cnd_t *cond)
{
if (!cond) return thrd_error;
#ifdef EMULATED_THREADS_USE_NATIVE_CV
WakeConditionVariable(&cond->condvar);
#else
impl_cond_do_signal(cond, 0);
#endif
assert(cond != NULL);
WakeConditionVariable(cond);
return thrd_success;
}
// 7.25.3.5
static inline int
cnd_timedwait(cnd_t *cond, mtx_t *mtx, const xtime *xt)
{
if (!cond || !mtx || !xt) return thrd_error;
#ifdef EMULATED_THREADS_USE_NATIVE_CV
if (SleepConditionVariableCS(&cond->condvar, mtx, impl_xtime2msec(xt)))
cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *abs_time)
{
assert(cond != NULL);
assert(mtx != NULL);
assert(abs_time != NULL);
#ifdef HAVE_TIMESPEC_GET
const DWORD timeout = impl_abs2relmsec(abs_time);
if (SleepConditionVariableCS(cond, mtx, timeout))
return thrd_success;
return (GetLastError() == ERROR_TIMEOUT) ? thrd_busy : thrd_error;
#else
return impl_cond_do_wait(cond, mtx, xt);
return thrd_error;
#endif
}
@ -394,12 +269,9 @@ cnd_timedwait(cnd_t *cond, mtx_t *mtx, const xtime *xt)
static inline int
cnd_wait(cnd_t *cond, mtx_t *mtx)
{
if (!cond || !mtx) return thrd_error;
#ifdef EMULATED_THREADS_USE_NATIVE_CV
SleepConditionVariableCS(&cond->condvar, mtx, INFINITE);
#else
impl_cond_do_wait(cond, mtx, NULL);
#endif
assert(cond != NULL);
assert(mtx != NULL);
SleepConditionVariableCS(cond, mtx, INFINITE);
return thrd_success;
}
@ -417,7 +289,7 @@ mtx_destroy(mtx_t *mtx)
static inline int
mtx_init(mtx_t *mtx, int type)
{
if (!mtx) return thrd_error;
assert(mtx != NULL);
if (type != mtx_plain && type != mtx_timed && type != mtx_try
&& type != (mtx_plain|mtx_recursive)
&& type != (mtx_timed|mtx_recursive)
@ -431,34 +303,35 @@ mtx_init(mtx_t *mtx, int type)
static inline int
mtx_lock(mtx_t *mtx)
{
if (!mtx) return thrd_error;
assert(mtx != NULL);
EnterCriticalSection(mtx);
return thrd_success;
}
// 7.25.4.4
static inline int
mtx_timedlock(mtx_t *mtx, const xtime *xt)
mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
{
time_t expire, now;
if (!mtx || !xt) return thrd_error;
expire = time(NULL);
expire += xt->sec;
assert(mtx != NULL);
assert(ts != NULL);
#ifdef HAVE_TIMESPEC_GET
while (mtx_trylock(mtx) != thrd_success) {
now = time(NULL);
if (expire < now)
if (impl_abs2relmsec(ts) == 0)
return thrd_busy;
// busy loop!
thrd_yield();
}
return thrd_success;
#else
return thrd_error;
#endif
}
// 7.25.4.5
static inline int
mtx_trylock(mtx_t *mtx)
{
if (!mtx) return thrd_error;
assert(mtx != NULL);
return TryEnterCriticalSection(mtx) ? thrd_success : thrd_busy;
}
@ -466,7 +339,7 @@ mtx_trylock(mtx_t *mtx)
static inline int
mtx_unlock(mtx_t *mtx)
{
if (!mtx) return thrd_error;
assert(mtx != NULL);
LeaveCriticalSection(mtx);
return thrd_success;
}
@ -479,7 +352,7 @@ thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
{
struct impl_thrd_param *pack;
uintptr_t handle;
if (!thr) return thrd_error;
assert(thr != NULL);
pack = (struct impl_thrd_param *)malloc(sizeof(struct impl_thrd_param));
if (!pack) return thrd_nomem;
pack->func = func;
@ -502,9 +375,13 @@ thrd_current(void)
HANDLE hCurrentThread;
BOOL bRet;
/* GetCurrentThread() returns a pseudo-handle, which is useless. We need
* to call DuplicateHandle to get a real handle. However the handle value
* will not match the one returned by thread_create.
/* GetCurrentThread() returns a pseudo-handle, which we need
* to pass to DuplicateHandle(). Only the resulting handle can be used
* from other threads.
*
* Note that neither handle can be compared to the one by thread_create.
* Only the thread IDs - as returned by GetThreadId() and GetCurrentThreadId()
* can be compared directly.
*
* Other potential solutions would be:
* - define thrd_t as a thread Ids, but this would mean we'd need to OpenThread for many operations
@ -575,10 +452,11 @@ thrd_join(thrd_t thr, int *res)
// 7.25.5.7
static inline void
thrd_sleep(const xtime *xt)
thrd_sleep(const struct timespec *time_point, struct timespec *remaining)
{
assert(xt);
Sleep(impl_xtime2msec(xt));
assert(time_point);
assert(!remaining); /* not implemented */
Sleep((DWORD)impl_timespec2msec(time_point));
}
// 7.25.5.8
@ -594,7 +472,7 @@ thrd_yield(void)
static inline int
tss_create(tss_t *key, tss_dtor_t dtor)
{
if (!key) return thrd_error;
assert(key != NULL);
*key = TlsAlloc();
if (dtor) {
if (impl_tss_dtor_register(*key, dtor)) {
@ -629,14 +507,16 @@ tss_set(tss_t key, void *val)
/*-------------------- 7.25.7 Time functions --------------------*/
// 7.25.6.1
#ifndef HAVE_TIMESPEC_GET
static inline int
xtime_get(xtime *xt, int base)
timespec_get(struct timespec *ts, int base)
{
if (!xt) return 0;
assert(ts != NULL);
if (base == TIME_UTC) {
xt->sec = time(NULL);
xt->nsec = 0;
ts->tv_sec = time(NULL);
ts->tv_nsec = 0;
return base;
}
return 0;
}
#endif

@ -0,0 +1,27 @@
/* Copyright 2019 Intel Corporation */
/* SPDX-License-Identifier: MIT */
#include "no_extern_c.h"
#ifndef _C11_COMPAT_H_
#define _C11_COMPAT_H_
#if defined(__cplusplus)
/* This is C++ code, not C */
#elif (__STDC_VERSION__ >= 201112L)
/* Already C11 */
#else
/*
* C11 static_assert() macro
* assert.h only defines that name for C11 and above
*/
#ifndef static_assert
#define static_assert _Static_assert
#endif
#endif /* !C++ && !C11 */
#endif /* _C11_COMPAT_H_ */

@ -36,17 +36,17 @@
*/
#if defined(_MSC_VER)
# if _MSC_VER < 1500
# error "Microsoft Visual Studio 2008 or higher required"
# if _MSC_VER < 1900
# error "Microsoft Visual Studio 2015 or higher required"
# endif
/*
* Visual Studio 2012 will complain if we define the `inline` keyword, but
* Visual Studio will complain if we define the `inline` keyword, but
* actually it only supports the keyword on C++.
*
* To avoid this the _ALLOW_KEYWORD_MACROS must be set.
*/
# if (_MSC_VER >= 1700) && !defined(_ALLOW_KEYWORD_MACROS)
# if !defined(_ALLOW_KEYWORD_MACROS)
# define _ALLOW_KEYWORD_MACROS
# endif
@ -96,7 +96,7 @@
* - http://cellperformance.beyond3d.com/articles/2006/05/demystifying-the-restrict-keyword.html
*/
#ifndef restrict
# if (__STDC_VERSION__ >= 199901L)
# if (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
/* C99 */
# elif defined(__GNUC__)
# define restrict __restrict__

@ -0,0 +1,211 @@
/**************************************************************************
*
* Copyright 2007-2015 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/**
* Wrapper for math.h which makes sure we have definitions of all the c99
* functions.
*/
#ifndef _C99_MATH_H_
#define _C99_MATH_H_
#include <math.h>
#include "c99_compat.h"
/* This is to ensure that we get M_PI, etc. definitions */
#if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
#error _USE_MATH_DEFINES define required when building with MSVC
#endif
#if !defined(_MSC_VER) && \
__STDC_VERSION__ < 199901L && \
(!defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600) && \
!defined(__cplusplus)
static inline long int
lrint(double d)
{
long int rounded = (long int)(d + 0.5);
if (d - floor(d) == 0.5) {
if (rounded % 2 != 0)
rounded += (d > 0) ? -1 : 1;
}
return rounded;
}
static inline long int
lrintf(float f)
{
long int rounded = (long int)(f + 0.5f);
if (f - floorf(f) == 0.5f) {
if (rounded % 2 != 0)
rounded += (f > 0) ? -1 : 1;
}
return rounded;
}
static inline long long int
llrint(double d)
{
long long int rounded = (long long int)(d + 0.5);
if (d - floor(d) == 0.5) {
if (rounded % 2 != 0)
rounded += (d > 0) ? -1 : 1;
}
return rounded;
}
static inline long long int
llrintf(float f)
{
long long int rounded = (long long int)(f + 0.5f);
if (f - floorf(f) == 0.5f) {
if (rounded % 2 != 0)
rounded += (f > 0) ? -1 : 1;
}
return rounded;
}
static inline float
exp2f(float f)
{
return powf(2.0f, f);
}
static inline double
exp2(double d)
{
return pow(2.0, d);
}
#endif /* C99 */
/*
* signbit() is a macro on Linux. Not available on Windows.
*/
#ifndef signbit
#define signbit(x) ((x) < 0.0f)
#endif
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif
#ifndef M_E
#define M_E (2.7182818284590452354)
#endif
#ifndef M_LOG2E
#define M_LOG2E (1.4426950408889634074)
#endif
#ifndef FLT_MAX_EXP
#define FLT_MAX_EXP 128
#endif
#if defined(fpclassify)
/* ISO C99 says that fpclassify is a macro. Assume that any implementation
* of fpclassify, whether it's in a C99 compiler or not, will be a macro.
*/
#elif defined(__cplusplus)
/* For C++, fpclassify() should be defined in <cmath> */
#elif defined(_MSC_VER)
/* Not required on VS2013 and above. Oddly, the fpclassify() function
* doesn't exist in such a form on MSVC. This is an implementation using
* slightly different lower-level Windows functions.
*/
#include <float.h>
static inline enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL}
fpclassify(double x)
{
switch(_fpclass(x)) {
case _FPCLASS_SNAN: /* signaling NaN */
case _FPCLASS_QNAN: /* quiet NaN */
return FP_NAN;
case _FPCLASS_NINF: /* negative infinity */
case _FPCLASS_PINF: /* positive infinity */
return FP_INFINITE;
case _FPCLASS_NN: /* negative normal */
case _FPCLASS_PN: /* positive normal */
return FP_NORMAL;
case _FPCLASS_ND: /* negative denormalized */
case _FPCLASS_PD: /* positive denormalized */
return FP_SUBNORMAL;
case _FPCLASS_NZ: /* negative zero */
case _FPCLASS_PZ: /* positive zero */
return FP_ZERO;
default:
/* Should never get here; but if we do, this will guarantee
* that the pattern is not treated like a number.
*/
return FP_NAN;
}
}
#else
#error "Need to include or define an fpclassify function"
#endif
/* Since C++11, the following functions are part of the std namespace. Their C
* counteparts should still exist in the global namespace, however cmath
* undefines those functions, which in glibc 2.23, are defined as macros rather
* than functions as in glibc 2.22.
*/
#if __cplusplus >= 201103L && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 23))
#include <cmath>
using std::fpclassify;
using std::isfinite;
using std::isinf;
using std::isnan;
using std::isnormal;
using std::signbit;
using std::isgreater;
using std::isgreaterequal;
using std::isless;
using std::islessequal;
using std::islessgreater;
using std::isunordered;
#endif
#endif /* #define _C99_MATH_H_ */

@ -27,7 +27,7 @@
/*
* Including system's headers inside `extern "C" { ... }` is not safe, as system
* headers may have C++ code in them, and C++ code inside extern "C"
* leads to syntatically incorrect code.
* leads to syntactically incorrect code.
*
* This is because putting code inside extern "C" won't make __cplusplus define
* go away, that is, the system header being included thinks is free to use C++

@ -1,12 +1,14 @@
# Copyright 2021 Google LLC
# SPDX-License-Identifier: MIT
inc_mesa = include_directories('.')
inc_mesa = include_directories('.', 'compat')
files_mesa = files(
)
deps_mesa = [
m_dep,
thread_dep,
]
libmesa = static_library(

Loading…
Cancel
Save