00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef VLC_THREADS_H_
00029 #define VLC_THREADS_H_
00030
00031
00032
00033
00034
00035
00036
00037 #if defined( UNDER_CE )
00038 #elif defined( WIN32 )
00039 # include <process.h>
00040
00041 #elif defined( __OS2__ )
00042 # include <errno.h>
00043
00044 # define pthread_sigmask sigprocmask
00045
00046 #else
00047 # define LIBVLC_USE_PTHREAD 1
00048 # define LIBVLC_USE_PTHREAD_CANCEL 1
00049 # define _APPLE_C_SOURCE 1
00050
00051 # include <unistd.h>
00052 # include <pthread.h>
00053
00054
00055 # if defined (__APPLE__)
00056 # include <mach/semaphore.h>
00057 # include <mach/task.h>
00058 # else
00059 # include <semaphore.h>
00060 # endif
00061
00062 #endif
00063
00064
00065
00066
00067
00068
00069 #ifdef __APPLE__
00070 # define VLC_THREAD_PRIORITY_LOW 0
00071 # define VLC_THREAD_PRIORITY_INPUT 22
00072 # define VLC_THREAD_PRIORITY_AUDIO 22
00073 # define VLC_THREAD_PRIORITY_VIDEO 0
00074 # define VLC_THREAD_PRIORITY_OUTPUT 22
00075 # define VLC_THREAD_PRIORITY_HIGHEST 22
00076
00077 #elif defined(LIBVLC_USE_PTHREAD)
00078 # define VLC_THREAD_PRIORITY_LOW 0
00079 # define VLC_THREAD_PRIORITY_INPUT 10
00080 # define VLC_THREAD_PRIORITY_AUDIO 5
00081 # define VLC_THREAD_PRIORITY_VIDEO 0
00082 # define VLC_THREAD_PRIORITY_OUTPUT 15
00083 # define VLC_THREAD_PRIORITY_HIGHEST 20
00084
00085 #elif defined(WIN32) || defined(UNDER_CE)
00086
00087 # define VLC_THREAD_PRIORITY_LOW 0
00088 # define VLC_THREAD_PRIORITY_INPUT \
00089 THREAD_PRIORITY_ABOVE_NORMAL
00090 # define VLC_THREAD_PRIORITY_AUDIO \
00091 THREAD_PRIORITY_HIGHEST
00092 # define VLC_THREAD_PRIORITY_VIDEO 0
00093 # define VLC_THREAD_PRIORITY_OUTPUT \
00094 THREAD_PRIORITY_ABOVE_NORMAL
00095 # define VLC_THREAD_PRIORITY_HIGHEST \
00096 THREAD_PRIORITY_TIME_CRITICAL
00097
00098 #elif defined(__OS2__)
00099 # define VLC_THREAD_PRIORITY_LOW 0
00100 # define VLC_THREAD_PRIORITY_INPUT MAKESHORT( PRTYD_MAXIMUM / 2, PRTYC_REGULAR )
00101 # define VLC_THREAD_PRIORITY_AUDIO MAKESHORT( PRTYD_MAXIMUM, PRTYC_REGULAR )
00102 # define VLC_THREAD_PRIORITY_VIDEO 0
00103 # define VLC_THREAD_PRIORITY_OUTPUT MAKESHORT( PRTYD_MAXIMUM / 2, PRTYC_REGULAR )
00104 # define VLC_THREAD_PRIORITY_HIGHEST MAKESHORT( 0, PRTYC_TIMECRITICAL )
00105
00106 #else
00107 # define VLC_THREAD_PRIORITY_LOW 0
00108 # define VLC_THREAD_PRIORITY_INPUT 0
00109 # define VLC_THREAD_PRIORITY_AUDIO 0
00110 # define VLC_THREAD_PRIORITY_VIDEO 0
00111 # define VLC_THREAD_PRIORITY_OUTPUT 0
00112 # define VLC_THREAD_PRIORITY_HIGHEST 0
00113
00114 #endif
00115
00116
00117
00118
00119
00120 #if defined (LIBVLC_USE_PTHREAD)
00121 typedef pthread_t vlc_thread_t;
00122 typedef pthread_mutex_t vlc_mutex_t;
00123 #define VLC_STATIC_MUTEX PTHREAD_MUTEX_INITIALIZER
00124 typedef pthread_cond_t vlc_cond_t;
00125 #define VLC_STATIC_COND PTHREAD_COND_INITIALIZER
00126 typedef pthread_rwlock_t vlc_rwlock_t;
00127 #define VLC_STATIC_RWLOCK PTHREAD_RWLOCK_INITIALIZER
00128 typedef pthread_key_t vlc_threadvar_t;
00129 typedef struct vlc_timer *vlc_timer_t;
00130
00131 #if defined (__APPLE__)
00132 typedef semaphore_t vlc_sem_t;
00133 #else
00134 typedef sem_t vlc_sem_t;
00135 #endif
00136
00137 #elif defined( WIN32 )
00138 typedef struct vlc_thread *vlc_thread_t;
00139
00140 typedef struct
00141 {
00142 bool dynamic;
00143 union
00144 {
00145 struct
00146 {
00147 bool locked;
00148 unsigned long contention;
00149 };
00150 CRITICAL_SECTION mutex;
00151 };
00152 } vlc_mutex_t;
00153 #define VLC_STATIC_MUTEX { false, { { false, 0 } } }
00154
00155 typedef struct
00156 {
00157 HANDLE handle;
00158 unsigned clock;
00159 } vlc_cond_t;
00160 #define VLC_STATIC_COND { 0, 0 }
00161
00162 typedef HANDLE vlc_sem_t;
00163
00164 typedef struct
00165 {
00166 vlc_mutex_t mutex;
00167 vlc_cond_t wait;
00168 unsigned long readers;
00169 DWORD writer;
00170 } vlc_rwlock_t;
00171 #define VLC_STATIC_RWLOCK \
00172 { VLC_STATIC_MUTEX, VLC_STATIC_COND, 0, 0 }
00173
00174 typedef struct vlc_threadvar *vlc_threadvar_t;
00175 typedef struct vlc_timer *vlc_timer_t;
00176
00177 #elif defined( __OS2__ )
00178 typedef struct vlc_thread *vlc_thread_t;
00179
00180 typedef struct
00181 {
00182 bool dynamic;
00183 union
00184 {
00185 struct
00186 {
00187 bool locked;
00188 unsigned long contention;
00189 };
00190 HMTX hmtx;
00191 };
00192 } vlc_mutex_t;
00193
00194 #define VLC_STATIC_MUTEX { false, { { false, 0 } } }
00195
00196 typedef struct
00197 {
00198 HEV hev;
00199 unsigned clock;
00200 } vlc_cond_t;
00201
00202 #define VLC_STATIC_COND { 0, 0 }
00203
00204 typedef struct
00205 {
00206 HEV hev;
00207 HMTX wait_mutex;
00208 HMTX count_mutex;
00209 int count;
00210 } vlc_sem_t;
00211
00212 typedef struct
00213 {
00214 vlc_mutex_t mutex;
00215 vlc_cond_t wait;
00216 unsigned long readers;
00217 int writer;
00218 } vlc_rwlock_t;
00219 #define VLC_STATIC_RWLOCK \
00220 { VLC_STATIC_MUTEX, VLC_STATIC_COND, 0, 0 }
00221
00222 typedef struct vlc_threadvar *vlc_threadvar_t;
00223 typedef struct vlc_timer *vlc_timer_t;
00224
00225 #endif
00226
00227 #if defined( WIN32 ) && !defined ETIMEDOUT
00228 # define ETIMEDOUT 10060
00229 #endif
00230
00231
00232
00233
00234 VLC_API void vlc_mutex_init( vlc_mutex_t * );
00235 VLC_API void vlc_mutex_init_recursive( vlc_mutex_t * );
00236 VLC_API void vlc_mutex_destroy( vlc_mutex_t * );
00237 VLC_API void vlc_mutex_lock( vlc_mutex_t * );
00238 VLC_API int vlc_mutex_trylock( vlc_mutex_t * ) VLC_USED;
00239 VLC_API void vlc_mutex_unlock( vlc_mutex_t * );
00240 VLC_API void vlc_cond_init( vlc_cond_t * );
00241 VLC_API void vlc_cond_init_daytime( vlc_cond_t * );
00242 VLC_API void vlc_cond_destroy( vlc_cond_t * );
00243 VLC_API void vlc_cond_signal(vlc_cond_t *);
00244 VLC_API void vlc_cond_broadcast(vlc_cond_t *);
00245 VLC_API void vlc_cond_wait(vlc_cond_t *, vlc_mutex_t *);
00246 VLC_API int vlc_cond_timedwait(vlc_cond_t *, vlc_mutex_t *, mtime_t);
00247 VLC_API void vlc_sem_init(vlc_sem_t *, unsigned);
00248 VLC_API void vlc_sem_destroy(vlc_sem_t *);
00249 VLC_API int vlc_sem_post(vlc_sem_t *);
00250 VLC_API void vlc_sem_wait(vlc_sem_t *);
00251
00252 VLC_API void vlc_rwlock_init(vlc_rwlock_t *);
00253 VLC_API void vlc_rwlock_destroy(vlc_rwlock_t *);
00254 VLC_API void vlc_rwlock_rdlock(vlc_rwlock_t *);
00255 VLC_API void vlc_rwlock_wrlock(vlc_rwlock_t *);
00256 VLC_API void vlc_rwlock_unlock(vlc_rwlock_t *);
00257 VLC_API int vlc_threadvar_create(vlc_threadvar_t * , void (*) (void *) );
00258 VLC_API void vlc_threadvar_delete(vlc_threadvar_t *);
00259 VLC_API int vlc_threadvar_set(vlc_threadvar_t, void *);
00260 VLC_API void * vlc_threadvar_get(vlc_threadvar_t);
00261
00262 VLC_API int vlc_clone(vlc_thread_t *, void * (*) (void *), void *, int) VLC_USED;
00263 VLC_API void vlc_cancel(vlc_thread_t);
00264 VLC_API void vlc_join(vlc_thread_t, void **);
00265 VLC_API void vlc_control_cancel (int cmd, ...);
00266
00267 VLC_API mtime_t mdate(void);
00268 VLC_API void mwait(mtime_t deadline);
00269 VLC_API void msleep(mtime_t delay);
00270
00271 #define VLC_HARD_MIN_SLEEP 10000
00272 #define VLC_SOFT_MIN_SLEEP 9000000
00273
00274 #if VLC_GCC_VERSION(4,3)
00275
00276
00277
00278
00279
00280 static
00281 __attribute__((unused))
00282 __attribute__((noinline))
00283 __attribute__((error("sorry, cannot sleep for such short a time")))
00284 mtime_t impossible_delay( mtime_t delay )
00285 {
00286 (void) delay;
00287 return VLC_HARD_MIN_SLEEP;
00288 }
00289
00290 static
00291 __attribute__((unused))
00292 __attribute__((noinline))
00293 __attribute__((warning("use proper event handling instead of short delay")))
00294 mtime_t harmful_delay( mtime_t delay )
00295 {
00296 return delay;
00297 }
00298
00299 # define check_delay( d ) \
00300 ((__builtin_constant_p(d < VLC_HARD_MIN_SLEEP) \
00301 && (d < VLC_HARD_MIN_SLEEP)) \
00302 ? impossible_delay(d) \
00303 : ((__builtin_constant_p(d < VLC_SOFT_MIN_SLEEP) \
00304 && (d < VLC_SOFT_MIN_SLEEP)) \
00305 ? harmful_delay(d) \
00306 : d))
00307
00308 static
00309 __attribute__((unused))
00310 __attribute__((noinline))
00311 __attribute__((error("deadlines can not be constant")))
00312 mtime_t impossible_deadline( mtime_t deadline )
00313 {
00314 return deadline;
00315 }
00316
00317 # define check_deadline( d ) \
00318 (__builtin_constant_p(d) ? impossible_deadline(d) : d)
00319 #else
00320 # define check_delay(d) (d)
00321 # define check_deadline(d) (d)
00322 #endif
00323
00324 #define msleep(d) msleep(check_delay(d))
00325 #define mwait(d) mwait(check_deadline(d))
00326
00327 VLC_API int vlc_timer_create(vlc_timer_t *, void (*) (void *), void *) VLC_USED;
00328 VLC_API void vlc_timer_destroy(vlc_timer_t);
00329 VLC_API void vlc_timer_schedule(vlc_timer_t, bool, mtime_t, mtime_t);
00330 VLC_API unsigned vlc_timer_getoverrun(vlc_timer_t) VLC_USED;
00331
00332 VLC_API unsigned vlc_GetCPUCount(void);
00333
00334 #ifndef LIBVLC_USE_PTHREAD_CANCEL
00335 enum {
00336 VLC_CLEANUP_PUSH,
00337 VLC_CLEANUP_POP,
00338 };
00339 #endif
00340
00341 VLC_API int vlc_savecancel(void);
00342 VLC_API void vlc_restorecancel(int state);
00343 VLC_API void vlc_testcancel(void);
00344
00345 #if defined (LIBVLC_USE_PTHREAD_CANCEL)
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 # define vlc_cleanup_push( routine, arg ) pthread_cleanup_push (routine, arg)
00358
00359
00360
00361
00362
00363 # define vlc_cleanup_pop( ) pthread_cleanup_pop (0)
00364
00365
00366
00367
00368
00369 # define vlc_cleanup_run( ) pthread_cleanup_pop (1)
00370 #else
00371 typedef struct vlc_cleanup_t vlc_cleanup_t;
00372
00373 struct vlc_cleanup_t
00374 {
00375 vlc_cleanup_t *next;
00376 void (*proc) (void *);
00377 void *data;
00378 };
00379
00380
00381
00382
00383 # define vlc_cleanup_push( routine, arg ) \
00384 do { \
00385 vlc_cleanup_t vlc_cleanup_data = { NULL, routine, arg, }; \
00386 vlc_control_cancel (VLC_CLEANUP_PUSH, &vlc_cleanup_data)
00387
00388 # define vlc_cleanup_pop( ) \
00389 vlc_control_cancel (VLC_CLEANUP_POP); \
00390 } while (0)
00391
00392 # define vlc_cleanup_run( ) \
00393 vlc_control_cancel (VLC_CLEANUP_POP); \
00394 vlc_cleanup_data.proc (vlc_cleanup_data.data); \
00395 } while (0)
00396
00397
00398 static inline int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
00399 {
00400 vlc_testcancel ();
00401
00402 while (timeout > 50)
00403 {
00404 int val = poll (fds, nfds, timeout);
00405 if (val != 0)
00406 return val;
00407 timeout -= 50;
00408 vlc_testcancel ();
00409 }
00410
00411 return poll (fds, nfds, timeout);
00412 }
00413 # define poll(u,n,t) vlc_poll(u, n, t)
00414
00415 #endif
00416
00417 static inline void vlc_cleanup_lock (void *lock)
00418 {
00419 vlc_mutex_unlock ((vlc_mutex_t *)lock);
00420 }
00421 #define mutex_cleanup_push( lock ) vlc_cleanup_push (vlc_cleanup_lock, lock)
00422
00423 # if defined (_POSIX_SPIN_LOCKS) && ((_POSIX_SPIN_LOCKS - 0) > 0)
00424 typedef pthread_spinlock_t vlc_spinlock_t;
00425
00426
00427
00428
00429 static inline void vlc_spin_init (vlc_spinlock_t *spin)
00430 {
00431 if (pthread_spin_init (spin, PTHREAD_PROCESS_PRIVATE))
00432 abort ();
00433 }
00434
00435
00436
00437
00438 static inline void vlc_spin_lock (vlc_spinlock_t *spin)
00439 {
00440 pthread_spin_lock (spin);
00441 }
00442
00443
00444
00445
00446 static inline void vlc_spin_unlock (vlc_spinlock_t *spin)
00447 {
00448 pthread_spin_unlock (spin);
00449 }
00450
00451
00452
00453
00454 static inline void vlc_spin_destroy (vlc_spinlock_t *spin)
00455 {
00456 pthread_spin_destroy (spin);
00457 }
00458
00459 #elif defined (WIN32) && !defined (UNDER_CE)
00460
00461 typedef CRITICAL_SECTION vlc_spinlock_t;
00462
00463
00464
00465
00466 static inline void vlc_spin_init (vlc_spinlock_t *spin)
00467 {
00468 if (!InitializeCriticalSectionAndSpinCount(spin, 4000))
00469 abort ();
00470 }
00471
00472
00473
00474
00475 static inline void vlc_spin_lock (vlc_spinlock_t *spin)
00476 {
00477 EnterCriticalSection(spin);
00478 }
00479
00480
00481
00482
00483 static inline void vlc_spin_unlock (vlc_spinlock_t *spin)
00484 {
00485 LeaveCriticalSection(spin);
00486 }
00487
00488
00489
00490
00491 static inline void vlc_spin_destroy (vlc_spinlock_t *spin)
00492 {
00493 DeleteCriticalSection(spin);
00494 }
00495
00496 #else
00497
00498
00499 typedef vlc_mutex_t vlc_spinlock_t;
00500
00501 static inline void vlc_spin_init (vlc_spinlock_t *spin)
00502 {
00503 vlc_mutex_init (spin);
00504 }
00505
00506 # define vlc_spin_lock vlc_mutex_lock
00507 # define vlc_spin_unlock vlc_mutex_unlock
00508 # define vlc_spin_destroy vlc_mutex_destroy
00509 #endif
00510
00511
00512
00513
00514 #if defined (__APPLE__)
00515 # include <libkern/OSAtomic.h>
00516 #endif
00517 static inline void barrier (void)
00518 {
00519 #if defined (__GNUC__) && !defined (__APPLE__) && \
00520 ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
00521 __sync_synchronize ();
00522 #elif defined(__APPLE__)
00523 OSMemoryBarrier ();
00524 #elif defined(__powerpc__)
00525 asm volatile ("sync":::"memory");
00526 #elif 0 // defined(__i386__)
00527 asm volatile ("mfence":::"memory");
00528 #else
00529 vlc_spinlock_t spin;
00530 vlc_spin_init (&spin);
00531 vlc_spin_lock (&spin);
00532 vlc_spin_unlock (&spin);
00533 vlc_spin_destroy (&spin);
00534 #endif
00535 }
00536
00537 #ifdef __cplusplus
00538
00539
00540
00541
00542
00543 class vlc_mutex_locker
00544 {
00545 private:
00546 vlc_mutex_t *lock;
00547 public:
00548 vlc_mutex_locker (vlc_mutex_t *m) : lock (m)
00549 {
00550 vlc_mutex_lock (lock);
00551 }
00552
00553 ~vlc_mutex_locker (void)
00554 {
00555 vlc_mutex_unlock (lock);
00556 }
00557 };
00558 #endif
00559
00560 enum {
00561 VLC_AVCODEC_MUTEX = 0,
00562 VLC_GCRYPT_MUTEX,
00563 VLC_XLIB_MUTEX,
00564 VLC_MOSAIC_MUTEX,
00565 VLC_HIGHLIGHT_MUTEX,
00566
00567 VLC_MAX_MUTEX
00568 };
00569
00570 VLC_API void vlc_global_mutex( unsigned, bool );
00571 #define vlc_global_lock( n ) vlc_global_mutex( n, true )
00572 #define vlc_global_unlock( n ) vlc_global_mutex( n, false )
00573
00574 #endif