Branch data Line data Source code
1 : : /* 2 : : * This file is part of libplacebo. 3 : : * 4 : : * libplacebo is free software; you can redistribute it and/or 5 : : * modify it under the terms of the GNU Lesser General Public 6 : : * License as published by the Free Software Foundation; either 7 : : * version 2.1 of the License, or (at your option) any later version. 8 : : * 9 : : * libplacebo is distributed in the hope that it will be useful, 10 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 : : * GNU Lesser General Public License for more details. 13 : : * 14 : : * You should have received a copy of the GNU Lesser General Public 15 : : * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>. 16 : : */ 17 : : 18 : : #pragma once 19 : : 20 : : #include <errno.h> 21 : : #include <pthread.h> 22 : : #include <sys/time.h> 23 : : #include <time.h> 24 : : 25 : : #include <pl_assert.h> 26 : : 27 : : typedef pthread_mutex_t pl_mutex; 28 : : typedef pthread_cond_t pl_cond; 29 : : typedef pthread_mutex_t pl_static_mutex; 30 : : typedef pthread_t pl_thread; 31 : : #define PL_STATIC_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 32 : : 33 : 140 : static inline int pl_mutex_init_type_internal(pl_mutex *mutex, enum pl_mutex_type mtype) 34 : : { 35 : : int mutex_type; 36 [ + + ]: 140 : switch (mtype) { 37 : : case PL_MUTEX_RECURSIVE: 38 : : mutex_type = PTHREAD_MUTEX_RECURSIVE; 39 : : break; 40 : 133 : case PL_MUTEX_NORMAL: 41 : : default: 42 : : #ifndef NDEBUG 43 : : mutex_type = PTHREAD_MUTEX_ERRORCHECK; 44 : : #else 45 : : mutex_type = PTHREAD_MUTEX_DEFAULT; 46 : : #endif 47 : 133 : break; 48 : : } 49 : : 50 : : int ret = 0; 51 : : pthread_mutexattr_t attr; 52 : 140 : ret = pthread_mutexattr_init(&attr); 53 [ + - ]: 140 : if (ret != 0) 54 : : return ret; 55 : : 56 : 140 : pthread_mutexattr_settype(&attr, mutex_type); 57 : 140 : ret = pthread_mutex_init(mutex, &attr); 58 : 140 : pthread_mutexattr_destroy(&attr); 59 : 140 : return ret; 60 : : } 61 : : 62 : : #define pl_mutex_init_type(mutex, mtype) \ 63 : : pl_assert(!pl_mutex_init_type_internal(mutex, mtype)) 64 : : 65 : : #define pl_mutex_destroy pthread_mutex_destroy 66 : : #define pl_mutex_lock pthread_mutex_lock 67 : : #define pl_mutex_unlock pthread_mutex_unlock 68 : : 69 : 4 : static inline int pl_cond_init(pl_cond *cond) 70 : : { 71 : : int ret = 0; 72 : : pthread_condattr_t attr; 73 : 4 : ret = pthread_condattr_init(&attr); 74 [ + - ]: 4 : if (ret != 0) 75 : : return ret; 76 : : 77 : : #ifdef PTHREAD_HAS_SETCLOCK 78 : 4 : pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); 79 : : #endif 80 : 4 : ret = pthread_cond_init(cond, &attr); 81 : 4 : pthread_condattr_destroy(&attr); 82 : 4 : return ret; 83 : : } 84 : : 85 : : #define pl_cond_destroy pthread_cond_destroy 86 : : #define pl_cond_broadcast pthread_cond_broadcast 87 : : #define pl_cond_signal pthread_cond_signal 88 : : #define pl_cond_wait pthread_cond_wait 89 : : 90 : 72 : static inline int pl_cond_timedwait(pl_cond *cond, pl_mutex *mutex, uint64_t timeout) 91 : : { 92 [ - + ]: 72 : if (timeout == UINT64_MAX) 93 : 0 : return pthread_cond_wait(cond, mutex); 94 : : 95 : : struct timespec ts; 96 : : #ifdef PTHREAD_HAS_SETCLOCK 97 [ - + ]: 72 : if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) 98 : 0 : return errno; 99 : : #else 100 : : struct timeval tv; 101 : : if (gettimeofday(&tv, NULL) < 0) // equivalent to CLOCK_REALTIME 102 : : return errno; 103 : : ts.tv_sec = tv.tv_sec; 104 : : ts.tv_nsec = tv.tv_usec * 1000; 105 : : #endif 106 : : 107 : 72 : ts.tv_sec += timeout / 1000000000LLU; 108 : 72 : ts.tv_nsec += timeout % 1000000000LLU; 109 : : 110 [ - + ]: 72 : if (ts.tv_nsec > 1000000000L) { 111 : 0 : ts.tv_nsec -= 1000000000L; 112 : 0 : ts.tv_sec++; 113 : : } 114 : : 115 : 72 : return pthread_cond_timedwait(cond, mutex, &ts); 116 : : } 117 : : 118 : : #define pl_static_mutex_lock pthread_mutex_lock 119 : : #define pl_static_mutex_unlock pthread_mutex_unlock 120 : : 121 : : #define PL_THREAD_VOID void * 122 : : #define PL_THREAD_RETURN() return NULL 123 : : 124 : : #define pl_thread_create(t, f, a) pthread_create(t, NULL, f, a) 125 : : #define pl_thread_join(t) pthread_join(t, NULL) 126 : : 127 : : static inline bool pl_thread_sleep(double t) 128 : : { 129 : : if (t <= 0.0) 130 : : return true; 131 : : 132 : : struct timespec ts; 133 : : ts.tv_sec = (time_t) t; 134 : : ts.tv_nsec = (t - ts.tv_sec) * 1e9; 135 : : 136 : : return nanosleep(&ts, NULL) == 0; 137 : : }