barrier.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /* POSIX barrier implementation for LinuxThreads.
  2. Copyright (C) 2000, 2003 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. Contributed by Kaz Kylheku <kaz@ashi.footprints.net>, 2000.
  5. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public License as
  7. published by the Free Software Foundation; either version 2.1 of the
  8. License, or (at your option) any later version.
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; see the file COPYING.LIB. If
  15. not, see <http://www.gnu.org/licenses/>. */
  16. #include <errno.h>
  17. #include "pthread.h"
  18. #include "internals.h"
  19. #include "spinlock.h"
  20. #include "queue.h"
  21. #include "restart.h"
  22. int
  23. pthread_barrier_wait(pthread_barrier_t *barrier)
  24. {
  25. pthread_descr self = thread_self();
  26. pthread_descr temp_wake_queue, th;
  27. int result = 0;
  28. __pthread_lock(&barrier->__ba_lock, self);
  29. /* If the required number of threads have achieved rendezvous... */
  30. if (barrier->__ba_present >= barrier->__ba_required - 1)
  31. {
  32. /* ... then this last caller shall be the serial thread */
  33. result = PTHREAD_BARRIER_SERIAL_THREAD;
  34. /* Copy and clear wait queue and reset barrier. */
  35. temp_wake_queue = barrier->__ba_waiting;
  36. barrier->__ba_waiting = NULL;
  37. barrier->__ba_present = 0;
  38. }
  39. else
  40. {
  41. result = 0;
  42. barrier->__ba_present++;
  43. enqueue(&barrier->__ba_waiting, self);
  44. }
  45. __pthread_unlock(&barrier->__ba_lock);
  46. if (result == 0)
  47. {
  48. /* Non-serial threads have to suspend */
  49. suspend(self);
  50. /* We don't bother dealing with cancellation because the POSIX
  51. spec for barriers doesn't mention that pthread_barrier_wait
  52. is a cancellation point. */
  53. }
  54. else
  55. {
  56. /* Serial thread wakes up all others. */
  57. while ((th = dequeue(&temp_wake_queue)) != NULL)
  58. restart(th);
  59. }
  60. return result;
  61. }
  62. int
  63. pthread_barrier_init(pthread_barrier_t *barrier,
  64. const pthread_barrierattr_t *attr,
  65. unsigned int count)
  66. {
  67. if (count == 0)
  68. return EINVAL;
  69. __pthread_init_lock(&barrier->__ba_lock);
  70. barrier->__ba_required = count;
  71. barrier->__ba_present = 0;
  72. barrier->__ba_waiting = NULL;
  73. return 0;
  74. }
  75. int
  76. pthread_barrier_destroy(pthread_barrier_t *barrier)
  77. {
  78. if (barrier->__ba_waiting != NULL) return EBUSY;
  79. return 0;
  80. }
  81. int
  82. pthread_barrierattr_init(pthread_barrierattr_t *attr)
  83. {
  84. attr->__pshared = PTHREAD_PROCESS_PRIVATE;
  85. return 0;
  86. }
  87. int
  88. pthread_barrierattr_destroy(pthread_barrierattr_t *attr)
  89. {
  90. return 0;
  91. }
  92. int
  93. __pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr,
  94. int *pshared)
  95. {
  96. *pshared = PTHREAD_PROCESS_PRIVATE;
  97. return 0;
  98. }
  99. int
  100. pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared)
  101. {
  102. if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
  103. return EINVAL;
  104. /* For now it is not possible to shared a conditional variable. */
  105. if (pshared != PTHREAD_PROCESS_PRIVATE)
  106. return ENOSYS;
  107. return 0;
  108. }