threads.h 8.38 KB
Newer Older
1
/*****************************************************************************
2
 * threads.h : thread implementation for VideoLAN client
3
 * This header is supposed to provide a portable threads implementation.
4 5
 * Currently, it is a wrapper to either the POSIX pthreads library, or
 * the Mach cthreads (for the GNU/Hurd).
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *****************************************************************************
 * Copyright (C) 1999, 2000 VideoLAN
 *
 * Authors:
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
25
 *****************************************************************************/
26

27 28 29
#ifdef SYS_GNU
#include <cthreads.h>
#else
30
#include <pthread.h>
31
#endif
32

33
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
34
 * Constants
35 36
 *****************************************************************************
 * These constants are used by all threads in *_CreateThread() and
Vincent Seguin's avatar
Vincent Seguin committed
37 38
 * *_DestroyThreads() functions. Since those calls are non-blocking, an integer
 * value is used as a shared flag to represent the status of the thread.
39
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
40 41 42

/* Void status - this value can be used to be sure, in an array of recorded
 * threads, that no operation is currently in progress on the concerned thread */
43
#define THREAD_NOP          0                            /* nothing happened */
Vincent Seguin's avatar
Vincent Seguin committed
44 45

/* Creation status */
46 47 48
#define THREAD_CREATE       10                     /* thread is initializing */
#define THREAD_START        11                          /* thread has forked */
#define THREAD_READY        19                            /* thread is ready */
49

Vincent Seguin's avatar
Vincent Seguin committed
50
/* Destructions status */
51 52 53
#define THREAD_DESTROY      20            /* destruction order has been sent */
#define THREAD_END          21        /* destruction order has been received */
#define THREAD_OVER         29             /* thread does not exist any more */
Vincent Seguin's avatar
Vincent Seguin committed
54 55

/* Error status */
56 57
#define THREAD_ERROR        30                           /* an error occured */
#define THREAD_FATAL        31  /* an fatal error occured - program must end */
Vincent Seguin's avatar
Vincent Seguin committed
58

59
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
60
 * Types definition
61
 *****************************************************************************/
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

#ifdef SYS_GNU

typedef cthread_t        vlc_thread_t;

/* those structs are the ones defined in /include/cthreads.h but we need
 *  * to handle *foo where foo is a mutex_t */
typedef struct s_mutex {
    spin_lock_t held;
    spin_lock_t lock;
    char *name;
    struct cthread_queue queue;
} vlc_mutex_t;

typedef struct s_condition {
    spin_lock_t lock;
    struct cthread_queue queue;
    char *name;
    struct cond_imp *implications;
} vlc_cond_t;

#else /* SYS_GNU */

85 86 87 88
typedef pthread_t        vlc_thread_t;
typedef pthread_mutex_t  vlc_mutex_t;
typedef pthread_cond_t   vlc_cond_t;

89 90
#endif /* SYS_GNU */

Vincent Seguin's avatar
Vincent Seguin committed
91
typedef void *(*vlc_thread_func_t)(void *p_data);
92

93
/*****************************************************************************
94
 * Prototypes
95
 *****************************************************************************/
96

Vincent Seguin's avatar
Vincent Seguin committed
97
static __inline__ int  vlc_thread_create( vlc_thread_t *p_thread, char *psz_name,
98
                                          vlc_thread_func_t func, void *p_data );
Vincent Seguin's avatar
Vincent Seguin committed
99 100
static __inline__ void vlc_thread_exit  ( void );
static __inline__ void vlc_thread_join  ( vlc_thread_t thread );
101

Vincent Seguin's avatar
Vincent Seguin committed
102 103 104
static __inline__ int  vlc_mutex_init   ( vlc_mutex_t *p_mutex );
static __inline__ int  vlc_mutex_lock   ( vlc_mutex_t *p_mutex );
static __inline__ int  vlc_mutex_unlock ( vlc_mutex_t *p_mutex );
105

Vincent Seguin's avatar
Vincent Seguin committed
106 107 108
static __inline__ int  vlc_cond_init    ( vlc_cond_t *p_condvar );
static __inline__ int  vlc_cond_signal  ( vlc_cond_t *p_condvar );
static __inline__ int  vlc_cond_wait    ( vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex );
109

110 111 112 113
#if 0
static _inline__ int    vlc_cond_timedwait   ( vlc_cond_t * condvar, vlc_mutex_t * mutex,
                              mtime_t absoute_timeout_time );
#endif
114

115
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
116
 * vlc_thread_create: create a thread
117
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
118
static __inline__ int vlc_thread_create( vlc_thread_t *p_thread,
119 120
                                         char *psz_name, vlc_thread_func_t func,
                                         void *p_data)
121
{
122 123 124 125
#ifdef SYS_GNU
    *p_thread = cthread_fork( (cthread_fn_t)func, (any_t)p_data );
    return( 0 );
#else
Vincent Seguin's avatar
Vincent Seguin committed
126
    return pthread_create( p_thread, NULL, func, p_data );
127
#endif
128 129
}

130
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
131
 * vlc_thread_exit: terminate a thread
132
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
133
static __inline__ void vlc_thread_exit( void )
134
{
135 136 137 138
#ifdef SYS_GNU
    int result;
    cthread_exit( &result );
#else		
139
    pthread_exit( 0 );
140
#endif
141 142
}

143
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
144
 * vlc_thread_join: wait until a thread exits
145
 *****************************************************************************/
146 147
static __inline__ void vlc_thread_join( vlc_thread_t thread )
{
148 149 150
#ifdef SYS_GNU
    cthread_join( thread );
#else	
151
    pthread_join( thread, NULL );
152
#endif
153 154
}

155
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
156
 * vlc_mutex_init: initialize a mutex
157
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
158
static __inline__ int vlc_mutex_init( vlc_mutex_t *p_mutex )
159
{
160 161 162 163
#ifdef SYS_GNU
    mutex_init( p_mutex );
    return( 0 );
#else
Vincent Seguin's avatar
Vincent Seguin committed
164
    return pthread_mutex_init( p_mutex, NULL );
165
#endif
166 167
}

168
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
169
 * vlc_mutex_lock: lock a mutex
170
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
171
static __inline__ int vlc_mutex_lock( vlc_mutex_t *p_mutex )
172
{
173 174 175 176
#ifdef SYS_GNU
    mutex_lock( p_mutex );
    return( 0 );
#else
Vincent Seguin's avatar
Vincent Seguin committed
177
    return pthread_mutex_lock( p_mutex );
178
#endif
179 180
}

181
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
182
 * vlc_mutex_unlock: unlock a mutex
183
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
184
static __inline__ int vlc_mutex_unlock( vlc_mutex_t *p_mutex )
185
{
186 187 188 189
#ifdef SYS_GNU
    mutex_unlock( p_mutex );
    return( 0 );
#else
Vincent Seguin's avatar
Vincent Seguin committed
190
    return pthread_mutex_unlock( p_mutex );
191
#endif
192 193
}

194
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
195
 * vlc_cond_init: initialize a condition
196
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
197
static __inline__ int vlc_cond_init( vlc_cond_t *p_condvar )
198
{
199 200 201 202 203 204 205 206 207
#ifdef SYS_GNU
    /* condition_init() */
    spin_lock_init( &p_condvar->lock );
    cthread_queue_init( &p_condvar->queue );
    p_condvar->name = 0;
    p_condvar->implications = 0;

    return( 0 );
#else			    
Vincent Seguin's avatar
Vincent Seguin committed
208
    return pthread_cond_init( p_condvar, NULL );
209
#endif
210 211
}

212
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
213
 * vlc_cond_signal: start a thread on condition completion
214
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
215
static __inline__ int vlc_cond_signal( vlc_cond_t *p_condvar )
216
{
217 218 219 220 221 222 223 224
#ifdef SYS_GNU
    /* condition_signal() */
    if ( p_condvar->queue.head || p_condvar->implications )
    {
        cond_signal( (condition_t)p_condvar );
    }
    return( 0 );
#else		
Vincent Seguin's avatar
Vincent Seguin committed
225
    return pthread_cond_signal( p_condvar );
226
#endif
227
}
Vincent Seguin's avatar
Vincent Seguin committed
228

229
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
230
 * vlc_cond_wait: wait until condition completion
231
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
232
static __inline__ int vlc_cond_wait( vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex )
233
{
234 235 236 237
#ifdef SYS_GNU
    condition_wait( (condition_t)p_condvar, (mutex_t)p_mutex );
    return( 0 );
#else
Vincent Seguin's avatar
Vincent Seguin committed
238
    return pthread_cond_wait( p_condvar, p_mutex );
239
#endif
240
}
241