source: trunk/sys/libpthread/pthread_barrier.c @ 216

Last change on this file since 216 was 1, checked in by alain, 8 years ago

First import

File size: 3.6 KB
Line 
1/*
2 * pthread_barrier.c - pthread barrier related functions
3 *
4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless
5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites
6 *
7 * This file is part of ALMOS.
8 *
9 * ALMOS is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2.0 of the License.
12 *
13 * ALMOS is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with ALMOS; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <errno.h>
24#include <sys/types.h>
25#include <sys/syscall.h>
26#include <cpu-syscall.h>
27
28#include <pthread.h>
29
30typedef enum
31{
32        BARRIER_INIT_PRIVATE,
33        BARRIER_WAIT,
34        BARRIER_DESTROY,
35        BARRIER_INIT_SHARED
36} barrier_operation_t;
37
38
39void __pthread_barrier_init(void)
40{
41        /* Nothing to do in this version */
42}
43
44
45static int __sys_barrier(void *sysid, uint_t operation, uint_t count)
46{
47        register int retval;
48 
49        retval = (int)cpu_syscall(sysid,(void*)operation,(void*)count,NULL,SYS_BARRIER);
50
51        return retval;
52}
53
54int pthread_barrierattr_destroy(pthread_barrierattr_t *attr)
55{
56        if(attr == NULL)
57                return EINVAL;
58
59        attr->scope = -1;
60        return 0;
61}
62
63int pthread_barrierattr_init(pthread_barrierattr_t *attr)
64{
65        if(attr == NULL)
66                return EINVAL;
67
68        attr->scope = PTHREAD_PROCESS_PRIVATE;
69        return 0;
70}
71
72int pthread_barrierattr_getpshared(pthread_barrierattr_t *attr, int *scope)
73{
74        if((attr == NULL) || (attr->scope < 0) || (scope == NULL))
75                return EINVAL;
76
77        *scope = attr->scope;
78        return 0;
79}
80
81int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int scope)
82{
83        if((attr == NULL) || ((scope != PTHREAD_PROCESS_PRIVATE) && (scope != PTHREAD_PROCESS_SHARED)))
84                return EINVAL;
85
86        attr->scope = scope;
87        return 0;
88}
89
90int pthread_barrier_init (pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned count)
91{
92        if((attr != NULL) && (attr->scope == PTHREAD_PROCESS_SHARED))
93        {
94                barrier->scope = PTHREAD_PROCESS_SHARED;
95                return __sys_barrier(&barrier->sysid, BARRIER_INIT_SHARED, count);
96        }
97
98        barrier->scope          = PTHREAD_PROCESS_PRIVATE;
99        barrier->cntr.value     = count;
100        barrier->count.value    = count;
101        barrier->state[0].value = 0;
102        barrier->state[1].value = 0;
103        barrier->phase          = 0;
104 
105        return 0;
106}
107
108int pthread_barrier_wait (pthread_barrier_t *barrier)
109{
110        sint_t ticket;
111        uint_t phase;
112        uint_t signature;
113
114        if(barrier->scope == PTHREAD_PROCESS_SHARED)
115                return __sys_barrier(&barrier->sysid, BARRIER_WAIT, 0);
116
117        phase  = barrier->phase;
118        ticket = cpu_atomic_add(&barrier->cntr.value, -1);
119
120        if(ticket == 1)
121        {
122                barrier->cntr.value                  = barrier->count.value;
123                barrier->phase                       = ~(barrier->phase) & 0x1;
124                barrier->state[barrier->phase].value = 0;
125                barrier->state[phase].value          = 1;
126
127                cpu_invalid_dcache_line(&barrier->phase);
128                cpu_invalid_dcache_line((void*)&barrier->state[phase].value);
129
130                return PTHREAD_BARRIER_SERIAL_THREAD;
131        }
132
133        cpu_invalid_dcache_line(&barrier->phase);
134
135        while(barrier->state[phase].value == 0)
136                ;               /* wait */
137
138        cpu_invalid_dcache_line((void*)&barrier->state[phase].value);
139        return 0;
140}
141
142int pthread_barrier_destroy(pthread_barrier_t *barrier)
143{
144        if(barrier->scope == PTHREAD_PROCESS_SHARED)
145                return __sys_barrier(barrier, BARRIER_DESTROY, 0);
146
147        if(barrier->cntr.value != barrier->count.value)
148                return EBUSY;
149
150        return 0;
151}
152
Note: See TracBrowser for help on using the repository browser.