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

Last change on this file since 624 was 624, checked in by alain, 3 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: 7.5 KB
Line 
1/*
2 * sys_sem.c - Acces a POSIX unamed semaphore.
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_uspace.h>
26#include <hal_vmm.h>
27#include <shared_semaphore.h>
28#include <errno.h>
29#include <thread.h>
30#include <printk.h>
31#include <vmm.h>
32#include <remote_sem.h>
33#include <syscalls.h>
34
35#if DEBUG_SYS_SEM
36//////////////////////////////////////////////////
37static char * sys_sem_op_str( uint32_t operation )
38{
39        if     ( operation == SEM_INIT     ) return "INIT";
40        else if( operation == SEM_WAIT     ) return "WAIT";
41        else if( operation == SEM_POST     ) return "POST";
42        else if( operation == SEM_GETVALUE ) return "GETVALUE";
43        else if( operation == SEM_DESTROY  ) return "DESTROY";
44        else                                 return "undefined";
45}
46#endif
47
48//////////////////////////////////
49int sys_sem( void         * vaddr,            // semaphore virtual  address
50             uint32_t       operation,        // requested operation type
51             uint32_t       init_value,       // initial value
52             uint32_t     * current_value )   // pointer on current value buffer
53{
54        vseg_t         * vseg;        // for vaddr check
55    error_t          error;
56
57    thread_t       * this    = CURRENT_THREAD;
58    process_t      * process = this->process;
59
60#if DEBUG_SYS_SEM
61uint64_t    tm_start;
62uint64_t    tm_end;
63tm_start = hal_get_cycles();
64if( DEBUG_SYS_SEM < tm_start )
65printk("\n[DBG] %s : thread %x in process %x enter for %s / cycle %d\n",
66__FUNCTION__, this->trdid, process->pid, sys_sem_op_str( operation ), (uint32_t)tm_start );
67#endif
68
69    // check vaddr in user vspace
70        error = vmm_get_vseg( process , (intptr_t)vaddr , &vseg );
71        if( error )
72    {
73
74#if DEBUG_SYSCALLS_ERROR
75printk("\n[ERROR] in %s : unmapped semaphore pointer %x / thread %x in process %x / cycle %d\n",
76__FUNCTION__ , (intptr_t)vaddr, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
77hal_vmm_display( process , false );
78#endif
79        this->errno = EINVAL;
80        return -1;
81    }
82
83    // execute requested operation
84        switch( operation )
85        {
86        //////////////
87            case SEM_INIT:
88        {
89            // call relevant kernel function to initialize semaphore
90            error = remote_sem_create( (intptr_t)vaddr , 
91                                       init_value );
92            if ( error )
93            {
94
95#if DEBUG_SYSCALLS_ERROR
96printk("\n[ERROR] in %s INIT: cannot create semaphore / thread %x in process %x / cycle %d\n",
97__FUNCTION__, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
98#endif
99                this->errno = ENOMEM;
100                return -1;
101            }
102        }
103        break;
104        //////////////////
105        case SEM_GETVALUE:
106        {
107            // check current_value buffer in user vspace
108                error = vmm_get_vseg( process , (intptr_t)current_value , &vseg );
109            if( error )
110            {
111
112#if DEBUG_SYSCALLS_ERROR
113printk("\n[ERROR] in %s GETVALUE: unmapped buffer %x / thread %x in process %x / cycle %d\n",
114__FUNCTION__ , (intptr_t)current_value, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
115hal_vmm_display( process , false );
116#endif
117                this->errno = EINVAL;
118                return -1;
119            }
120
121            // get extended pointer on remote semaphore
122            xptr_t sem_xp = remote_sem_from_ident( (intptr_t)vaddr );
123
124            // check semaphore registered
125            if( sem_xp == XPTR_NULL )
126            {
127
128#if DEBUG_SYSCALLS_ERROR
129printk("\n[ERROR] in %s GETVALUE: semaphore %x not found / thread %x in process %x / cycle %d\n",
130__FUNCTION__ , (intptr_t)vaddr, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
131#endif
132                this->errno = EINVAL;
133                return -1;
134            }
135
136            // call relevant kernel function to get semaphore current value
137            uint32_t current;
138                    remote_sem_get_value( sem_xp , &current );
139 
140            // return value to user
141            hal_copy_to_uspace( current_value , &current , sizeof(uint32_t) );
142        }
143        break;
144        //////////////
145            case SEM_WAIT:
146        { 
147            // get extended pointer on remote semaphore
148            xptr_t sem_xp = remote_sem_from_ident( (intptr_t)vaddr );
149
150            // check semaphore registered
151            if( sem_xp == XPTR_NULL )
152            {
153
154#if DEBUG_SYSCALLS_ERROR
155printk("\n[ERROR] in %s WAIT: semaphore %x not found / thread %x in process %x / cycle %d\n",
156__FUNCTION__ , (intptr_t)vaddr, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
157hal_vmm_display( process , true );
158#endif
159                this->errno = EINVAL;
160                return -1;
161            }
162
163            // call relevant kernel function to wait semaphore available
164            remote_sem_wait( sem_xp );
165        }
166        break;
167        //////////////
168            case SEM_POST:
169        {
170            // get extended pointer on remote semaphore
171            xptr_t sem_xp = remote_sem_from_ident( (intptr_t)vaddr );
172
173            // check semaphore registered
174            if( sem_xp == XPTR_NULL )
175            {
176
177#if DEBUG_SYSCALLS_ERROR
178printk("\n[ERROR] in %s POST: semaphore %x not found / thread %x in process %x / cycle %d\n",
179__FUNCTION__ , (intptr_t)vaddr, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
180#endif
181                this->errno = EINVAL;
182                return -1;
183            }
184
185            // call relevant kernel function to release semaphore
186            remote_sem_post( sem_xp );
187        }
188                break;
189        /////////////////
190            case SEM_DESTROY:
191        {
192            // get extended pointer on remote semaphore
193            xptr_t sem_xp = remote_sem_from_ident( (intptr_t)vaddr );
194
195            // check semaphore registered
196            if( sem_xp == XPTR_NULL )
197            {
198
199#if DEBUG_SYSCALLS_ERROR
200printk("\n[ERROR] in %s DESTROY: semaphore %x not found / thread %x in process %x / cycle %d\n",
201__FUNCTION__ , (intptr_t)vaddr, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
202#endif
203                this->errno = EINVAL;
204                return -1;
205            }
206
207            // destroy semaphore
208            remote_sem_destroy( sem_xp );
209            }   
210        break;
211        ///////
212            default:  // undefined operation                       
213        {
214
215#if DEBUG_SYSCALLS_ERROR
216printk("\n[ERROR] in %s : undefined operation type %d / thread %x in process %x / cycle %d\n",
217__FUNCTION__ , operation, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
218#endif
219            this->errno = EINVAL;
220            return -1;
221        }
222        }
223
224    hal_fence();
225
226#if DEBUG_SYS_SEM
227tm_end = hal_get_cycles();
228if( DEBUG_SYS_SEM < tm_end )
229printk("\n[DBG] %s : thread %x in process %x exit for %s / cost = %d / cycle %d\n",
230__FUNCTION__, this->trdid, process->pid, sys_sem_op_str( operation ),
231(uint32_t)(tm_end - tm_start), (uint32_t)tm_end );
232#endif
233
234    return 0;
235
236}  // end sys_sem()
Note: See TracBrowser for help on using the repository browser.