~siretart/xine-lib/ubuntu

« back to all changes in this revision

Viewing changes to win32/contrib/pthreads/barrier.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2005-12-15 13:13:45 UTC
  • mfrom: (0.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051215131345-8n4osv1j7fy9c1s1
* SECURITY UPDATE: Fix arbitrary code execution with crafted PNG images in
  embedded ffmpeg copy.
* src/libffmpeg/libavcodec/utils.c, avcodec_default_get_buffer(): Apply
  upstream patch to fix buffer overflow on decoding of small PIX_FMT_PAL8
  PNG files.
* References:
  CVE-2005-4048
  http://mplayerhq.hu/pipermail/ffmpeg-devel/2005-November/005333.html
  http://www1.mplayerhq.hu/cgi-bin/cvsweb.cgi/ffmpeg/libavcodec/
  utils.c.diff?r1=1.161&r2=1.162&cvsroot=FFMpeg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * barrier.c
3
 
 *
4
 
 * Description:
5
 
 * This translation unit implements barrier primitives.
6
 
 *
7
 
 * Pthreads-win32 - POSIX Threads Library for Win32
8
 
 * Copyright (C) 1998
9
 
 *
10
 
 * This library is free software; you can redistribute it and/or
11
 
 * modify it under the terms of the GNU Library General Public
12
 
 * License as published by the Free Software Foundation; either
13
 
 * version 2 of the License, or (at your option) any later version.
14
 
 *
15
 
 * This library is distributed in the hope that it will be useful,
16
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 
 * Library General Public License for more details.
19
 
 *
20
 
 * You should have received a copy of the GNU Library General Public
21
 
 * License along with this library; if not, write to the Free
22
 
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23
 
 * MA 02111-1307, USA
24
 
 */
25
 
 
26
 
#include "pthread.h"
27
 
#include "implement.h"
28
 
 
29
 
 
30
 
#ifdef __MINGW32__
31
 
#define _LONG long
32
 
#define _LPLONG long*
33
 
#else
34
 
#define _LONG PVOID
35
 
#define _LPLONG PVOID*
36
 
#endif
37
 
 
38
 
int
39
 
pthread_barrier_init(pthread_barrier_t * barrier,
40
 
                     const pthread_barrierattr_t * attr,
41
 
                     unsigned int count)
42
 
{
43
 
  pthread_barrier_t b;
44
 
 
45
 
  if (barrier == NULL || count == 0)
46
 
    {
47
 
      return EINVAL;
48
 
    }
49
 
 
50
 
  if (NULL != (b = (pthread_barrier_t) calloc(1, sizeof(*b))))
51
 
    {
52
 
      b->pshared = (attr != NULL && *attr != NULL
53
 
                    ? (*attr)->pshared
54
 
                    : PTHREAD_PROCESS_PRIVATE);
55
 
 
56
 
      b->nCurrentBarrierHeight = b->nInitialBarrierHeight = count;
57
 
      b->iStep = 0;
58
 
 
59
 
      /*
60
 
       * Two semaphores are used in the same way as two stepping
61
 
       * stones might be used in crossing a stream. Once all
62
 
       * threads are safely on one stone, the other stone can
63
 
       * be moved ahead, and the threads can start moving to it.
64
 
       * If some threads decide to eat their lunch before moving
65
 
       * then the other threads have to wait.
66
 
       */
67
 
      if (0 == sem_init(&(b->semBarrierBreeched[0]), b->pshared, 0))
68
 
        {
69
 
          if (0 == sem_init(&(b->semBarrierBreeched[1]), b->pshared, 0))
70
 
            {
71
 
              *barrier = b;
72
 
              return 0;
73
 
            }
74
 
          (void) sem_destroy(&(b->semBarrierBreeched[0]));
75
 
        }
76
 
      (void) free(b);
77
 
    }
78
 
 
79
 
  return ENOMEM;
80
 
}
81
 
 
82
 
int
83
 
pthread_barrier_destroy(pthread_barrier_t *barrier)
84
 
{
85
 
  int result = 0;
86
 
  pthread_barrier_t b;
87
 
 
88
 
  if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID)
89
 
    {
90
 
      return EINVAL;
91
 
    }
92
 
 
93
 
  b = *barrier;
94
 
  *barrier = NULL;
95
 
 
96
 
  if (0 == (result = sem_destroy(&(b->semBarrierBreeched[0]))))
97
 
    {
98
 
      if (0 == (result = sem_destroy(&(b->semBarrierBreeched[1]))))
99
 
        {
100
 
          (void) free(b);
101
 
          return 0;
102
 
        }
103
 
      (void) sem_init(&(b->semBarrierBreeched[0]),
104
 
                        b->pshared,
105
 
                        0);
106
 
    }
107
 
 
108
 
  *barrier = b;
109
 
  return(result);
110
 
}
111
 
 
112
 
 
113
 
int
114
 
pthread_barrier_wait(pthread_barrier_t *barrier)
115
 
{
116
 
  int result;
117
 
  int step;
118
 
  pthread_barrier_t b;
119
 
 
120
 
  if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID)
121
 
    {
122
 
      return EINVAL;
123
 
    }
124
 
 
125
 
  b = *barrier;
126
 
  step = b->iStep;
127
 
 
128
 
  if (0 == InterlockedDecrement((long *) &(b->nCurrentBarrierHeight)))
129
 
    {
130
 
      /* Must be done before posting the semaphore. */
131
 
      b->nCurrentBarrierHeight = b->nInitialBarrierHeight;
132
 
 
133
 
      /*
134
 
       * There is no race condition between the semaphore wait and post
135
 
       * because we are using two alternating semas and all threads have
136
 
       * entered barrier_wait and checked nCurrentBarrierHeight before this
137
 
       * barrier's sema can be posted. Any threads that have not quite
138
 
       * entered sem_wait below when the multiple_post has completed
139
 
       * will nevertheless continue through the semaphore (barrier)
140
 
       * and will not be left stranded.
141
 
       */
142
 
      result = (b->nInitialBarrierHeight > 1
143
 
                ? sem_post_multiple(&(b->semBarrierBreeched[step]),
144
 
                                    b->nInitialBarrierHeight - 1)
145
 
                : 0);
146
 
    }
147
 
  else
148
 
    {
149
 
      BOOL switchCancelState;
150
 
      int oldCancelState;
151
 
      pthread_t self = pthread_self();
152
 
 
153
 
      /*
154
 
       * This routine is not a cancelation point, so temporarily
155
 
       * prevent sem_wait() from being one.
156
 
       * PTHREAD_CANCEL_ASYNCHRONOUS threads can still be canceled.
157
 
       */
158
 
      switchCancelState = (self->cancelType == PTHREAD_CANCEL_DEFERRED &&
159
 
                           0 == pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,
160
 
                                                       &oldCancelState));
161
 
 
162
 
      result = sem_wait(&(b->semBarrierBreeched[step]));
163
 
 
164
 
      if (switchCancelState)
165
 
        {
166
 
          (void) pthread_setcancelstate(oldCancelState, NULL);
167
 
        }
168
 
    }
169
 
 
170
 
  /*
171
 
   * The first thread across will be the PTHREAD_BARRIER_SERIAL_THREAD.
172
 
   * It also sets up the alternate semaphore as the next barrier.
173
 
   */
174
 
  if (0 == result)
175
 
    {
176
 
      result = ((_LONG) step ==
177
 
                InterlockedCompareExchange((_LPLONG) &(b->iStep),
178
 
                                           (_LONG) (1L - step),
179
 
                                           (_LONG) step)
180
 
                ? PTHREAD_BARRIER_SERIAL_THREAD
181
 
                : 0);
182
 
    }
183
 
 
184
 
  return(result);
185
 
}
186
 
 
187
 
 
188
 
int
189
 
pthread_barrierattr_init (pthread_barrierattr_t * attr)
190
 
     /*
191
 
      * ------------------------------------------------------
192
 
      * DOCPUBLIC
193
 
      *      Initializes a barrier attributes object with default
194
 
      *      attributes.
195
 
      *
196
 
      * PARAMETERS
197
 
      *      attr
198
 
      *              pointer to an instance of pthread_barrierattr_t
199
 
      *
200
 
      *
201
 
      * DESCRIPTION
202
 
      *      Initializes a barrier attributes object with default
203
 
      *      attributes.
204
 
      *
205
 
      *      NOTES:
206
 
      *              1)      Used to define barrier types
207
 
      *
208
 
      * RESULTS
209
 
      *              0               successfully initialized attr,
210
 
      *              ENOMEM          insufficient memory for attr.
211
 
      *
212
 
      * ------------------------------------------------------
213
 
      */
214
 
{
215
 
  pthread_barrierattr_t ba;
216
 
  int result = 0;
217
 
 
218
 
  ba = (pthread_barrierattr_t) calloc (1, sizeof (*ba));
219
 
 
220
 
  if (ba == NULL)
221
 
    {
222
 
      result = ENOMEM;
223
 
    }
224
 
 
225
 
  ba->pshared = PTHREAD_PROCESS_PRIVATE;
226
 
 
227
 
  *attr = ba;
228
 
 
229
 
  return (result);
230
 
 
231
 
}                               /* pthread_barrierattr_init */
232
 
 
233
 
 
234
 
int
235
 
pthread_barrierattr_destroy (pthread_barrierattr_t * attr)
236
 
     /*
237
 
      * ------------------------------------------------------
238
 
      * DOCPUBLIC
239
 
      *      Destroys a barrier attributes object. The object can
240
 
      *      no longer be used.
241
 
      *
242
 
      * PARAMETERS
243
 
      *      attr
244
 
      *              pointer to an instance of pthread_barrierattr_t
245
 
      *
246
 
      *
247
 
      * DESCRIPTION
248
 
      *      Destroys a barrier attributes object. The object can
249
 
      *      no longer be used.
250
 
      *
251
 
      *      NOTES:
252
 
      *              1)      Does not affect barrieres created using 'attr'
253
 
      *
254
 
      * RESULTS
255
 
      *              0               successfully released attr,
256
 
      *              EINVAL          'attr' is invalid.
257
 
      *
258
 
      * ------------------------------------------------------
259
 
      */
260
 
{
261
 
  int result = 0;
262
 
 
263
 
  if (attr == NULL || *attr == NULL)
264
 
    {
265
 
      result = EINVAL;
266
 
    }
267
 
  else
268
 
    {
269
 
      pthread_barrierattr_t ba = *attr;
270
 
 
271
 
      *attr = NULL;
272
 
      free (ba);
273
 
 
274
 
      result = 0;
275
 
    }
276
 
 
277
 
  return (result);
278
 
 
279
 
}                               /* pthread_barrierattr_destroy */
280
 
 
281
 
 
282
 
int
283
 
pthread_barrierattr_getpshared (const pthread_barrierattr_t * attr,
284
 
                                int *pshared)
285
 
     /*
286
 
      * ------------------------------------------------------
287
 
      * DOCPUBLIC
288
 
      *      Determine whether barriers created with 'attr' can be
289
 
      *      shared between processes.
290
 
      *
291
 
      * PARAMETERS
292
 
      *      attr
293
 
      *              pointer to an instance of pthread_barrierattr_t
294
 
      *
295
 
      *      pshared
296
 
      *              will be set to one of:
297
 
      *
298
 
      *                      PTHREAD_PROCESS_SHARED
299
 
      *                              May be shared if in shared memory
300
 
      *
301
 
      *                      PTHREAD_PROCESS_PRIVATE
302
 
      *                              Cannot be shared.
303
 
      *
304
 
      *
305
 
      * DESCRIPTION
306
 
      *      Mutexes creatd with 'attr' can be shared between
307
 
      *      processes if pthread_barrier_t variable is allocated
308
 
      *      in memory shared by these processes.
309
 
      *      NOTES:
310
 
      *              1)      pshared barriers MUST be allocated in shared
311
 
      *                      memory.
312
 
      *              2)      The following macro is defined if shared barriers
313
 
      *                      are supported:
314
 
      *                              _POSIX_THREAD_PROCESS_SHARED
315
 
      *
316
 
      * RESULTS
317
 
      *              0               successfully retrieved attribute,
318
 
      *              EINVAL          'attr' is invalid,
319
 
      *
320
 
      * ------------------------------------------------------
321
 
      */
322
 
{
323
 
  int result;
324
 
 
325
 
  if ((attr != NULL && *attr != NULL) &&
326
 
      (pshared != NULL))
327
 
    {
328
 
      *pshared = (*attr)->pshared;
329
 
      result = 0;
330
 
    }
331
 
  else
332
 
    {
333
 
      *pshared = PTHREAD_PROCESS_PRIVATE;
334
 
      result = EINVAL;
335
 
    }
336
 
 
337
 
  return (result);
338
 
 
339
 
}                               /* pthread_barrierattr_getpshared */
340
 
 
341
 
 
342
 
int
343
 
pthread_barrierattr_setpshared (pthread_barrierattr_t * attr,
344
 
                                int pshared)
345
 
     /*
346
 
      * ------------------------------------------------------
347
 
      * DOCPUBLIC
348
 
      *      Barriers created with 'attr' can be shared between
349
 
      *      processes if pthread_barrier_t variable is allocated
350
 
      *      in memory shared by these processes.
351
 
      *
352
 
      * PARAMETERS
353
 
      *      attr
354
 
      *              pointer to an instance of pthread_barrierattr_t
355
 
      *
356
 
      *      pshared
357
 
      *              must be one of:
358
 
      *
359
 
      *                      PTHREAD_PROCESS_SHARED
360
 
      *                              May be shared if in shared memory
361
 
      *
362
 
      *                      PTHREAD_PROCESS_PRIVATE
363
 
      *                              Cannot be shared.
364
 
      *
365
 
      * DESCRIPTION
366
 
      *      Mutexes creatd with 'attr' can be shared between
367
 
      *      processes if pthread_barrier_t variable is allocated
368
 
      *      in memory shared by these processes.
369
 
      *
370
 
      *      NOTES:
371
 
      *              1)      pshared barriers MUST be allocated in shared
372
 
      *                      memory.
373
 
      *
374
 
      *              2)      The following macro is defined if shared barriers
375
 
      *                      are supported:
376
 
      *                              _POSIX_THREAD_PROCESS_SHARED
377
 
      *
378
 
      * RESULTS
379
 
      *              0               successfully set attribute,
380
 
      *              EINVAL          'attr' or pshared is invalid,
381
 
      *              ENOSYS          PTHREAD_PROCESS_SHARED not supported,
382
 
      *
383
 
      * ------------------------------------------------------
384
 
      */
385
 
{
386
 
  int result;
387
 
 
388
 
  if ((attr != NULL && *attr != NULL) &&
389
 
      ((pshared == PTHREAD_PROCESS_SHARED) ||
390
 
       (pshared == PTHREAD_PROCESS_PRIVATE)))
391
 
    {
392
 
      if (pshared == PTHREAD_PROCESS_SHARED)
393
 
        {
394
 
 
395
 
#if !defined( _POSIX_THREAD_PROCESS_SHARED )
396
 
 
397
 
          result = ENOSYS;
398
 
          pshared = PTHREAD_PROCESS_PRIVATE;
399
 
 
400
 
#else
401
 
 
402
 
          result = 0;
403
 
 
404
 
#endif /* _POSIX_THREAD_PROCESS_SHARED */
405
 
 
406
 
        }
407
 
      else
408
 
        {
409
 
          result = 0;
410
 
        }
411
 
 
412
 
      (*attr)->pshared = pshared;
413
 
    }
414
 
  else
415
 
    {
416
 
      result = EINVAL;
417
 
    }
418
 
 
419
 
  return (result);
420
 
 
421
 
}                               /* pthread_barrierattr_setpshared */