rpm  5.4.15
yarn.c
Go to the documentation of this file.
1 /* yarn.c -- generic thread operations implemented using pthread functions
2  * Copyright (C) 2008 Mark Adler
3  * Version 1.1 26 Oct 2008 Mark Adler
4  * For conditions of distribution and use, see copyright notice in yarn.h
5  */
6 
7 /* Basic thread operations implemented using the POSIX pthread library. All
8  pthread references are isolated within this module to allow alternate
9  implementations with other thread libraries. See yarn.h for the description
10  of these operations. */
11 
12 /* Version history:
13  1.0 19 Oct 2008 First version
14  1.1 26 Oct 2008 No need to set the stack size -- remove
15  Add yarn_abort() function for clean-up on error exit
16  */
17 
18 #include "system.h"
19 
20 #include <rpmiotypes.h>
21 
22 /* for thread portability */
23 #if defined(WITH_PTHREADS)
24 #if !defined(_POSIX_PTHREAD_SEMANTICS)
25 #define _POSIX_PTHREAD_SEMANTICS
26 #endif
27 #if !defined(_REENTRANT)
28 #define _REENTRANT
29 #endif
30 #else /* WITH_PTHREADS */
31 #undef _POSIX_PTHREAD_SEMANTICS
32 #undef _REENTRANT
33 #endif /* WITH_PTHREADS */
34 
35 /* external libraries and entities referenced */
36 #include <stdio.h> /* fprintf(), stderr */
37 #include <stdlib.h> /* exit(), malloc(), free(), NULL */
38 
39 #if defined(WITH_PTHREADS)
40 
41 /*@-incondefs@*/
42 #include <pthread.h> /* pthread_t, pthread_create(), pthread_join(), */
43  /* pthread_attr_t, pthread_attr_init(), pthread_attr_destroy(),
44  PTHREAD_CREATE_JOINABLE, pthread_attr_setdetachstate(),
45  pthread_self(), pthread_equal(),
46  pthread_mutex_t, PTHREAD_MUTEX_INITIALIZER, pthread_mutex_init(),
47  pthread_mutex_lock(), pthread_mutex_unlock(), pthread_mutex_destroy(),
48  pthread_cond_t, PTHREAD_COND_INITIALIZER, pthread_cond_init(),
49  pthread_cond_broadcast(), pthread_cond_wait(), pthread_cond_destroy() */
50 /*@=incondefs@*/
51 
52 #else /* WITH_PTHREADS */
53 
54 #define pthread_t int
55 #define pthread_self() 0
56 #define pthread_equal(_t1, _t2) ((_t1) == (_t2))
57 #define pthread_create(__newthread, __attr, __start_routine, arg) (EINVAL)
58 #define pthread_join(__thread, __value_ptr) (EINVAL)
59 #define pthread_cancel(__th) (EINVAL)
60 #define pthread_cleanup_pop(__execute)
61 #define pthread_cleanup_push(__routine, __arg)
62 
63 #define pthread_attr_t int
64 #define pthread_attr_init(__attr) (EINVAL)
65 #define pthread_attr_destroy(__attr) (EINVAL)
66 #define pthread_attr_setdetachstate(__attr, __detachstate) (EINVAL)
67 
68 #define pthread_mutex_t int
69 #define PTHREAD_MUTEX_INITIALIZER 0
70 #define PTHREAD_CREATE_JOINABLE 0
71 #define pthread_mutex_destroy(__mutex) (0) /* FreeLock */
72 #define pthread_mutex_init(__mutex, __attr) (0) /* NewLock */
73 #define pthread_mutex_lock(__mutex) (0) /* Possess */
74 #define pthread_mutex_unlock(__mutex) (0) /* Twist/Release */
75 
76 #define pthread_cond_t int
77 #define PTHREAD_COND_INITIALIZER 0
78 #define pthread_cond_destroy(__cond) (0) /* FreeLock */
79 #define pthread_cond_init(__cond, __attr) (0) /* NewLock */
80 #define pthread_cond_wait(__cond, __mutex) (EINVAL)/* WaitFor */
81 #define pthread_cond_broadcast(__cond) (0) /* Twist */
82 
83 #endif /* WITH_PTHREADS */
84 
85 #include <errno.h> /* ENOMEM, EAGAIN, EINVAL */
86 
87 #if defined(__LCLINT__)
88 /*@-incondefs -protoparammatch -redecl @*/
89 /*@-exportheader@*/
90 #ifdef NOTYET
91 extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __THROW
92  /*@*/;
93 extern void (*__cancel_routine) (void *)
94  /*@*/;
95 extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf)
96  /*@*/;
97 extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
98  /*@*/;
99 extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf)
100  /*@*/;
101 #endif
102 
103 extern pthread_t pthread_self(void)
104  /*@*/;
105 extern int pthread_equal(pthread_t t1, pthread_t t2)
106  /*@*/;
107 
108 extern int pthread_attr_init (pthread_attr_t *__attr)
109  __THROW __nonnull ((1))
110  /*@*/;
111 extern int pthread_attr_destroy (pthread_attr_t *__attr)
112  __THROW __nonnull ((1))
113  /*@*/;
114 
115 extern int pthread_attr_setdetachstate (pthread_attr_t *__attr,
116  int __detachstate)
117  __THROW __nonnull ((1))
118  /*@*/;
119 
120 extern int pthread_create(/*@out@*/ pthread_t *__restrict __newthread,
121  /*@null@*/ __const pthread_attr_t *__restrict __attr,
122  void *(*__start_routine)(void*),
123  void *__restrict arg) __THROW __nonnull ((1, 3))
124  /*@modifies *__newthread @*/;
125 extern int pthread_join(pthread_t thread, /*@null@*/ /*@out@*/ void **value_ptr)
126  /*@modifies *value_ptr @*/;
127 
128 extern int pthread_mutex_destroy(pthread_mutex_t *mutex)
129  /*@modifies *mutex @*/;
130 extern int pthread_mutex_init(/*@out@*/ pthread_mutex_t *restrict mutex,
131  /*@null@*/ const pthread_mutexattr_t *restrict attr)
132  /*@globals errno, internalState @*/
133  /*@modifies *mutex, errno, internalState @*/;
134 
135 extern int pthread_mutex_lock(pthread_mutex_t *mutex)
136  /*@globals errno @*/
137  /*@modifies *mutex, errno @*/;
138 extern int pthread_mutex_trylock(pthread_mutex_t *mutex)
139  /*@globals errno @*/
140  /*@modifies *mutex, errno @*/;
141 extern int pthread_mutex_unlock(pthread_mutex_t *mutex)
142  /*@globals errno @*/
143  /*@modifies *mutex, errno @*/;
144 
146  /*@modifies *cond @*/;
147 extern int pthread_cond_init(/*@out@*/ pthread_cond_t *restrict cond,
148  /*@null@*/ const pthread_condattr_t *restrict attr)
149  /*@globals errno, internalState @*/
150  /*@modifies *cond, errno, internalState @*/;
151 
152 extern int pthread_cond_timedwait(pthread_cond_t *restrict cond,
153  pthread_mutex_t *restrict mutex,
154  const struct timespec *restrict abstime)
155  /*@modifies *cond, *mutex @*/;
156 extern int pthread_cond_wait(pthread_cond_t *restrict cond,
157  pthread_mutex_t *restrict mutex)
158  /*@modifies *cond, *mutex @*/;
160  /*@globals errno, internalState @*/
161  /*@modifies *cond, errno, internalState @*/;
162 extern int pthread_cond_signal(pthread_cond_t *cond)
163  /*@globals errno, internalState @*/
164  /*@modifies *cond, errno, internalState @*/;
165 
166 extern int pthread_cancel (pthread_t __th)
167  /*@*/;
168 
169 /*@=exportheader@*/
170 /*@=incondefs =protoparammatch =redecl @*/
171 #endif /* __LCLINT__ */
172 
173 /* interface definition */
174 #include "yarn.h"
175 
176 #include "debug.h"
177 
178 /* error handling external globals, resettable by application */
179 /*@unchecked@*/ /*@observer@*/
180 const char *yarnPrefix = "yarn";
181 /*@-nullassign -redecl @*/
182 void (*yarnAbort)(int) = NULL;
183 /*@=nullassign =redecl @*/
184 
185 
186 /* immediately exit -- use for errors that shouldn't ever happen */
187 /*@exits@*/
188 static void _fail(int err, const char * fn, unsigned ln)
189  /*@globals fileSystem, internalState @*/
190  /*@modifies fileSystem, internalState @*/
191 {
192  fprintf(stderr, "%s: pthread error: %s(%d) -- aborting at %s:%u\n", yarnPrefix,
193  strerror(err), err, fn, ln);
194  if (yarnAbort != NULL)
195  yarnAbort(err);
196 assert(0);
197  exit(err == ENOMEM || err == EAGAIN ? err : EINVAL);
198 }
199 #define fail(_err) _fail((_err), __FILE__, __LINE__)
200 
201 /* memory handling routines provided by user -- if none are provided, malloc()
202  and free() are used, which are therefore assumed to be thread-safe */
203 typedef void *(*malloc_t)(size_t);
204 typedef void (*free_t)(void *);
205 #if defined(__LCLINT__)
206 static void *(*my_malloc_f)(size_t nb)
207  /*@*/
208  = malloc;
209 static void (*my_free)(/*@only@*/ void * p)
210  /*@modifies p @*/
211  = free;
212 #else
213 static malloc_t my_malloc_f = malloc;
214 static free_t my_free = free;
215 #endif
216 
217 /* use user-supplied allocation routines instead of malloc() and free() */
218 /*@-mustmod @*/
219 void yarnMem(malloc_t lease, free_t vacate)
220  /*@globals my_malloc_f, my_free @*/
221  /*@modifies my_malloc_f, my_free @*/
222 {
223  my_malloc_f = lease;
224  my_free = vacate;
225 }
226 /*@=mustmod @*/
227 
228 /* memory allocation that cannot fail (from the point of view of the caller) */
229 static void *my_malloc(size_t size)
230  /*@globals fileSystem, internalState @*/
231  /*@modifies fileSystem, internalState @*/
232 {
233  void *block;
234 
235  if ((block = my_malloc_f(size)) == NULL)
236  fail(ENOMEM);
237  return block;
238 }
239 
240 /* -- lock functions -- */
241 
242 struct yarnLock_s {
245  long value;
246 };
247 
248 yarnLock yarnNewLock(long initial)
249 {
250  int ret;
251  yarnLock bolt;
252 
253  bolt = (yarnLock) my_malloc(sizeof(*bolt));
254  if ((ret = pthread_mutex_init(&(bolt->mutex), NULL)) ||
255  (ret = pthread_cond_init(&(bolt->cond), NULL)))
256  fail(ret);
257  bolt->value = initial;
258  return bolt;
259 }
260 
261 /*@-mustmod@*/
263 {
264  int ret;
265 
266  if ((ret = pthread_mutex_lock(&(bolt->mutex))) != 0)
267  fail(ret);
268 }
269 
271 {
272  int ret;
273 
274  if ((ret = pthread_mutex_unlock(&(bolt->mutex))) != 0)
275  fail(ret);
276 }
277 /*@=mustmod@*/
278 
279 void yarnTwist(yarnLock bolt, yarnTwistOP op, long val)
280 {
281  int ret;
282 
283  if (op == TO)
284  bolt->value = val;
285  else if (op == BY)
286  bolt->value += val;
287  if ((ret = pthread_cond_broadcast(&(bolt->cond))) ||
288  (ret = pthread_mutex_unlock(&(bolt->mutex))))
289  fail(ret);
290 }
291 
292 #define until(a) while(!(a))
293 
294 /*@-mustmod@*/
295 void yarnWaitFor(yarnLock bolt, yarnWaitOP op, long val)
296 {
297  int ret;
298 
299 /*@-infloops -whileblock@*/ /* XXX splint can't see non-annotated effects */
300  switch (op) {
301  case TO_BE:
302  until (bolt->value == val)
303  if ((ret = pthread_cond_wait(&(bolt->cond), &(bolt->mutex))) != 0)
304  fail(ret);
305  break;
306  case NOT_TO_BE:
307  until (bolt->value != val)
308  if ((ret = pthread_cond_wait(&(bolt->cond), &(bolt->mutex))) != 0)
309  fail(ret);
310  break;
311  case TO_BE_MORE_THAN:
312  until (bolt->value > val)
313  if ((ret = pthread_cond_wait(&(bolt->cond), &(bolt->mutex))) != 0)
314  fail(ret);
315  break;
316  case TO_BE_LESS_THAN:
317  until (bolt->value < val)
318  if ((ret = pthread_cond_wait(&(bolt->cond), &(bolt->mutex))) != 0)
319  fail(ret);
320  }
321 /*@=infloops =whileblock@*/
322 }
323 /*@=mustmod@*/
324 
326 {
327  return bolt->value;
328 }
329 
331 {
332  int ret;
333  if ((ret = pthread_cond_destroy(&(bolt->cond))) ||
334  (ret = pthread_mutex_destroy(&(bolt->mutex))))
335  fail(ret);
336  my_free(bolt);
337  return NULL;
338 }
339 
340 /* -- thread functions (uses lock functions above) -- */
341 
342 struct yarnThread_s {
344  int done; /* true if this thread has exited */
345 /*@dependent@*/ /*@null@*/
346  yarnThread next; /* for list of all launched threads */
347 };
348 
349 /* list of threads launched but not joined, count of threads exited but not
350  joined (incremented by yarnIgnition() just before exiting) */
351 /*@unchecked@*/
352 static struct yarnLock_s threads_lock = {
355  0 /* number of threads exited but not joined */
356 };
357 /*@unchecked@*/ /*@owned@*/ /*@null@*/
358 static yarnThread threads = NULL; /* list of extant threads */
359 
360 /* structure in which to pass the probe and its payload to yarnIgnition() */
361 struct capsule {
362  void (*probe)(void *)
363  /*@*/;
364  void * payload;
365 };
366 
367 /* mark the calling thread as done and alert yarnJoinAll() */
368 #if defined(WITH_PTHREADS)
369 static void yarnReenter(/*@unused@*/ void * dummy)
370  /*@globals threads, threads_lock, fileSystem, internalState @*/
371  /*@modifies threads, threads_lock, fileSystem, internalState @*/
372 {
373  yarnThread match;
374  yarnThread *prior;
375  pthread_t me;
376 
377  /* find this thread in the threads list by matching the thread id */
378  me = pthread_self();
379  yarnPossess(&(threads_lock));
380  prior = &(threads);
381  while ((match = *prior) != NULL) {
382  if (pthread_equal(match->id, me))
383  break;
384  prior = &(match->next);
385  }
386  if (match == NULL)
387  fail(EINVAL);
388 
389  /* mark this thread as done and move it to the head of the list */
390  match->done = 1;
391  if (threads != match) {
392  *prior = match->next;
393  match->next = threads;
394  threads = match;
395  }
396 
397  /* update the count of threads to be joined and alert yarnJoinAll() */
398  yarnTwist(&(threads_lock), BY, 1);
399 }
400 #endif
401 
402 /* all threads go through this routine so that just before the thread exits,
403  it marks itself as done in the threads list and alerts yarnJoinAll() so that
404  the thread resources can be released -- use cleanup stack so that the
405  marking occurs even if the thread is cancelled */
406 /*@null@*/
407 #if defined(WITH_PTHREADS)
408 static void * yarnIgnition(/*@only@*/ void * arg)
409  /*@*/
410 {
411  struct capsule *capsule = (struct capsule *)arg;
412 
413  /* run yarnReenter() before leaving */
414 /*@-moduncon -noeffectuncon -sysunrecog @*/
415  pthread_cleanup_push(yarnReenter, NULL);
416 /*@=moduncon =noeffectuncon =sysunrecog @*/
417 
418  /* execute the requested function with argument */
419 /*@-noeffectuncon@*/
420  capsule->probe(capsule->payload);
421 /*@=noeffectuncon@*/
422  my_free(capsule);
423 
424  /* mark this thread as done and let yarnJoinAll() know */
425 /*@-moduncon -noeffect -noeffectuncon @*/
427 /*@=moduncon =noeffect =noeffectuncon @*/
428 
429  /* exit thread */
430  return NULL;
431 }
432 #endif
433 
434 /* not all POSIX implementations create threads as joinable by default, so that
435  is made explicit here */
436 yarnThread yarnLaunchStack(void (*probe)(void *), void * payload,
437  void * stack, size_t nstack)
438  /*@globals threads @*/
439  /*@modifies threads @*/
440 {
441  int ret;
442  yarnThread th;
443  struct capsule * capsule;
444 #if defined(WITH_PTHREADS)
445  pthread_attr_t attr;
446 #endif
447 
448  /* construct the requested call and argument for the yarnIgnition() routine
449  (allocated instead of automatic so that we're sure this will still be
450  there when yarnIgnition() actually starts up -- yarnIgnition() will free this
451  allocation) */
452  capsule = (struct capsule *) my_malloc(sizeof(*capsule));
453  capsule->probe = probe;
454 /*@-mustfreeonly -temptrans @*/
455  capsule->payload = payload;
456 /*@=mustfreeonly =temptrans @*/
457 
458  /* assure this thread is in the list before yarnJoinAll() or yarnIgnition() looks
459  for it */
460  yarnPossess(&(threads_lock));
461 
462  /* create the thread and call yarnIgnition() from that thread */
463  th = (yarnThread) my_malloc(sizeof(*th));
464  if ((ret = pthread_attr_init(&attr))
465  || (ret = (stack ? pthread_attr_setstack(&attr, stack, nstack) : 0))
467  || (ret = pthread_create(&(th->id), &attr, yarnIgnition, capsule))
468  || (ret = pthread_attr_destroy(&attr)))
469  fail(ret);
470 
471  /* put the thread in the threads list for yarnJoinAll() */
472  th->done = 0;
473  th->next = threads;
474  threads = th;
475  yarnRelease(&(threads_lock));
476 /*@-dependenttrans -globstate -mustfreefresh -retalias @*/ /* XXX what frees capsule?!? */
477  return th;
478 /*@=dependenttrans =globstate =mustfreefresh =retalias @*/
479 }
480 
481 yarnThread yarnLaunch(void (*probe)(void *), void * payload)
482  /*@globals threads @*/
483  /*@modifies threads @*/
484 {
485  return yarnLaunchStack(probe, payload, NULL, 0);
486 }
487 
489  /*@globals threads, threads_lock @*/
490  /*@modifies threads, threads_lock @*/
491 {
492  yarnThread match;
493  yarnThread *prior;
494  int ret;
495 
496  /* wait for thread to exit and return its resources */
497  if ((ret = pthread_join(ally->id, NULL)) != 0)
498  fail(ret);
499 
500  /* find the thread in the threads list */
501  yarnPossess(&(threads_lock));
502  prior = &(threads);
503  while ((match = *prior) != NULL) {
504  if (match == ally)
505  break;
506  prior = &(match->next);
507  }
508  if (match == NULL)
509  fail(EINVAL);
510 
511  /* remove thread from list and update exited count, free thread */
512  if (match->done)
513  threads_lock.value--;
514  *prior = match->next;
515  yarnRelease(&(threads_lock));
516  my_free(ally);
517  return NULL;
518 }
519 
520 /* This implementation of yarnJoinAll() only attempts to join threads that have
521  announced that they have exited (see yarnIgnition()). When there are many
522  threads, this is faster than waiting for some random thread to exit while a
523  bunch of other threads have already exited. */
524 int yarnJoinAll(void)
525  /*@globals threads, threads_lock @*/
526  /*@modifies threads, threads_lock @*/
527 {
528  yarnThread match;
529  yarnThread *prior;
530  int ret;
531  int count;
532 
533  /* grab the threads list and initialize the joined count */
534  count = 0;
535  yarnPossess(&(threads_lock));
536 
537  /* do until threads list is empty */
538  while (threads != NULL) {
539  /* wait until at least one thread has reentered */
540  yarnWaitFor(&(threads_lock), NOT_TO_BE, 0);
541 
542  /* find the first thread marked done (should be at or near the top) */
543  prior = &(threads);
544  while ((match = *prior) != NULL) {
545  if (match->done)
546  /*@innerbreak@*/ break;
547  prior = &(match->next);
548  }
549  if (match == NULL)
550  fail(EINVAL);
551 
552  /* join the thread (will be almost immediate), remove from the threads
553  list, update the reenter count, and free the thread */
554  if ((ret = pthread_join(match->id, NULL)) != 0)
555  fail(ret);
556  threads_lock.value--;
557  *prior = match->next;
558  my_free(match);
559  count++;
560  }
561 
562  /* let go of the threads list and return the number of threads joined */
563  yarnRelease(&(threads_lock));
564 /*@-globstate@*/
565  return count;
566 /*@=globstate@*/
567 }
568 
569 /* cancel and join the thread -- the thread will cancel when it gets to a file
570  operation, a sleep or pause, or a condition wait */
571 void yarnDestruct(yarnThread off_course)
572 {
573  int ret;
574 
575  if ((ret = pthread_cancel(off_course->id)) != 0)
576  fail(ret);
577  (void) yarnJoin(off_course);
578 }
static void * my_malloc(size_t size)
Definition: yarn.c:229
#define pthread_cleanup_push(__routine, __arg)
Definition: yarn.c:61
enum yarnTwistOP_e yarnTwistOP
void yarnTwist(yarnLock bolt, yarnTwistOP op, long val)
Definition: yarn.c:279
Definition: yarn.c:361
#define PTHREAD_MUTEX_INITIALIZER
Definition: yarn.c:69
void yarnPossess(yarnLock bolt)
Definition: yarn.c:262
#define pthread_attr_t
Definition: yarn.c:63
#define pthread_attr_init(__attr)
Definition: yarn.c:64
Definition: yarn.h:171
long yarnPeekLock(yarnLock bolt)
Definition: yarn.c:325
#define pthread_equal(_t1, _t2)
Definition: yarn.c:56
const char const bson * cond
Definition: mongo.h:505
Definition: yarn.h:166
void *(* malloc_t)(size_t)
Definition: yarn.c:203
int yarnJoinAll(void)
Definition: yarn.c:524
#define __const
Definition: fnmatch.h:30
#define pthread_mutex_lock(__mutex)
Definition: yarn.c:73
void yarnMem(malloc_t lease, free_t vacate)
Definition: yarn.c:219
static yarnThread threads
Definition: yarn.c:358
struct yarnThread_s * yarnThread
Definition: yarn.h:136
#define pthread_cond_destroy(__cond)
Definition: yarn.c:78
#define pthread_cond_wait(__cond, __mutex)
Definition: yarn.c:80
#define pthread_mutex_t
Definition: yarn.c:68
yarnThread next
Definition: yarn.c:346
void yarnWaitFor(yarnLock bolt, yarnWaitOP op, long val)
Definition: yarn.c:295
yarnThread yarnJoin(yarnThread ally)
Definition: yarn.c:488
#define pthread_attr_setdetachstate(__attr, __detachstate)
Definition: yarn.c:66
enum yarnWaitOP_e yarnWaitOP
mongo_error_t err
Definition: mongo.h:922
#define pthread_mutex_unlock(__mutex)
Definition: yarn.c:74
yarnLock yarnNewLock(long initial)
Definition: yarn.c:248
yarnLock yarnFreeLock(yarnLock bolt)
Definition: yarn.c:330
#define pthread_attr_destroy(__attr)
Definition: yarn.c:65
static free_t my_free
Definition: yarn.c:214
#define fail(_err)
Definition: yarn.c:199
#define pthread_cond_t
Definition: yarn.c:76
void yarnDestruct(yarnThread off_course)
Definition: yarn.c:571
#define pthread_join(__thread, __value_ptr)
Definition: yarn.c:58
#define pthread_cleanup_pop(__execute)
Definition: yarn.c:60
void(* free_t)(void *)
Definition: yarn.c:204
const char const bson const bson * op
Definition: mongo.h:505
const char const char int arg
Definition: mongo.h:777
static struct yarnLock_s threads_lock
Definition: yarn.c:352
const char * yarnPrefix
Definition: yarn.c:180
#define pthread_mutex_destroy(__mutex)
Definition: yarn.c:71
void yarnRelease(yarnLock bolt)
Definition: yarn.c:270
int done
Definition: yarn.c:344
#define pthread_self()
Definition: yarn.c:55
yarnThread yarnLaunchStack(void(*probe)(void *), void *payload, void *stack, size_t nstack)
Definition: yarn.c:436
yarnThread yarnLaunch(void(*probe)(void *), void *payload)
Definition: yarn.c:481
const char const char size_t size
Definition: bson.h:895
long value
Definition: yarn.c:245
int cond
Definition: yarn.c:244
int id
Definition: yarn.c:343
void(* probe)(void *)
Definition: yarn.c:362
#define PTHREAD_COND_INITIALIZER
Definition: yarn.c:77
#define pthread_cancel(__th)
Definition: yarn.c:59
#define until(a)
Definition: yarn.c:292
struct yarnLock_s * yarnLock
Definition: rpmiotypes.h:37
#define pthread_cond_init(__cond, __attr)
Definition: yarn.c:79
Definition: yarn.h:166
#define pthread_mutex_init(__mutex, __attr)
Definition: yarn.c:72
#define pthread_t
Definition: yarn.c:54
#define __THROW
Definition: fts.h:38
int mutex
Definition: yarn.c:243
void(* yarnAbort)(int)
Definition: yarn.c:182
#define pthread_cond_broadcast(__cond)
Definition: yarn.c:81
static malloc_t my_malloc_f
Definition: yarn.c:213
void * payload
Definition: yarn.c:364
#define pthread_create(__newthread, __attr, __start_routine, arg)
Definition: yarn.c:57
#define PTHREAD_CREATE_JOINABLE
Definition: yarn.c:70
static void _fail(int err, const char *fn, unsigned ln)
Definition: yarn.c:188