Пример #1
0
/**
 * Waits for a condition variable up to a certain date.
 * 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,
 *                then locked again when waking up.
 * @param deadline <b>absolute</b> timeout
 *
 * @return 0 if the condition was signaled, an error code in case of timeout.
 */
int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
                        mtime_t deadline)
{
#if defined(__APPLE__) && !defined(__powerpc__) && !defined( __ppc__ ) && !defined( __ppc64__ )
    /* mdate() is the monotonic clock, timedwait origin is gettimeofday() which
     * isn't monotonic. Use imedwait_relative_np() instead
    */
    mtime_t base = mdate();
    deadline -= base;
    if (deadline < 0)
        deadline = 0;
    lldiv_t d = lldiv( deadline, CLOCK_FREQ );
    struct timespec ts = { d.quot, d.rem * (1000000000 / CLOCK_FREQ) };

    int val = pthread_cond_timedwait_relative_np(p_condvar, p_mutex, &ts);
    if (val != ETIMEDOUT)
        VLC_THREAD_ASSERT ("timed-waiting on condition");
    return val;
#else
    lldiv_t d = lldiv( deadline, CLOCK_FREQ );
    struct timespec ts = { d.quot, d.rem * (1000000000 / CLOCK_FREQ) };
    int val = pthread_cond_timedwait (p_condvar, p_mutex, &ts);
    if (val != ETIMEDOUT)
        VLC_THREAD_ASSERT ("timed-waiting on condition");
    return val;
#endif
}
Пример #2
0
/**
 * Increments the value of a semaphore.
 */
int vlc_sem_post (vlc_sem_t *sem)
{
    int val = sem_post (sem);
    if (val != EOVERFLOW)
        VLC_THREAD_ASSERT ("unlocking semaphore");
    return val;
}
Пример #3
0
/* Destroys a condition variable. No threads shall be waiting or signaling the
 * condition.
 * parameter: p_condvar condition variable to destroy */
void vlc_cond_destroy (vlc_cond_t *p_condvar)
{
    int val = pthread_cond_destroy( p_condvar );

    /* due to a faulty pthread implementation within Darwin 11 and
     * later condition variables cannot be destroyed without
     * terminating the application immediately.
     * This Darwin kernel issue is still present in version 13
     * and might not be resolved prior to Darwin 15.
     * radar://12496249
     *
     * To work-around this, we are just leaking the condition variable
     * which is acceptable due to VLC's low number of created variables
     * and its usually limited runtime.
     * Ideally, we should implement a re-useable pool.
     */
    if (val != 0) {
        #ifndef NDEBUG
        printf("pthread_cond_destroy returned %i\n", val);
        #endif

        if (val == EBUSY)
            return;
    }

    VLC_THREAD_ASSERT ("destroying condition");
}
Пример #4
0
/**
 * Atomically wait for the semaphore to become non-zero (if needed),
 * then decrements it.
 */
void vlc_sem_wait (vlc_sem_t *sem)
{
    int val;
    do
        val = sem_wait (sem);
    while (val == EINTR);
    VLC_THREAD_ASSERT ("locking semaphore");
}
Пример #5
0
/**
 * Acquires a mutex if and only if it is not currently held by another thread.
 * This function never sleeps and can be used in delay-critical code paths.
 * This function is not a cancellation-point.
 *
 * <b>Beware</b>: If this function fails, then the mutex is held... by another
 * thread. The calling thread must deal with the error appropriately. That
 * typically implies postponing the operations that would have required the
 * mutex. If the thread cannot defer those operations, then it must use
 * vlc_mutex_lock(). If in doubt, use vlc_mutex_lock() instead.
 *
 * @param p_mutex mutex initialized with vlc_mutex_init() or
 *                vlc_mutex_init_recursive()
 * @return 0 if the mutex could be acquired, an error code otherwise.
 */
int vlc_mutex_trylock (vlc_mutex_t *p_mutex)
{
    int val = pthread_mutex_trylock( p_mutex );

    if (val != EBUSY)
        VLC_THREAD_ASSERT ("locking mutex");
    return val;
}
Пример #6
0
/**
 * Save the current cancellation state (enabled or disabled), then disable
 * cancellation for the calling thread.
 * This function must be called before entering a piece of code that is not
 * cancellation-safe, unless it can be proven that the calling thread will not
 * be cancelled.
 * @return Previous cancellation state (opaque value for vlc_restorecancel()).
 */
int vlc_savecancel (void)
{
    int state;
    int val = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);

    VLC_THREAD_ASSERT ("saving cancellation");
    return state;
}
Пример #7
0
/**
 * Waits for a condition variable up to a certain date.
 * 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,
 *                then locked again when waking up.
 * @param deadline <b>absolute</b> timeout
 *
 * @return 0 if the condition was signaled, an error code in case of timeout.
 */
int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
                        mtime_t deadline)
{
    struct timespec ts = mtime_to_ts (deadline);
    int val = pthread_cond_timedwait (p_condvar, p_mutex, &ts);
    if (val != ETIMEDOUT)
        VLC_THREAD_ASSERT ("timed-waiting on condition");
    return val;
}
Пример #8
0
void vlc_join (vlc_thread_t handle, void **result)
{
    vlc_sem_wait (&handle->finished);
    vlc_sem_destroy (&handle->finished);

    int val = pthread_join (handle->thread, result);
    VLC_THREAD_ASSERT ("joining thread");
    clean_detached_thread(handle);
}
Пример #9
0
/**
 * Destroys an initialized timer. If needed, the timer is first disarmed.
 * This function is undefined if the specified timer is not initialized.
 *
 * @warning This function <b>must</b> be called before the timer data can be
 * freed and before the timer callback function can be unloaded.
 *
 * @param timer to destroy
 */
void vlc_timer_destroy (vlc_timer_t *id)
{
#ifdef HAVE_POSIX_TIMER
    int val = timer_delete (id->handle);
    VLC_THREAD_ASSERT ("deleting timer");
#else
    timer_not_supported();
#endif
}
Пример #10
0
void vlc_join (vlc_thread_t handle, void **result)
{
    vlc_sem_wait (&handle->finished);
    vlc_sem_destroy (&handle->finished);

    int val = pthread_join (handle->thread, result);
    VLC_THREAD_ASSERT ("joining thread");
    vlc_mutex_destroy(&handle->lock);
    free(handle);
}
Пример #11
0
/* 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 (likely(semaphore_wait(*sem) == KERN_SUCCESS))
        return;

    val = EINVAL;

    VLC_THREAD_ASSERT ("locking semaphore");
}
Пример #12
0
/* Destroy a semaphore. */
void vlc_sem_destroy (vlc_sem_t *sem)
{
    int val;

    if (likely(semaphore_destroy(mach_task_self(), *sem) == KERN_SUCCESS))
        return;

    val = EINVAL;

    VLC_THREAD_ASSERT ("destroying semaphore");
}
Пример #13
0
int vlc_cond_timedwait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex,
                        mtime_t deadline)
{
    struct timespec ts = mtime_to_ts (deadline);
    vlc_thread_t th = thread;
    int (*cb)(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);

    if (th != NULL)
    {
        vlc_testcancel ();
        if (vlc_mutex_trylock (&th->lock) == 0)
        {
            th->cond = &condvar->cond;
            vlc_mutex_unlock (&th->lock);
        }
        else
        {   /* The lock is already held by another thread.
             * => That other thread has just cancelled this one. */
            vlc_testcancel ();
            /* Cancellation did not occur even though this thread is cancelled.
             * => Cancellation is disabled. */
            th = NULL;
        }
    }

    switch (condvar->clock)
    {
         case CLOCK_REALTIME:
             cb = pthread_cond_timedwait;
             break;
         case CLOCK_MONOTONIC:
             cb = pthread_cond_timedwait_monotonic_np;
             break;
         default:
             assert (0);
    }

    int val = cb (&condvar->cond, p_mutex, &ts);
    if (val != ETIMEDOUT)
        VLC_THREAD_ASSERT ("timed-waiting on condition");

    if (th != NULL)
    {
        if (vlc_mutex_trylock (&th->lock) == 0)
        {
            thread->cond = NULL;
            vlc_mutex_unlock (&th->lock);
        }
        /* Else: This thread was cancelled and is cancellable.
                 vlc_testcancel() will take of it right there: */
        vlc_testcancel();
    }
    return val;
}
Пример #14
0
/**
 * Atomically wait for the semaphore to become non-zero (if needed),
 * then decrements it.
 */
void vlc_sem_wait (vlc_sem_t *sem)
{
    int val;

    do
        if (likely(sem_wait (sem) == 0))
            return;
    while ((val = errno) == EINTR);

    VLC_THREAD_ASSERT ("locking semaphore");
}
Пример #15
0
/**
 * Destroys a semaphore.
 */
void vlc_sem_destroy (vlc_sem_t *sem)
{
    int val;

    if (likely(sem_destroy (sem) == 0))
        return;

    val = errno;

    VLC_THREAD_ASSERT ("destroying semaphore");
}
Пример #16
0
/* Increment the value of a semaphore.
 * returns 0 on success, EOVERFLOW in case of integer overflow */
int vlc_sem_post (vlc_sem_t *sem)
{
    int val;

    if (likely(semaphore_signal(*sem) == KERN_SUCCESS))
        return 0;

    val = EINVAL;

    if (unlikely(val != EOVERFLOW))
        VLC_THREAD_ASSERT ("unlocking semaphore");
    return val;
}
Пример #17
0
/**
 * 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 (likely(sem_post (sem) == 0))
        return 0;

    val = errno;

    if (unlikely(val != EOVERFLOW))
        VLC_THREAD_ASSERT ("unlocking semaphore");
    return val;
}
Пример #18
0
/*****************************************************************************
 * vlc_cond_destroy: destroy a condition, inner version
 *****************************************************************************/
void __vlc_cond_destroy( const char * psz_file, int i_line, vlc_cond_t *p_condvar )
{
#if defined( LIBVLC_USE_PTHREAD )
    int val = pthread_cond_destroy( p_condvar );
    VLC_THREAD_ASSERT ("destroying condition");

#elif defined( UNDER_CE ) || defined( WIN32 )
    VLC_UNUSED( psz_file); VLC_UNUSED( i_line );

    CloseHandle( *p_condvar );

#elif defined( HAVE_KERNEL_SCHEDULER_H )
    p_condvar->init = 0;

#endif
}
Пример #19
0
/**
 * Restore the cancellation state for the calling thread.
 * @param state previous state as returned by vlc_savecancel().
 * @return Nothing, always succeeds.
 */
void vlc_restorecancel (int state)
{
#ifndef NDEBUG
    int oldstate, val;

    val = pthread_setcancelstate (state, &oldstate);
    /* This should fail if an invalid value for given for state */
    VLC_THREAD_ASSERT ("restoring cancellation");

    if (unlikely(oldstate != PTHREAD_CANCEL_DISABLE))
         vlc_thread_fatal ("restoring cancellation while not disabled", EINVAL,
                           __func__, __FILE__, __LINE__);
#else
    pthread_setcancelstate (state, NULL);
#endif
}
Пример #20
0
/**
 * 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");
}
Пример #21
0
/**
 * 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");
}
Пример #22
0
/**
 * 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;
}
Пример #23
0
/**
 * Waits for a condition variable up to a certain date.
 * 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,
 *                then locked again when waking up.
 * @param deadline <b>absolute</b> timeout
 *
 * @return 0 if the condition was signaled, an error code in case of timeout.
 */
int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
                        mtime_t deadline)
{
#if defined(__APPLE__) && !defined(__powerpc__) && !defined( __ppc__ ) && !defined( __ppc64__ )
    /* mdate() is mac_absolute_time on OSX, which we must convert to do
     * the same base than gettimeofday() which pthread_cond_timedwait
     * relies on. */
    mtime_t oldbase = mdate();
    struct timeval tv;
    gettimeofday(&tv, NULL);
    mtime_t newbase = (mtime_t)tv.tv_sec * 1000000 + (mtime_t) tv.tv_usec;
    deadline = deadline - oldbase + newbase;
#endif
    lldiv_t d = lldiv( deadline, CLOCK_FREQ );
    struct timespec ts = { d.quot, d.rem * (1000000000 / CLOCK_FREQ) };

    int val = pthread_cond_timedwait (p_condvar, p_mutex, &ts);
    if (val != ETIMEDOUT)
        VLC_THREAD_ASSERT ("timed-waiting on condition");
    return val;
}
Пример #24
0
void vlc_cond_wait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex)
{
    vlc_thread_t th = thread;

    if (th != NULL)
    {
        vlc_testcancel ();
        if (vlc_mutex_trylock (&th->lock) == 0)
        {
            th->cond = &condvar->cond;
            vlc_mutex_unlock (&th->lock);
        }
        else
        {   /* The lock is already held by another thread.
             * => That other thread has just cancelled this one. */
            vlc_testcancel ();
            /* Cancellation did not occur even though this thread is cancelled.
             * => Cancellation is disabled. */
            th = NULL;
        }
    }

    int val = pthread_cond_wait (&condvar->cond, p_mutex);
    VLC_THREAD_ASSERT ("waiting on condition");

    if (th != NULL)
    {
        if (vlc_mutex_trylock (&th->lock) == 0)
        {
            thread->cond = NULL;
            vlc_mutex_unlock (&th->lock);
        }
        /* Else: This thread was cancelled and is cancellable.
                 vlc_testcancel() will take of it right there: */
        vlc_testcancel();
    }
}
Пример #25
0
/*****************************************************************************
 * vlc_mutex_destroy: destroy a mutex, inner version
 *****************************************************************************/
void __vlc_mutex_destroy( const char * psz_file, int i_line, vlc_mutex_t *p_mutex )
{
#if defined( LIBVLC_USE_PTHREAD )
    int val = pthread_mutex_destroy( p_mutex );
    VLC_THREAD_ASSERT ("destroying mutex");

#elif defined( UNDER_CE )
    VLC_UNUSED( psz_file); VLC_UNUSED( i_line );

    DeleteCriticalSection( &p_mutex->csection );

#elif defined( WIN32 )
    VLC_UNUSED( psz_file); VLC_UNUSED( i_line );

    CloseHandle( *p_mutex );

#elif defined( HAVE_KERNEL_SCHEDULER_H )
    if( p_mutex->init == 9999 )
        delete_sem( p_mutex->lock );

    p_mutex->init = 0;

#endif
}
Пример #26
0
void vlc_rwlock_unlock(vlc_rwlock_t* lock) {
  const int val = pthread_rwlock_unlock(lock);
  VLC_THREAD_ASSERT("releasing R/W lock");
}
Пример #27
0
void vlc_rwlock_wrlock(vlc_rwlock_t* lock) {
  const int val = pthread_rwlock_wrlock(lock);
  VLC_THREAD_ASSERT("acquiring R/W lock for writing");
}
Пример #28
0
void vlc_rwlock_destroy(vlc_rwlock_t* lock) {
  const int val = pthread_rwlock_destroy(lock);
  VLC_THREAD_ASSERT("destroying R/W lock");
}
Пример #29
0
void vlc_rwlock_init(vlc_rwlock_t* lock) {
  const int val = pthread_rwlock_init(lock, NULL);
  VLC_THREAD_ASSERT("initializing R/W lock");
}
Пример #30
0
/**
 * Detaches a thread. When the specified thread completes, it will be
 * automatically destroyed (in particular, its stack will be reclaimed),
 * instead of waiting for another thread to call vlc_join(). If the thread has
 * already completed, it will be destroyed immediately.
 *
 * When a thread performs some work asynchronously and may complete much
 * earlier than it can be joined, detaching the thread can save memory.
 * However, care must be taken that any resources used by a detached thread
 * remains valid until the thread completes. This will typically involve some
 * kind of thread-safe signaling.
 *
 * A thread may detach itself.
 *
 * @param handle thread handle
 */
void vlc_detach (vlc_thread_t handle)
{
    int val = pthread_detach (handle);
    VLC_THREAD_ASSERT ("detaching thread");
}