| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: pthread_barrier.c,v 1.20 2016/07/03 14:24:58 christos Exp $ */ | | 1 | /* $NetBSD: pthread_barrier.c,v 1.21 2020/01/29 14:41:57 kamil Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2001, 2003, 2006, 2007, 2009 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2001, 2003, 2006, 2007, 2009 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Nathan J. Williams, by Jason R. Thorpe, and by Andrew Doran. | | 8 | * by Nathan J. Williams, by Jason R. Thorpe, and by Andrew Doran. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -20,71 +20,74 @@ | | | @@ -20,71 +20,74 @@ |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __RCSID("$NetBSD: pthread_barrier.c,v 1.20 2016/07/03 14:24:58 christos Exp $"); | | 33 | __RCSID("$NetBSD: pthread_barrier.c,v 1.21 2020/01/29 14:41:57 kamil Exp $"); |
34 | | | 34 | |
35 | #include <errno.h> | | 35 | #include <errno.h> |
36 | | | 36 | |
37 | #include "pthread.h" | | 37 | #include "pthread.h" |
38 | #include "pthread_int.h" | | 38 | #include "pthread_int.h" |
39 | | | 39 | |
40 | int | | 40 | int |
41 | pthread_barrier_init(pthread_barrier_t *barrier, | | 41 | pthread_barrier_init(pthread_barrier_t *barrier, |
42 | const pthread_barrierattr_t *attr, unsigned int count) | | 42 | const pthread_barrierattr_t *attr, unsigned int count) |
43 | { | | 43 | { |
44 | | | 44 | |
45 | if (attr != NULL && attr->ptba_magic != _PT_BARRIERATTR_MAGIC) | | 45 | pthread__error(EINVAL, "Invalid barrier attribute", |
46 | return EINVAL; | | 46 | attr == NULL || attr->ptba_magic == _PT_BARRIERATTR_MAGIC); |
47 | if (count == 0) | | 47 | if (count == 0) |
48 | return EINVAL; | | 48 | return EINVAL; |
49 | | | 49 | |
50 | barrier->ptb_magic = _PT_BARRIER_MAGIC; | | 50 | barrier->ptb_magic = _PT_BARRIER_MAGIC; |
51 | PTQ_INIT(&barrier->ptb_waiters); | | 51 | PTQ_INIT(&barrier->ptb_waiters); |
52 | barrier->ptb_initcount = count; | | 52 | barrier->ptb_initcount = count; |
53 | barrier->ptb_curcount = 0; | | 53 | barrier->ptb_curcount = 0; |
54 | barrier->ptb_generation = 0; | | 54 | barrier->ptb_generation = 0; |
55 | return 0; | | 55 | return 0; |
56 | } | | 56 | } |
57 | | | 57 | |
58 | int | | 58 | int |
59 | pthread_barrier_destroy(pthread_barrier_t *barrier) | | 59 | pthread_barrier_destroy(pthread_barrier_t *barrier) |
60 | { | | 60 | { |
61 | | | 61 | |
62 | if (barrier->ptb_magic != _PT_BARRIER_MAGIC) | | 62 | pthread__error(EINVAL, "Invalid barrier", |
63 | return EINVAL; | | 63 | barrier->ptb_magic == _PT_BARRIER_MAGIC); |
64 | if (barrier->ptb_curcount != 0) | | 64 | if (barrier->ptb_curcount != 0) |
65 | return EBUSY; | | 65 | return EBUSY; |
| | | 66 | |
| | | 67 | barrier->ptb_magic = _PT_BARRIER_DEAD; |
| | | 68 | |
66 | return 0; | | 69 | return 0; |
67 | } | | 70 | } |
68 | | | 71 | |
69 | int | | 72 | int |
70 | pthread_barrier_wait(pthread_barrier_t *barrier) | | 73 | pthread_barrier_wait(pthread_barrier_t *barrier) |
71 | { | | 74 | { |
72 | pthread_mutex_t *interlock; | | 75 | pthread_mutex_t *interlock; |
73 | pthread_t self; | | 76 | pthread_t self; |
74 | unsigned int gen; | | 77 | unsigned int gen; |
75 | | | 78 | |
76 | if (barrier->ptb_magic != _PT_BARRIER_MAGIC) | | 79 | pthread__error(EINVAL, "Invalid barrier", |
77 | return EINVAL; | | 80 | barrier->ptb_magic == _PT_BARRIER_MAGIC); |
78 | | | 81 | |
79 | /* | | 82 | /* |
80 | * A single arbitrary thread is supposed to return | | 83 | * A single arbitrary thread is supposed to return |
81 | * PTHREAD_BARRIER_SERIAL_THREAD, and everone else | | 84 | * PTHREAD_BARRIER_SERIAL_THREAD, and everone else |
82 | * is supposed to return 0. Since pthread_barrier_wait() | | 85 | * is supposed to return 0. Since pthread_barrier_wait() |
83 | * is not a cancellation point, this is trivial; we | | 86 | * is not a cancellation point, this is trivial; we |
84 | * simply elect that the thread that causes the barrier | | 87 | * simply elect that the thread that causes the barrier |
85 | * to be satisfied gets the special return value. Note | | 88 | * to be satisfied gets the special return value. Note |
86 | * that this final thread does not actually need to block, | | 89 | * that this final thread does not actually need to block, |
87 | * but instead is responsible for waking everyone else up. | | 90 | * but instead is responsible for waking everyone else up. |
88 | */ | | 91 | */ |
89 | self = pthread__self(); | | 92 | self = pthread__self(); |
90 | interlock = pthread__hashlock(barrier); | | 93 | interlock = pthread__hashlock(barrier); |
| @@ -113,48 +116,54 @@ pthread_barrier_wait(pthread_barrier_t * | | | @@ -113,48 +116,54 @@ pthread_barrier_wait(pthread_barrier_t * |
113 | break; | | 116 | break; |
114 | } | | 117 | } |
115 | } | | 118 | } |
116 | | | 119 | |
117 | return 0; | | 120 | return 0; |
118 | } | | 121 | } |
119 | | | 122 | |
120 | #ifdef _PTHREAD_PSHARED | | 123 | #ifdef _PTHREAD_PSHARED |
121 | int | | 124 | int |
122 | pthread_barrierattr_getpshared(const pthread_barrierattr_t * __restrict attr, | | 125 | pthread_barrierattr_getpshared(const pthread_barrierattr_t * __restrict attr, |
123 | int * __restrict pshared) | | 126 | int * __restrict pshared) |
124 | { | | 127 | { |
125 | | | 128 | |
| | | 129 | pthread__error(EINVAL, "Invalid barrier attribute", |
| | | 130 | attr->ptba_magic == _PT_BARRIERATTR_MAGIC); |
| | | 131 | |
126 | *pshared = PTHREAD_PROCESS_PRIVATE; | | 132 | *pshared = PTHREAD_PROCESS_PRIVATE; |
127 | return 0; | | 133 | return 0; |
128 | } | | 134 | } |
129 | | | 135 | |
130 | int | | 136 | int |
131 | pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) | | 137 | pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) |
132 | { | | 138 | { |
133 | | | 139 | |
| | | 140 | pthread__error(EINVAL, "Invalid barrier attribute", |
| | | 141 | attr->ptba_magic == _PT_BARRIERATTR_MAGIC); |
| | | 142 | |
134 | switch(pshared) { | | 143 | switch(pshared) { |
135 | case PTHREAD_PROCESS_PRIVATE: | | 144 | case PTHREAD_PROCESS_PRIVATE: |
136 | return 0; | | 145 | return 0; |
137 | case PTHREAD_PROCESS_SHARED: | | 146 | case PTHREAD_PROCESS_SHARED: |
138 | return ENOSYS; | | 147 | return ENOSYS; |
139 | } | | 148 | } |
140 | return EINVAL; | | 149 | return EINVAL; |
141 | } | | 150 | } |
142 | #endif | | 151 | #endif |
143 | | | 152 | |
144 | int | | 153 | int |
145 | pthread_barrierattr_init(pthread_barrierattr_t *attr) | | 154 | pthread_barrierattr_init(pthread_barrierattr_t *attr) |
146 | { | | 155 | { |
147 | | | 156 | |
148 | attr->ptba_magic = _PT_BARRIERATTR_MAGIC; | | 157 | attr->ptba_magic = _PT_BARRIERATTR_MAGIC; |
149 | return 0; | | 158 | return 0; |
150 | } | | 159 | } |
151 | | | 160 | |
152 | int | | 161 | int |
153 | pthread_barrierattr_destroy(pthread_barrierattr_t *attr) | | 162 | pthread_barrierattr_destroy(pthread_barrierattr_t *attr) |
154 | { | | 163 | { |
155 | | | 164 | |
156 | if (attr->ptba_magic != _PT_BARRIERATTR_MAGIC) | | 165 | pthread__error(EINVAL, "Invalid barrier attribute", |
157 | return EINVAL; | | 166 | attr->ptba_magic == _PT_BARRIERATTR_MAGIC); |
158 | attr->ptba_magic = _PT_BARRIERATTR_DEAD; | | 167 | attr->ptba_magic = _PT_BARRIERATTR_DEAD; |
159 | return 0; | | 168 | return 0; |
160 | } | | 169 | } |