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