Unbreak LINT by including <sys/thread2.h> where proper and remove some
[dragonfly.git] / lib / libthread_xu / thread / thr_barrier.c
1 /*-
2  * Copyright (c) 2003 David Xu <davidxu@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/lib/libpthread/thread/thr_barrier.c,v 1.1 2003/09/04 14:06:43 davidxu Exp $
27  * $DragonFly: src/lib/libthread_xu/thread/thr_barrier.c,v 1.4 2005/03/29 19:26:20 joerg Exp $
28  */
29
30 #include <machine/tls.h>
31
32 #include <errno.h>
33 #include <stdlib.h>
34 #include <pthread.h>
35
36 #include "thr_private.h"
37
38 __weak_reference(_pthread_barrier_init,         pthread_barrier_init);
39 __weak_reference(_pthread_barrier_wait,         pthread_barrier_wait);
40 __weak_reference(_pthread_barrier_destroy,      pthread_barrier_destroy);
41
42 int
43 _pthread_barrier_destroy(pthread_barrier_t *barrier)
44 {
45         pthread_barrier_t       bar;
46
47         if (barrier == NULL || *barrier == NULL)
48                 return (EINVAL);
49
50         bar = *barrier;
51         if (bar->b_waiters > 0)
52                 return (EBUSY);
53         *barrier = NULL;
54         free(bar);
55         return (0);
56 }
57
58 int
59 _pthread_barrier_init(pthread_barrier_t *barrier,
60                       const pthread_barrierattr_t *attr, int count)
61 {
62         pthread_barrier_t       bar;
63
64         if (barrier == NULL || count <= 0)
65                 return (EINVAL);
66
67         bar = malloc(sizeof(struct pthread_barrier));
68         if (bar == NULL)
69                 return (ENOMEM);
70
71         _thr_umtx_init(&bar->b_lock);
72         bar->b_cycle    = 0;
73         bar->b_waiters  = 0;
74         bar->b_count    = count;
75         *barrier        = bar;
76
77         return (0);
78 }
79
80 int
81 _pthread_barrier_wait(pthread_barrier_t *barrier)
82 {
83         struct pthread *curthread = tls_get_curthread();
84         pthread_barrier_t bar;
85         long cycle;
86         int ret;
87
88         if (barrier == NULL || *barrier == NULL)
89                 return (EINVAL);
90
91         bar = *barrier;
92         THR_UMTX_LOCK(curthread, &bar->b_lock);
93         if (++bar->b_waiters == bar->b_count) {
94                 /* Current thread is lastest thread */
95                 bar->b_waiters = 0;
96                 bar->b_cycle++;
97                 _thr_umtx_wake(&bar->b_cycle, bar->b_count);
98                 THR_UMTX_UNLOCK(curthread, &bar->b_lock);
99                 ret = PTHREAD_BARRIER_SERIAL_THREAD;
100         } else {
101                 cycle = bar->b_cycle;
102                 THR_UMTX_UNLOCK(curthread, &bar->b_lock);
103                 do {
104                         _thr_umtx_wait(&bar->b_cycle, cycle, NULL, 0);
105                         /* test cycle to avoid bogus wakeup */
106                 } while (cycle == bar->b_cycle);
107                 ret = 0;
108         }
109         return (ret);
110 }