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

Last change on this file since 625 was 625, checked in by alain, 5 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
RevLine 
[1]1/*
[23]2 * sys_mutex.c - Access a POSIX mutex.
[1]3 *
[625]4 * Author    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_special.h>
[625]26#include <hal_vmm.h>
[1]27#include <errno.h>
28#include <thread.h>
[23]29#include <printk.h>
[1]30#include <vmm.h>
[23]31#include <syscalls.h>
32#include <remote_mutex.h>
[1]33
34
[566]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
[23]48/////////////////////////////////
49int sys_mutex( void     * vaddr,
50               uint32_t   operation,
51               uint32_t   attr )
[1]52{
[440]53        error_t     error;
[566]54    vseg_t    * vseg;      // for vaddr check
[1]55
[440]56    thread_t  * this    = CURRENT_THREAD;
57    process_t * process = this->process;
[1]58
[625]59#if (DEBUG_SYS_MUTEX || CONFIG_INSTRUMENTATION_SYSCALLS)
60uint64_t     tm_start = hal_get_cycles();
61#endif
62
[566]63#if DEBUG_SYS_MUTEX
64if( DEBUG_SYS_MUTEX < tm_start )
[625]65printk("\n[%s] thread[%x,%x] enter for %s / cycle %d\n",
[566]66__FUNCTION__, this->trdid, process->pid, sys_mutex_op_str( operation ), (uint32_t)tm_start );
67#endif
68
[23]69    // check vaddr in user vspace
[440]70        error = vmm_get_vseg( process , (intptr_t)vaddr , &vseg );
71
[23]72        if( error )
73    {
[440]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 );
[624]78hal_vmm_display( process , false );
[440]79#endif
[23]80        this->errno = error;
81        return -1;
82    }
[1]83
[23]84    // execute requested operation
85        switch( operation )
86        {   
87        ////////////////
88            case MUTEX_INIT:
89        { 
90            if( attr != 0 )
91            {
[440]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
[23]97                this->errno = error;
98                return -1;
99            }
100   
101            error = remote_mutex_create( (intptr_t)vaddr );
[1]102
[23]103            if( error )
104            {
[440]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
[23]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 );
[1]119
[23]120            if( mutex_xp == XPTR_NULL )     // user error
121            {
[440]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
[23]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 );
[1]140
[23]141            if( mutex_xp == XPTR_NULL )     // user error
142            {
[440]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
[23]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 );
[1]161
[23]162            if( mutex_xp == XPTR_NULL )     // user error
163            {
[440]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
[23]169                this->errno = EINVAL;
170                return -1;
171            }
172            else                          // success
173            {
[566]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                }
[23]186            }
187            break;
188        }
[566]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        }
[23]216        ////////
[566]217        default: 
218        {
[508]219            assert ( false, "illegal operation type <%x>", operation );
[23]220        }
221        }
[1]222
[566]223    hal_fence();
224
[625]225#if (DEBUG_SYS_MUTEX || CONFIG_INSTRUMENTATION_SYSCALLS)
226uint64_t     tm_end = hal_get_cycles();
227#endif
228
[566]229#if DEBUG_SYS_MUTEX
[625]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 );
[566]233#endif
234
[625]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
[23]240        return 0;
[1]241
[23]242}  // end sys_mutex()
[1]243
Note: See TracBrowser for help on using the repository browser.