From 90ab7ae537400a75f6a504a6ea3af4443e2cd511 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 23 Sep 2021 14:37:28 -0700 Subject: [PATCH] mesa: update to the latest c99/c11 compat headers No visible API change. Signed-off-by: Chia-I Wu Reviewed-by: Yiwei Zhang Reviewed-by: Ryan Neph Acked-by: Gert Wollny --- config.h.meson | 2 + meson.build | 13 + src/gallium/meson.build | 5 - .../include => mesa/compat}/c11/threads.h | 6 - .../compat}/c11/threads_posix.h | 74 +++-- .../compat}/c11/threads_win32.h | 258 +++++------------- src/mesa/compat/c11_compat.h | 27 ++ .../include => mesa/compat}/c99_compat.h | 10 +- src/mesa/compat/c99_math.h | 211 ++++++++++++++ .../include => mesa/compat}/no_extern_c.h | 2 +- src/mesa/meson.build | 4 +- 11 files changed, 379 insertions(+), 233 deletions(-) rename src/{gallium/include => mesa/compat}/c11/threads.h (96%) rename src/{gallium/include => mesa/compat}/c11/threads_posix.h (82%) rename src/{gallium/include => mesa/compat}/c11/threads_win32.h (65%) create mode 100644 src/mesa/compat/c11_compat.h rename src/{gallium/include => mesa/compat}/c99_compat.h (93%) create mode 100644 src/mesa/compat/c99_math.h rename src/{gallium/include => mesa/compat}/no_extern_c.h (97%) diff --git a/config.h.meson b/config.h.meson index be10030..1b59cd3 100644 --- a/config.h.meson +++ b/config.h.meson @@ -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 diff --git a/meson.build b/meson.build index 0ac36dc..d2c159a 100644 --- a/meson.build +++ b/meson.build @@ -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' diff --git a/src/gallium/meson.build b/src/gallium/meson.build index 67decf4..019b034 100644 --- a/src/gallium/meson.build +++ b/src/gallium/meson.build @@ -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', diff --git a/src/gallium/include/c11/threads.h b/src/mesa/compat/c11/threads.h similarity index 96% rename from src/gallium/include/c11/threads.h rename to src/mesa/compat/c11/threads.h index 45823df..3c3f23a 100644 --- a/src/gallium/include/c11/threads.h +++ b/src/mesa/compat/c11/threads.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 { diff --git a/src/gallium/include/c11/threads_posix.h b/src/mesa/compat/c11/threads_posix.h similarity index 82% rename from src/gallium/include/c11/threads_posix.h rename to src/mesa/compat/c11/threads_posix.h index ce9853b..45cb607 100644 --- a/src/gallium/include/c11/threads_posix.h +++ b/src/mesa/compat/c11/threads_posix.h @@ -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 diff --git a/src/gallium/include/c11/threads_win32.h b/src/mesa/compat/c11/threads_win32.h similarity index 65% rename from src/gallium/include/c11/threads_win32.h rename to src/mesa/compat/c11/threads_win32.h index d017c31..02c2a73 100644 --- a/src/gallium/include/c11/threads_win32.h +++ b/src/mesa/compat/c11/threads_win32.h @@ -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 diff --git a/src/mesa/compat/c11_compat.h b/src/mesa/compat/c11_compat.h new file mode 100644 index 0000000..d35740f --- /dev/null +++ b/src/mesa/compat/c11_compat.h @@ -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_ */ diff --git a/src/gallium/include/c99_compat.h b/src/mesa/compat/c99_compat.h similarity index 93% rename from src/gallium/include/c99_compat.h rename to src/mesa/compat/c99_compat.h index 4be5b7e..ab1ec53 100644 --- a/src/gallium/include/c99_compat.h +++ b/src/mesa/compat/c99_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__ diff --git a/src/mesa/compat/c99_math.h b/src/mesa/compat/c99_math.h new file mode 100644 index 0000000..e906c26 --- /dev/null +++ b/src/mesa/compat/c99_math.h @@ -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 +#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 */ +#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 + +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 + +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_ */ diff --git a/src/gallium/include/no_extern_c.h b/src/mesa/compat/no_extern_c.h similarity index 97% rename from src/gallium/include/no_extern_c.h rename to src/mesa/compat/no_extern_c.h index f79602c..f2f14aa 100644 --- a/src/gallium/include/no_extern_c.h +++ b/src/mesa/compat/no_extern_c.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++ diff --git a/src/mesa/meson.build b/src/mesa/meson.build index e132510..772b739 100644 --- a/src/mesa/meson.build +++ b/src/mesa/meson.build @@ -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(