bar.h revision 1.1 1 1.1 mrg /* Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc.
2 1.1 mrg Contributed by Richard Henderson <rth (at) redhat.com>.
3 1.1 mrg
4 1.1 mrg This file is part of the GNU OpenMP Library (libgomp).
5 1.1 mrg
6 1.1 mrg Libgomp is free software; you can redistribute it and/or modify it
7 1.1 mrg under the terms of the GNU General Public License as published by
8 1.1 mrg the Free Software Foundation; either version 3, or (at your option)
9 1.1 mrg any later version.
10 1.1 mrg
11 1.1 mrg Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
12 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 1.1 mrg FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 1.1 mrg more details.
15 1.1 mrg
16 1.1 mrg Under Section 7 of GPL version 3, you are granted additional
17 1.1 mrg permissions described in the GCC Runtime Library Exception, version
18 1.1 mrg 3.1, as published by the Free Software Foundation.
19 1.1 mrg
20 1.1 mrg You should have received a copy of the GNU General Public License and
21 1.1 mrg a copy of the GCC Runtime Library Exception along with this program;
22 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 1.1 mrg <http://www.gnu.org/licenses/>. */
24 1.1 mrg
25 1.1 mrg /* This is a Linux specific implementation of a barrier synchronization
26 1.1 mrg mechanism for libgomp. This type is private to the library. This
27 1.1 mrg implementation uses atomic instructions and the futex syscall. */
28 1.1 mrg
29 1.1 mrg #ifndef GOMP_BARRIER_H
30 1.1 mrg #define GOMP_BARRIER_H 1
31 1.1 mrg
32 1.1 mrg #include "mutex.h"
33 1.1 mrg
34 1.1 mrg typedef struct
35 1.1 mrg {
36 1.1 mrg /* Make sure total/generation is in a mostly read cacheline, while
37 1.1 mrg awaited in a separate cacheline. */
38 1.1 mrg unsigned total __attribute__((aligned (64)));
39 1.1 mrg unsigned generation;
40 1.1 mrg unsigned awaited __attribute__((aligned (64)));
41 1.1 mrg } gomp_barrier_t;
42 1.1 mrg typedef unsigned int gomp_barrier_state_t;
43 1.1 mrg
44 1.1 mrg static inline void gomp_barrier_init (gomp_barrier_t *bar, unsigned count)
45 1.1 mrg {
46 1.1 mrg bar->total = count;
47 1.1 mrg bar->awaited = count;
48 1.1 mrg bar->generation = 0;
49 1.1 mrg }
50 1.1 mrg
51 1.1 mrg static inline void gomp_barrier_reinit (gomp_barrier_t *bar, unsigned count)
52 1.1 mrg {
53 1.1 mrg __sync_fetch_and_add (&bar->awaited, count - bar->total);
54 1.1 mrg bar->total = count;
55 1.1 mrg }
56 1.1 mrg
57 1.1 mrg static inline void gomp_barrier_destroy (gomp_barrier_t *bar)
58 1.1 mrg {
59 1.1 mrg }
60 1.1 mrg
61 1.1 mrg extern void gomp_barrier_wait (gomp_barrier_t *);
62 1.1 mrg extern void gomp_barrier_wait_last (gomp_barrier_t *);
63 1.1 mrg extern void gomp_barrier_wait_end (gomp_barrier_t *, gomp_barrier_state_t);
64 1.1 mrg extern void gomp_team_barrier_wait (gomp_barrier_t *);
65 1.1 mrg extern void gomp_team_barrier_wait_end (gomp_barrier_t *,
66 1.1 mrg gomp_barrier_state_t);
67 1.1 mrg extern void gomp_team_barrier_wake (gomp_barrier_t *, int);
68 1.1 mrg
69 1.1 mrg static inline gomp_barrier_state_t
70 1.1 mrg gomp_barrier_wait_start (gomp_barrier_t *bar)
71 1.1 mrg {
72 1.1 mrg unsigned int ret = bar->generation & ~3;
73 1.1 mrg /* Do we need any barrier here or is __sync_add_and_fetch acting
74 1.1 mrg as the needed LoadLoad barrier already? */
75 1.1 mrg ret += __sync_add_and_fetch (&bar->awaited, -1) == 0;
76 1.1 mrg return ret;
77 1.1 mrg }
78 1.1 mrg
79 1.1 mrg static inline bool
80 1.1 mrg gomp_barrier_last_thread (gomp_barrier_state_t state)
81 1.1 mrg {
82 1.1 mrg return state & 1;
83 1.1 mrg }
84 1.1 mrg
85 1.1 mrg /* All the inlines below must be called with team->task_lock
86 1.1 mrg held. */
87 1.1 mrg
88 1.1 mrg static inline void
89 1.1 mrg gomp_team_barrier_set_task_pending (gomp_barrier_t *bar)
90 1.1 mrg {
91 1.1 mrg bar->generation |= 1;
92 1.1 mrg }
93 1.1 mrg
94 1.1 mrg static inline void
95 1.1 mrg gomp_team_barrier_clear_task_pending (gomp_barrier_t *bar)
96 1.1 mrg {
97 1.1 mrg bar->generation &= ~1;
98 1.1 mrg }
99 1.1 mrg
100 1.1 mrg static inline void
101 1.1 mrg gomp_team_barrier_set_waiting_for_tasks (gomp_barrier_t *bar)
102 1.1 mrg {
103 1.1 mrg bar->generation |= 2;
104 1.1 mrg }
105 1.1 mrg
106 1.1 mrg static inline bool
107 1.1 mrg gomp_team_barrier_waiting_for_tasks (gomp_barrier_t *bar)
108 1.1 mrg {
109 1.1 mrg return (bar->generation & 2) != 0;
110 1.1 mrg }
111 1.1 mrg
112 1.1 mrg static inline void
113 1.1 mrg gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state)
114 1.1 mrg {
115 1.1 mrg bar->generation = (state & ~3) + 4;
116 1.1 mrg }
117 1.1 mrg
118 1.1 mrg #endif /* GOMP_BARRIER_H */
119