| [1] | 1 | /* | 
|---|
 | 2 |  * sys_sem.c - Acces a POSIX unamed semaphore. | 
|---|
 | 3 |  *  | 
|---|
| [440] | 4 |  * Authors     Alain Greiner (2016,2017,2018) | 
|---|
| [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_uspace.h> | 
|---|
| [457] | 26 | #include <shared_semaphore.h> | 
|---|
| [23] | 27 | #include <errno.h> | 
|---|
 | 28 | #include <thread.h> | 
|---|
 | 29 | #include <printk.h> | 
|---|
 | 30 | #include <vmm.h> | 
|---|
| [1] | 31 | #include <remote_sem.h> | 
|---|
| [23] | 32 | #include <syscalls.h> | 
|---|
| [1] | 33 |  | 
|---|
| [457] | 34 | #if DEBUG_SYS_SEM | 
|---|
 | 35 | ////////////////////////////////////////////////// | 
|---|
 | 36 | static char * sys_sem_op_str( uint32_t operation ) | 
|---|
 | 37 | { | 
|---|
 | 38 |         if     ( operation == SEM_INIT     ) return "INIT"; | 
|---|
 | 39 |         else if( operation == SEM_WAIT     ) return "WAIT"; | 
|---|
 | 40 |         else if( operation == SEM_POST     ) return "POST"; | 
|---|
 | 41 |         else if( operation == SEM_GETVALUE ) return "GETVALUE"; | 
|---|
 | 42 |         else if( operation == SEM_DESTROY  ) return "DESTROY"; | 
|---|
 | 43 |         else                                 return "undefined"; | 
|---|
 | 44 | } | 
|---|
 | 45 | #endif | 
|---|
 | 46 |  | 
|---|
| [1] | 47 | ////////////////////////////////// | 
|---|
| [457] | 48 | int sys_sem( void         * vaddr,            // semaphore virtual  address  | 
|---|
 | 49 |              uint32_t       operation,        // requested operation type | 
|---|
 | 50 |              uint32_t       init_value,       // initial value | 
|---|
 | 51 |              uint32_t     * current_value )   // pointer on current value buffer | 
|---|
| [1] | 52 | { | 
|---|
| [566] | 53 |         vseg_t         * vseg;        // for vaddr check | 
|---|
| [440] | 54 |     error_t          error; | 
|---|
| [1] | 55 |  | 
|---|
| [440] | 56 |     thread_t       * this    = CURRENT_THREAD; | 
|---|
 | 57 |     process_t      * process = this->process; | 
|---|
| [1] | 58 |  | 
|---|
| [457] | 59 | #if DEBUG_SYS_SEM | 
|---|
 | 60 | uint64_t    tm_start; | 
|---|
 | 61 | uint64_t    tm_end; | 
|---|
 | 62 | tm_start = hal_get_cycles(); | 
|---|
 | 63 | if( DEBUG_SYS_SEM < tm_start ) | 
|---|
 | 64 | printk("\n[DBG] %s : thread %x in process %x enter for %s / cycle %d\n", | 
|---|
 | 65 | __FUNCTION__, this->trdid, process->pid, sys_sem_op_str( operation ), (uint32_t)tm_start ); | 
|---|
 | 66 | #endif | 
|---|
 | 67 |  | 
|---|
| [1] | 68 |     // check vaddr in user vspace | 
|---|
| [440] | 69 |         error = vmm_get_vseg( process , (intptr_t)vaddr , &vseg ); | 
|---|
| [23] | 70 |         if( error ) | 
|---|
| [1] | 71 |     { | 
|---|
| [440] | 72 |  | 
|---|
 | 73 | #if DEBUG_SYSCALLS_ERROR | 
|---|
| [469] | 74 | printk("\n[ERROR] in %s : unmapped semaphore pointer %x / thread %x in process %x / cycle %d\n", | 
|---|
 | 75 | __FUNCTION__ , (intptr_t)vaddr, this->trdid, process->pid, (uint32_t)hal_get_cycles() ); | 
|---|
| [440] | 76 | vmm_display( process , false ); | 
|---|
 | 77 | #endif | 
|---|
 | 78 |         this->errno = EINVAL; | 
|---|
| [1] | 79 |         return -1; | 
|---|
 | 80 |     } | 
|---|
 | 81 |  | 
|---|
 | 82 |     // execute requested operation | 
|---|
 | 83 |         switch( operation ) | 
|---|
 | 84 |         { | 
|---|
 | 85 |         ////////////// | 
|---|
 | 86 |             case SEM_INIT: | 
|---|
 | 87 |         { | 
|---|
| [457] | 88 |             // call relevant kernel function to initialize semaphore | 
|---|
 | 89 |             error = remote_sem_create( (intptr_t)vaddr ,  | 
|---|
| [566] | 90 |                                        init_value ); | 
|---|
| [1] | 91 |             if ( error ) | 
|---|
 | 92 |             { | 
|---|
| [457] | 93 |  | 
|---|
 | 94 | #if DEBUG_SYSCALLS_ERROR | 
|---|
| [469] | 95 | printk("\n[ERROR] in %s INIT: cannot create semaphore / thread %x in process %x / cycle %d\n", | 
|---|
 | 96 | __FUNCTION__, this->trdid, process->pid, (uint32_t)hal_get_cycles() ); | 
|---|
| [457] | 97 | #endif | 
|---|
 | 98 |                 this->errno = ENOMEM; | 
|---|
| [1] | 99 |                 return -1; | 
|---|
 | 100 |             } | 
|---|
 | 101 |         } | 
|---|
| [566] | 102 |         break; | 
|---|
| [1] | 103 |         ////////////////// | 
|---|
 | 104 |         case SEM_GETVALUE: | 
|---|
 | 105 |         { | 
|---|
| [457] | 106 |             // check current_value buffer in user vspace | 
|---|
 | 107 |                 error = vmm_get_vseg( process , (intptr_t)current_value , &vseg ); | 
|---|
 | 108 |             if( error ) | 
|---|
 | 109 |             { | 
|---|
 | 110 |  | 
|---|
 | 111 | #if DEBUG_SYSCALLS_ERROR | 
|---|
| [566] | 112 | printk("\n[ERROR] in %s GETVALUE: unmapped buffer %x / thread %x in process %x / cycle %d\n", | 
|---|
| [469] | 113 | __FUNCTION__ , (intptr_t)current_value, this->trdid, process->pid, (uint32_t)hal_get_cycles() ); | 
|---|
| [457] | 114 | vmm_display( process , false ); | 
|---|
 | 115 | #endif | 
|---|
 | 116 |                 this->errno = EINVAL; | 
|---|
 | 117 |                 return -1; | 
|---|
 | 118 |             } | 
|---|
 | 119 |  | 
|---|
| [1] | 120 |             // get extended pointer on remote semaphore | 
|---|
| [566] | 121 |             xptr_t sem_xp = remote_sem_from_ident( (intptr_t)vaddr ); | 
|---|
| [1] | 122 |  | 
|---|
| [457] | 123 |             // check semaphore registered | 
|---|
 | 124 |             if( sem_xp == XPTR_NULL ) | 
|---|
| [1] | 125 |             { | 
|---|
| [440] | 126 |  | 
|---|
 | 127 | #if DEBUG_SYSCALLS_ERROR | 
|---|
| [469] | 128 | printk("\n[ERROR] in %s GETVALUE: semaphore %x not found / thread %x in process %x / cycle %d\n", | 
|---|
 | 129 | __FUNCTION__ , (intptr_t)vaddr, this->trdid, process->pid, (uint32_t)hal_get_cycles() ); | 
|---|
| [440] | 130 | #endif | 
|---|
| [1] | 131 |                 this->errno = EINVAL; | 
|---|
 | 132 |                 return -1; | 
|---|
 | 133 |             } | 
|---|
| [457] | 134 |  | 
|---|
 | 135 |             // call relevant kernel function to get semaphore current value | 
|---|
| [566] | 136 |             uint32_t current; | 
|---|
| [457] | 137 |                     remote_sem_get_value( sem_xp , ¤t ); | 
|---|
| [1] | 138 |   | 
|---|
| [457] | 139 |             // return value to user | 
|---|
 | 140 |             hal_copy_to_uspace( current_value , ¤t , sizeof(uint32_t) ); | 
|---|
| [1] | 141 |         } | 
|---|
| [566] | 142 |         break; | 
|---|
| [1] | 143 |         ////////////// | 
|---|
 | 144 |             case SEM_WAIT: | 
|---|
 | 145 |         {   | 
|---|
 | 146 |             // get extended pointer on remote semaphore | 
|---|
| [566] | 147 |             xptr_t sem_xp = remote_sem_from_ident( (intptr_t)vaddr ); | 
|---|
| [1] | 148 |  | 
|---|
| [457] | 149 |             // check semaphore registered | 
|---|
 | 150 |             if( sem_xp == XPTR_NULL ) | 
|---|
| [1] | 151 |             { | 
|---|
| [440] | 152 |  | 
|---|
 | 153 | #if DEBUG_SYSCALLS_ERROR | 
|---|
| [469] | 154 | printk("\n[ERROR] in %s WAIT: semaphore %x not found / thread %x in process %x / cycle %d\n", | 
|---|
 | 155 | __FUNCTION__ , (intptr_t)vaddr, this->trdid, process->pid, (uint32_t)hal_get_cycles() ); | 
|---|
 | 156 | vmm_display( process , true ); | 
|---|
| [440] | 157 | #endif | 
|---|
| [1] | 158 |                 this->errno = EINVAL; | 
|---|
 | 159 |                 return -1; | 
|---|
 | 160 |             } | 
|---|
| [457] | 161 |  | 
|---|
 | 162 |             // call relevant kernel function to wait semaphore available | 
|---|
 | 163 |             remote_sem_wait( sem_xp ); | 
|---|
| [1] | 164 |         } | 
|---|
| [566] | 165 |         break; | 
|---|
| [1] | 166 |         ////////////// | 
|---|
 | 167 |             case SEM_POST: | 
|---|
 | 168 |         { | 
|---|
 | 169 |             // get extended pointer on remote semaphore | 
|---|
| [566] | 170 |             xptr_t sem_xp = remote_sem_from_ident( (intptr_t)vaddr ); | 
|---|
| [1] | 171 |  | 
|---|
| [457] | 172 |             // check semaphore registered | 
|---|
 | 173 |             if( sem_xp == XPTR_NULL ) | 
|---|
| [1] | 174 |             { | 
|---|
| [440] | 175 |  | 
|---|
 | 176 | #if DEBUG_SYSCALLS_ERROR | 
|---|
| [469] | 177 | printk("\n[ERROR] in %s POST: semaphore %x not found / thread %x in process %x / cycle %d\n", | 
|---|
 | 178 | __FUNCTION__ , (intptr_t)vaddr, this->trdid, process->pid, (uint32_t)hal_get_cycles() ); | 
|---|
| [440] | 179 | #endif | 
|---|
| [1] | 180 |                 this->errno = EINVAL; | 
|---|
 | 181 |                 return -1; | 
|---|
 | 182 |             } | 
|---|
| [457] | 183 |  | 
|---|
 | 184 |             // call relevant kernel function to release semaphore  | 
|---|
 | 185 |             remote_sem_post( sem_xp ); | 
|---|
| [1] | 186 |         } | 
|---|
| [566] | 187 |                 break; | 
|---|
| [1] | 188 |         ///////////////// | 
|---|
 | 189 |             case SEM_DESTROY: | 
|---|
 | 190 |         { | 
|---|
 | 191 |             // get extended pointer on remote semaphore | 
|---|
| [566] | 192 |             xptr_t sem_xp = remote_sem_from_ident( (intptr_t)vaddr ); | 
|---|
| [1] | 193 |  | 
|---|
| [457] | 194 |             // check semaphore registered | 
|---|
 | 195 |             if( sem_xp == XPTR_NULL ) | 
|---|
| [1] | 196 |             { | 
|---|
| [440] | 197 |  | 
|---|
 | 198 | #if DEBUG_SYSCALLS_ERROR | 
|---|
| [469] | 199 | printk("\n[ERROR] in %s DESTROY: semaphore %x not found / thread %x in process %x / cycle %d\n", | 
|---|
 | 200 | __FUNCTION__ , (intptr_t)vaddr, this->trdid, process->pid, (uint32_t)hal_get_cycles() ); | 
|---|
| [440] | 201 | #endif | 
|---|
| [1] | 202 |                 this->errno = EINVAL; | 
|---|
 | 203 |                 return -1; | 
|---|
 | 204 |             } | 
|---|
| [457] | 205 |  | 
|---|
 | 206 |             // destroy semaphore | 
|---|
 | 207 |             remote_sem_destroy( sem_xp ); | 
|---|
| [1] | 208 |             }    | 
|---|
| [566] | 209 |         break; | 
|---|
| [1] | 210 |         /////// | 
|---|
 | 211 |             default:  // undefined operation                        | 
|---|
 | 212 |         { | 
|---|
| [457] | 213 |  | 
|---|
 | 214 | #if DEBUG_SYSCALLS_ERROR | 
|---|
| [469] | 215 | printk("\n[ERROR] in %s : undefined operation type %d / thread %x in process %x / cycle %d\n", | 
|---|
 | 216 | __FUNCTION__ , operation, this->trdid, process->pid, (uint32_t)hal_get_cycles() ); | 
|---|
| [457] | 217 | #endif | 
|---|
 | 218 |             this->errno = EINVAL; | 
|---|
 | 219 |             return -1; | 
|---|
| [1] | 220 |         } | 
|---|
 | 221 |         } | 
|---|
 | 222 |  | 
|---|
| [457] | 223 |     hal_fence(); | 
|---|
 | 224 |  | 
|---|
 | 225 | #if DEBUG_SYS_SEM | 
|---|
 | 226 | tm_end = hal_get_cycles(); | 
|---|
 | 227 | if( DEBUG_SYS_SEM < tm_end ) | 
|---|
| [566] | 228 | printk("\n[DBG] %s : thread %x in process %x exit for %s / cost = %d / cycle %d\n", | 
|---|
 | 229 | __FUNCTION__, this->trdid, process->pid, sys_sem_op_str( operation ), | 
|---|
 | 230 | (uint32_t)(tm_end - tm_start), (uint32_t)tm_end ); | 
|---|
| [457] | 231 | #endif | 
|---|
 | 232 |  | 
|---|
| [1] | 233 |     return 0; | 
|---|
 | 234 |  | 
|---|
 | 235 | }  // end sys_sem() | 
|---|