source: trunk/kernel/syscalls/sys_mutex.c @ 632

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