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

Last change on this file since 625 was 624, checked in by alain, 6 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
RevLine 
[1]1/*
2 * sys_sem.c - Acces a POSIX unamed semaphore.
3 *
[624]4 * Authors     Alain Greiner (2016,2017,2018,2019)
[1]5 *
[23]6 * Copyright (c) UPMC Sorbonne Universites
[1]7 *
[23]8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
[1]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 *
[23]14 * ALMOS-MKH is distributed in the hope that it will be useful, but
[1]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
[23]20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
[1]21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
[457]24#include <hal_kernel_types.h>
[23]25#include <hal_uspace.h>
[624]26#include <hal_vmm.h>
[457]27#include <shared_semaphore.h>
[23]28#include <errno.h>
29#include <thread.h>
30#include <printk.h>
31#include <vmm.h>
[1]32#include <remote_sem.h>
[23]33#include <syscalls.h>
[1]34
[457]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
[1]48//////////////////////////////////
[457]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
[1]53{
[566]54        vseg_t         * vseg;        // for vaddr check
[440]55    error_t          error;
[1]56
[440]57    thread_t       * this    = CURRENT_THREAD;
58    process_t      * process = this->process;
[1]59
[457]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
[1]69    // check vaddr in user vspace
[440]70        error = vmm_get_vseg( process , (intptr_t)vaddr , &vseg );
[23]71        if( error )
[1]72    {
[440]73
74#if DEBUG_SYSCALLS_ERROR
[469]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() );
[624]77hal_vmm_display( process , false );
[440]78#endif
79        this->errno = EINVAL;
[1]80        return -1;
81    }
82
83    // execute requested operation
84        switch( operation )
85        {
86        //////////////
87            case SEM_INIT:
88        {
[457]89            // call relevant kernel function to initialize semaphore
90            error = remote_sem_create( (intptr_t)vaddr , 
[566]91                                       init_value );
[1]92            if ( error )
93            {
[457]94
95#if DEBUG_SYSCALLS_ERROR
[469]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() );
[457]98#endif
99                this->errno = ENOMEM;
[1]100                return -1;
101            }
102        }
[566]103        break;
[1]104        //////////////////
105        case SEM_GETVALUE:
106        {
[457]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
[566]113printk("\n[ERROR] in %s GETVALUE: unmapped buffer %x / thread %x in process %x / cycle %d\n",
[469]114__FUNCTION__ , (intptr_t)current_value, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
[624]115hal_vmm_display( process , false );
[457]116#endif
117                this->errno = EINVAL;
118                return -1;
119            }
120
[1]121            // get extended pointer on remote semaphore
[566]122            xptr_t sem_xp = remote_sem_from_ident( (intptr_t)vaddr );
[1]123
[457]124            // check semaphore registered
125            if( sem_xp == XPTR_NULL )
[1]126            {
[440]127
128#if DEBUG_SYSCALLS_ERROR
[469]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() );
[440]131#endif
[1]132                this->errno = EINVAL;
133                return -1;
134            }
[457]135
136            // call relevant kernel function to get semaphore current value
[566]137            uint32_t current;
[457]138                    remote_sem_get_value( sem_xp , &current );
[1]139 
[457]140            // return value to user
141            hal_copy_to_uspace( current_value , &current , sizeof(uint32_t) );
[1]142        }
[566]143        break;
[1]144        //////////////
145            case SEM_WAIT:
146        { 
147            // get extended pointer on remote semaphore
[566]148            xptr_t sem_xp = remote_sem_from_ident( (intptr_t)vaddr );
[1]149
[457]150            // check semaphore registered
151            if( sem_xp == XPTR_NULL )
[1]152            {
[440]153
154#if DEBUG_SYSCALLS_ERROR
[469]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() );
[624]157hal_vmm_display( process , true );
[440]158#endif
[1]159                this->errno = EINVAL;
160                return -1;
161            }
[457]162
163            // call relevant kernel function to wait semaphore available
164            remote_sem_wait( sem_xp );
[1]165        }
[566]166        break;
[1]167        //////////////
168            case SEM_POST:
169        {
170            // get extended pointer on remote semaphore
[566]171            xptr_t sem_xp = remote_sem_from_ident( (intptr_t)vaddr );
[1]172
[457]173            // check semaphore registered
174            if( sem_xp == XPTR_NULL )
[1]175            {
[440]176
177#if DEBUG_SYSCALLS_ERROR
[469]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() );
[440]180#endif
[1]181                this->errno = EINVAL;
182                return -1;
183            }
[457]184
185            // call relevant kernel function to release semaphore
186            remote_sem_post( sem_xp );
[1]187        }
[566]188                break;
[1]189        /////////////////
190            case SEM_DESTROY:
191        {
192            // get extended pointer on remote semaphore
[566]193            xptr_t sem_xp = remote_sem_from_ident( (intptr_t)vaddr );
[1]194
[457]195            // check semaphore registered
196            if( sem_xp == XPTR_NULL )
[1]197            {
[440]198
199#if DEBUG_SYSCALLS_ERROR
[469]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() );
[440]202#endif
[1]203                this->errno = EINVAL;
204                return -1;
205            }
[457]206
207            // destroy semaphore
208            remote_sem_destroy( sem_xp );
[1]209            }   
[566]210        break;
[1]211        ///////
212            default:  // undefined operation                       
213        {
[457]214
215#if DEBUG_SYSCALLS_ERROR
[469]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() );
[457]218#endif
219            this->errno = EINVAL;
220            return -1;
[1]221        }
222        }
223
[457]224    hal_fence();
225
226#if DEBUG_SYS_SEM
227tm_end = hal_get_cycles();
228if( DEBUG_SYS_SEM < tm_end )
[566]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 );
[457]232#endif
233
[1]234    return 0;
235
236}  // end sys_sem()
Note: See TracBrowser for help on using the repository browser.