sections.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /* Copyright (C) 2005-2015 Free Software Foundation, Inc.
  2. Contributed by Richard Henderson <rth@redhat.com>.
  3. This file is part of the GNU Offloading and Multi Processing Library
  4. (libgomp).
  5. Libgomp is free software; you can redistribute it and/or modify it
  6. under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3, or (at your option)
  8. any later version.
  9. Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. more details.
  13. Under Section 7 of GPL version 3, you are granted additional
  14. permissions described in the GCC Runtime Library Exception, version
  15. 3.1, as published by the Free Software Foundation.
  16. You should have received a copy of the GNU General Public License and
  17. a copy of the GCC Runtime Library Exception along with this program;
  18. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. <http://www.gnu.org/licenses/>. */
  20. /* This file handles the SECTIONS construct. */
  21. #include "libgomp.h"
  22. /* Initialize the given work share construct from the given arguments. */
  23. static inline void
  24. gomp_sections_init (struct gomp_work_share *ws, unsigned count)
  25. {
  26. ws->sched = GFS_DYNAMIC;
  27. ws->chunk_size = 1;
  28. ws->end = count + 1L;
  29. ws->incr = 1;
  30. ws->next = 1;
  31. #ifdef HAVE_SYNC_BUILTINS
  32. /* Prepare things to make each iteration faster. */
  33. if (sizeof (long) > sizeof (unsigned))
  34. ws->mode = 1;
  35. else
  36. {
  37. struct gomp_thread *thr = gomp_thread ();
  38. struct gomp_team *team = thr->ts.team;
  39. long nthreads = team ? team->nthreads : 1;
  40. ws->mode = ((nthreads | ws->end)
  41. < 1UL << (sizeof (long) * __CHAR_BIT__ / 2 - 1));
  42. }
  43. #else
  44. ws->mode = 0;
  45. #endif
  46. }
  47. /* This routine is called when first encountering a sections construct
  48. that is not bound directly to a parallel construct. The first thread
  49. that arrives will create the work-share construct; subsequent threads
  50. will see the construct exists and allocate work from it.
  51. COUNT is the number of sections in this construct.
  52. Returns the 1-based section number for this thread to perform, or 0 if
  53. all work was assigned to other threads prior to this thread's arrival. */
  54. unsigned
  55. GOMP_sections_start (unsigned count)
  56. {
  57. struct gomp_thread *thr = gomp_thread ();
  58. long s, e, ret;
  59. if (gomp_work_share_start (false))
  60. {
  61. gomp_sections_init (thr->ts.work_share, count);
  62. gomp_work_share_init_done ();
  63. }
  64. #ifdef HAVE_SYNC_BUILTINS
  65. if (gomp_iter_dynamic_next (&s, &e))
  66. ret = s;
  67. else
  68. ret = 0;
  69. #else
  70. gomp_mutex_lock (&thr->ts.work_share->lock);
  71. if (gomp_iter_dynamic_next_locked (&s, &e))
  72. ret = s;
  73. else
  74. ret = 0;
  75. gomp_mutex_unlock (&thr->ts.work_share->lock);
  76. #endif
  77. return ret;
  78. }
  79. /* This routine is called when the thread completes processing of the
  80. section currently assigned to it. If the work-share construct is
  81. bound directly to a parallel construct, then the construct may have
  82. been set up before the parallel. In which case, this may be the
  83. first iteration for the thread.
  84. Returns the 1-based section number for this thread to perform, or 0 if
  85. all work was assigned to other threads prior to this thread's arrival. */
  86. unsigned
  87. GOMP_sections_next (void)
  88. {
  89. long s, e, ret;
  90. #ifdef HAVE_SYNC_BUILTINS
  91. if (gomp_iter_dynamic_next (&s, &e))
  92. ret = s;
  93. else
  94. ret = 0;
  95. #else
  96. struct gomp_thread *thr = gomp_thread ();
  97. gomp_mutex_lock (&thr->ts.work_share->lock);
  98. if (gomp_iter_dynamic_next_locked (&s, &e))
  99. ret = s;
  100. else
  101. ret = 0;
  102. gomp_mutex_unlock (&thr->ts.work_share->lock);
  103. #endif
  104. return ret;
  105. }
  106. /* This routine pre-initializes a work-share construct to avoid one
  107. synchronization once we get into the loop. */
  108. void
  109. GOMP_parallel_sections_start (void (*fn) (void *), void *data,
  110. unsigned num_threads, unsigned count)
  111. {
  112. struct gomp_team *team;
  113. num_threads = gomp_resolve_num_threads (num_threads, count);
  114. team = gomp_new_team (num_threads);
  115. gomp_sections_init (&team->work_shares[0], count);
  116. gomp_team_start (fn, data, num_threads, 0, team);
  117. }
  118. ialias_redirect (GOMP_parallel_end)
  119. void
  120. GOMP_parallel_sections (void (*fn) (void *), void *data,
  121. unsigned num_threads, unsigned count, unsigned flags)
  122. {
  123. struct gomp_team *team;
  124. num_threads = gomp_resolve_num_threads (num_threads, count);
  125. team = gomp_new_team (num_threads);
  126. gomp_sections_init (&team->work_shares[0], count);
  127. gomp_team_start (fn, data, num_threads, flags, team);
  128. fn (data);
  129. GOMP_parallel_end ();
  130. }
  131. /* The GOMP_section_end* routines are called after the thread is told
  132. that all sections are complete. The first two versions synchronize
  133. all threads; the nowait version does not. */
  134. void
  135. GOMP_sections_end (void)
  136. {
  137. gomp_work_share_end ();
  138. }
  139. bool
  140. GOMP_sections_end_cancel (void)
  141. {
  142. return gomp_work_share_end_cancel ();
  143. }
  144. void
  145. GOMP_sections_end_nowait (void)
  146. {
  147. gomp_work_share_end_nowait ();
  148. }