source: trunk/kernel/syscalls/sys_mutex.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: 6.5 KB
Line 
1/*
2 * sys_mutex.c - Access a POSIX mutex.
3 *
4 * Author    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 <errno.h>
27#include <thread.h>
28#include <printk.h>
29#include <vmm.h>
30#include <syscalls.h>
31#include <remote_mutex.h>
32
33
34#if DEBUG_SYS_MUTEX
35////////////////////////////////////////////////////
36static char * sys_mutex_op_str( uint32_t operation )
37{
38        if     ( operation == MUTEX_INIT     ) return "INIT";
39        else if( operation == MUTEX_LOCK     ) return "LOCK";
40        else if( operation == MUTEX_UNLOCK   ) return "UNLOCK";
41        else if( operation == MUTEX_TRYLOCK  ) return "TRYLOCK";
42        else if( operation == MUTEX_DESTROY  ) return "DESTROY";
43        else                                   return "undefined";
44}
45#endif
46
47/////////////////////////////////
48int sys_mutex( void     * vaddr,
49               uint32_t   operation,
50               uint32_t   attr )
51{
52        error_t     error;
53    vseg_t    * vseg;      // for vaddr check
54
55    thread_t  * this    = CURRENT_THREAD;
56    process_t * process = this->process;
57
58#if DEBUG_SYS_MUTEX
59uint64_t    tm_start;
60uint64_t    tm_end;
61tm_start = hal_get_cycles();
62if( DEBUG_SYS_MUTEX < tm_start )
63printk("\n[DBG] %s : thread %x in process %x enter for %s / cycle %d\n",
64__FUNCTION__, this->trdid, process->pid, sys_mutex_op_str( operation ), (uint32_t)tm_start );
65#endif
66
67    // check vaddr in user vspace
68        error = vmm_get_vseg( process , (intptr_t)vaddr , &vseg );
69
70        if( error )
71    {
72
73#if DEBUG_SYSCALLS_ERROR
74printk("\n[ERROR] in %s : mutex unmapped %x / thread %x / process %x\n",
75__FUNCTION__ , (intptr_t)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 MUTEX_INIT:
87        { 
88            if( attr != 0 )
89            {
90
91#if DEBUG_SYSCALLS_ERROR
92printk("\n[ERROR] in %s : mutex attribute non supported / thread %x / process %x\n",
93__FUNCTION__ , this->trdid , process->pid );
94#endif
95                this->errno = error;
96                return -1;
97            }
98   
99            error = remote_mutex_create( (intptr_t)vaddr );
100
101            if( error )
102            {
103
104#if DEBUG_SYSCALLS_ERROR
105printk("\n[ERROR] in %s : cannot create mutex / thread %x / process %x\n",
106__FUNCTION__ , this->trdid , process->pid );
107#endif
108                this->errno = error;
109                return -1;
110            } 
111                    break;
112                }
113        ///////////////////
114            case MUTEX_DESTROY:
115        {
116            xptr_t mutex_xp = remote_mutex_from_ident( (intptr_t)vaddr );
117
118            if( mutex_xp == XPTR_NULL )     // user error
119            {
120
121#if DEBUG_SYSCALLS_ERROR
122printk("\n[ERROR] in %s : mutex %x not registered / thread %x / process %x\n",
123__FUNCTION__ , (intptr_t)vaddr , this->trdid , process->pid );
124#endif
125                this->errno = EINVAL;
126                return -1;
127            }
128            else                          // success
129            {
130                remote_mutex_destroy( mutex_xp ); 
131            }
132            break;
133        }
134        ////////////////
135            case MUTEX_LOCK:
136        {
137            xptr_t mutex_xp = remote_mutex_from_ident( (intptr_t)vaddr );
138
139            if( mutex_xp == XPTR_NULL )     // user error
140            {
141
142#if DEBUG_SYSCALLS_ERROR
143printk("\n[ERROR] in %s : mutex %x not registered / thread %x / process %x\n",
144__FUNCTION__ , (intptr_t)vaddr , this->trdid , process->pid );
145#endif
146                this->errno = EINVAL;
147                return -1;
148            }
149            else                          // success
150            {
151                remote_mutex_lock( mutex_xp ); 
152            }
153            break;
154        }
155        //////////////////
156            case MUTEX_UNLOCK:
157        {
158            xptr_t mutex_xp = remote_mutex_from_ident( (intptr_t)vaddr );
159
160            if( mutex_xp == XPTR_NULL )     // user error
161            {
162
163#if DEBUG_SYSCALLS_ERROR
164printk("\n[ERROR] in %s : mutex %x not registered / thread %x / process %x\n",
165__FUNCTION__ , (intptr_t)vaddr , this->trdid , process->pid );
166#endif
167                this->errno = EINVAL;
168                return -1;
169            }
170            else                          // success
171            {
172                error = remote_mutex_unlock( mutex_xp ); 
173
174                if( error )
175                {
176
177#if DEBUG_SYSCALLS_ERROR
178printk("\n[ERROR] in %s : mutex %x not owned in UNLOCK / thread %x / process %x\n",
179__FUNCTION__ , (intptr_t)vaddr , this->trdid , process->pid );
180#endif
181                    this->errno = EINVAL;
182                    return -1;
183                }
184            }
185            break;
186        }
187        ///////////////////
188            case MUTEX_TRYLOCK:
189        {
190            xptr_t mutex_xp = remote_mutex_from_ident( (intptr_t)vaddr );
191
192            if( mutex_xp == XPTR_NULL )     // user error
193            {
194
195#if DEBUG_SYSCALLS_ERROR
196printk("\n[ERROR] in %s : mutex %x not registered / thread %x / process %x\n",
197__FUNCTION__ , (intptr_t)vaddr , this->trdid , process->pid );
198#endif
199                this->errno = EINVAL;
200                return -1;
201            }
202            else                          // success
203            {
204                error = remote_mutex_trylock( mutex_xp ); 
205
206                if( error ) // non fatal : mutex already taken
207                {
208                    this->errno = EBUSY;
209                    return -1; 
210                }
211            }
212            break;
213        }
214        ////////
215        default: 
216        {
217            assert ( false, "illegal operation type <%x>", operation );
218        }
219        }
220
221    hal_fence();
222
223#if DEBUG_SYS_MUTEX
224tm_end = hal_get_cycles();
225if( DEBUG_SYS_MUTEX < tm_start )
226printk("\n[DBG] %s : thread %x in process %x exit for %s / cost %d / cycle %d\n",
227__FUNCTION__, this->trdid, process->pid, sys_mutex_op_str( operation ),
228(uint32_t)(tm_end - tm_start), (uint32_t)tm_end );
229#endif
230
231        return 0;
232
233}  // end sys_mutex()
234
Note: See TracBrowser for help on using the repository browser.