| 1 | /* | 
|---|
| 2 |  * sys_sem.c - Acces a POSIX unamed semaphore. | 
|---|
| 3 |  *  | 
|---|
| 4 |  * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless | 
|---|
| 5 |  * Copyright (c) 2011,2012 UPMC Sorbonne Universites | 
|---|
| 6 |  * | 
|---|
| 7 |  * This file is part of ALMOS-kernel. | 
|---|
| 8 |  * | 
|---|
| 9 |  * ALMOS-kernel is free software; you can redistribute it and/or modify it | 
|---|
| 10 |  * under the terms of the GNU General Public License as published by | 
|---|
| 11 |  * the Free Software Foundation; version 2.0 of the License. | 
|---|
| 12 |  * | 
|---|
| 13 |  * ALMOS-kernel is distributed in the hope that it will be useful, but | 
|---|
| 14 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 15 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 16 |  * General Public License for more details. | 
|---|
| 17 |  * | 
|---|
| 18 |  * You should have received a copy of the GNU General Public License | 
|---|
| 19 |  * along with ALMOS-kernel; if not, write to the Free Software Foundation, | 
|---|
| 20 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
| 21 |  */ | 
|---|
| 22 |  | 
|---|
| 23 | #include <hal_types.h> | 
|---|
| 24 | #include <hal_uspace. | 
|---|
| 25 | #include <remote_sem.h> | 
|---|
| 26 |  | 
|---|
| 27 | ////////////////////////////////// | 
|---|
| 28 | int sys_sem( void         * vaddr,        // semaphore virtual  address  | 
|---|
| 29 |              uint32_t       operation,    // requested operation type | 
|---|
| 30 |              uint32_t     * value )       // pointer on in/out argument | 
|---|
| 31 | { | 
|---|
| 32 |         uint32_t             data;    | 
|---|
| 33 |         error_t              error; | 
|---|
| 34 |  | 
|---|
| 35 |     thread_t           * this      = CURRENT_THREAD; | 
|---|
| 36 |         process_t          * process   = CURRENT_PROCESS; | 
|---|
| 37 |  | 
|---|
| 38 |     // check vaddr in user vspace | 
|---|
| 39 |         error = vmm_check_address( process , vaddr , sizeof(unsigned long) ); | 
|---|
| 40 |         if( error )  | 
|---|
| 41 |     { | 
|---|
| 42 |         this->errno = error; | 
|---|
| 43 |         return -1; | 
|---|
| 44 |     } | 
|---|
| 45 |  | 
|---|
| 46 |     // check value in user vspace | 
|---|
| 47 |     error = vmm_check_address( process , value , sizeof(int*) ); | 
|---|
| 48 |         if( error )  | 
|---|
| 49 |     { | 
|---|
| 50 |         this->errno = error; | 
|---|
| 51 |         return -1;    | 
|---|
| 52 |     } | 
|---|
| 53 |      | 
|---|
| 54 |     // execute requested operation | 
|---|
| 55 |         switch( operation ) | 
|---|
| 56 |         { | 
|---|
| 57 |         ////////////// | 
|---|
| 58 |             case SEM_INIT: | 
|---|
| 59 |         { | 
|---|
| 60 |             // get argument | 
|---|
| 61 |                     hal_copy_from_uspace( &data , value , sizeof(uint32_t) ); | 
|---|
| 62 |  | 
|---|
| 63 |             // call init function | 
|---|
| 64 |             error = remote_sem_init( (intptr_t)vaddr , data ); | 
|---|
| 65 |  | 
|---|
| 66 |             if ( error ) | 
|---|
| 67 |             { | 
|---|
| 68 |                 this->errno = error; | 
|---|
| 69 |                 return -1; | 
|---|
| 70 |             } | 
|---|
| 71 |             break; | 
|---|
| 72 |         } | 
|---|
| 73 |         ////////////////// | 
|---|
| 74 |         case SEM_GETVALUE: | 
|---|
| 75 |         { | 
|---|
| 76 |             // get extended pointer on remote semaphore | 
|---|
| 77 |             xptr_t sem_xp = remote_sem_from_vaddr( (intptr_t)vaddr ); | 
|---|
| 78 |  | 
|---|
| 79 |             if( sem_xp == XPTR_NULL )     // user error | 
|---|
| 80 |             { | 
|---|
| 81 |                 this->errno = EINVAL; | 
|---|
| 82 |                 return -1; | 
|---|
| 83 |             } | 
|---|
| 84 |             else                          // success | 
|---|
| 85 |             { | 
|---|
| 86 |                 // get semaphore current value | 
|---|
| 87 |                         remote_sem_get_value( sem_xp , &data ); | 
|---|
| 88 |   | 
|---|
| 89 |                 // return value to user | 
|---|
| 90 |                 hal_copy_to_uspace( value , &data , sizeof(uint32_t) ); | 
|---|
| 91 |             } | 
|---|
| 92 |             break; | 
|---|
| 93 |         } | 
|---|
| 94 |         ////////////// | 
|---|
| 95 |             case SEM_WAIT: | 
|---|
| 96 |         {   | 
|---|
| 97 |             // get extended pointer on remote semaphore | 
|---|
| 98 |             xptr_t sem_xp = remote_sem_from_vaddr( (intptr_t)vaddr ); | 
|---|
| 99 |  | 
|---|
| 100 |             if( sem_xp == XPTR_NULL )     // user error | 
|---|
| 101 |             { | 
|---|
| 102 |                 this->errno = EINVAL; | 
|---|
| 103 |                 return -1; | 
|---|
| 104 |             } | 
|---|
| 105 |             else                          // success | 
|---|
| 106 |             { | 
|---|
| 107 |                 // wait semaphore available | 
|---|
| 108 |                 remote_sem_wait( sem_xp ); | 
|---|
| 109 |             } | 
|---|
| 110 |             break; | 
|---|
| 111 |         } | 
|---|
| 112 |         ////////////// | 
|---|
| 113 |             case SEM_POST: | 
|---|
| 114 |         { | 
|---|
| 115 |             // get extended pointer on remote semaphore | 
|---|
| 116 |             xptr_t sem_xp = remote_sem_from_vaddr( (intptr_t)vaddr ); | 
|---|
| 117 |  | 
|---|
| 118 |             if( sem_xp == XPTR_NULL )     // user error | 
|---|
| 119 |             { | 
|---|
| 120 |                 this->errno = EINVAL; | 
|---|
| 121 |                 return -1; | 
|---|
| 122 |             } | 
|---|
| 123 |             else                          // success | 
|---|
| 124 |             { | 
|---|
| 125 |                 // release semaphore  | 
|---|
| 126 |                 remote_sem_post( sem_xp ); | 
|---|
| 127 |             } | 
|---|
| 128 |                         break; | 
|---|
| 129 |         } | 
|---|
| 130 |         ///////////////// | 
|---|
| 131 |             case SEM_DESTROY: | 
|---|
| 132 |         { | 
|---|
| 133 |             // get extended pointer on remote semaphore | 
|---|
| 134 |             xptr_t sem_xp = remote_sem_from_vaddr( (intptr_t)vaddr ); | 
|---|
| 135 |  | 
|---|
| 136 |             if( sem_xp == XPTR_NULL )     // user error | 
|---|
| 137 |             { | 
|---|
| 138 |                 this->errno = EINVAL; | 
|---|
| 139 |                 return -1; | 
|---|
| 140 |             } | 
|---|
| 141 |             else                          // success  | 
|---|
| 142 |             { | 
|---|
| 143 |                 // destroy semaphore | 
|---|
| 144 |                 remote_sem_destroy( sem_xp ); | 
|---|
| 145 |             } | 
|---|
| 146 |             break; | 
|---|
| 147 |             }    | 
|---|
| 148 |         /////// | 
|---|
| 149 |             default:  // undefined operation                        | 
|---|
| 150 |         { | 
|---|
| 151 |                     this->errno = EINVAL; | 
|---|
| 152 |             return -1; | 
|---|
| 153 |         } | 
|---|
| 154 |         } | 
|---|
| 155 |  | 
|---|
| 156 |     return 0; | 
|---|
| 157 |  | 
|---|
| 158 | }  // end sys_sem() | 
|---|