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

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

Fix several bugs to use the instruction MMU in kernel mode
in replacement of the instruction address extension register,
and remove the "kentry" segment.

This version is running on the tsar_generic_iob" platform.

One interesting bug: the cp0_ebase defining the kernel entry point
(for interrupts, exceptions and syscalls) must be initialized
early in kernel_init(), because the VFS initialisation done by
kernel_ini() uses RPCs, and RPCs uses Inter-Processor-Interrup.

File size: 5.8 KB
Line 
1/*
2 * sys_barrier.c - Access a POSIX barrier.
3 *
4 * authors       Alain Greiner (2016,2017,2018)
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 <errno.h>
28#include <thread.h>
29#include <printk.h>
30#include <vmm.h>
31#include <syscalls.h>
32#include <remote_barrier.h>
33
34#if DEBUG_SYS_BARRIER
35//////////////////////////////////////////////////////
36static char * sys_barrier_op_str( uint32_t operation )
37{
38        if     ( operation == BARRIER_INIT    ) return "INIT";
39        else if( operation == BARRIER_DESTROY ) return "DESTROY";
40        else if( operation == BARRIER_WAIT    ) return "WAIT";
41        else                                    return "undefined";
42}
43#endif
44
45//////////////////////////////////
46int sys_barrier( intptr_t   vaddr,
47                 uint32_t   operation,
48                 uint32_t   count,
49                 intptr_t   attr )   
50{
51        error_t                 error;
52    vseg_t                * vseg;
53    pthread_barrierattr_t   k_attr;
54
55    thread_t  * this    = CURRENT_THREAD;
56    process_t * process = this->process;
57
58#if DEBUG_SYS_BARRIER
59uint64_t   tm_start;
60uint64_t   tm_end;
61tm_start = hal_get_cycles();
62if( DEBUG_SYS_BARRIER < tm_start )
63printk("\n[%s] thread[%x,%x] enters for %s / count %d / cycle %d\n",
64__FUNCTION__, process->pid, this->trdid, sys_barrier_op_str(operation), count,
65(uint32_t)tm_start );
66#endif
67
68    // check vaddr in user vspace
69        error = vmm_get_vseg( process , vaddr , &vseg );
70        if( error )
71    {
72
73#if DEBUG_SYSCALLS_ERROR
74printk("\n[ERROR] in %s : unmapped barrier %x / thread %x / process %x\n",
75__FUNCTION__ , vaddr , this->trdid , process->pid );
76hal_vmm_display( process , false );
77#endif
78        this->errno = error;
79        return -1;
80    }
81
82    // execute requested operation
83        switch( operation )
84        {
85        //////////////////
86            case BARRIER_INIT:
87        {
88            if( attr != 0 )   // QDT barrier required
89            {
90                error = vmm_get_vseg( process , attr , &vseg );
91                if( error )
92                {
93
94#if DEBUG_SYSCALLS_ERROR
95printk("\n[ERROR] in %s : unmapped barrier attributes %x / thread %x / process %x\n",
96__FUNCTION__ , attr , this->trdid , process->pid );
97hal_vmm_display( process , false );
98#endif
99                    this->errno = EINVAL;
100                    return -1;
101                }
102 
103                // copy barrier attributes into kernel space
104                hal_copy_from_uspace( &k_attr , (void*)attr , sizeof(pthread_barrierattr_t) );
105
106                if ( count != k_attr.x_size * k_attr.y_size *k_attr.nthreads ) 
107                {
108
109#if DEBUG_SYSCALLS_ERROR
110printk("\n[ERROR] in %s : wrong arguments / count %d / x_size %d / y_size %d / nthreads %x\n",
111__FUNCTION__, count, k_attr.x_size, k_attr.y_size, k_attr.nthreads );
112#endif
113                    this->errno = EINVAL;
114                    return -1;
115                }
116 
117
118                // call relevant system function
119                error = generic_barrier_create( vaddr , count , &k_attr );
120            }
121            else               // simple barrier required
122            {
123                error = generic_barrier_create( vaddr , count , NULL );
124            }
125
126                    if( error )
127            {
128
129#if DEBUG_SYSCALLS_ERROR
130printk("\n[ERROR] in %s : cannot create barrier %x / thread %x / process %x\n",
131__FUNCTION__ , vaddr , this->trdid , process->pid );
132#endif
133                this->errno = ENOMEM;
134                return -1;
135            }
136                        break;
137        }
138        //////////////////
139            case BARRIER_WAIT:
140        {
141            xptr_t barrier_xp = generic_barrier_from_ident( vaddr );
142
143            if( barrier_xp == XPTR_NULL )     // user error
144            {
145
146#if DEBUG_SYSCALLS_ERROR
147printk("\n[ERROR] in %s : barrier %x not registered / thread %x / process %x\n",
148__FUNCTION__ , (intptr_t)vaddr , this->trdid , process->pid );
149#endif
150                this->errno = EINVAL;
151                return -1;
152            }
153            else                          // success
154            {
155                generic_barrier_wait( barrier_xp ); 
156            }
157            break;
158        }
159        /////////////////////
160            case BARRIER_DESTROY:
161        {
162            xptr_t barrier_xp = generic_barrier_from_ident( vaddr );
163
164            if( barrier_xp == XPTR_NULL )     // user error
165            {
166
167#if DEBUG_SYSCALLS_ERROR
168printk("\n[ERROR] in %s : barrier %x not registered / thread %x / process %x\n",
169__FUNCTION__ , (intptr_t)vaddr , this->trdid , process->pid );
170#endif
171                this->errno = EINVAL;
172                return -1;
173            }
174            else                          // success
175            {
176                generic_barrier_destroy( barrier_xp ); 
177            }
178            break;
179        }
180        ////////
181        default: {
182            assert ( false, "illegal operation type <%x>", operation );
183        }
184        }  // end switch
185
186#if DEBUG_SYS_BARRIER
187tm_end = hal_get_cycles();
188if( DEBUG_SYS_BARRIER < tm_end )
189printk("\n[%s] thread[%x,%x] exit for %s / cost %d / cycle %d\n",
190__FUNCTION__, process->pid, this->trdid, sys_barrier_op_str(operation), 
191(uint32_t)(tm_end - tm_start), (uint32_t)tm_end );
192#endif
193
194        return 0;
195
196}  // end sys_barrier()
197
Note: See TracBrowser for help on using the repository browser.