vlc_threads.h 19.1 KB
Newer Older
1
/*****************************************************************************
2 3
 * vlc_threads.h : threads implementation for the VideoLAN client
 * This header provides portable declarations for mutexes & conditions
4
 *****************************************************************************
5
 * Copyright (C) 1999, 2002 the VideoLAN team
Gildas Bazin's avatar
Gildas Bazin committed
6
 * $Id$
7
 *
8 9
 * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
 *          Samuel Hocevar <sam@via.ecp.fr>
Gildas Bazin's avatar
 
Gildas Bazin committed
10
 *          Gildas Bazin <gbazin@netcourrier.com>
11
 *          Christophe Massiot <massiot@via.ecp.fr>
12 13 14 15 16
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
17
 *
18 19
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
22
 *
23 24
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
Antoine Cellerier's avatar
Antoine Cellerier committed
25
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26
 *****************************************************************************/
27

28 29
#ifndef VLC_THREADS_H_
#define VLC_THREADS_H_
30

31
#if defined( UNDER_CE )
32
                                                                /* WinCE API */
33 34
#elif defined( WIN32 )
#   include <process.h>                                         /* Win32 API */
35
#   include <errno.h>
Sam Hocevar's avatar
 
Sam Hocevar committed
36

37
#elif defined( SYS_BEOS )                                            /* BeOS */
38 39 40 41
#   include <kernel/OS.h>
#   include <kernel/scheduler.h>
#   include <byteorder.h>

42
#else                                         /* pthreads (like Linux & BSD) */
43
#   define LIBVLC_USE_PTHREAD 1
44
#   define _APPLE_C_SOURCE    1 /* Proper pthread semantics on OSX */
45

Rafaël Carré's avatar
Rafaël Carré committed
46
#   include <stdlib.h> /* lldiv_t definition (only in C99) */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
47
#   include <unistd.h> /* _POSIX_SPIN_LOCKS */
Sam Hocevar's avatar
 
Sam Hocevar committed
48
#   include <pthread.h>
49 50
    /* Needed for pthread_cond_timedwait */
#   include <errno.h>
51
#   include <time.h>
52

53
#endif
54

55
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
56
 * Constants
57
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
58

59
/* Thread priorities */
60
#ifdef __APPLE__
61 62 63 64 65 66
#   define VLC_THREAD_PRIORITY_LOW      0
#   define VLC_THREAD_PRIORITY_INPUT   22
#   define VLC_THREAD_PRIORITY_AUDIO   22
#   define VLC_THREAD_PRIORITY_VIDEO    0
#   define VLC_THREAD_PRIORITY_OUTPUT  22
#   define VLC_THREAD_PRIORITY_HIGHEST 22
Vincent Seguin's avatar
Vincent Seguin committed
67

68 69 70 71 72 73
#elif defined(SYS_BEOS)
#   define VLC_THREAD_PRIORITY_LOW 5
#   define VLC_THREAD_PRIORITY_INPUT 10
#   define VLC_THREAD_PRIORITY_AUDIO 10
#   define VLC_THREAD_PRIORITY_VIDEO 5
#   define VLC_THREAD_PRIORITY_OUTPUT 15
74
#   define VLC_THREAD_PRIORITY_HIGHEST 15
75

76
#elif defined(LIBVLC_USE_PTHREAD)
77 78 79 80 81 82
#   define VLC_THREAD_PRIORITY_LOW      0
#   define VLC_THREAD_PRIORITY_INPUT   10
#   define VLC_THREAD_PRIORITY_AUDIO    5
#   define VLC_THREAD_PRIORITY_VIDEO    0
#   define VLC_THREAD_PRIORITY_OUTPUT  15
#   define VLC_THREAD_PRIORITY_HIGHEST 20
83

84
#elif defined(WIN32) || defined(UNDER_CE)
Gildas Bazin's avatar
 
Gildas Bazin committed
85
/* Define different priorities for WinNT/2K/XP and Win9x/Me */
86
#   define VLC_THREAD_PRIORITY_LOW 0
Gildas Bazin's avatar
 
Gildas Bazin committed
87
#   define VLC_THREAD_PRIORITY_INPUT \
Gildas Bazin's avatar
Gildas Bazin committed
88
        (IS_WINNT ? THREAD_PRIORITY_ABOVE_NORMAL : 0)
Gildas Bazin's avatar
 
Gildas Bazin committed
89 90
#   define VLC_THREAD_PRIORITY_AUDIO \
        (IS_WINNT ? THREAD_PRIORITY_HIGHEST : 0)
Gildas Bazin's avatar
 
Gildas Bazin committed
91 92
#   define VLC_THREAD_PRIORITY_VIDEO \
        (IS_WINNT ? 0 : THREAD_PRIORITY_BELOW_NORMAL )
Gildas Bazin's avatar
 
Gildas Bazin committed
93 94 95 96
#   define VLC_THREAD_PRIORITY_OUTPUT \
        (IS_WINNT ? THREAD_PRIORITY_ABOVE_NORMAL : 0)
#   define VLC_THREAD_PRIORITY_HIGHEST \
        (IS_WINNT ? THREAD_PRIORITY_TIME_CRITICAL : 0)
97

98 99 100 101
#else
#   define VLC_THREAD_PRIORITY_LOW 0
#   define VLC_THREAD_PRIORITY_INPUT 0
#   define VLC_THREAD_PRIORITY_AUDIO 0
102
#   define VLC_THREAD_PRIORITY_VIDEO 0
103
#   define VLC_THREAD_PRIORITY_OUTPUT 0
104
#   define VLC_THREAD_PRIORITY_HIGHEST 0
Vincent Seguin's avatar
Vincent Seguin committed
105

106
#endif
Vincent Seguin's avatar
Vincent Seguin committed
107

108
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
109
 * Type definitions
110
 *****************************************************************************/
111

112 113 114 115 116 117 118
#if defined (LIBVLC_USE_PTHREAD)
typedef pthread_t       vlc_thread_t;
typedef pthread_mutex_t vlc_mutex_t;
typedef pthread_cond_t  vlc_cond_t;
typedef pthread_key_t   vlc_threadvar_t;

#elif defined( WIN32 ) || defined( UNDER_CE )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
119
typedef HANDLE  vlc_thread_t;
Gildas Bazin's avatar
 
Gildas Bazin committed
120
typedef BOOL (WINAPI *SIGNALOBJECTANDWAIT) ( HANDLE, HANDLE, DWORD, BOOL );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
121
typedef HANDLE  vlc_mutex_t;
122
typedef HANDLE  vlc_cond_t;
123
typedef DWORD   vlc_threadvar_t;
124

125
#elif defined( SYS_BEOS )
126 127
/* This is the BeOS implementation of the vlc threads, note that the mutex is
 * not a real mutex and the cond_var is not like a pthread cond_var but it is
Rémi Denis-Courmont's avatar
Typo  
Rémi Denis-Courmont committed
128
 * enough for what we need */
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143

typedef thread_id vlc_thread_t;

typedef struct
{
    int32_t         init;
    sem_id          lock;
} vlc_mutex_t;

typedef struct
{
    int32_t         init;
    thread_id       thread;
} vlc_cond_t;

144 145 146 147
typedef struct
{
} vlc_threadvar_t;

148 149 150 151 152 153 154 155 156 157 158 159 160 161
#endif

#if defined( WIN32 ) && !defined ETIMEDOUT
#  define ETIMEDOUT 10060 /* This is the value in winsock.h. */
#endif

/*****************************************************************************
 * Function definitions
 *****************************************************************************/
VLC_EXPORT( int,  vlc_mutex_init,    ( vlc_mutex_t * ) );
VLC_EXPORT( int,  vlc_mutex_init_recursive, ( vlc_mutex_t * ) );
VLC_EXPORT( void,  __vlc_mutex_destroy, ( const char *, int, vlc_mutex_t * ) );
VLC_EXPORT( int,  __vlc_cond_init,     ( vlc_cond_t * ) );
VLC_EXPORT( void,  __vlc_cond_destroy,  ( const char *, int, vlc_cond_t * ) );
162 163
VLC_EXPORT( int, vlc_threadvar_create, (vlc_threadvar_t * , void (*) (void *) ) );
VLC_EXPORT( void, vlc_threadvar_delete, (vlc_threadvar_t *) );
164
VLC_EXPORT( int,  __vlc_thread_create, ( vlc_object_t *, const char *, int, const char *, void * ( * ) ( vlc_object_t * ), int, bool ) );
165 166 167
VLC_EXPORT( int,  __vlc_thread_set_priority, ( vlc_object_t *, const char *, int, int ) );
VLC_EXPORT( void, __vlc_thread_join,   ( vlc_object_t *, const char *, int ) );

168 169
#define vlc_thread_ready vlc_object_signal

170 171 172 173 174 175 176
/*****************************************************************************
 * vlc_mutex_lock: lock a mutex
 *****************************************************************************/
#define vlc_mutex_lock( P_MUTEX )                                           \
    __vlc_mutex_lock( __FILE__, __LINE__, P_MUTEX )

VLC_EXPORT(void, vlc_pthread_fatal, (const char *action, int error, const char *file, unsigned line));
177

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
178
#if defined(LIBVLC_USE_PTHREAD)
179 180 181
# define VLC_THREAD_ASSERT( action ) \
    if (val) \
        vlc_pthread_fatal (action, val, psz_file, i_line)
182
#else
183
# define VLC_THREAD_ASSERT ((void)(val))
184 185 186 187 188 189 190 191 192 193 194 195
#endif

static inline void __vlc_mutex_lock( const char * psz_file, int i_line,
                                    vlc_mutex_t * p_mutex )
{
#if defined(LIBVLC_USE_PTHREAD)
#   define vlc_assert_locked( m ) \
           assert (pthread_mutex_lock (m) == EDEADLK)
    int val = pthread_mutex_lock( p_mutex );
    VLC_THREAD_ASSERT ("locking mutex");

#elif defined( UNDER_CE )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
196
    (void)psz_file; (void)i_line;
197 198 199 200

    EnterCriticalSection( &p_mutex->csection );

#elif defined( WIN32 )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
201
    (void)psz_file; (void)i_line;
202 203 204

    WaitForSingleObject( *p_mutex, INFINITE );

205
#elif defined( SYS_BEOS )
206 207 208 209 210 211
    acquire_sem( p_mutex->lock );

#endif
}

#ifndef vlc_assert_locked
212
# define vlc_assert_locked( m ) (void)m
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
#endif

/*****************************************************************************
 * vlc_mutex_unlock: unlock a mutex
 *****************************************************************************/
#define vlc_mutex_unlock( P_MUTEX )                                         \
    __vlc_mutex_unlock( __FILE__, __LINE__, P_MUTEX )

static inline void __vlc_mutex_unlock( const char * psz_file, int i_line,
                                      vlc_mutex_t *p_mutex )
{
#if defined(LIBVLC_USE_PTHREAD)
    int val = pthread_mutex_unlock( p_mutex );
    VLC_THREAD_ASSERT ("unlocking mutex");

#elif defined( UNDER_CE )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
229
    (void)psz_file; (void)i_line;
230 231 232 233

    LeaveCriticalSection( &p_mutex->csection );

#elif defined( WIN32 )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
234
    (void)psz_file; (void)i_line;
235 236 237

    ReleaseMutex( *p_mutex );

238
#elif defined( SYS_BEOS )
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
    release_sem( p_mutex->lock );

#endif
}

/*****************************************************************************
 * vlc_mutex_destroy: destroy a mutex
 *****************************************************************************/
#define vlc_mutex_destroy( P_MUTEX )                                        \
    __vlc_mutex_destroy( __FILE__, __LINE__, P_MUTEX )

/*****************************************************************************
 * vlc_cond_init: initialize a condition
 *****************************************************************************/
#define vlc_cond_init( P_THIS, P_COND )                                     \
    __vlc_cond_init( P_COND )

/*****************************************************************************
 * vlc_cond_signal: start a thread on condition completion
 *****************************************************************************/
#define vlc_cond_signal( P_COND )                                           \
    __vlc_cond_signal( __FILE__, __LINE__, P_COND )

static inline void __vlc_cond_signal( const char * psz_file, int i_line,
                                      vlc_cond_t *p_condvar )
{
#if defined(LIBVLC_USE_PTHREAD)
    int val = pthread_cond_signal( p_condvar );
    VLC_THREAD_ASSERT ("signaling condition variable");

#elif defined( UNDER_CE ) || defined( WIN32 )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
270
    (void)psz_file; (void)i_line;
271 272 273 274 275 276 277

    /* Release one waiting thread if one is available. */
    /* For this trick to work properly, the vlc_cond_signal must be surrounded
     * by a mutex. This will prevent another thread from stealing the signal */
    /* PulseEvent() only works if none of the waiting threads is suspended.
     * This is particularily problematic under a debug session.
     * as documented in http://support.microsoft.com/kb/q173260/ */
278
    PulseEvent( *p_condvar );
279

280
#elif defined( SYS_BEOS )
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
    while( p_condvar->thread != -1 )
    {
        thread_info info;
        if( get_thread_info(p_condvar->thread, &info) == B_BAD_VALUE )
            return;

        if( info.state != B_THREAD_SUSPENDED )
        {
            /* The  waiting thread is not suspended so it could
             * have been interrupted beetwen the unlock and the
             * suspend_thread line. That is why we sleep a little
             * before retesting p_condver->thread. */
            snooze( 10000 );
        }
        else
        {
            /* Ok, we have to wake up that thread */
            resume_thread( p_condvar->thread );
        }
    }

#endif
}

/*****************************************************************************
 * vlc_cond_wait: wait until condition completion
 *****************************************************************************/
#define vlc_cond_wait( P_COND, P_MUTEX )                                     \
    __vlc_cond_wait( __FILE__, __LINE__, P_COND, P_MUTEX  )

static inline void __vlc_cond_wait( const char * psz_file, int i_line,
                                    vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex )
{
#if defined(LIBVLC_USE_PTHREAD)
    int val = pthread_cond_wait( p_condvar, p_mutex );
    VLC_THREAD_ASSERT ("waiting on condition");

#elif defined( UNDER_CE )
    LeaveCriticalSection( &p_mutex->csection );
320
    WaitForSingleObject( *p_condvar, INFINITE );
321 322 323 324 325

    /* Reacquire the mutex before returning. */
    vlc_mutex_lock( p_mutex );

#elif defined( WIN32 )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
326
    (void)psz_file; (void)i_line;
327 328

    /* Increase our wait count */
329
    SignalObjectAndWait( *p_mutex, *p_condvar, INFINITE, FALSE );
330 331 332 333

    /* Reacquire the mutex before returning. */
    vlc_mutex_lock( p_mutex );

334
#elif defined( SYS_BEOS )
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
    /* The p_condvar->thread var is initialized before the unlock because
     * it enables to identify when the thread is interrupted beetwen the
     * unlock line and the suspend_thread line */
    p_condvar->thread = find_thread( NULL );
    vlc_mutex_unlock( p_mutex );
    suspend_thread( p_condvar->thread );
    p_condvar->thread = -1;

    vlc_mutex_lock( p_mutex );

#endif
}


/*****************************************************************************
 * vlc_cond_timedwait: wait until condition completion or expiration
 *****************************************************************************
 * Returns 0 if object signaled, an error code in case of timeout or error.
 *****************************************************************************/
#define vlc_cond_timedwait( P_COND, P_MUTEX, DEADLINE )                      \
    __vlc_cond_timedwait( __FILE__, __LINE__, P_COND, P_MUTEX, DEADLINE  )

static inline int __vlc_cond_timedwait( const char * psz_file, int i_line,
                                        vlc_cond_t *p_condvar,
                                        vlc_mutex_t *p_mutex,
                                        mtime_t deadline )
{
#if defined(LIBVLC_USE_PTHREAD)
    lldiv_t d = lldiv( deadline, 1000000 );
    struct timespec ts = { d.quot, d.rem * 1000 };

    int val = pthread_cond_timedwait (p_condvar, p_mutex, &ts);
    if (val == ETIMEDOUT)
        return ETIMEDOUT; /* this error is perfectly normal */
    VLC_THREAD_ASSERT ("timed-waiting on condition");

#elif defined( UNDER_CE )
    mtime_t delay_ms = (deadline - mdate())/1000;
    DWORD result;
    if( delay_ms < 0 )
        delay_ms = 0;

    LeaveCriticalSection( &p_mutex->csection );
378
    result = WaitForSingleObject( *p_condvar, delay_ms );
379 380 381 382 383 384 385

    /* Reacquire the mutex before returning. */
    vlc_mutex_lock( p_mutex );

    if(result == WAIT_TIMEOUT)
       return ETIMEDOUT; /* this error is perfectly normal */

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
386
    (void)psz_file; (void)i_line;
387

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
388
#elif defined( WIN32 )
389
    mtime_t total = (deadline - mdate())/1000;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
390
    DWORD result;
391 392
    if( total < 0 )
        total = 0;
393

394 395 396 397 398 399
    do
    {
        DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total;
        result = SignalObjectAndWait( *p_mutex, *p_condvar,
                                      delay, FALSE );
        total -= delay;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
400
        vlc_mutex_lock (p_mutex);
401 402
    }
    while (total);
403 404 405 406 407

    /* Reacquire the mutex before returning. */
    if(result == WAIT_TIMEOUT)
       return ETIMEDOUT; /* this error is perfectly normal */

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
408 409
    (void)psz_file; (void)i_line;

410
#elif defined( SYS_BEOS )
411
#   error Unimplemented
412

Gildas Bazin's avatar
 
Gildas Bazin committed
413 414
#endif

415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
    return 0;
}

/*****************************************************************************
 * vlc_cond_destroy: destroy a condition
 *****************************************************************************/
#define vlc_cond_destroy( P_COND )                                          \
    __vlc_cond_destroy( __FILE__, __LINE__, P_COND )

/*****************************************************************************
 * vlc_threadvar_set: create: set the value of a thread-local variable
 *****************************************************************************/
static inline int vlc_threadvar_set( vlc_threadvar_t * p_tls, void *p_value )
{
    int i_ret;

#if defined(LIBVLC_USE_PTHREAD)
    i_ret = pthread_setspecific( *p_tls, p_value );

434
#elif defined( SYS_BEOS )
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
    i_ret = EINVAL;

#elif defined( UNDER_CE ) || defined( WIN32 )
    i_ret = TlsSetValue( *p_tls, p_value ) ? EINVAL : 0;

#endif

    return i_ret;
}

/*****************************************************************************
 * vlc_threadvar_get: create: get the value of a thread-local variable
 *****************************************************************************/
static inline void* vlc_threadvar_get( vlc_threadvar_t * p_tls )
{
    void *p_ret;

#if defined(LIBVLC_USE_PTHREAD)
    p_ret = pthread_getspecific( *p_tls );

455
#elif defined( SYS_BEOS )
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
    p_ret = NULL;

#elif defined( UNDER_CE ) || defined( WIN32 )
    p_ret = TlsGetValue( *p_tls );

#endif

    return p_ret;
}

# if defined (_POSIX_SPIN_LOCKS) && ((_POSIX_SPIN_LOCKS - 0) > 0)
typedef pthread_spinlock_t vlc_spinlock_t;

/**
 * Initializes a spinlock.
 */
static inline int vlc_spin_init (vlc_spinlock_t *spin)
{
    return pthread_spin_init (spin, PTHREAD_PROCESS_PRIVATE);
}

/**
 * Acquires a spinlock.
 */
static inline void vlc_spin_lock (vlc_spinlock_t *spin)
{
    pthread_spin_lock (spin);
}

/**
 * Releases a spinlock.
 */
static inline void vlc_spin_unlock (vlc_spinlock_t *spin)
{
    pthread_spin_unlock (spin);
}

/**
 * Deinitializes a spinlock.
 */
static inline void vlc_spin_destroy (vlc_spinlock_t *spin)
{
    pthread_spin_destroy (spin);
}

#elif defined( WIN32 )

typedef CRITICAL_SECTION vlc_spinlock_t;

/**
 * Initializes a spinlock.
 */
static inline int vlc_spin_init (vlc_spinlock_t *spin)
{
    return !InitializeCriticalSectionAndSpinCount(spin, 4000);
}

/**
 * Acquires a spinlock.
 */
static inline void vlc_spin_lock (vlc_spinlock_t *spin)
{
    EnterCriticalSection(spin);
}

/**
 * Releases a spinlock.
 */
static inline void vlc_spin_unlock (vlc_spinlock_t *spin)
{
    LeaveCriticalSection(spin);
}

/**
 * Deinitializes a spinlock.
 */
static inline void vlc_spin_destroy (vlc_spinlock_t *spin)
{
    DeleteCriticalSection(spin);
}

#else

/* Fallback to plain mutexes if spinlocks are not available */
typedef vlc_mutex_t vlc_spinlock_t;

static inline int vlc_spin_init (vlc_spinlock_t *spin)
{
    return vlc_mutex_init (spin);
}

# define vlc_spin_lock    vlc_mutex_lock
# define vlc_spin_unlock  vlc_mutex_unlock
# define vlc_spin_destroy vlc_mutex_destroy
#endif

552 553 554
/**
 * Issues a full memory barrier.
 */
555 556 557
#if defined (__APPLE__)
# include <libkern/OSAtomic.h> /* OSMemoryBarrier() */
#endif
558 559
static inline void barrier (void)
{
560
#if defined (__GNUC__) && (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
561
    __sync_synchronize ();
562 563 564 565 566 567
#elif defined(__APPLE__)
    OSMemoryBarrier ();
#elif defined(__powerpc__)
    asm volatile ("sync":::"memory");
#elif defined(__i386__)
    asm volatile ("mfence":::"memory");
568
#else
569 570 571 572 573
    vlc_spin_t spin;
    vlc_spin_init (&spin);
    vlc_spin_lock (&spin);
    vlc_spin_unlock (&spin);
    vlc_spin_destroy (&spin);
574 575 576
#endif
}

577 578 579 580
/*****************************************************************************
 * vlc_thread_create: create a thread
 *****************************************************************************/
#define vlc_thread_create( P_THIS, PSZ_NAME, FUNC, PRIORITY, WAIT )         \
581
    __vlc_thread_create( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PSZ_NAME, FUNC, PRIORITY, WAIT )
582 583 584 585 586 587 588 589 590 591 592 593 594

/*****************************************************************************
 * vlc_thread_set_priority: set the priority of the calling thread
 *****************************************************************************/
#define vlc_thread_set_priority( P_THIS, PRIORITY )                         \
    __vlc_thread_set_priority( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PRIORITY )

/*****************************************************************************
 * vlc_thread_join: wait until a thread exits
 *****************************************************************************/
#define vlc_thread_join( P_THIS )                                           \
    __vlc_thread_join( VLC_OBJECT(P_THIS), __FILE__, __LINE__ )

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
595
#endif /* !_VLC_THREADS_H */