1 1.1.1.12 mrg /* Copyright (C) 2005-2024 Free Software Foundation, Inc. 2 1.1 mrg Contributed by Richard Henderson <rth (at) redhat.com>. 3 1.1 mrg 4 1.1.1.3 mrg This file is part of the GNU Offloading and Multi Processing Library 5 1.1.1.3 mrg (libgomp). 6 1.1 mrg 7 1.1 mrg Libgomp is free software; you can redistribute it and/or modify it 8 1.1 mrg under the terms of the GNU General Public License as published by 9 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 10 1.1 mrg any later version. 11 1.1 mrg 12 1.1 mrg Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY 13 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 1.1 mrg FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 1.1 mrg more details. 16 1.1 mrg 17 1.1 mrg Under Section 7 of GPL version 3, you are granted additional 18 1.1 mrg permissions described in the GCC Runtime Library Exception, version 19 1.1 mrg 3.1, as published by the Free Software Foundation. 20 1.1 mrg 21 1.1 mrg You should have received a copy of the GNU General Public License and 22 1.1 mrg a copy of the GCC Runtime Library Exception along with this program; 23 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 1.1 mrg <http://www.gnu.org/licenses/>. */ 25 1.1 mrg 26 1.1 mrg /* This is the default implementation of a barrier synchronization mechanism 27 1.1 mrg for libgomp. This type is private to the library. Note that we rely on 28 1.1 mrg being able to adjust the barrier count while threads are blocked, so the 29 1.1 mrg POSIX pthread_barrier_t won't work. */ 30 1.1 mrg 31 1.1 mrg #ifndef GOMP_BARRIER_H 32 1.1 mrg #define GOMP_BARRIER_H 1 33 1.1 mrg 34 1.1 mrg #include <pthread.h> 35 1.1 mrg 36 1.1 mrg typedef struct 37 1.1 mrg { 38 1.1 mrg gomp_mutex_t mutex1; 39 1.1 mrg #ifndef HAVE_SYNC_BUILTINS 40 1.1 mrg gomp_mutex_t mutex2; 41 1.1 mrg #endif 42 1.1 mrg gomp_sem_t sem1; 43 1.1 mrg gomp_sem_t sem2; 44 1.1 mrg unsigned total; 45 1.1 mrg unsigned arrived; 46 1.1 mrg unsigned generation; 47 1.1.1.3 mrg bool cancellable; 48 1.1 mrg } gomp_barrier_t; 49 1.1.1.3 mrg 50 1.1 mrg typedef unsigned int gomp_barrier_state_t; 51 1.1 mrg 52 1.1.1.3 mrg /* The generation field contains a counter in the high bits, with a few 53 1.1.1.3 mrg low bits dedicated to flags. Note that TASK_PENDING and WAS_LAST can 54 1.1.1.3 mrg share space because WAS_LAST is never stored back to generation. */ 55 1.1.1.3 mrg #define BAR_TASK_PENDING 1 56 1.1.1.3 mrg #define BAR_WAS_LAST 1 57 1.1.1.3 mrg #define BAR_WAITING_FOR_TASK 2 58 1.1.1.3 mrg #define BAR_CANCELLED 4 59 1.1.1.3 mrg #define BAR_INCR 8 60 1.1.1.3 mrg 61 1.1 mrg extern void gomp_barrier_init (gomp_barrier_t *, unsigned); 62 1.1 mrg extern void gomp_barrier_reinit (gomp_barrier_t *, unsigned); 63 1.1 mrg extern void gomp_barrier_destroy (gomp_barrier_t *); 64 1.1 mrg 65 1.1 mrg extern void gomp_barrier_wait (gomp_barrier_t *); 66 1.1 mrg extern void gomp_barrier_wait_end (gomp_barrier_t *, gomp_barrier_state_t); 67 1.1 mrg extern void gomp_team_barrier_wait (gomp_barrier_t *); 68 1.1 mrg extern void gomp_team_barrier_wait_end (gomp_barrier_t *, 69 1.1 mrg gomp_barrier_state_t); 70 1.1.1.3 mrg extern bool gomp_team_barrier_wait_cancel (gomp_barrier_t *); 71 1.1.1.3 mrg extern bool gomp_team_barrier_wait_cancel_end (gomp_barrier_t *, 72 1.1.1.3 mrg gomp_barrier_state_t); 73 1.1 mrg extern void gomp_team_barrier_wake (gomp_barrier_t *, int); 74 1.1.1.3 mrg struct gomp_team; 75 1.1.1.3 mrg extern void gomp_team_barrier_cancel (struct gomp_team *); 76 1.1 mrg 77 1.1 mrg static inline gomp_barrier_state_t 78 1.1 mrg gomp_barrier_wait_start (gomp_barrier_t *bar) 79 1.1 mrg { 80 1.1 mrg unsigned int ret; 81 1.1 mrg gomp_mutex_lock (&bar->mutex1); 82 1.1.1.3 mrg ret = bar->generation & (-BAR_INCR | BAR_CANCELLED); 83 1.1.1.3 mrg if (++bar->arrived == bar->total) 84 1.1.1.3 mrg ret |= BAR_WAS_LAST; 85 1.1.1.3 mrg return ret; 86 1.1.1.3 mrg } 87 1.1.1.3 mrg 88 1.1.1.3 mrg static inline gomp_barrier_state_t 89 1.1.1.3 mrg gomp_barrier_wait_cancel_start (gomp_barrier_t *bar) 90 1.1.1.3 mrg { 91 1.1.1.3 mrg unsigned int ret; 92 1.1.1.3 mrg gomp_mutex_lock (&bar->mutex1); 93 1.1.1.3 mrg ret = bar->generation & (-BAR_INCR | BAR_CANCELLED); 94 1.1.1.3 mrg if (ret & BAR_CANCELLED) 95 1.1.1.3 mrg return ret; 96 1.1.1.3 mrg if (++bar->arrived == bar->total) 97 1.1.1.3 mrg ret |= BAR_WAS_LAST; 98 1.1 mrg return ret; 99 1.1 mrg } 100 1.1 mrg 101 1.1.1.3 mrg static inline void 102 1.1.1.3 mrg gomp_team_barrier_wait_final (gomp_barrier_t *bar) 103 1.1.1.3 mrg { 104 1.1.1.3 mrg gomp_team_barrier_wait (bar); 105 1.1.1.3 mrg } 106 1.1.1.3 mrg 107 1.1 mrg static inline bool 108 1.1 mrg gomp_barrier_last_thread (gomp_barrier_state_t state) 109 1.1 mrg { 110 1.1.1.3 mrg return state & BAR_WAS_LAST; 111 1.1 mrg } 112 1.1 mrg 113 1.1 mrg static inline void 114 1.1 mrg gomp_barrier_wait_last (gomp_barrier_t *bar) 115 1.1 mrg { 116 1.1 mrg gomp_barrier_wait (bar); 117 1.1 mrg } 118 1.1 mrg 119 1.1 mrg /* All the inlines below must be called with team->task_lock 120 1.1 mrg held. */ 121 1.1 mrg 122 1.1 mrg static inline void 123 1.1 mrg gomp_team_barrier_set_task_pending (gomp_barrier_t *bar) 124 1.1 mrg { 125 1.1.1.3 mrg bar->generation |= BAR_TASK_PENDING; 126 1.1 mrg } 127 1.1 mrg 128 1.1 mrg static inline void 129 1.1 mrg gomp_team_barrier_clear_task_pending (gomp_barrier_t *bar) 130 1.1 mrg { 131 1.1.1.3 mrg bar->generation &= ~BAR_TASK_PENDING; 132 1.1 mrg } 133 1.1 mrg 134 1.1 mrg static inline void 135 1.1 mrg gomp_team_barrier_set_waiting_for_tasks (gomp_barrier_t *bar) 136 1.1 mrg { 137 1.1.1.3 mrg bar->generation |= BAR_WAITING_FOR_TASK; 138 1.1 mrg } 139 1.1 mrg 140 1.1 mrg static inline bool 141 1.1 mrg gomp_team_barrier_waiting_for_tasks (gomp_barrier_t *bar) 142 1.1 mrg { 143 1.1.1.3 mrg return (bar->generation & BAR_WAITING_FOR_TASK) != 0; 144 1.1.1.3 mrg } 145 1.1.1.3 mrg 146 1.1.1.3 mrg static inline bool 147 1.1.1.3 mrg gomp_team_barrier_cancelled (gomp_barrier_t *bar) 148 1.1.1.3 mrg { 149 1.1.1.3 mrg return __builtin_expect ((bar->generation & BAR_CANCELLED) != 0, 0); 150 1.1 mrg } 151 1.1 mrg 152 1.1 mrg static inline void 153 1.1 mrg gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state) 154 1.1 mrg { 155 1.1.1.3 mrg bar->generation = (state & -BAR_INCR) + BAR_INCR; 156 1.1 mrg } 157 1.1 mrg 158 1.1 mrg #endif /* GOMP_BARRIER_H */ 159