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