source: trunk/kernel/syscalls/sys_barrier.c @ 625

Last change on this file since 625 was 625, checked in by alain, 5 years ago

Fix a bug in the vmm_remove_vseg() function: the physical pages
associated to an user DATA vseg were released to the kernel when
the target process descriptor was in the reference cluster.
This physical pages release should be done only when the page
forks counter value is zero.
All other modifications are cosmetic.

File size: 6.1 KB
Line 
1/*
2 * sys_barrier.c - Access a POSIX barrier.
3 *
4 * authors       Alain Greiner (2016,2017,2018,2019)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_kernel_types.h>
25#include <hal_special.h>
26#include <hal_uspace.h>
27#include <hal_vmm.h>
28#include <errno.h>
29#include <thread.h>
30#include <printk.h>
31#include <vmm.h>
32#include <syscalls.h>
33#include <remote_barrier.h>
34
35#if DEBUG_SYS_BARRIER
36//////////////////////////////////////////////////////
37static char * sys_barrier_op_str( uint32_t operation )
38{
39        if     ( operation == BARRIER_INIT    ) return "INIT";
40        else if( operation == BARRIER_DESTROY ) return "DESTROY";
41        else if( operation == BARRIER_WAIT    ) return "WAIT";
42        else                                    return "undefined";
43}
44#endif
45
46//////////////////////////////////
47int sys_barrier( intptr_t   vaddr,
48                 uint32_t   operation,
49                 uint32_t   count,
50                 intptr_t   attr )   
51{
52        error_t                 error;
53    vseg_t                * vseg;
54    pthread_barrierattr_t   k_attr;
55
56    thread_t  * this    = CURRENT_THREAD;
57    process_t * process = this->process;
58
59#if (DEBUG_SYS_BARRIER || CONFIG_INSTRUMENTATION_SYSCALLS)
60uint64_t     tm_start = hal_get_cycles();
61#endif
62
63#if DEBUG_SYS_BARRIER
64if( DEBUG_SYS_BARRIER < tm_start )
65printk("\n[%s] thread[%x,%x] enters for %s / count %d / cycle %d\n",
66__FUNCTION__, process->pid, this->trdid, sys_barrier_op_str(operation), count,
67(uint32_t)tm_start );
68#endif
69
70    // check vaddr in user vspace
71        error = vmm_get_vseg( process , vaddr , &vseg );
72        if( error )
73    {
74
75#if DEBUG_SYSCALLS_ERROR
76printk("\n[ERROR] in %s : unmapped barrier %x / thread %x / process %x\n",
77__FUNCTION__ , vaddr , this->trdid , process->pid );
78hal_vmm_display( process , false );
79#endif
80        this->errno = error;
81        return -1;
82    }
83
84    // execute requested operation
85        switch( operation )
86        {
87        //////////////////
88            case BARRIER_INIT:
89        {
90            if( attr != 0 )   // QDT barrier required
91            {
92                error = vmm_get_vseg( process , attr , &vseg );
93                if( error )
94                {
95
96#if DEBUG_SYSCALLS_ERROR
97printk("\n[ERROR] in %s : unmapped barrier attributes %x / thread %x / process %x\n",
98__FUNCTION__ , attr , this->trdid , process->pid );
99hal_vmm_display( process , false );
100#endif
101                    this->errno = EINVAL;
102                    return -1;
103                }
104 
105                // copy barrier attributes into kernel space
106                hal_copy_from_uspace( &k_attr , (void*)attr , sizeof(pthread_barrierattr_t) );
107
108                if ( count != k_attr.x_size * k_attr.y_size *k_attr.nthreads ) 
109                {
110
111#if DEBUG_SYSCALLS_ERROR
112printk("\n[ERROR] in %s : wrong arguments / count %d / x_size %d / y_size %d / nthreads %x\n",
113__FUNCTION__, count, k_attr.x_size, k_attr.y_size, k_attr.nthreads );
114#endif
115                    this->errno = EINVAL;
116                    return -1;
117                }
118 
119
120                // call relevant system function
121                error = generic_barrier_create( vaddr , count , &k_attr );
122            }
123            else               // simple barrier required
124            {
125                error = generic_barrier_create( vaddr , count , NULL );
126            }
127
128                    if( error )
129            {
130
131#if DEBUG_SYSCALLS_ERROR
132printk("\n[ERROR] in %s : cannot create barrier %x / thread %x / process %x\n",
133__FUNCTION__ , vaddr , this->trdid , process->pid );
134#endif
135                this->errno = ENOMEM;
136                return -1;
137            }
138                        break;
139        }
140        //////////////////
141            case BARRIER_WAIT:
142        {
143            xptr_t barrier_xp = generic_barrier_from_ident( vaddr );
144
145            if( barrier_xp == XPTR_NULL )     // user error
146            {
147
148#if DEBUG_SYSCALLS_ERROR
149printk("\n[ERROR] in %s : barrier %x not registered / thread %x / process %x\n",
150__FUNCTION__ , (intptr_t)vaddr , this->trdid , process->pid );
151#endif
152                this->errno = EINVAL;
153                return -1;
154            }
155            else                          // success
156            {
157                generic_barrier_wait( barrier_xp ); 
158            }
159            break;
160        }
161        /////////////////////
162            case BARRIER_DESTROY:
163        {
164            xptr_t barrier_xp = generic_barrier_from_ident( vaddr );
165
166            if( barrier_xp == XPTR_NULL )     // user error
167            {
168
169#if DEBUG_SYSCALLS_ERROR
170printk("\n[ERROR] in %s : barrier %x not registered / thread %x / process %x\n",
171__FUNCTION__ , (intptr_t)vaddr , this->trdid , process->pid );
172#endif
173                this->errno = EINVAL;
174                return -1;
175            }
176            else                          // success
177            {
178                generic_barrier_destroy( barrier_xp ); 
179            }
180            break;
181        }
182        ////////
183        default: {
184            assert ( false, "illegal operation type <%x>", operation );
185        }
186        }  // end switch
187
188    hal_fence();
189
190#if (DEBUG_SYS_BARRIER || CONFIG_INSTRUMENTATION_SYSCALLS)
191uint64_t     tm_end = hal_get_cycles();
192#endif
193
194#if DEBUG_SYS_BARRIER
195if( DEBUG_SYS_BARRIER < tm_end )
196printk("\n[%s] thread[%x,%x] exit for %s / cycle %d\n",
197__FUNCTION__, process->pid, this->trdid, sys_barrier_op_str(operation), (uint32_t)tm_end );
198#endif
199
200#if CONFIG_INSTRUMENTATION_SYSCALLS
201hal_atomic_add( &syscalls_cumul_cost[SYS_BARRIER] , tm_end - tm_start );
202hal_atomic_add( &syscalls_occurences[SYS_BARRIER] , 1 );
203#endif
204
205        return 0;
206
207}  // end sys_barrier()
208
Note: See TracBrowser for help on using the repository browser.