X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fpthread.c;h=5385d7c0a08594b43ea54e783023690300eb0481;hb=7f42234cabfde2f61ced5694eb9e09ea49c40987;hp=47ac47831d2a120bc01bb560bbcf8db85de8ed35;hpb=4428a70078bb99e670a6a994bce4d21ea412353c;p=vlc diff --git a/src/misc/pthread.c b/src/misc/pthread.c index 47ac47831d..5385d7c0a0 100644 --- a/src/misc/pthread.c +++ b/src/misc/pthread.c @@ -35,6 +35,7 @@ #include #include /* fsync() */ #include +#include #include #ifdef __linux__ @@ -47,6 +48,7 @@ #ifdef __APPLE__ # include /* gettimeofday in vlc_cond_timedwait */ +# include /* mach_task_self in semaphores */ #endif /** @@ -88,6 +90,7 @@ static void vlc_thread_fatal (const char *action, int error, const char *function, const char *file, unsigned line) { + int canc = vlc_savecancel (); fprintf (stderr, "LibVLC fatal error %s (%d) in thread %lu ", action, error, vlc_threadid ()); vlc_trace (function, file, line); @@ -118,11 +121,13 @@ vlc_thread_fatal (const char *action, int error, #endif fflush (stderr); + vlc_restorecancel (canc); abort (); } # define VLC_THREAD_ASSERT( action ) \ - if (val) vlc_thread_fatal (action, val, __func__, __FILE__, __LINE__) + if (unlikely(val)) \ + vlc_thread_fatal (action, val, __func__, __FILE__, __LINE__) #else # define VLC_THREAD_ASSERT( action ) ((void)val) #endif @@ -139,7 +144,7 @@ void vlc_mutex_init( vlc_mutex_t *p_mutex ) { pthread_mutexattr_t attr; - if( pthread_mutexattr_init( &attr ) ) + if (unlikely(pthread_mutexattr_init (&attr))) abort(); #ifdef NDEBUG pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_NORMAL ); @@ -151,7 +156,7 @@ void vlc_mutex_init( vlc_mutex_t *p_mutex ) pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ERRORCHECK ); # endif #endif - if( pthread_mutex_init( p_mutex, &attr ) ) + if (unlikely(pthread_mutex_init (p_mutex, &attr))) abort(); pthread_mutexattr_destroy( &attr ); } @@ -163,13 +168,14 @@ void vlc_mutex_init_recursive( vlc_mutex_t *p_mutex ) { pthread_mutexattr_t attr; - pthread_mutexattr_init( &attr ); + if (unlikely(pthread_mutexattr_init (&attr))) + abort(); #if defined (__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ < 6) pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_RECURSIVE_NP ); #else pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ); #endif - if( pthread_mutex_init( p_mutex, &attr ) ) + if (unlikely(pthread_mutex_init (p_mutex, &attr))) abort(); pthread_mutexattr_destroy( &attr ); } @@ -251,14 +257,14 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex) VLC_THREAD_ASSERT ("unlocking mutex"); } -/***************************************************************************** - * vlc_cond_init: initialize a condition variable - *****************************************************************************/ -void vlc_cond_init( vlc_cond_t *p_condvar ) +/** + * Initializes a condition variable. + */ +void vlc_cond_init (vlc_cond_t *p_condvar) { pthread_condattr_t attr; - if (pthread_condattr_init (&attr)) + if (unlikely(pthread_condattr_init (&attr))) abort (); #if !defined (_POSIX_CLOCK_SELECTION) /* Fairly outdated POSIX support (that was defined in 2001) */ @@ -269,11 +275,22 @@ void vlc_cond_init( vlc_cond_t *p_condvar ) pthread_condattr_setclock (&attr, CLOCK_MONOTONIC); #endif - if (pthread_cond_init (p_condvar, &attr)) + if (unlikely(pthread_cond_init (p_condvar, &attr))) abort (); pthread_condattr_destroy (&attr); } +/** + * Initializes a condition variable. + * Contrary to vlc_cond_init(), the wall clock will be used as a reference for + * the vlc_cond_timedwait() time-out parameter. + */ +void vlc_cond_init_daytime (vlc_cond_t *p_condvar) +{ + if (unlikely(pthread_cond_init (p_condvar, NULL))) + abort (); +} + /** * Destroys a condition variable. No threads shall be waiting or signaling the * condition. @@ -346,7 +363,11 @@ void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex) /** * Waits for a condition variable up to a certain date. - * This works like vlc_cond_wait(), except for the additional timeout. + * This works like vlc_cond_wait(), except for the additional time-out. + * + * If the variable was initialized with vlc_cond_init(), the timeout has the + * same arbitrary origin as mdate(). If the variable was initialized with + * vlc_cond_init_daytime(), the timeout is expressed from the Unix epoch. * * @param p_condvar condition variable to wait on * @param p_mutex mutex which is unlocked while waiting, @@ -377,12 +398,96 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex, return val; } +/** + * Initializes a semaphore. + */ +void vlc_sem_init (vlc_sem_t *sem, unsigned value) +{ +#if defined(__APPLE__) + if (unlikely(semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, value) != KERN_SUCCESS)) + abort (); +#else + if (unlikely(sem_init (sem, 0, value))) + abort (); +#endif +} + +/** + * Destroys a semaphore. + */ +void vlc_sem_destroy (vlc_sem_t *sem) +{ + int val; + +#if defined(__APPLE__) + if (likely(semaphore_destroy(mach_task_self(), *sem) == KERN_SUCCESS)) + return; + + val = EINVAL; +#else + if (likely(sem_destroy (sem) == 0)) + return; + + val = errno; +#endif + + VLC_THREAD_ASSERT ("destroying semaphore"); +} + +/** + * Increments the value of a semaphore. + * @return 0 on success, EOVERFLOW in case of integer overflow + */ +int vlc_sem_post (vlc_sem_t *sem) +{ + int val; + +#if defined(__APPLE__) + if (likely(semaphore_signal(*sem) == KERN_SUCCESS)) + return 0; + + val = EINVAL; +#else + if (likely(sem_post (sem) == 0)) + return 0; + + val = errno; +#endif + + if (unlikely(val != EOVERFLOW)) + VLC_THREAD_ASSERT ("unlocking semaphore"); + return val; +} + +/** + * Atomically wait for the semaphore to become non-zero (if needed), + * then decrements it. + */ +void vlc_sem_wait (vlc_sem_t *sem) +{ + int val; + +#if defined(__APPLE__) + if (likely(semaphore_wait(*sem) == KERN_SUCCESS)) + return; + + val = EINVAL; +#else + do + if (likely(sem_wait (sem) == 0)) + return; + while ((val = errno) == EINTR); +#endif + + VLC_THREAD_ASSERT ("locking semaphore"); +} + /** * Initializes a read/write lock. */ void vlc_rwlock_init (vlc_rwlock_t *lock) { - if (pthread_rwlock_init (lock, NULL)) + if (unlikely(pthread_rwlock_init (lock, NULL))) abort (); } @@ -477,10 +582,10 @@ void vlc_threads_setup (libvlc_int_t *p_libvlc) if (!initialized) { #ifndef __APPLE__ - if (config_GetInt (p_libvlc, "rt-priority")) + if (var_InheritBool (p_libvlc, "rt-priority")) #endif { - rt_offset = config_GetInt (p_libvlc, "rt-offset"); + rt_offset = var_InheritInteger (p_libvlc, "rt-offset"); rt_priorities = true; } initialized = true; @@ -583,6 +688,9 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data, void vlc_cancel (vlc_thread_t thread_id) { pthread_cancel (thread_id); +#ifdef HAVE_MAEMO + pthread_kill (thread_id, SIGRTMIN); +#endif } /** @@ -655,7 +763,7 @@ void vlc_restorecancel (int state) /* This should fail if an invalid value for given for state */ VLC_THREAD_ASSERT ("restoring cancellation"); - if (oldstate != PTHREAD_CANCEL_DISABLE) + if (unlikely(oldstate != PTHREAD_CANCEL_DISABLE)) vlc_thread_fatal ("restoring cancellation while not disabled", EINVAL, __func__, __FILE__, __LINE__); #else @@ -755,7 +863,7 @@ int vlc_timer_create (vlc_timer_t *id, void (*func) (void *), void *data) { struct vlc_timer *timer = malloc (sizeof (*timer)); - if (timer == NULL) + if (unlikely(timer == NULL)) return ENOMEM; vlc_mutex_init (&timer->lock); vlc_cond_init (&timer->wait); @@ -812,11 +920,16 @@ void vlc_timer_destroy (vlc_timer_t timer) void vlc_timer_schedule (vlc_timer_t timer, bool absolute, mtime_t value, mtime_t interval) { + static vlc_mutex_t lock = VLC_STATIC_MUTEX; + + vlc_mutex_lock (&lock); vlc_mutex_lock (&timer->lock); if (timer->value) { + vlc_mutex_unlock (&timer->lock); vlc_cancel (timer->thread); vlc_join (timer->thread, NULL); + vlc_mutex_lock (&timer->lock); timer->value = 0; } if ((value != 0) @@ -827,6 +940,7 @@ void vlc_timer_schedule (vlc_timer_t timer, bool absolute, timer->interval = interval; } vlc_mutex_unlock (&timer->lock); + vlc_mutex_unlock (&lock); } /**