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 # include <errno.h>
00039 #elif defined( WIN32 )
00040 # include <process.h>
00041 # include <errno.h>
00042
00043 #else
00044 # define LIBVLC_USE_PTHREAD 1
00045 # define LIBVLC_USE_PTHREAD_CANCEL 1
00046 # define _APPLE_C_SOURCE 1
00047
00048 # include <stdlib.h>
00049 # include <unistd.h>
00050 # include <pthread.h>
00051 # include <semaphore.h>
00052 # include <time.h>
00053
00054 #endif
00055
00056
00057
00058
00059
00060
00061 #ifdef __APPLE__
00062 # define VLC_THREAD_PRIORITY_LOW 0
00063 # define VLC_THREAD_PRIORITY_INPUT 22
00064 # define VLC_THREAD_PRIORITY_AUDIO 22
00065 # define VLC_THREAD_PRIORITY_VIDEO 0
00066 # define VLC_THREAD_PRIORITY_OUTPUT 22
00067 # define VLC_THREAD_PRIORITY_HIGHEST 22
00068
00069 #elif defined(LIBVLC_USE_PTHREAD)
00070 # define VLC_THREAD_PRIORITY_LOW 0
00071 # define VLC_THREAD_PRIORITY_INPUT 10
00072 # define VLC_THREAD_PRIORITY_AUDIO 5
00073 # define VLC_THREAD_PRIORITY_VIDEO 0
00074 # define VLC_THREAD_PRIORITY_OUTPUT 15
00075 # define VLC_THREAD_PRIORITY_HIGHEST 20
00076
00077 #elif defined(WIN32) || defined(UNDER_CE)
00078
00079 # define VLC_THREAD_PRIORITY_LOW 0
00080 # define VLC_THREAD_PRIORITY_INPUT \
00081 THREAD_PRIORITY_ABOVE_NORMAL
00082 # define VLC_THREAD_PRIORITY_AUDIO \
00083 THREAD_PRIORITY_HIGHEST
00084 # define VLC_THREAD_PRIORITY_VIDEO 0
00085 # define VLC_THREAD_PRIORITY_OUTPUT \
00086 THREAD_PRIORITY_ABOVE_NORMAL
00087 # define VLC_THREAD_PRIORITY_HIGHEST \
00088 THREAD_PRIORITY_TIME_CRITICAL
00089
00090 #else
00091 # define VLC_THREAD_PRIORITY_LOW 0
00092 # define VLC_THREAD_PRIORITY_INPUT 0
00093 # define VLC_THREAD_PRIORITY_AUDIO 0
00094 # define VLC_THREAD_PRIORITY_VIDEO 0
00095 # define VLC_THREAD_PRIORITY_OUTPUT 0
00096 # define VLC_THREAD_PRIORITY_HIGHEST 0
00097
00098 #endif
00099
00100
00101
00102
00103
00104 #if defined (LIBVLC_USE_PTHREAD)
00105 typedef pthread_t vlc_thread_t;
00106 typedef pthread_mutex_t vlc_mutex_t;
00107 #define VLC_STATIC_MUTEX PTHREAD_MUTEX_INITIALIZER
00108 typedef pthread_cond_t vlc_cond_t;
00109 typedef sem_t vlc_sem_t;
00110 typedef pthread_rwlock_t vlc_rwlock_t;
00111 typedef pthread_key_t vlc_threadvar_t;
00112 typedef struct vlc_timer *vlc_timer_t;
00113
00114 #elif defined( WIN32 )
00115 #if !defined( UNDER_CE )
00116 typedef HANDLE vlc_thread_t;
00117 #else
00118 typedef struct
00119 {
00120 HANDLE handle;
00121 HANDLE cancel_event;
00122 } *vlc_thread_t;
00123 #endif
00124
00125 typedef struct
00126 {
00127 LONG initialized;
00128 CRITICAL_SECTION mutex;
00129 } vlc_mutex_t;
00130 #define VLC_STATIC_MUTEX { 0, }
00131
00132 typedef HANDLE vlc_cond_t;
00133 typedef HANDLE vlc_sem_t;
00134
00135 typedef struct
00136 {
00137 vlc_mutex_t mutex;
00138 vlc_cond_t read_wait;
00139 vlc_cond_t write_wait;
00140 unsigned long readers;
00141 unsigned long writers;
00142 DWORD writer;
00143 } vlc_rwlock_t;
00144
00145 typedef DWORD vlc_threadvar_t;
00146 typedef struct vlc_timer *vlc_timer_t;
00147 #endif
00148
00149 #if defined( WIN32 ) && !defined ETIMEDOUT
00150 # define ETIMEDOUT 10060
00151 #endif
00152
00153
00154
00155
00156 VLC_EXPORT( void, vlc_mutex_init, ( vlc_mutex_t * ) );
00157 VLC_EXPORT( void, vlc_mutex_init_recursive, ( vlc_mutex_t * ) );
00158 VLC_EXPORT( void, vlc_mutex_destroy, ( vlc_mutex_t * ) );
00159 VLC_EXPORT( void, vlc_mutex_lock, ( vlc_mutex_t * ) );
00160 VLC_EXPORT( int, vlc_mutex_trylock, ( vlc_mutex_t * ) LIBVLC_USED );
00161 VLC_EXPORT( void, vlc_mutex_unlock, ( vlc_mutex_t * ) );
00162 VLC_EXPORT( void, vlc_cond_init, ( vlc_cond_t * ) );
00163 VLC_EXPORT( void, vlc_cond_destroy, ( vlc_cond_t * ) );
00164 VLC_EXPORT( void, vlc_cond_signal, (vlc_cond_t *) );
00165 VLC_EXPORT( void, vlc_cond_broadcast, (vlc_cond_t *) );
00166 VLC_EXPORT( void, vlc_cond_wait, (vlc_cond_t *, vlc_mutex_t *) );
00167 VLC_EXPORT( int, vlc_cond_timedwait, (vlc_cond_t *, vlc_mutex_t *, mtime_t) );
00168 VLC_EXPORT( void, vlc_sem_init, (vlc_sem_t *, unsigned) );
00169 VLC_EXPORT( void, vlc_sem_destroy, (vlc_sem_t *) );
00170 VLC_EXPORT( int, vlc_sem_post, (vlc_sem_t *) );
00171 VLC_EXPORT( void, vlc_sem_wait, (vlc_sem_t *) );
00172
00173 VLC_EXPORT( void, vlc_rwlock_init, (vlc_rwlock_t *) );
00174 VLC_EXPORT( void, vlc_rwlock_destroy, (vlc_rwlock_t *) );
00175 VLC_EXPORT( void, vlc_rwlock_rdlock, (vlc_rwlock_t *) );
00176 VLC_EXPORT( void, vlc_rwlock_wrlock, (vlc_rwlock_t *) );
00177 VLC_EXPORT( void, vlc_rwlock_unlock, (vlc_rwlock_t *) );
00178 VLC_EXPORT( int, vlc_threadvar_create, (vlc_threadvar_t * , void (*) (void *) ) );
00179 VLC_EXPORT( void, vlc_threadvar_delete, (vlc_threadvar_t *) );
00180 VLC_EXPORT( int, vlc_threadvar_set, (vlc_threadvar_t, void *) );
00181 VLC_EXPORT( void *, vlc_threadvar_get, (vlc_threadvar_t) );
00182 VLC_EXPORT( int, vlc_thread_create, ( vlc_object_t *, const char *, int, const char *, void * ( * ) ( vlc_object_t * ), int ) LIBVLC_USED );
00183 VLC_EXPORT( int, __vlc_thread_set_priority, ( vlc_object_t *, const char *, int, int ) );
00184 VLC_EXPORT( void, __vlc_thread_join, ( vlc_object_t * ) );
00185
00186 VLC_EXPORT( int, vlc_clone, (vlc_thread_t *, void * (*) (void *), void *, int) LIBVLC_USED );
00187 VLC_EXPORT( void, vlc_cancel, (vlc_thread_t) );
00188 VLC_EXPORT( void, vlc_join, (vlc_thread_t, void **) );
00189 VLC_EXPORT (void, vlc_control_cancel, (int cmd, ...));
00190
00191 VLC_EXPORT( int, vlc_timer_create, (vlc_timer_t *, void (*) (void *), void *) LIBVLC_USED );
00192 VLC_EXPORT( void, vlc_timer_destroy, (vlc_timer_t) );
00193 VLC_EXPORT( void, vlc_timer_schedule, (vlc_timer_t, bool, mtime_t, mtime_t) );
00194 VLC_EXPORT( unsigned, vlc_timer_getoverrun, (vlc_timer_t) LIBVLC_USED );
00195
00196 #ifndef LIBVLC_USE_PTHREAD_CANCEL
00197 enum {
00198 VLC_DO_CANCEL,
00199 VLC_CLEANUP_PUSH,
00200 VLC_CLEANUP_POP,
00201 };
00202 #endif
00203
00204 VLC_EXPORT( int, vlc_savecancel, (void) );
00205 VLC_EXPORT( void, vlc_restorecancel, (int state) );
00206 VLC_EXPORT( void, vlc_testcancel, (void) );
00207
00208 #if defined (LIBVLC_USE_PTHREAD_CANCEL)
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 # define vlc_cleanup_push( routine, arg ) pthread_cleanup_push (routine, arg)
00221
00222
00223
00224
00225
00226 # define vlc_cleanup_pop( ) pthread_cleanup_pop (0)
00227
00228
00229
00230
00231
00232 # define vlc_cleanup_run( ) pthread_cleanup_pop (1)
00233 #else
00234 typedef struct vlc_cleanup_t vlc_cleanup_t;
00235
00236 struct vlc_cleanup_t
00237 {
00238 vlc_cleanup_t *next;
00239 void (*proc) (void *);
00240 void *data;
00241 };
00242
00243
00244
00245
00246 # define vlc_cleanup_push( routine, arg ) \
00247 do { \
00248 vlc_cleanup_t vlc_cleanup_data = { NULL, routine, arg, }; \
00249 vlc_control_cancel (VLC_CLEANUP_PUSH, &vlc_cleanup_data)
00250
00251 # define vlc_cleanup_pop( ) \
00252 vlc_control_cancel (VLC_CLEANUP_POP); \
00253 } while (0)
00254
00255 # define vlc_cleanup_run( ) \
00256 vlc_control_cancel (VLC_CLEANUP_POP); \
00257 vlc_cleanup_data.proc (vlc_cleanup_data.data); \
00258 } while (0)
00259
00260 #endif
00261
00262 static inline void vlc_cleanup_lock (void *lock)
00263 {
00264 vlc_mutex_unlock ((vlc_mutex_t *)lock);
00265 }
00266 #define mutex_cleanup_push( lock ) vlc_cleanup_push (vlc_cleanup_lock, lock)
00267
00268 # if defined (_POSIX_SPIN_LOCKS) && ((_POSIX_SPIN_LOCKS - 0) > 0)
00269 typedef pthread_spinlock_t vlc_spinlock_t;
00270
00271
00272
00273
00274 static inline void vlc_spin_init (vlc_spinlock_t *spin)
00275 {
00276 if (pthread_spin_init (spin, PTHREAD_PROCESS_PRIVATE))
00277 abort ();
00278 }
00279
00280
00281
00282
00283 static inline void vlc_spin_lock (vlc_spinlock_t *spin)
00284 {
00285 pthread_spin_lock (spin);
00286 }
00287
00288
00289
00290
00291 static inline void vlc_spin_unlock (vlc_spinlock_t *spin)
00292 {
00293 pthread_spin_unlock (spin);
00294 }
00295
00296
00297
00298
00299 static inline void vlc_spin_destroy (vlc_spinlock_t *spin)
00300 {
00301 pthread_spin_destroy (spin);
00302 }
00303
00304 #elif defined (WIN32) && !defined (UNDER_CE)
00305
00306 typedef CRITICAL_SECTION vlc_spinlock_t;
00307
00308
00309
00310
00311 static inline void vlc_spin_init (vlc_spinlock_t *spin)
00312 {
00313 if (!InitializeCriticalSectionAndSpinCount(spin, 4000))
00314 abort ();
00315 }
00316
00317
00318
00319
00320 static inline void vlc_spin_lock (vlc_spinlock_t *spin)
00321 {
00322 EnterCriticalSection(spin);
00323 }
00324
00325
00326
00327
00328 static inline void vlc_spin_unlock (vlc_spinlock_t *spin)
00329 {
00330 LeaveCriticalSection(spin);
00331 }
00332
00333
00334
00335
00336 static inline void vlc_spin_destroy (vlc_spinlock_t *spin)
00337 {
00338 DeleteCriticalSection(spin);
00339 }
00340
00341 #else
00342
00343
00344 typedef vlc_mutex_t vlc_spinlock_t;
00345
00346 static inline void vlc_spin_init (vlc_spinlock_t *spin)
00347 {
00348 vlc_mutex_init (spin);
00349 }
00350
00351 # define vlc_spin_lock vlc_mutex_lock
00352 # define vlc_spin_unlock vlc_mutex_unlock
00353 # define vlc_spin_destroy vlc_mutex_destroy
00354 #endif
00355
00356
00357
00358
00359 #if defined (__APPLE__)
00360 # include <libkern/OSAtomic.h>
00361 #endif
00362 static inline void barrier (void)
00363 {
00364 #if defined (__GNUC__) && !defined (__APPLE__) && \
00365 ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
00366 __sync_synchronize ();
00367 #elif defined(__APPLE__)
00368 OSMemoryBarrier ();
00369 #elif defined(__powerpc__)
00370 asm volatile ("sync":::"memory");
00371 #elif 0 // defined(__i386__)
00372 asm volatile ("mfence":::"memory");
00373 #else
00374 vlc_spinlock_t spin;
00375 vlc_spin_init (&spin);
00376 vlc_spin_lock (&spin);
00377 vlc_spin_unlock (&spin);
00378 vlc_spin_destroy (&spin);
00379 #endif
00380 }
00381
00382
00383
00384
00385 #define vlc_thread_create( P_THIS, PSZ_NAME, FUNC, PRIORITY ) \
00386 vlc_thread_create( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PSZ_NAME, FUNC, PRIORITY )
00387
00388
00389
00390
00391 #define vlc_thread_set_priority( P_THIS, PRIORITY ) \
00392 __vlc_thread_set_priority( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PRIORITY )
00393
00394
00395
00396
00397 #define vlc_thread_join( P_THIS ) \
00398 __vlc_thread_join( VLC_OBJECT(P_THIS) )
00399
00400 #ifdef __cplusplus
00401
00402
00403
00404
00405
00406 class vlc_mutex_locker
00407 {
00408 private:
00409 vlc_mutex_t *lock;
00410 public:
00411 vlc_mutex_locker (vlc_mutex_t *m) : lock (m)
00412 {
00413 vlc_mutex_lock (lock);
00414 }
00415
00416 ~vlc_mutex_locker (void)
00417 {
00418 vlc_mutex_unlock (lock);
00419 }
00420 };
00421 #endif
00422
00423 #endif