Changeset 23 for trunk/kernel
- Timestamp:
- Jun 18, 2017, 10:06:41 PM (7 years ago)
- Location:
- trunk/kernel
- Files:
-
- 9 added
- 2 deleted
- 95 edited
- 4 copied
- 6 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/devices/dev_dma.c
r3 r23 45 45 void dev_dma_init( chdev_t * chdev ) 46 46 { 47 // get implementation index from DMA chdev descriptor 48 uint32_t impl = chdev->impl; 47 // get implementation & channel from DMA chdev descriptor 48 uint32_t impl = chdev->impl; 49 uint32_t channel = chdev->channel; 50 51 // set chdev name 52 snprintf( chdev->name , 16 , "dma_%d_%x" , channel , local_cxy ); 49 53 50 54 // set field "cmd", "isr", and call the relevant driver init function … … 59 63 assert( false , __FUNCTION__ , "undefined DMA implementation" ); 60 64 } 61 62 // get DMA channel index63 uint32_t channel = chdev->channel;64 65 65 66 // get DMA HWI IRQ index -
trunk/kernel/devices/dev_fbf.c
r14 r23 57 57 uint32_t impl = chdev->impl; 58 58 59 // set chdev name 60 strcpy( chdev->name, "fbf" ); 59 61 // call driver init function 60 62 if( impl == IMPL_FBF_SCL ) … … 136 138 error_t error; 137 139 paddr_t buf_paddr; 138 bool_t ident = CONFIG_KERNEL_IDENTITY;139 140 140 141 thread_t * this = CURRENT_THREAD; // pointer on client thread 141 142 142 143 // Get buffer physical address 143 error = vmm_v2p_translate( ident, buffer , &buf_paddr );144 error = vmm_v2p_translate( CONFIG_KERNEL_IDENTITY_MAP , buffer , &buf_paddr ); 144 145 145 146 if( error ) -
trunk/kernel/devices/dev_icu.c
r14 r23 47 47 uint32_t pti_nr ) 48 48 { 49 // set chdev name 50 snprintf( icu->name , 16 , "icu_%x" , local_cxy ); 51 49 52 // set ICU chdev extension fields 50 53 icu->ext.icu.hwi_nr = hwi_nr; -
trunk/kernel/devices/dev_iob.c
r14 r23 36 36 // get implementation 37 37 uint32_t impl = chdev->impl; 38 39 // set chdev name 40 strcpy( chdev->name , "iob" ); 38 41 39 42 // call driver init function -
trunk/kernel/devices/dev_ioc.c
r14 r23 55 55 uint32_t channel = chdev->channel; 56 56 57 // set chdev name 58 strcpy( chdev->name , "ioc" ); 59 57 60 // set driver specific fields in chdev descriptor and call driver init function 58 61 if( impl == IMPL_IOC_BDV ) … … 64 67 else if( impl == IMPL_IOC_HBA ) 65 68 { 66 chdev->cmd = &soclib_hba_c ommand;69 chdev->cmd = &soclib_hba_cmd; 67 70 chdev->isr = &soclib_hba_isr; 68 71 soclib_hba_init( chdev ); … … 109 112 ////////////////////////////////////////////////////////////////////////////////// 110 113 // This static function is called by dev_ioc_read() & dev_ioc_write() functions. 111 // It builds and registers the command in the calling thread descriptor, after 112 // translation of buffer virtual address to physical address. 114 // It builds and registers the command in the calling thread descriptor. 113 115 // Then, it registers the calling thead in chdev waiting queue. 114 116 // Finally it blocks on the THREAD_BLOCKED_DEV condition and deschedule. 115 117 ////////////////////////////////////i///////////////////////////////////////////// 116 static error_t dev_ioc_access( bool_t to_mem,117 char* buffer,118 uint32_t lba,119 uint32_t count )118 static error_t dev_ioc_access( uint32_t cmd_type, 119 uint8_t * buffer, 120 uint32_t lba, 121 uint32_t count ) 120 122 { 121 123 thread_t * this = CURRENT_THREAD; // pointer on client thread 122 124 123 error_t error;124 paddr_t buf_paddr;125 126 // Get buffer physical address127 error = vmm_v2p_translate( CONFIG_KERNEL_IDENTITY , buffer , &buf_paddr );128 129 if( error ) return EINVAL;130 131 125 ioc_dmsg("\n[INFO] in %s : thread %x in process %x" 132 " for lba = %x / vaddr = %x / paddr = %l/ at cycle %d\n",126 " for lba = %x / buffer = %x / at cycle %d\n", 133 127 __FUNCTION__ , this->trdid , this->process->pid , 134 lba , ( uint32_t)buffer , buf_paddr , hal_time_stamp() );128 lba , (intptr_t)buffer , hal_time_stamp() ); 135 129 136 130 #if USE_IOB // software L2/L3 cache coherence for memory buffer 137 131 138 if ( t o_mem ) dev_mmc_inval( buf_paddr, count<<9 );139 else dev_mmc_sync( buf_paddr, count<<9 );132 if ( type == IOC_READ ) dev_mmc_inval( XPTR( local_cxy , buffer ) , count<<9 ); 133 else dev_mmc_sync ( XPTR( local_cxy , buffer ) , count<<9 ); 140 134 141 135 #endif // end software L2/L3 cache coherence … … 148 142 // register command in calling thread descriptor 149 143 this->command.ioc.dev_xp = dev_xp; 150 this->command.ioc.t o_mem = to_mem;144 this->command.ioc.type = cmd_type; 151 145 this->command.ioc.buf_xp = XPTR( local_cxy , buffer ); 152 146 this->command.ioc.lba = lba; … … 169 163 170 164 //////////////////////////////////////////// 171 error_t dev_ioc_read( char* buffer,165 error_t dev_ioc_read( uint8_t * buffer, 172 166 uint32_t lba, 173 167 uint32_t count ) 174 168 { 175 return dev_ioc_access( true, buffer , lba , count );169 return dev_ioc_access( IOC_READ , buffer , lba , count ); 176 170 } 177 171 178 172 //////////////////////////////////////////// 179 error_t dev_ioc_write( char* buffer,180 uint32_t 181 uint32_t 182 { 183 return dev_ioc_access( false, buffer , lba , count );173 error_t dev_ioc_write( uint8_t * buffer, 174 uint32_t lba, 175 uint32_t count ) 176 { 177 return dev_ioc_access( IOC_WRITE , buffer , lba , count ); 184 178 } 179 180 ///////////////////////////////////////////// 181 error_t dev_ioc_sync_read( uint8_t * buffer, 182 uint32_t lba, 183 uint32_t count ) 184 { 185 // get pointer on calling thread 186 thread_t * this = CURRENT_THREAD; 187 188 #if USE_IOB // software L2/L3 cache coherence for memory buffer 189 190 dev_mmc_inval( XPTR( local_cxy , buffer ) , count<<9 ); 191 192 #endif // end software L2/L3 cache coherence 193 194 // get extended pointer on IOC[0] chdev 195 xptr_t dev_xp = chdev_dir.ioc[0]; 196 197 assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined IOC chdev descriptor" ); 198 199 // register command in calling thread descriptor 200 this->command.ioc.dev_xp = dev_xp; 201 this->command.ioc.type = IOC_SYNC_READ; 202 this->command.ioc.buf_xp = XPTR( local_cxy , buffer ); 203 this->command.ioc.lba = lba; 204 this->command.ioc.count = count; 205 206 // get driver command function 207 cxy_t dev_cxy = GET_CXY( dev_xp ); 208 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp ); 209 dev_cmd_t * cmd = (dev_cmd_t *)hal_remote_lpt( XPTR( dev_cxy , &dev_ptr->cmd ) ); 210 211 // call directly driver command 212 cmd( XPTR( local_cxy , this ) ); 213 214 // return I/O operation status from calling thread descriptor 215 return this->command.ioc.error; 216 } 217 -
trunk/kernel/devices/dev_ioc.h
r14 r23 38 38 * magnetic hard disk or a SD card, that can store blocks of data in a linear array 39 39 * of sectors indexed by a simple lba (logic block address). 40 * It supports two command types: 41 * - READ : move a given number of contiguous blocks from device to a memory buffer. 42 * - WRITE : move a given number of contiguous blocks from a memory buffer to device. 43 * 44 * An I/O operation requires dynamic ressource allocation, and is always blocking for 45 * the client thread. The general scenario is detailed below. 40 * It supports three command types: 41 * - READ : move blocks from device to memory, with a descheduling policy. 42 * - WRITE : move blocks from memory to device, with a descheduling policy. 43 * - SYNC_READ : move blocks from device to memory, with a busy waiting policy. 44 45 * A READ or WRITE operation requires dynamic ressource allocation. The calling thread 46 * is descheduled, and the work is done by the server thread associated to IOC device. 47 * The general scenario is detailed below. 46 48 * A) the client thread start the I/O operation, by calling the dev_ioc_read() 47 49 * or the dev_ioc_write() kernel functions that perform the following actions: … … 50 52 * 3) it access the PIC to link the WTI mailbox to the IOC IRQ. 51 53 * 4) it builds the command descriptor. 52 * 5) it registers in the IOC device waiting queue.54 * 5) it registers in the IOC device waiting queue. 53 55 * 6) itblock on the THREAD_BLOCKED_IO condition and deschedule. 54 56 * B) The server thread attached to the IOC device descriptor handles the commands … … 61 63 * 2) disable the WTI IRQ in the client cluster ICU and update interrupt vector. 62 64 * 3) release the WTI mailbox to the client cluster WTI allocator. 65 * 66 * The SYNC_READ operation is used by the kernel in the initialisation phase. It does 67 * not uses the IOC device waiting queue and server thread, and does not use the IOC IRQ, 68 * but implement a busy-waiting policy for the calling thread. 63 69 *****************************************************************************************/ 64 70 … … 93 99 *****************************************************************************************/ 94 100 101 enum 102 { 103 IOC_READ = 0, 104 IOC_WRITE = 1, 105 IOC_SYNC_READ = 2, 106 }; 107 95 108 typedef struct ioc_command_s 96 109 { 97 xptr_t dev_xp; 98 uint32_t t o_mem; /*! requested operation (WRITE if zero / READ if non-zero)*/110 xptr_t dev_xp; /*! extended pointer on device descriptor */ 111 uint32_t type; /*! IOC_READ / IOC_WRITE / IOC_SYNC_READ */ 99 112 uint32_t lba; /*! first block index */ 100 113 uint32_t count; /*! number of blocks */ … … 119 132 /****************************************************************************************** 120 133 * This blocking function try to tranfer one or several contiguous blocks of data 121 * from the block device to a memory buffer. The corresponding request is actually134 * from the block device to a local memory buffer. The corresponding request is actually 122 135 * registered in the device pending request queue, and the calling thread is descheduled, 123 136 * waiting on transfer completion. It will be resumed by the IRQ signaling completion. 124 137 * It must be called in the client cluster. 125 138 ****************************************************************************************** 126 * @ buffer : local pointer on target buffer in memory .139 * @ buffer : local pointer on target buffer in memory (must be block aligned). 127 140 * @ lba : first block index on device. 128 141 * @ count : number of blocks to transfer. 129 142 * @ returns 0 if success / returns EINVAL if error. 130 143 *****************************************************************************************/ 131 error_t dev_ioc_read( char* buffer,144 error_t dev_ioc_read( uint8_t * buffer, 132 145 uint32_t lba, 133 146 uint32_t count ); … … 135 148 /****************************************************************************************** 136 149 * This blocking function try to tranfer one or several contiguous blocks of data 137 * from a memory buffer to the block device. The corresponding request is actually150 * from a local memory buffer to the block device. The corresponding request is actually 138 151 * registered in the device pending request queue, and the calling thread is descheduled, 139 152 * waiting on transfer completion. It will be resumed by the IRQ signaling completion. 140 153 * It must be called in the client cluster. 141 154 ****************************************************************************************** 142 * @ buffer : local pointer on source buffer in memory .155 * @ buffer : local pointer on source buffer in memory (must be block aligned). 143 156 * @ lba : first block index on device. 144 157 * @ count : number of blocks to transfer. 145 158 * @ returns 0 if success / returns EINVAL if error. 146 159 *****************************************************************************************/ 147 error_t dev_ioc_write( char* buffer,160 error_t dev_ioc_write( uint8_t * buffer, 148 161 uint32_t lba, 149 162 uint32_t count ); 150 163 164 /****************************************************************************************** 165 * This blocking function try to tranfer one or several contiguous blocks of data 166 * from the block device to a memory buffer. 167 * It does not uses the IOC device waiting queue and server thread, and does not use 168 * the IOC IRQ, but call directly the relevant OIC driver, implementing a busy-waiting 169 * policy for the calling thread. 170 * It must be called in the client cluster. 171 ****************************************************************************************** 172 * @ buffer : local pointer on target buffer in memory (must be block aligned). 173 * @ lba : first block index on device. 174 * @ count : number of blocks to transfer. 175 * @ returns 0 if success / returns EINVAL if error. 176 *****************************************************************************************/ 177 error_t dev_ioc_sync_read( uint8_t * buffer, 178 uint32_t lba, 179 uint32_t count ); 180 151 181 #endif /* _DEV_IOC_H */ -
trunk/kernel/devices/dev_mmc.c
r14 r23 43 43 // get implementation from device descriptor 44 44 uint32_t impl = chdev->impl; 45 46 // set chdev name 47 snprintf( chdev->name , 16 , "mmc_%x" , local_cxy ); 45 48 46 49 // set driver specific fields in device descriptor and call driver init function … … 65 68 66 69 ///////////////////////////////////////////////////////////////////////////// 67 // This static function makes some checking, takes the lock granting 68 // exclusive access to MMC peripheral, call the driver to execute the command 70 // This static function is called by all MMC device functions. 71 // It makes some checking, takes the lock granting exclusive 72 // access to MMC peripheral, call the driver to execute the command 69 73 // registered in the calling thread descriptor, and releases the lock. 70 74 ///////////////////////////////////////////////////////////////////////////// 71 static void dev_mmc_access( thread_t * this ) 72 { 73 mmc_dmsg("\n[INFO] %s enters for thread %x in process %x : command = %d\n", 74 __FUNCTION__ , this->trdid , this->process->pid , this->command.mmc.type ); 75 76 // get extended pointer on MMC device 77 xptr_t dev_xp = this->command.mmc.dev_xp; 78 79 assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined MMC device descriptor" ); 75 static error_t dev_mmc_access( thread_t * this ) 76 { 77 // get extended pointer on MMC device descriptor 78 xptr_t dev_xp = this->command.mmc.dev_xp; 79 80 assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "target MMC device undefined" ); 80 81 81 82 // get MMC device cluster identifier & local pointer … … 95 96 remote_spinlock_unlock( XPTR( dev_cxy , &dev_ptr->wait_lock ) ); 96 97 97 mmc_dmsg("\n[INFO] %s completes for thread %x in process %x / error = %d\n",98 __FUNCTION__ , this->trdid , this->process->pid , this->dev.ioc.error );98 // return operation status 99 return this->command.mmc.error; 99 100 100 101 } // end dev_mmc_access() 101 102 102 ///////////////////////////////////////// ///103 error_t dev_mmc_inval( paddr_t buf_paddr,103 ///////////////////////////////////////// 104 error_t dev_mmc_inval( xptr_t buf_xp, 104 105 uint32_t buf_size ) 105 106 { 106 // get calling thread local pointer 107 thread_t * this = CURRENT_THREAD; 108 109 // get target cluster from paddr 110 cxy_t cxy = CXY_FROM_PADDR( buf_paddr ); 111 112 assert( ((buf_paddr & (CONFIG_CACHE_LINE_SIZE -1)) == 0) , __FUNCTION__ , 107 error_t error; 108 109 // get calling thread local pointer 110 thread_t * this = CURRENT_THREAD; 111 112 mmc_dmsg("\n[INFO] %s enters for thread %x in process %x / buf_xp = %l\n", 113 __FUNCTION__ , this->trdid , this->process->pid , buf_xp ); 114 115 // get buffer cluster and local pointer 116 cxy_t buf_cxy = GET_CXY( buf_xp ); 117 void * buf_ptr = GET_PTR( buf_xp ); 118 119 assert( (((intptr_t)buf_ptr & (CONFIG_CACHE_LINE_SIZE -1)) == 0) , __FUNCTION__ , 113 120 "buffer not aligned on cache line" ); 114 121 115 // get extended pointer on MMC device descriptor 116 xptr_t dev_xp = chdev_dir.mmc[cxy]; 117 118 // store command arguments in thread descriptor 119 this->command.mmc.dev_xp = dev_xp; 122 // get buffer physical address 123 paddr_t buf_paddr; 124 error = vmm_v2p_translate( CONFIG_KERNEL_IDENTITY_MAP , buf_ptr , &buf_paddr ); 125 126 assert( (error == 0) , __FUNCTION__ , "cannot get buffer paddr" ); 127 128 // store command arguments in thread descriptor 129 this->command.mmc.dev_xp = chdev_dir.mmc[buf_cxy]; 120 130 this->command.mmc.type = MMC_CC_INVAL; 121 131 this->command.mmc.buf_paddr = buf_paddr; 122 132 this->command.mmc.buf_size = buf_size; 123 133 124 // execute operation 125 dev_mmc_access( this ); 126 127 // return operation status 128 return this->command.mmc.error; 129 } 130 131 ///////////////////////////////////// 132 error_t dev_mmc_sync( paddr_t buf_paddr, 134 // call MMC driver 135 error = dev_mmc_access( this ); 136 137 mmc_dmsg("\n[INFO] %s completes for thread %x in process %x / error = %d\n", 138 __FUNCTION__ , this->trdid , this->process->pid , error ); 139 140 return error; 141 } 142 143 //////////////////////////////////////// 144 error_t dev_mmc_sync( xptr_t buf_xp, 133 145 uint32_t buf_size ) 134 146 { 135 // get calling thread local pointer 136 thread_t * this = CURRENT_THREAD; 137 138 // get target cluster from paddr 139 cxy_t cxy = CXY_FROM_PADDR( buf_paddr ); 140 141 assert( ((buf_paddr & (CONFIG_CACHE_LINE_SIZE -1)) == 0) , __FUNCTION__ , 147 error_t error; 148 149 // get calling thread local pointer 150 thread_t * this = CURRENT_THREAD; 151 152 mmc_dmsg("\n[INFO] %s enters for thread %x in process %x / buf_xp = %l\n", 153 __FUNCTION__ , this->trdid , this->process->pid , buf_xp ); 154 155 // get buffer cluster and local pointer 156 cxy_t buf_cxy = GET_CXY( buf_xp ); 157 void * buf_ptr = GET_PTR( buf_xp ); 158 159 assert( (((intptr_t)buf_ptr & (CONFIG_CACHE_LINE_SIZE -1)) == 0) , __FUNCTION__ , 142 160 "buffer not aligned on cache line" ); 143 161 144 // store command arguments in thread descriptor 145 this->command.mmc.dev_xp = chdev_dir.mmc[cxy]; 162 // get buffer physical address 163 paddr_t buf_paddr; 164 error = vmm_v2p_translate( CONFIG_KERNEL_IDENTITY_MAP , buf_ptr , &buf_paddr ); 165 166 assert( (error == 0) , __FUNCTION__ , "cannot get buffer paddr" ); 167 168 // store command arguments in thread descriptor 169 this->command.mmc.dev_xp = chdev_dir.mmc[buf_cxy]; 146 170 this->command.mmc.type = MMC_CC_SYNC; 147 171 this->command.mmc.buf_paddr = buf_paddr; 148 172 this->command.mmc.buf_size = buf_size; 149 173 150 // execute operation 151 dev_mmc_access( this ); 152 153 // return operation status 154 return this->command.mmc.error; 155 } 174 // call MMC driver 175 error = dev_mmc_access( this ); 176 177 mmc_dmsg("\n[INFO] %s completes for thread %x in process %x / error = %d\n", 178 __FUNCTION__ , this->trdid , this->process->pid , error ); 179 180 return error; 181 } 156 182 157 183 ///////////////////////////////////////// … … 170 196 171 197 // execute operation 172 dev_mmc_access( this ); 173 174 // return operation status 175 return this->command.mmc.error; 198 return dev_mmc_access( this ); 176 199 } 177 200 … … 191 214 192 215 // execute operation 193 dev_mmc_access( this ); 194 195 // return operation status 196 return this->command.mmc.error; 216 return dev_mmc_access( this ); 197 217 } 198 218 … … 212 232 213 233 // execute operation 214 dev_mmc_access( this ); 215 216 // return operation status 217 return this->command.mmc.error; 218 } 219 234 return dev_mmc_access( this ); 235 } 236 -
trunk/kernel/devices/dev_mmc.h
r14 r23 81 81 typedef struct mmc_command_s 82 82 { 83 xptr_t dev_xp; /*! extended pointer on t he relevant MMC device descriptor*/83 xptr_t dev_xp; /*! extended pointer on target MMC device descriptor */ 84 84 uint32_t type; /*! CC_INVAL / CC_SYNC / GET_ERROR / SET_ERROR / GET_INSTRU */ 85 paddr_t buf_paddr; /*! buffer physical address (used by INVAL/SYNC)*/86 uint32_t buf_size; /*! buffer size in bytes (used by INVAL/SYNC)*/87 uint32_t reg_index; /*! register index in MMC peripheral (used by SET/GET)*/88 uint32_t * reg_ptr; /*! local pointer on src/dst buffer (used by SET/GET)*/85 paddr_t buf_paddr; /*! physical address of memory buffer (used by INVAL/SYNC) */ 86 uint32_t buf_size; /*! buffer size in bytes (used by INVAL/SYNC) */ 87 uint32_t reg_index; /*! register index in MMC peripheral (used by SET/GET) */ 88 uint32_t * reg_ptr; /*! local pointer on src/dst buffer (used by SET/GET) */ 89 89 error_t error; /*! operation status (0 if success) */ 90 90 } … … 106 106 * to access both the MMC device descriptor, and the L2 cache configuration interface. 107 107 ***************************************************************************************** 108 * @ buf_ paddr : buffer local physical addresse.108 * @ buf_xp : extended pointer on memory buffer. 109 109 * @ buf_size : buffer size (bytes). 110 110 * @ return 0 if success / return EINVAL if failure 111 111 ****************************************************************************************/ 112 error_t dev_mmc_inval( paddr_t buf_paddr,113 uint32_t buf_size );112 error_t dev_mmc_inval( xptr_t buf_xp, 113 uint32_t buf_size ); 114 114 115 115 /***************************************************************************************** … … 119 119 * to access both the MMC device descriptor, and the L2 cache configuration interface. 120 120 ***************************************************************************************** 121 * @ buf_ paddr : buffer local physical addresse.121 * @ buf_xp : extended pointer on memory buffer. 122 122 * @ buf_size : buffer size (bytes). 123 123 * @ return 0 if success / return EINVAL if failure 124 124 ****************************************************************************************/ 125 error_t dev_mmc_sync( paddr_t buf_paddr,125 error_t dev_mmc_sync( xptr_t buf_xp, 126 126 uint32_t buf_size ); 127 127 -
trunk/kernel/devices/dev_nic.c
r3 r23 51 51 uint32_t channel = chdev->channel; 52 52 53 // set chdev name 54 snprintf( chdev->name , 16 , "nic_%d" , chdev->channel ); 55 53 56 // set driver specific fields in chdev descriptor and call driver init function 54 57 if( impl == IMPL_NIC_SOC ) -
trunk/kernel/devices/dev_pic.c
r3 r23 49 49 uint32_t impl = chdev->impl; 50 50 51 // set chdev name 52 strcpy( chdev->name , "pic" ); 53 51 54 // call the relevant driver init function 52 55 if( impl == IMPL_PIC_SOC ) -
trunk/kernel/devices/dev_txt.c
r16 r23 50 50 uint32_t impl = chdev->impl; 51 51 uint32_t channel = chdev->channel; 52 53 // set chdev name 54 snprintf( chdev->name , 16 , "txt_%d" , chdev->channel ); 52 55 53 56 // set fields "cmd", "isr", and call driver init function … … 164 167 xptr_t dev_xp = chdev_dir.txt[channel]; 165 168 169 assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined TXT0 chdev descriptor" ); 170 166 171 // register command in calling thread 167 172 this->command.txt.dev_xp = dev_xp; -
trunk/kernel/devices/dev_txt.h
r14 r23 106 106 107 107 /****************************************************************************************** 108 * This blocking function writes a character stringon the terminal identified108 * This blocking function writes characters on the terminal identified 109 109 * by the "channel" argument. The corresponding request is actually registered in the 110 110 * chdev requests queue, and the calling thread is descheduled, blocked until -
trunk/kernel/drivers/soclib/soclib_bdv.c
r4 r23 53 53 void __attribute__ ((noinline)) soclib_bdv_cmd( xptr_t th_xp ) 54 54 { 55 uint32_t to_mem; // command argument55 uint32_t cmd_type; // IOC_READ / IOC_WRITE / IOC_SYNC_READ 56 56 uint32_t lba; // command argument 57 57 uint32_t count; // command argument … … 64 64 65 65 // get command arguments and extended pointer on IOC device 66 to_mem = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.to_mem) );67 lba = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.lba ) );68 count = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.count ) );69 buf_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->command.ioc.buf_xp ) );70 dev_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->command.ioc.dev_xp ) );66 cmd_type = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.type ) ); 67 lba = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.lba ) ); 68 count = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.count ) ); 69 buf_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->command.ioc.buf_xp ) ); 70 dev_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->command.ioc.dev_xp ) ); 71 71 72 72 // get IOC device cluster and local pointer … … 85 85 uint32_t buf_msb = (uint32_t)(buf_xp>>32); 86 86 87 // get access type 88 uint32_t type = to_mem ? BDV_OP_READ : BDV_OP_WRITE; 87 // set operation 88 uint32_t op; 89 if( cmd_type == IOC_WRITE ) op = BDV_OP_WRITE; 90 else op = BDV_OP_READ; 89 91 90 92 // set SOCLIB_BDV registers to start one I/O operation … … 94 96 hal_remote_sw( XPTR( bdv_cxy , bdv_ptr + BDV_LBA_REG ) , lba ); 95 97 hal_remote_sw( XPTR( bdv_cxy , bdv_ptr + BDV_COUNT_REG ) , count ); 96 hal_remote_sw( XPTR( bdv_cxy , bdv_ptr + BDV_OP_REG ) , type);98 hal_remote_sw( XPTR( bdv_cxy , bdv_ptr + BDV_OP_REG ) , op ); 97 99 98 // Block and deschedule server thread 99 thread_block( CURRENT_THREAD , THREAD_BLOCKED_DEV_ISR ); 100 sched_yield(); 100 // waiting policy depends on the command type 101 102 if( cmd_type == IOC_SYNC_READ ) // polling policy 103 { 104 uint32_t status; 105 while (1) 106 { 107 status = hal_remote_lw( XPTR( bdv_cxy , bdv_ptr + BDV_STATUS_REG ) ); 108 109 if( status == BDV_READ_SUCCESS ) // successfully completed 110 { 111 hal_remote_sw( XPTR( th_cxy , &th_ptr->command.ioc.error ) , 0 ); 112 break; 113 } 114 else if( status == BDV_BUSY ) // non completed 115 { 116 continue; 117 } 118 else // error reported 119 { 120 hal_remote_sw( XPTR( th_cxy , &th_ptr->command.ioc.error ) , 1 ); 121 break; 122 } 123 } 124 } 125 else // descheduling + IRQ policy 126 { 127 thread_block( CURRENT_THREAD , THREAD_BLOCKED_DEV_ISR ); 128 sched_yield(); 129 } 101 130 102 131 } // end soclib_bdv_cmd() -
trunk/kernel/drivers/soclib/soclib_hba.c
r4 r23 72 72 chdev->ext.ioc.count = block_count; 73 73 74 // reset SOCLIB_HBA driver global variables 74 // activate HBA interrupts 75 hal_remote_sw( XPTR( hba_cxy , hba_ptr + HBA_PXIE_REG ) , 0x1 ); 76 77 // reset SOCLIB_HBA driver global variable 75 78 hba_active_slots = 0; 76 79 … … 78 81 79 82 80 ////////////////////////////////////////////////////////////// ////81 void __attribute__ ((noinline)) soclib_hba_c ommand( xptr_t th_xp )83 ////////////////////////////////////////////////////////////// 84 void __attribute__ ((noinline)) soclib_hba_cmd( xptr_t th_xp ) 82 85 { 83 86 84 uint32_t to_mem; // to_mem : command argument87 uint32_t cmd_type; // IOC_READ / IOC_WRITE / IOC_SYNC_READ 85 88 uint32_t lba; // lba : command argument 86 89 uint32_t count; // count : command argument 87 90 xptr_t buf_xp; // buffer : command argument 88 91 xptr_t dev_xp; // device : command argument 92 89 93 uint32_t cmd_id; // current slot index in command bit_vector 90 94 hba_cmd_desc_t * cmd_desc; // command descriptor pointer 91 95 hba_cmd_table_t * cmd_table; // command table pointer 96 92 97 bool_t found; 93 98 uint32_t iter; … … 98 103 99 104 // get command arguments and extended pointer on IOC device 100 to_mem = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.to_mem) );105 cmd_type = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.type ) ); 101 106 lba = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.lba ) ); 102 107 count = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.count ) ); … … 135 140 } 136 141 137 if( found ) // register and starts the I/O operation142 if( found ) // slot available in SOCLIB_HBA 138 143 { 139 144 // compute pointers on command descriptor and command table … … 157 162 cmd_desc->prdtl[0] = 1; 158 163 cmd_desc->prdtl[1] = 0; 159 if( to_mem ) cmd_desc->flag[0] = 0x00;160 else cmd_desc->flag[0] = 0x40;164 if( cmd_type == IOC_WRITE ) cmd_desc->flag[0] = 0x40; 165 else cmd_desc->flag[0] = 0x00; 161 166 162 167 #if USE_IOB // software L2/L3 cache coherence 163 168 164 // compute physical addresses 165 paddr_t cmd_desc_paddr; // command descriptor physical address 166 paddr_t cmd_table_paddr; // command table header physical address 167 bool_t ident = CONFIG_KERNEL_IDENTITY; 168 169 error = vmm_v2p_translate( ident , cmd_table , &cmd_table_paddr ); 170 if( error ) 171 { 172 printk("\n[PANIC] in %s : cannot get paddr fo cmd_table\n", __FUNCTION__ ); 173 hal_core_sleep() 174 } 175 176 error = vmm_v2p_translate( ident , cmd_desc , &cmd_desc_paddr ); 177 if( error ) 178 { 179 printk("\n[PANIC] in %s : cannot get paddr fo cmd_desc\n", __FUNCTION__ ); 180 hal_core_sleep() 181 } 182 183 // update L3 for command table 184 dev_mmc_sync( cmd_table_paddr , sizeof(hba_cmd_table_t) ); 185 186 // update L3 for command descriptor 187 dev_mmc_sync( cmd_desc_paddr , sizeof(hba_cmd_desc_t) ); 169 dev_mmc_sync( cmd_table , sizeof(hba_cmd_table_t) ); 170 dev_mmc_sync( cmd_desc , sizeof(hba_cmd_desc_t) ); 188 171 189 172 #endif // end software L2/L3 cache coherence 190 191 // activates HBA interrupts192 hal_remote_sw( XPTR( hba_cxy , hba_ptr + HBA_PXIE_REG ) , 0x1 );193 173 194 174 // set hba_owner_thread[slot] 195 175 hba_owner_thread[cmd_id] = th_xp; 196 176 177 // register slot in bit_vector 178 hba_active_slots |= 1<<cmd_id; 179 197 180 // set HBA_PXCI_REG to start transfer 198 181 hal_remote_sw( XPTR( hba_cxy , hba_ptr + HBA_PXCI_REG ) , 1<<cmd_id ); 199 182 200 ioc_dmsg("INFO in %s : thread %x / buffer = %llx at cycle %d\n",201 __FUNCTION__ , hal_remote_lw( XPTR( th_cxy , &th_ptr->trdid ) ) ,202 buf_xp , hal_time_stamp() );203 204 183 // exit the while 205 184 break; 206 185 } 207 else // deschedule if no slot available in SOCLIB_HBA 208 { 209 sched_yield(); 210 } 211 } // end while 186 else // no slot available in SOCLIB_HBA 187 { 188 if( cmd_type == IOC_SYNC_READ ) // fatal if synchronous access 189 { 190 printk("\n[PANIC] in %s : no slot available for a SYNC_READ\n", __FUNCTION__ ); 191 hal_core_sleep(); 192 } 193 else // retry if asynchronous access. 194 { 195 sched_yield(); 196 } 197 } 198 } // end while to get a slot 199 200 // waiting policy depends on the command type 201 202 if( cmd_type == IOC_SYNC_READ ) // polling, busy waiting 203 { 204 uint32_t pxis; 205 uint32_t pxci; 206 uint32_t error; 207 uint32_t fault_id; 208 while(1) 209 { 210 pxis = hal_remote_lw( XPTR( hba_cxy , hba_ptr + HBA_PXIS_REG ) ); 211 pxci = hal_remote_lw( XPTR( hba_cxy , hba_ptr + HBA_PXCI_REG ) ); 212 error = (pxis & 0x40000000) >> 30; 213 fault_id = (pxis & 0x1F000000) >> 24; 214 215 if( (pxci & (1<<cmd_id)) == 0 ) // completed 216 { 217 // release slot 218 hba_active_slots &= ~(1<<cmd_id); 219 220 // set operation status in client thread command 221 if( error && (fault_id == cmd_id) ) 222 { 223 hal_remote_sw( XPTR( th_cxy , &th_ptr->command.ioc.error ) , 1 ); 224 } 225 else 226 { 227 hal_remote_sw( XPTR( th_cxy , &th_ptr->command.ioc.error ) , 0 ); 228 } 229 230 // exit while 231 break; 232 } 233 } 234 } 235 else // descheduling + IRQ 236 { 237 thread_block( CURRENT_THREAD , THREAD_BLOCKED_DEV_ISR ); 238 sched_yield(); 239 } 212 240 213 241 } // end soclib_hba_cmd() … … 229 257 uint32_t * hba_ptr = (uint32_t *)GET_PTR( chdev->base ); 230 258 231 // get HBA_PXIS_REG and HBA_PX IS_REG current values259 // get HBA_PXIS_REG and HBA_PXCI_REG current values 232 260 uint32_t current_pxis = hal_remote_lw( XPTR( hba_cxy , hba_ptr + HBA_PXIS_REG ) ); 233 261 uint32_t current_pxci = hal_remote_lw( XPTR( hba_cxy , hba_ptr + HBA_PXCI_REG ) ); -
trunk/kernel/drivers/soclib/soclib_hba.h
r4 r23 145 145 * @ xp_thread : extended pointer on the client thread. 146 146 *******************************************************************************************/ 147 extern void soclib_hba_c ommand( xptr_t thread_xp );147 extern void soclib_hba_cmd( xptr_t thread_xp ); 148 148 149 149 /******************************************************************************************** -
trunk/kernel/kern/chdev.c
r16 r23 32 32 #include <rpc.h> 33 33 #include <chdev.h> 34 #include <devfs.h> 34 35 35 36 //////////////////////////////////////////// -
trunk/kernel/kern/chdev.h
r16 r23 41 41 * This file defines the kernel representation of a generic (i.e. implementation 42 42 * independant) Channel Device descriptor (in brief "chdev"). 43 * ALMOS-MKH supports multi-channels peripherals, and defines one separated descriptor44 * for each channel (and for each RX/TX direction for the NIC device).43 * ALMOS-MKH supports multi-channels peripherals, and defines one separated chdev 44 * descriptor for each channel (and for each RX/TX direction for the NIC device). 45 45 * Each chdev contains a waiting queue, registering the "client threads" requests, 46 46 * and an associated "server thread", handling these requests. … … 107 107 /****************************************************************************************** 108 108 * This structure defines a chdev descriptor. 109 * There is one chdev descriptor per channel.109 * For multi-channels device, there is one chdev descriptor per channel. 110 110 * This structure is NOT replicated, and can be located in any cluster. 111 111 * One kernel thread, in charge of handling the commands registered in the waiting queue … … 120 120 uint32_t channel; /*! channel index */ 121 121 bool_t is_rx; /*! relevant for NIC peripheral channels only */ 122 xptr_t base; /*! extended pointer on channel segment */ 122 xptr_t base; /*! extended pointer on channel segment paddr */ 123 char name[16]; /*! name (required by DEVFS) */ 123 124 124 125 dev_cmd_t * cmd; /*! local pointer on driver command function */ -
trunk/kernel/kern/cluster.c
r19 r23 4 4 * Author Ghassan Almaless (2008,2009,2010,2011,2012) 5 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016 )6 * Alain Greiner (2016,2017) 7 7 * 8 8 * Copyright (c) UPMC Sorbonne Universites … … 49 49 /////////////////////////////////////////////////////////////////////////////////////////// 50 50 51 process_t process_zero; // allocated in kernel_init.c file51 extern process_t process_zero; // allocated in kernel_init.c file 52 52 53 53 … … 121 121 122 122 // initialise local_list in process manager 123 spinlock_init( &cluster->pmgr.local_lock);124 list_root_init( &cluster->pmgr.local_root);123 remote_spinlock_init( XPTR( local_cxy , &cluster->pmgr.local_lock ) ); 124 xlist_root_init( XPTR( local_cxy , &cluster->pmgr.local_root ) ); 125 125 cluster->pmgr.local_nr = 0; 126 126 … … 162 162 { 163 163 cluster_t * cluster = LOCAL_CLUSTER; 164 hal_atomic_ inc( &cluster->cores_in_kernel);164 hal_atomic_add( &cluster->cores_in_kernel , 1 ); 165 165 } 166 166 … … 169 169 { 170 170 cluster_t * cluster = LOCAL_CLUSTER; 171 hal_atomic_ dec( &cluster->cores_in_kernel);171 hal_atomic_add( &cluster->cores_in_kernel , -1 ); 172 172 } 173 173 … … 199 199 xptr_t cluster_get_reference_process_from_pid( pid_t pid ) 200 200 { 201 xptr_t xp; // extended pointer onprocess descriptor201 xptr_t ref_xp; // extended pointer on reference process descriptor 202 202 203 203 cluster_t * cluster = LOCAL_CLUSTER; … … 208 208 209 209 // Check valid PID 210 if( lpid >= CONFIG_MAX_PROCESS_PER_CLUSTER ) 211 { 212 printk("\n[PANIC] in %s : illegal PID\n", __FUNCTION__ ); 213 hal_core_sleep(); 214 } 210 if( lpid >= CONFIG_MAX_PROCESS_PER_CLUSTER ) return XPTR_NULL; 215 211 216 212 if( local_cxy == owner_cxy ) // local cluster is owner cluster 217 213 { 218 xp = cluster->pmgr.pref_tbl[lpid];214 ref_xp = cluster->pmgr.pref_tbl[lpid]; 219 215 } 220 216 else // use a remote_lwd to access owner cluster 221 217 { 222 xp = (xptr_t)hal_remote_lwd( XPTR( owner_cxy , &cluster->pmgr.pref_tbl[lpid] ) );223 } 224 225 return xp;218 ref_xp = (xptr_t)hal_remote_lwd( XPTR( owner_cxy , &cluster->pmgr.pref_tbl[lpid] ) ); 219 } 220 221 return ref_xp; 226 222 } 227 223 … … 303 299 process_t * cluster_get_local_process_from_pid( pid_t pid ) 304 300 { 305 process_t * ret = NULL; 306 list_entry_t * root = &LOCAL_CLUSTER->pmgr.local_root; 307 list_entry_t * iter; 308 process_t * process; 309 310 LIST_FOREACH( root , iter ) 311 { 312 process = LIST_ELEMENT( iter , process_t , local_list ); 313 if( process->pid == pid ) 301 xptr_t process_xp; 302 process_t * process_ptr; 303 xptr_t root_xp; 304 xptr_t iter_xp; 305 bool_t found; 306 307 found = false; 308 root_xp = XPTR( local_cxy , &LOCAL_CLUSTER->pmgr.local_root ); 309 310 XLIST_FOREACH( root_xp , iter_xp ) 311 { 312 process_xp = XLIST_ELEMENT( iter_xp , process_t , local_list ); 313 process_ptr = (process_t *)GET_PTR( process_xp ); 314 if( process_ptr->pid == pid ) 314 315 { 315 ret = process;316 found = true; 316 317 break; 317 318 } 318 319 } 319 return ret; 320 321 if (found ) return process_ptr; 322 else return NULL; 320 323 321 324 } // end cluster_get_local_process_from_pid() … … 327 330 328 331 // get lock protecting the process manager local list 329 spinlock_lock( &pm->local_lock ); 330 331 list_add_first( &pm->local_root , &process->local_list ); 332 remote_spinlock_lock( XPTR( local_cxy , &pm->local_lock ) ); 333 334 xlist_add_first( XPTR( local_cxy , &pm->local_root ), 335 XPTR( local_cxy , &process->local_list ) ); 332 336 pm->local_nr++; 333 337 334 338 // release lock protecting the process manager local list 335 spinlock_unlock( &pm->local_lock);339 remote_spinlock_unlock( XPTR( local_cxy , &pm->local_lock ) ); 336 340 } 337 341 … … 342 346 343 347 // get lock protecting the process manager local list 344 spinlock_lock( &pm->local_lock);345 346 list_unlink( &process->local_list);348 remote_spinlock_lock( XPTR( local_cxy , &pm->local_lock ) ); 349 350 xlist_unlink( XPTR( local_cxy , &process->local_list ) ); 347 351 pm->local_nr--; 348 352 349 353 // release lock protecting the process manager local list 350 spinlock_unlock( &pm->local_lock);354 remote_spinlock_unlock( XPTR( local_cxy , &pm->local_lock ) ); 351 355 } 352 356 -
trunk/kernel/kern/cluster.h
r19 r23 4 4 * authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016 )6 * Alain Greiner (2016,2017) 7 7 * 8 8 * Copyright (c) UPMC Sorbonne Universites … … 49 49 struct core_s; 50 50 struct process_s; 51 struct device_s;52 51 53 52 … … 56 55 * For any process P, the process descriptor is replicated in all clusters containing 57 56 * at least one thread of process P, but only the "reference" cluster descriptor contains 58 * the reference (complete) structures such as the GPT, the VSL, or the FDT. 59 * The "owner" cluster is in charge to allocate a lpid (local process index), 60 * for all process owned by a cluster K, and to register the "reference" cluster for 61 * all process owned by K. 57 * the reference (complete) GPT, VSL, and FDT structures. 58 * The "owner" cluster K is in charge to allocate a lpid (local process index), 59 * to the owned processes, and to register the "reference" cluster for these processes. 62 60 * 63 61 * Warning : the "owner" cluster, and the "reference" cluster can be different clusters. 64 62 * 65 63 * The process manager of a cluster K maintains three structures: 66 * 1) The pref_tbl[] is an array indexed by lpid , for all processes owned by cluster K.64 * 1) The pref_tbl[] is an array indexed by lpid. There is one entry per owned process. 67 65 * Each entry contains an extended pointer on the reference process descriptor. 66 * 68 67 * 2) The local_root is the root of the local list of process descriptors in cluster K. 69 68 * A process descriptor P is present in K, as soon as P has a thread in cluster K. 70 * 3) The copies_root[] array is indexed by lpid. Each entry contains the root of 71 * the xlist of copies for a given process owned by cluster K. 69 * 70 * 3) The copies_root[] array is indexed by lpid. There is one entry per owned process, 71 * and each each entry contains the root of the xlist of copies for this process. 72 72 ******************************************************************************************/ 73 73 … … 78 78 uint32_t pref_nr; /*! number of processes owned by cluster */ 79 79 80 list_entry_tlocal_root; /*! root of list of process in cluster */81 spinlock_tlocal_lock; /*! lock protecting access to local list */80 xlist_entry_t local_root; /*! root of list of process in cluster */ 81 remote_spinlock_t local_lock; /*! lock protecting access to local list */ 82 82 uint32_t local_nr; /*! number of process in cluster */ 83 83 … … 96 96 typedef struct cluster_s 97 97 { 98 spinlock_t kcm_lock; /*! local, protect creation of KCM allocators*/98 spinlock_t kcm_lock; /*! local, protect creation of KCM allocators */ 99 99 100 100 // global parameters 101 101 102 uint32_t paddr_width; /*! numer of bits in physical address*/103 uint32_t x_width; /*! number of bits to code x_size (can be 0)*/104 uint32_t y_width; /*! number of bits to code y_size (can be 0)*/105 uint32_t x_size; /*! number of clusters in a row (can be 1)*/106 uint32_t y_size; /*! number of clusters in a column (can be 1)*/107 cxy_t io_cxy; /*! io cluster identifier*/108 uint32_t dqdt_root_level; /*! index of root node in dqdt_tbl[]*/102 uint32_t paddr_width; /*! numer of bits in physical address */ 103 uint32_t x_width; /*! number of bits to code x_size (can be 0) */ 104 uint32_t y_width; /*! number of bits to code y_size (can be 0) */ 105 uint32_t x_size; /*! number of clusters in a row (can be 1) */ 106 uint32_t y_size; /*! number of clusters in a column (can be 1) */ 107 cxy_t io_cxy; /*! io cluster identifier */ 108 uint32_t dqdt_root_level; /*! index of root node in dqdt_tbl[] */ 109 109 110 110 // local parameters 111 111 112 uint32_t cores_nr; /*! number of cores in cluster*/113 uint32_t cores_in_kernel; /*! number of cores currently in kernel mode*/112 uint32_t cores_nr; /*! number of cores in cluster */ 113 uint32_t cores_in_kernel; /*! number of cores currently in kernel mode */ 114 114 115 115 core_t core_tbl[CONFIG_MAX_LOCAL_CORES]; /*! embedded cores */ 116 116 117 ppm_t ppm; /*! embedded kernel page manager*/118 khm_t khm; /*! embedded kernel heap manager*/119 kcm_t kcm; /*! embedded kernel cache manager (for KCMs)*/117 ppm_t ppm; /*! embedded kernel page manager */ 118 khm_t khm; /*! embedded kernel heap manager */ 119 kcm_t kcm; /*! embedded kernel cache manager (for KCMs) */ 120 120 121 121 kcm_t * kcm_tbl[KMEM_TYPES_NR]; /*! pointers on allocated KCMs */ 122 122 123 uint32_t ram_size; /*! physical memory size */ 124 uint32_t ram_base; /*! physical memory base (local address) */ 125 126 rpc_fifo_t rpc_fifo; /*! cluster RPC fifo (shared) */ 127 list_entry_t devlist; /*! root of list of devices in cluster */ 128 struct device_s * icu; /*! pointer on local XCU device */ 129 130 int32_t pages_var; /*! pages number increment from last update */ 131 int32_t threads_var; /*! threads number increment from last update */ 123 uint32_t ram_size; /*! physical memory size */ 124 uint32_t ram_base; /*! physical memory base (local address) */ 125 126 rpc_fifo_t rpc_fifo; /*! cluster RPC fifo (shared) */ 127 list_entry_t devlist; /*! root of list of devices in cluster */ 128 129 int32_t pages_var; /*! pages number increment from last DQQT update */ 130 int32_t threads_var; /*! threads number increment from last DQDT update */ 132 131 133 132 dqdt_node_t dqdt_tbl[CONFIG_MAX_DQDT_DEPTH]; /*! embedded DQDT nodes */ 134 133 135 pmgr_t pmgr; /*! embedded process manager*/134 pmgr_t pmgr; /*! embedded process manager */ 136 135 137 136 char name[CONFIG_SYSFS_NAME_LEN]; … … 192 191 /****************************************************************************************** 193 192 * This function returns an extended pointer on the reference process descriptor 194 * from the process PID. It can be called by any thread running in any cluster,195 * as it uses a RPC to the owner cluster if the current cluster is not the owner.193 * from the process PID. This PID can be be different from the calling thread process. 194 * It can be called by any thread running in any cluster, 196 195 ****************************************************************************************** 197 196 * @ pid : process identifier. 198 * @ return extended pointer on the reference process descriptor.197 * @ return extended pointer on reference process if success / return XPTR_NULL if error. 199 198 *****************************************************************************************/ 200 199 xptr_t cluster_get_reference_process_from_pid( pid_t pid ); -
trunk/kernel/kern/core.c
r19 r23 38 38 #include <core.h> 39 39 40 // TODO #include <sysfs.h>41 42 40 ///////////////////////////////// 43 41 void core_init( core_t * core, … … 100 98 //////////////////////////////////// 101 99 void core_get_time( core_t * core, 102 uint32_t * tm_ ms,100 uint32_t * tm_s, 103 101 uint32_t * tm_us ) 104 102 { -
trunk/kernel/kern/do_syscall.c
r16 r23 2 2 * do_syscall.c - architecture independant entry-point for system calls. 3 3 * 4 * A Uthor Alain Greiner (2016)4 * Author Alain Greiner (2016) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 31 31 32 32 ///////////////////////////////////////////////////////////////////////////////////////////// 33 // This array of pointers define the kernel functions for syscalls. 33 ///////////////////////////////////////////////////////////////////////////////////////////// 34 static inline int sys_undefined() 35 { 36 printk("\n[PANIC] in %s : undefined system call\n", __FUNCTION__ ); 37 hal_core_sleep(); 38 return 0; 39 } 40 41 ///////////////////////////////////////////////////////////////////////////////////////////// 42 // This array of pointers define the kernel functions implementing the syscalls. 34 43 // It must be kept consistent with the enum in syscalls.h 35 44 ///////////////////////////////////////////////////////////////////////////////////////////// … … 39 48 static const sys_func_t syscall_tbl[SYSCALLS_NR] = 40 49 { 41 sys_thread_exit, // 0 42 sys_mmap, // 1 43 sys_thread_create, // 2 44 sys_thread_join, // 3 45 sys_thread_detach, // 4 46 sys_thread_yield, // 5 47 sys_sem, // 6 48 sys_cond_var, // 7 49 sys_barrier, // 8 50 sys_rwlock, // 9 51 sys_thread_sleep, // 10 52 sys_thread_wakeup, // 11 53 sys_open, // 12 54 sys_creat, // 13 55 sys_read, // 14 56 sys_write, // 15 57 sys_lseek, // 16 58 sys_close, // 17 59 sys_unlink, // 18 60 sys_pipe, // 19 61 sys_chdir, // 20 62 sys_mkdir, // 21 63 sys_mkfifo, // 22 64 sys_opendir, // 23 65 sys_readdir, // 24 66 sys_closedir, // 25 67 sys_getcwd, // 26 68 sys_clock, // 27 69 sys_alarm, // 28 70 sys_dma_memcpy, // 29 71 sys_utls, // 30 72 sys_notAvailable, // 31 Reserved for sigreturn TODO ??? 73 sys_signal, // 32 74 sys_sigreturn_setup, // 33 75 sys_kill, // 34 76 sys_getpid, // 35 77 sys_fork, // 36 78 sys_exec, // 37 79 sys_thread_getattr, // 38 80 sys_ps, // 39 81 sys_madvise, // 40 82 sys_mcntl, // 41 83 sys_stat, // 42 84 sys_thread_migrate, // 43 85 sys_sbrk, // 44 86 sys_rmdir, // 45 87 sys_ftime, // 46 88 sys_chmod, // 47 89 sys_fsync, // 48 90 sys_gettimeofday, // 49 91 sys_times // 50 50 sys_thread_exit, // 0 51 sys_mmap, // 1 52 sys_thread_create, // 2 53 sys_thread_join, // 3 54 sys_thread_detach, // 4 55 sys_thread_yield, // 5 56 sys_sem, // 6 57 sys_condvar, // 7 58 sys_barrier, // 8 59 sys_mutex, // 9 60 sys_thread_sleep, // 10 61 sys_thread_wakeup, // 11 62 sys_open, // 12 63 sys_creat, // 13 64 sys_read, // 14 65 sys_write, // 15 66 sys_lseek, // 16 67 sys_close, // 17 68 sys_unlink, // 18 69 sys_pipe, // 19 70 sys_chdir, // 20 71 sys_mkdir, // 21 72 sys_mkfifo, // 22 73 sys_opendir, // 23 74 sys_readdir, // 24 75 sys_closedir, // 25 76 sys_getcwd, // 26 77 sys_clock, // 27 78 sys_alarm, // 28 79 sys_rmdir, // 29 80 sys_utls, // 30 81 sys_chmod, // 31 82 sys_signal, // 32 83 sys_gettimeofday, // 33 84 sys_kill, // 34 85 sys_getpid, // 35 86 sys_fork, // 36 87 sys_exec, // 37 88 sys_stat, // 38 89 sys_trace, // 39 92 90 }; 93 91 -
trunk/kernel/kern/dqdt.c
r19 r23 150 150 151 151 // set child[3] extended pointer (coordinates may overflow) 152 if ( (level > 0) && ((x + (1<<(level-1))) < x_size) && ((y + (1<<(level-1))) < y_size) ) 152 if ( (level > 0) && 153 ((x + (1<<(level-1))) < x_size) && 154 ((y + (1<<(level-1))) < y_size) ) 153 155 { 154 156 c_cxy = local_cxy + ((1<<(level-1))<<y_width) + (1<<(level-1)); -
trunk/kernel/kern/kernel_init.c
r19 r23 2 2 * kernel_init.c - kernel parallel initialization 3 3 * 4 * Authors : Alain Greiner (2016)5 * Mohamed Lamine Karaoui (2016)4 * Authors : Mohamed Lamine Karaoui (2015) 5 * Alain Greiner (2016,2017) 6 6 * 7 7 * Copyright (c) Sorbonne Universites … … 53 53 #include <vfs.h> 54 54 #include <soclib_tty.h> 55 56 // TODO #include <devfs.h> 55 #include <devfs.h> 56 57 57 // TODO #include <sysfs.h> 58 58 … … 601 601 // @ return 0 if success / return EINVAL if not found. 602 602 /////////////////////////////////////////////////////////////////////////////////////////// 603 static error_t core_get_identifiers( boot_info_t * info,604 uint32_t* lid,603 static error_t get_core_identifiers( boot_info_t * info, 604 lid_t * lid, 605 605 cxy_t * cxy, 606 606 gid_t * gid ) … … 637 637 void kernel_init( boot_info_t * info ) 638 638 { 639 uint32_tcore_lid = -1; // running core local index639 lid_t core_lid = -1; // running core local index 640 640 cxy_t core_cxy = -1; // running core cluster identifier 641 641 gid_t core_gid; // running core hardware identifier … … 646 646 647 647 // all cores get core identifiers 648 error = core_get_identifiers( info,648 error = get_core_identifiers( info, 649 649 &core_lid, 650 650 &core_cxy, … … 664 664 ///////////////////////////////////////////////////////////////////////////////// 665 665 666 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 0 \n",667 __FUNCTION__ , core_cxy , core_lid );666 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 0 at cycle %d\n", 667 __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() ); 668 668 669 669 // all cores check core identifiers … … 675 675 hal_core_sleep(); 676 676 } 677 else678 {679 kinit_dmsg("\n[INFO] %s : core[%x][%d] enters at cycle %d / sp = %x\n",680 __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() , hal_get_stack() );681 }682 677 683 678 // CP0 initializes the local cluster manager (cores and memory allocators) … … 691 686 __FUNCTION__ , local_cxy ); 692 687 hal_core_sleep(); 693 }694 else695 {696 kinit_dmsg("\n[INFO] %s : core[%x][%d] initialised cluster at cycle %d\n",697 __FUNCTION__ , core_cxy , core_lid , hal_time_stamp());698 688 } 699 689 } … … 706 696 ///////////////////////////////////////////////////////////////////////////////// 707 697 708 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 1 \n",709 __FUNCTION__ , core_cxy , core_lid );698 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 1 at cycle %d\n", 699 __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() ); 710 700 711 701 // all cores get pointer on local cluster manager and on core descriptor … … 756 746 ///////////////////////////////////////////////////////////////////////////////// 757 747 758 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 2 \n",759 __FUNCTION__ , core_cxy , core_lid );748 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 2 at cycle %d\n", 749 __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() ); 760 750 761 751 // all cores initialize the private idle thread descriptor … … 789 779 } 790 780 791 // TODO CP0 in IO cluster initialize VFS, devFS and sysFS 792 { 793 // devfs_root_init(); 794 // sysfs_root_init(); 795 // clusters_sysfs_register(); 796 // vfs_init(); 797 // sysconf_init(); 798 } 781 printk("\n bloup 0\n"); 782 783 // CP0 in all clusters initializes cooperatively VFS and DEVFS 784 if( (core_lid == 0) ) 785 { 786 xptr_t root_inode_xp; 787 788 // initialize root File System 789 if( CONFIG_VFS_ROOT_IS_FATFS ) 790 { 791 root_inode_xp = fatfs_init(); 792 } 793 else 794 { 795 printk("\n[PANIC] in %s : root FS must be FATFS\n", __FUNCTION__ ); 796 hal_core_sleep(); 797 } 798 799 if( root_inode_xp == XPTR_NULL ) 800 { 801 printk("\n[PANIC] in %s : core[%x][%d] cannot initialize file system\n", 802 __FUNCTION__ , local_cxy , core_lid ); 803 hal_core_sleep(); 804 } 805 806 printk("\n bloup 1\n"); 807 808 // mount the DEVFS File system 809 devfs_mount( root_inode_xp , "dev" ); 810 } 811 812 printk("\n bloup 2\n"); 799 813 800 814 // CP0 in I/O cluster print banner … … 811 825 ///////////////////////////////////////////////////////////////////////////////// 812 826 813 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 3 \n",814 __FUNCTION__ , core_cxy , core_lid );827 kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 3 at cycle %d\n", 828 __FUNCTION__ , core_cxy , core_lid , hal_time_stamp() ); 815 829 816 830 // each core activates its private PTI IRQ -
trunk/kernel/kern/printk.c
r14 r23 37 37 extern chdev_t txt0_chdev; // allocated in kernel_init.c 38 38 39 ///////////////////////////////////// 40 uint32_t snprintf( char * string, 41 uint32_t length, 42 char * format, ... ) 43 { 44 45 #define TO_STREAM(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0); 46 47 va_list args; // printf arguments 48 uint32_t ps; // write pointer to the string buffer 49 50 ps = 0; 51 va_start( args , format ); 52 53 xprintf_text: 54 55 while ( *format != 0 ) 56 { 57 58 if (*format == '%') // copy argument to string 59 { 60 format++; 61 goto xprintf_arguments; 62 } 63 else // copy one char to string 64 { 65 TO_STREAM( *format ); 66 format++; 67 } 68 } 69 70 va_end( args ); 71 72 // add terminating NUL chracter 73 TO_STREAM( 0 ); 74 return ps; 75 76 xprintf_arguments: 77 78 { 79 char buf[30]; // buffer to display one number 80 char * pbuf; // pointer on first char to display 81 uint32_t len = 0; // number of char to display 82 static const char HexaTab[] = "0123456789ABCDEF"; 83 uint32_t i; 84 85 // Ignore fields width and precision 86 for ( ; (*format >= '0' && *format <= '9') || (*format == '.') ; format++ ); 87 88 switch (*format) 89 { 90 case ('c'): // char conversion 91 { 92 int val = va_arg( args, int ); 93 buf[0] = val; 94 pbuf = buf; 95 len = 1; 96 break; 97 } 98 case ('d'): // decimal signed integer 99 { 100 int val = va_arg( args, int ); 101 if (val < 0) 102 { 103 TO_STREAM( '-' ); 104 val = -val; 105 } 106 for(i = 0; i < 10; i++) 107 { 108 109 buf[9 - i] = HexaTab[val % 10]; 110 if (!(val /= 10)) break; 111 } 112 len = i + 1; 113 pbuf = &buf[9 - i]; 114 break; 115 } 116 case ('u'): // decimal unsigned integer 117 { 118 uint32_t val = va_arg( args, uint32_t ); 119 for(i = 0; i < 10; i++) 120 { 121 buf[9 - i] = HexaTab[val % 10]; 122 if (!(val /= 10)) break; 123 } 124 len = i + 1; 125 pbuf = &buf[9 - i]; 126 break; 127 } 128 case ('x'): // 32 bits hexadecimal 129 case ('l'): // 64 bits hexadecimal 130 { 131 uint32_t imax; 132 uint64_t val; 133 134 if ( *format == 'l' ) // 64 bits 135 { 136 val = va_arg( args, uint64_t); 137 imax = 16; 138 } 139 else // 32 bits 140 { 141 val = va_arg( args, uint32_t); 142 imax = 8; 143 } 144 145 TO_STREAM( '0' ); 146 TO_STREAM( 'x' ); 147 148 for(i = 0; i < imax; i++) 149 { 150 buf[(imax-1) - i] = HexaTab[val % 16]; 151 if (!(val /= 16)) break; 152 } 153 len = i + 1; 154 pbuf = &buf[(imax-1) - i]; 155 break; 156 } 157 case ('s'): /* string */ 158 { 159 char* str = va_arg( args, char* ); 160 while (str[len]) { len++; } 161 pbuf = str; 162 break; 163 } 164 default: // unsupported argument type 165 { 166 return -1; 167 } 168 } // end switch on argument type 169 170 format++; 171 172 // copy argument to string 173 for( i = 0 ; i < len ; i++ ) 174 { 175 TO_STREAM( pbuf[i] ); 176 } 177 178 goto xprintf_text; 179 } 180 } // end xprintf() 181 39 182 /////////////////////////////////////////////////////////////////////////////////// 40 183 // This static function is called by kernel_printf() to display a string on the … … 47 190 /////////////////////////////////////////////////////////////////////////////////// 48 191 // @ channel : TXT channel. 49 // @ busy : TXT device acces mode .192 // @ busy : TXT device acces mode (busy waiting if non zero). 50 193 // @ buf : buffer containing the characters. 51 194 // @ nc : number of characters. … … 66 209 ////////////////////////////////////////////////////////////////////////////////////// 67 210 // @ channel : channel index. 68 // @ busy : TXT device access mode .211 // @ busy : TXT device access mode (busy waiting if non zero). 69 212 // @ format : printf like format. 70 213 // @ args : format arguments. … … 267 410 } 268 411 412 269 413 // Local Variables: 270 414 // tab-width: 4 -
trunk/kernel/kern/printk.h
r16 r23 46 46 47 47 /********************************************************************************** 48 * This function build a formated string. 49 * The supported formats are defined below : 50 * %c : single character 51 * %d : signed decimal 32 bits integer 52 * %u : unsigned decimal 32 bits integer 53 * %x : hexadecimal 32 bits integer 54 * %l : hexadecimal 64 bits integer 55 * %s : NUL terminated character string 56 ********************************************************************************** 57 * @ string : pointer on target buffer (allocated by caller). 58 * @ length : target buffer length (number of bytes). 59 * @ format : format respecting the printf syntax. 60 * @ returns the string length (including NUL) if success / return -1 if error. 61 *********************************************************************************/ 62 uint32_t snprintf( char * string, 63 uint32_t length, 64 char * format, ... ); 65 66 /********************************************************************************** 48 67 * This function displays a formated string on the kernel terminal TXT0, 49 68 * using a busy waiting policy: It calls directly the relevant TXT driver, … … 52 71 * @ format : formated string. 53 72 *********************************************************************************/ 54 externvoid printk( char* format, ... );73 void printk( char* format, ... ); 55 74 56 75 /********************************************************************************** … … 62 81 * @ format : formated string. 63 82 *********************************************************************************/ 64 externvoid user_printk( char* format, ... );83 void user_printk( char* format, ... ); 65 84 66 85 /********************************************************************************** … … 211 230 #else 212 231 #define sched_dmsg(...) 232 #endif 233 234 #if CONFIG_SIGNAL_DEBUG 235 #define signal_dmsg(...) printk(__VA_ARGS__) 236 #else 237 #define signal_dmsg(...) 213 238 #endif 214 239 -
trunk/kernel/kern/process.c
r14 r23 4 4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016 )6 * Alain Greiner (2016,2017) 7 7 * 8 8 * Copyright (c) UPMC Sorbonne Universites … … 47 47 #include <process.h> 48 48 #include <elf.h> 49 #include <syscalls.h> 49 50 50 51 ////////////////////////////////////////////////////////////////////////////////////////// … … 103 104 pid_t ppid ) 104 105 { 105 // reset signal manager TODO [AG] 106 107 // reset the file descriptors array 106 // reset reference process vmm 107 vmm_init( process ); 108 109 // reset reference process file descriptors array 108 110 process_fd_init( process ); 109 111 110 // reset the process files structures and cd_lock112 // reset reference process files structures and cd_lock 111 113 process->vfs_root_xp = XPTR_NULL; 114 process->vfs_bin_xp = XPTR_NULL; 112 115 process->vfs_cwd_xp = XPTR_NULL; 113 process->vfs_bin_xp = XPTR_NULL; 114 115 spinlock_init( &process->cd_lock ); 116 remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) ); 116 117 117 118 // reset children list root … … 119 120 process->children_nr = 0; 120 121 121 // reset semaphore list root122 // reset semaphore / mutex / barrier / condvar list roots 122 123 xlist_root_init( XPTR( local_cxy , &process->sem_root ) ); 123 process->sem_nr = 0; 124 xlist_root_init( XPTR( local_cxy , &process->mutex_root ) ); 125 xlist_root_init( XPTR( local_cxy , &process->barrier_root ) ); 126 xlist_root_init( XPTR( local_cxy , &process->condvar_root ) ); 127 remote_spinlock_init( XPTR( local_cxy , &process->sync_lock ) ); 124 128 125 129 // register new process in the parent children list … … 128 132 xlist_add_first( root , entry ); 129 133 130 // reset th_tbl[] array 134 // reset th_tbl[] array as empty 131 135 uint32_t i; 132 136 for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ ) … … 137 141 spinlock_init( &process->th_lock ); 138 142 139 // reset process VMM140 memset( &process->vmm , 0 , sizeof(vmm_t) );141 142 143 // initialize PID and PPID 143 144 process->pid = pid; 144 145 process->ppid = ppid; 145 146 146 // set ref_xp field and is_ref flag 147 process->is_ref = true; 147 // set ref_xp field 148 148 process->ref_xp = XPTR( local_cxy , process ); 149 149 … … 153 153 // register new process descriptor in owner cluster manager copies_list 154 154 cluster_process_copies_link( process ); 155 156 // initalise signal manager TODO [AG] 155 157 156 158 hal_wbflush(); … … 162 164 xptr_t reference_process_xp ) 163 165 { 164 // replicate the remote process descriptor in new process descriptor 165 xptr_t local_process_xp = XPTR( local_cxy , local_process ); 166 hal_remote_memcpy( local_process_xp , reference_process_xp , sizeof(process_t) ); 167 168 // initalise signal manager TODO [AG] 169 170 // initialise file descriptors array TODO [AG] 171 172 // initialise process files structures TODO [AG] 173 174 // set the ref_xp field and clear the is_ref flag 166 // get reference process cluster and local pointer 167 cxy_t ref_cxy = GET_CXY( reference_process_xp ); 168 process_t * ref_ptr = (process_t *)GET_PTR( reference_process_xp ); 169 170 // reset local process vmm 171 vmm_init( local_process ); 172 173 // reset process file descriptors array 174 process_fd_init( local_process ); 175 176 // reset vfs_root_xp / vfs_bin_xp / vfs_cwd_xp fields 177 local_process->vfs_root_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_root_xp ) ); 178 local_process->vfs_bin_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_bin_xp ) ); 179 local_process->vfs_cwd_xp = XPTR_NULL; 180 181 // set the pid, ppid, ref_xp fields 182 local_process->pid = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->pid ) ); 183 local_process->ppid = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->ppid ) ); 175 184 local_process->ref_xp = reference_process_xp; 176 local_process->is_ref = false;177 185 178 186 // reset children list root (not used in a process descriptor copy) … … 185 193 // reset semaphores list root (not used in a process descriptor copy) 186 194 xlist_root_init( XPTR( local_cxy , &local_process->sem_root ) ); 187 local_process->sem_nr = 0; 188 189 // initialize th_tbl[] array as empty 195 xlist_root_init( XPTR( local_cxy , &local_process->mutex_root ) ); 196 xlist_root_init( XPTR( local_cxy , &local_process->barrier_root ) ); 197 xlist_root_init( XPTR( local_cxy , &local_process->condvar_root ) ); 198 199 // reset th_tbl[] array as empty 190 200 uint32_t i; 191 201 for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ ) … … 196 206 spinlock_init( &local_process->th_lock ); 197 207 198 // initialise process VMM TODO [AG]199 200 208 // register new process descriptor in local cluster manager local_list 201 209 cluster_process_local_link( local_process ); … … 203 211 // register new process descriptor in owner cluster manager copies_list 204 212 cluster_process_copies_link( local_process ); 213 214 // initalise signal manager TODO [AG] 205 215 206 216 hal_wbflush(); … … 223 233 pmgr_t * pmgr = &LOCAL_CLUSTER->pmgr; 224 234 235 // get the lock protecting the list of local process descriptors 236 remote_spinlock_lock( XPTR( local_cxy , &pmgr->local_lock ) ); 237 225 238 // remove the process descriptor from local_list in local cluster manager 226 spinlock_lock( &pmgr->local_lock );227 239 xlist_unlink( XPTR( local_cxy , &process->local_list ) ); 228 spinlock_unlock( &pmgr->local_lock ); 240 241 // release the lock protecting the list of local process descriptors 242 remote_spinlock_unlock( XPTR( local_cxy , &pmgr->local_lock ) ); 229 243 230 244 // get extended pointer on copies_lock in owner cluster manager … … 243 257 // From this point, the process descriptor is unreachable 244 258 259 // close all open files and update dirty TODO [AG] 260 245 261 // release signal manager TODO [AG] 246 262 247 // delete all open file descriptors 248 process_fd_destroy( process ); 249 250 // Close bin file and decrease refcount for root and cwd 251 if( process->vfs_bin_xp != XPTR_NULL ) vfs_close( process->vfs_bin_xp , NULL ); 263 // Decrease refcount for bin file, root file and cwd file 264 vfs_file_count_down( process->vfs_bin_xp ); 252 265 vfs_file_count_down( process->vfs_root_xp ); 253 266 vfs_file_count_down( process->vfs_cwd_xp ); … … 325 338 326 339 327 328 329 330 340 /////////////////////////////////////////////// 331 341 process_t * process_get_local_copy( pid_t pid ) 332 342 { 333 343 error_t error; 334 bool_t found;335 list_entry_t * iter;336 p rocess_t * process; // pointer on local copy344 process_t * process_ptr; // local pointer on process 345 xptr_t process_xp; // extended pointer on process 346 pid_t process_pid; // process identifier 337 347 338 348 cluster_t * cluster = LOCAL_CLUSTER; 339 349 340 350 // get lock protecting local list of processes 341 spinlock_lock( &cluster->pmgr.local_lock);351 remote_spinlock_lock( XPTR( local_cxy , &cluster->pmgr.local_lock ) ); 342 352 343 353 // scan the local list of process descriptors to find the process 344 found = false; 345 LIST_FOREACH( &cluster->pmgr.local_root , iter ) 346 { 347 process = LIST_ELEMENT( iter , process_t , local_list ); 348 if( process->pid == pid ) 354 xptr_t iter; 355 bool_t found = false; 356 XLIST_FOREACH( XPTR( local_cxy , &cluster->pmgr.local_root ) , iter ) 357 { 358 process_xp = XLIST_ELEMENT( iter , process_t , local_list ); 359 process_ptr = (process_t *)GET_PTR( process_xp ); 360 process_pid = hal_remote_lw( XPTR( local_cxy , &process_ptr->pid ) ); 361 if( process_ptr->pid == pid ) 349 362 { 350 363 found = true; … … 354 367 355 368 // release lock protecting local list of processes 356 spinlock_unlock( &cluster->pmgr.local_lock);357 358 // allocate memory for a local process descriptor359 // and initialise it from reference if required369 remote_spinlock_unlock( XPTR( local_cxy , &cluster->pmgr.local_lock ) ); 370 371 // allocate memory for a new local process descriptor 372 // and initialise it from reference cluster if required 360 373 if( !found ) 361 374 { 362 375 // get extended pointer on reference process descriptor 363 xptr_t reference = cluster_get_reference_process_from_pid( pid ); 376 xptr_t ref_xp = cluster_get_reference_process_from_pid( pid ); 377 378 assert( (ref_xp != XPTR_NULL) , __FUNCTION__ , "illegal pid\n" ); 364 379 365 380 // allocate memory for local process descriptor 366 process = process_alloc();367 if( process == NULL ) return NULL;381 process_ptr = process_alloc(); 382 if( process_ptr == NULL ) return NULL; 368 383 369 384 // initialize local process descriptor copy 370 error = process_copy_init( process , reference);385 error = process_copy_init( process_ptr , ref_xp ); 371 386 if( error ) return NULL; 372 373 374 // register process in global copies_list 375 } 376 377 return process; 387 } 388 389 return process_ptr; 378 390 } // end process_get_local_copy() 379 391 … … 389 401 390 402 remote_spinlock_init( XPTR( local_cxy , &process->fd_array.lock ) ); 391 process->fd_array.max = CONFIG_PROCESS_FILE_MAX_NR; 392 process->fd_array.current 403 404 process->fd_array.current = 0; 393 405 394 406 // initialize array 395 for ( fd = 0 ; fd < process->fd_array.max; fd++ )407 for ( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ ) 396 408 { 397 409 process->fd_array.array[fd] = XPTR_NULL; … … 399 411 } 400 412 401 ////////////////////////////////////////////// 402 void process_fd_destroy( process_t * process ) 403 { 404 uint32_t fd; 405 406 // loop on all open file descriptors to close all open files 407 for( fd = 0 ; fd < process->fd_array.max ; fd++ ) 408 { 409 xptr_t file_xp = process->fd_array.array[fd]; 410 if ( file_xp != XPTR_NULL ) vfs_close( file_xp , NULL ); 411 } 413 414 ////////////////////////////// 415 bool_t process_fd_array_full() 416 { 417 // get extended pointer on reference process 418 xptr_t ref_xp = CURRENT_THREAD->process->ref_xp; 419 420 // get reference process cluster and local pointer 421 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 422 cxy_t ref_cxy = GET_CXY( ref_xp ); 423 424 // get number of open file descriptors from reference fd_array 425 uint32_t current = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->fd_array.current ) ); 426 427 return ( current >= CONFIG_PROCESS_FILE_MAX_NR ); 412 428 } 413 429 414 ///////////////////////////////////////////////////415 bool_t process_fd_array_full( process_t * process )416 {417 return ( process->fd_array.current >= process->fd_array.max);418 }419 420 430 ///////////////////////////////////////////////// 421 error_t process_fd_allocate( process_t * process, 422 xptr_t file_xp, 423 uint32_t * ret_fd ) 431 error_t process_fd_register( xptr_t file_xp, 432 uint32_t * file_id ) 424 433 { 425 434 bool_t found; 426 uint32_t fd; 427 428 remote_spinlock_lock( XPTR( local_cxy , &process->fd_array.lock ) ); 435 uint32_t id; 436 xptr_t xp; 437 438 // get extended pointer on reference process 439 xptr_t ref_xp = CURRENT_THREAD->process->ref_xp; 440 441 // get reference process cluster and local pointer 442 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 443 cxy_t ref_cxy = GET_CXY( ref_xp ); 444 445 // take lock protecting reference fd_array 446 remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) ); 429 447 430 448 found = false; 431 449 432 for ( fd = 0; fd < process->fd_array.max; fd++ ) 433 { 434 if ( process->fd_array.array[fd] == XPTR_NULL ) 450 for ( id = 0; id < CONFIG_PROCESS_FILE_MAX_NR ; id++ ) 451 { 452 xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) ); 453 if ( xp == XPTR_NULL ) 435 454 { 436 455 found = true; 437 process->fd_array.array[fd] = file_xp;438 process->fd_array.current++;439 * ret_fd = fd;456 hal_remote_swd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) , file_xp ); 457 hal_remote_atomic_add( XPTR( ref_cxy , &ref_ptr->fd_array.current ) , 1 ); 458 *file_id = id; 440 459 break; 441 460 } 442 461 } 443 462 444 remote_spinlock_unlock( XPTR( local_cxy , &process->fd_array.lock ) ); 463 // release lock protecting reference fd_array 464 remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) ); 445 465 446 466 if ( !found ) return EMFILE; 447 467 else return 0; 448 } 449 450 //////////////////////////////////////////////// 451 error_t process_fd_release( process_t * process, 452 uint32_t fd ) 453 { 454 if ( (fd < 0) || (fd > process->fd_array.max) ) return EBADF; 455 456 remote_spinlock_lock( XPTR( local_cxy , &process->fd_array.lock ) ); 457 458 process->fd_array.array[fd] = XPTR_NULL; 459 process->fd_array.current--; 460 461 remote_spinlock_unlock( XPTR( local_cxy , &process->fd_array.lock ) ); 462 463 return 0; 464 } 465 466 /////////////////////////////////////// 467 void process_fd_copy( fd_array_t * dst, 468 fd_array_t * src ) 469 { 470 uint32_t fd; 471 xptr_t entry; 472 473 remote_spinlock_lock( XPTR( local_cxy , &src->lock ) ); 474 475 // loop on all entries in source process fd_array 476 for( fd = 0 ; fd < src->max ; fd++ ) 477 { 478 entry = src->array[fd]; 479 480 if( entry != XPTR_NULL ) 481 { 482 // increment file descriptor ref count 483 vfs_file_count_up( entry ); 484 485 // copy entry in destination process fd_array 486 dst->array[fd] = entry; 487 } 488 } 489 490 // release lock on source process fd_array 491 remote_spinlock_unlock( XPTR( local_cxy , &src->lock ) ); 492 } 468 469 } // end process_fd_register() 470 471 //////////////////////////////////////////////// 472 xptr_t process_fd_get_xptr( process_t * process, 473 uint32_t file_id ) 474 { 475 xptr_t file_xp; 476 477 // access local copy of process descriptor 478 file_xp = process->fd_array.array[file_id]; 479 480 if( file_xp == XPTR_NULL ) 481 { 482 // get reference process cluster and local pointer 483 xptr_t ref_xp = process->ref_xp; 484 cxy_t ref_cxy = GET_CXY( ref_xp ); 485 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 486 487 // access reference process descriptor 488 file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[file_id] ) ); 489 490 // update local fd_array if found 491 if( file_xp != XPTR_NULL ) 492 { 493 process->fd_array.array[file_id] = file_xp; 494 } 495 } 496 497 return file_xp; 498 499 } // end process_fd_get_xptr() 493 500 494 501 /////////////////////////////////////////// … … 510 517 remote_spinlock_lock( XPTR( src_cxy , &src_ptr->lock ) ); 511 518 512 // get number of entries in fd_array513 uint32_t max = hal_remote_lw( XPTR( src_cxy , &src_ptr->max ) );514 515 519 // loop on all entries in source process fd_array 516 for( fd = 0 ; fd < max; fd++ )520 for( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ ) 517 521 { 518 522 entry = (xptr_t)hal_remote_lwd( XPTR( src_cxy , &src_ptr->array[fd] ) ); … … 609 613 pid = exec_info->pid; 610 614 611 if( CXY_FROM_PID( pid ) != local_cxy ) 612 { 613 printk("\n[PANIC] in %s : illegal process PID %x in cluster %x\n", 614 __FUNCTION__ , pid , local_cxy ); 615 hal_core_sleep(); 616 } 615 assert( (CXY_FROM_PID( pid ) == local_cxy) , __FUNCTION__ , "illegal PID\n" ); 617 616 618 617 exec_dmsg("\n[INFO] %s enters in cluster %x for process %x / path = %s\n", … … 677 676 } 678 677 679 // create "stack" vseg descriptor for associated main thread680 vseg_t * stack_vseg = vmm_create_vseg( process,681 0, // base defined by VMM682 0, // size defined by VMM683 VSEG_TYPE_STACK );684 if( stack_vseg == NULL )685 {686 printk("\n[ERROR] in %s : cannot create stack vseg for process %x / path = %s\n",687 __FUNCTION__, pid , path );688 process_destroy( process );689 return error;690 }691 692 678 // select a core in cluster 693 679 lid = cluster_select_local_core(); … … 695 681 696 682 // initialize pthread attributes for main thread 697 attr.pid = pid; 698 attr.entry_func = (void*)process->vmm.entry_point; 699 attr.entry_args = exec_info->args_pointers; 700 attr.flags = PT_FLAG_DETACH; // main thread always detached 701 attr.cxy = local_cxy; 702 attr.lid = lid; 703 704 // create and initialise thread descriptor, link thread & process 705 error = thread_user_create( &thread, 683 attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED; 684 attr.cxy = local_cxy; 685 attr.lid = lid; 686 687 // create and initialise thread descriptor 688 error = thread_user_create( pid, 689 (void *)process->vmm.entry_point, 690 exec_info->args_pointers, 706 691 &attr, 707 stack_vseg->min, 708 stack_vseg->max - stack_vseg->min ); 692 &thread ); 709 693 if( error ) 710 694 { … … 732 716 { 733 717 process_t * process_init; // process_init descriptor 734 thread_t * thread_init; // process_init main thread descriptor735 718 pid_t init_pid; // process_init pid 736 719 exec_info_t exec_info; // structure to be passed to process_make_exec() … … 779 762 process_zero.children_nr = 1; 780 763 781 // TODO open stdin / stdout / stderr pseudo-files 782 xptr_t stdin_xp; 783 xptr_t stdout_xp; 784 xptr_t stderr_xp; 785 786 // error1 = vfs_open( process_init->vfs_cwd_xp, NULL, VFS_O_RDONLY, &stdin_xp ); 787 // error2 = vfs_open( process_init->vfs_cwd_xp, NULL, VFS_O_WRONLY, &stdout_xp ); 788 // error3 = vfs_open( process_init->vfs_cwd_xp, NULL, VFS_O_WRONLY, &stderr_xp ); 764 // TODO create inodes for stdin / stdout / stderr pseudo-files 765 // these inodes should be created in the cluster containing the relevant TXT chdev 766 767 // open stdin / stdout / stderr pseudo-files 768 xptr_t stdin_xp; 769 xptr_t stdout_xp; 770 xptr_t stderr_xp; 771 uint32_t stdin_id; 772 uint32_t stdout_id; 773 uint32_t stderr_id; 774 775 error1 = vfs_open( XPTR_NULL, CONFIG_DEV_STDIN , O_RDONLY, 0, &stdin_xp , &stdin_id ); 776 error2 = vfs_open( XPTR_NULL, CONFIG_DEV_STDOUT, O_WRONLY, 0, &stdout_xp, &stdout_id ); 777 error3 = vfs_open( XPTR_NULL, CONFIG_DEV_STDERR, O_WRONLY, 0, &stderr_xp, &stderr_id ); 789 778 790 779 if( error1 || error2 || error3 ) 791 780 { 792 if( !error1 ) vfs_close( stdin_xp , NULL);793 if( !error2 ) vfs_close( stdout_xp , NULL);794 if( !error3 ) vfs_close( stderr_xp , NULL);781 if( !error1 ) vfs_close( stdin_xp , stdin_id ); 782 if( !error2 ) vfs_close( stdout_xp , stdout_id ); 783 if( !error3 ) vfs_close( stderr_xp , stderr_id ); 795 784 796 785 printk("\n[PANIC] in %s : cannot open stdin/stdout/stderr in cluster %x\n", … … 799 788 } 800 789 801 // register stdin / stdout / stderr in the fd_array 3 first slots 802 process_init->fd_array.array[0] = stdin_xp; 803 process_init->fd_array.array[1] = stdout_xp; 804 process_init->fd_array.array[2] = stderr_xp; 805 process_init->fd_array.current = 3; 790 // check stdin / stdout / stderr indexes 791 if( (stdin_id != 0) || (stdout_id != 1) || (stderr_id != 2) ) 792 { 793 printk("\n[PANIC] in %s : bad indexes for stdin/stdout/stderr in cluster %x\n", 794 __FUNCTION__ , local_cxy ); 795 hal_core_sleep(); 796 } 806 797 807 798 // initialize the exec_info structure -
trunk/kernel/kern/process.h
r14 r23 4 4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016 )6 * Alain Greiner (2016,2017) 7 7 * 8 8 * Copyright (c) UPMC Sorbonne Universites … … 54 54 55 55 /********************************************************************************************* 56 * These macros are used to compose or decompose global thread identifier (TRDID)57 * to or from cluster identifier / local thread index (CXY , LTID)58 ********************************************************************************************/59 60 #define LTID_FROM_TRDID( trdid ) (ltid_t)(trdid & 0x0000FFFF)61 #define CXY_FROM_TRDID( trdid ) (cxy_t)(trdid >> 16)62 #define TRDID( cxy , ltid ) (trdid_t)((cxy << 16) | ltid )63 64 /*********************************************************************************************65 56 * This structure defines an array of extended pointers on the open file descriptors 66 57 * for a given process. We use an extended pointer because the open file descriptor … … 68 59 * A free entry in this array contains the XPTR_NULL value. 69 60 * The array size is defined by a the CONFIG_PROCESS_FILE_MAX_NR parameter. 70 * All modifications (open/close) must be done by the reference cluster, and reported 61 * All modifications (open/close) in this structure must be done by the reference cluster, 62 * and reported in process copies. 71 63 ********************************************************************************************/ 72 64 … … 75 67 remote_spinlock_t lock; /*! lock protecting fd_array[] change. */ 76 68 uint32_t current; /*! current number of open files */ 77 uint32_t max; /*! max number of open files (can be increased) */78 69 xptr_t array[CONFIG_PROCESS_FILE_MAX_NR]; 79 70 } … … 88 79 * allocated to this cluster. 89 80 * The process descriptor for a PID process is replicated in all clusters containing 90 * at least one thread of the PID process, with some restrictions: 91 * - The list of registered vsegs, the page table (contained in vmm), and the fd_array[] 92 * are only complete in the reference process descriptor, other copies are read-only caches. 93 * - The following fields are NOT defined in copies other than the reference: 94 * children_root , children_list , children_nr , sig_mgr 81 * at least one thread of the PID process, with the following rules : 82 * 83 * 1) The <pid>, <ppid>, <ref_xp>, <vfs_root_xp>, <vfs_bin_xp> fields are defined 84 * in all process descriptor copies. 85 * 2) The <vfs_cwd_xp> and associated <cwd_lock>, that can be dynamically modified, 86 * are only defined in the reference process descriptor. 87 * 2) The <vmm>, containing the list of registered vsegs, and the page table, are only 88 * complete in the reference process cluster, other copies are read-only caches. 89 * 3) the <fd_array>, containing extended pointers on the open file descriptors, is only 90 * complete in the reference process cluster, other copies are read-only caches. 91 * 4) The <sem_root>, <mutex_root>, <barrier_root>, <condvar_root>, and the associated 92 * <sync_lock>, that are dynamically allocated, are only defined in the reference cluster. 93 * 5) The <children_root>, and <children_nr> fields are only defined in the reference 94 * cluster, and are undefined in other clusters. 95 * 6) The <brothers_list>, <local_list>, <copies_list>, <th_tbl>, <th_nr>, <th_lock> fields 96 * are defined in all process descriptors copies. 97 * 7) The <sig_mgr> field is only defined in the reference cluster. TODO 95 98 ********************************************************************************************/ 96 99 97 100 typedef struct process_s 98 101 { 99 vmm_t vmm; /*! embedded virtual memory manager */ 100 101 fd_array_t fd_array; /*! embedded file descriptors array */ 102 103 xptr_t vfs_root_xp; /*! extende pointer on current file system root */ 104 xptr_t vfs_cwd_xp; /*! extended pointer on current working directory */ 105 xptr_t vfs_bin_xp; /*! extended pointer on associate .elf file */ 106 107 spinlock_t cd_lock; /*! lock protecting working directory changes */ 102 vmm_t vmm; /*! embedded virtual memory manager */ 103 104 fd_array_t fd_array; /*! embedded open file descriptors array */ 105 106 xptr_t vfs_root_xp; /*! extende pointer on current VFS root inode */ 107 xptr_t vfs_bin_xp; /*! extended pointer on .elf file inode */ 108 pid_t pid; /*! process identifier */ 109 pid_t ppid; /*! parent process identifier */ 110 xptr_t ref_xp; /*! extended pointer on reference process */ 111 112 xptr_t vfs_cwd_xp; /*! extended pointer on current working dir inode */ 113 remote_rwlock_t cwd_lock; /*! lock protecting working directory changes */ 108 114 109 pid_t pid; /*! process identifier */ 110 pid_t ppid; /*! parent process identifier */ 111 bool_t is_ref; /*! this is the reference process if true */ 112 xptr_t ref_xp; /*! extended pointer on reference process */ 113 114 xlist_entry_t children_root; /*! root of the children process xlist */ 115 uint32_t children_nr; /*! number of children processes */ 116 117 xlist_entry_t brothers_list; /*! member of list of children of same parent */ 118 119 list_entry_t local_list; /*! member of list of process in same cluster */ 120 121 xlist_entry_t copies_list; /*! member of list of copies of same process */ 122 123 spinlock_t th_lock; /*! lock protecting th_tbl[] concurrent access */ 124 uint32_t th_nr; /*! number of threads in this cluster */ 125 115 xlist_entry_t children_root; /*! root of the children process xlist */ 116 uint32_t children_nr; /*! number of children processes */ 117 118 xlist_entry_t brothers_list; /*! member of list of children of same parent */ 119 xlist_entry_t local_list; /*! member of list of process in same cluster */ 120 xlist_entry_t copies_list; /*! member of list of copies of same process */ 121 122 spinlock_t th_lock; /*! lock protecting th_tbl[] concurrent access */ 123 uint32_t th_nr; /*! number of threads in this cluster */ 126 124 struct thread_s * th_tbl[CONFIG_THREAD_MAX_PER_CLUSTER]; /*! pointers on local threads */ 127 125 128 xlist_entry_t sem_root; /*! root of the process semaphores list */ 129 uint32_t sem_nr; /*! number of semaphores */ 130 131 sig_mgr_t sig_mgr; /*! embedded signal manager TODO [AG] */ 126 xlist_entry_t sem_root; /*! root of the process semaphore list */ 127 xlist_entry_t mutex_root; /*! root of the process mutex list */ 128 xlist_entry_t barrier_root; /*! root of the process barrier list */ 129 xlist_entry_t condvar_root; /*! root of the process condvar list */ 130 131 remote_spinlock_t sync_lock; /*! lock protecting sem,mutex,barrier,condvar lists */ 132 133 sig_mgr_t sig_mgr; /*! embedded signal manager TODO [AG] */ 132 134 } 133 135 process_t; … … 149 151 xptr_t vfs_bin_xp; /*! extended pointer on process .elf file */ 150 152 151 char path[ 256]; /*! pathname for .elf file*/153 char path[CONFIG_VFS_MAX_PATH_LENGTH]; /*! .elf file path */ 152 154 153 155 char ** args_pointers; /*! physical base address of array of pointers */ … … 162 164 exec_info_t; 163 165 164 /*********************************************************************************************165 * This macro returns a pointer on the process descriptor for the calling thread.166 ********************************************************************************************/167 168 #define CURRENT_PROCESS (hal_get_current_thread()->process)169 170 166 /*************** Process Descriptor Operations *****************************************/ 171 167 … … 204 200 * The PID value must have been defined previously by the owner cluster manager. 205 201 * The reference cluster can be different from the owner cluster. 206 * It set the pid / ppid / is_ref / pref /fields.202 * It set the pid / ppid / ref_xp fields. 207 203 * It registers this process descriptor in three lists: 208 204 * - the children_list in the parent process descriptor. … … 232 228 /********************************************************************************************* 233 229 * This function releases all memory allocated for a process descriptor in the local cluster, 234 * after releasing memory allocated for embedded substructures (fd_array, vmm, etc).230 * including memory allocated for embedded substructures (fd_array, vmm, etc). 235 231 * The local th_tbl[] array must be empty. 236 232 ********************************************************************************************* … … 255 251 * If this local copy does not exist yet, it is dynamically created, from the reference 256 252 * process descriptor, registered in the global copies_list, and registered in the local_list. 257 * This function is used by both thread_user_create() and thread_user_copy() functions.253 * This function is used by the thread_user_create() function. 258 254 ********************************************************************************************* 259 255 * @ pid : searched process identifier. … … 288 284 289 285 /********************************************************************************************* 290 * This function reset the file descriptor array for a given process: no open file.286 * This function initialises all entries of the local fd_array as empty. 291 287 ********************************************************************************************* 292 288 * @ process : pointer on the local process descriptor. … … 295 291 296 292 /********************************************************************************************* 297 * This function closes all open files and releases all file descriptors. 293 * This function uses as many remote accesses as required, to reset an entry in fd_array[], 294 * in all clusters containing a copy. The entry is identified by the <file_id> argument. 295 * This function must be executed by a thread running reference cluster, that contain 296 * the complete list of process descriptors copies. 298 297 ********************************************************************************************* 299 298 * @ process : pointer on the local process descriptor. 300 ********************************************************************************************/ 301 void process_fd_destroy( process_t * process ); 299 * @ file_id : file descriptor index in the fd_array. 300 ********************************************************************************************/ 301 void process_fd_remove( process_t * process, 302 uint32_t file_id ); 303 304 /********************************************************************************************* 305 * This function returns an extended pointer on a file descriptor identified by its index 306 * in fd_array. It can be called by any thread running in any cluster. 307 * It access first the local process descriptor. In case of local miss, it uses remote access 308 * to access the reference process descriptor. 309 * It updates the local fd_array when the file descriptor exist in reference cluster. 310 * The file descriptor refcount is not incremented. 311 ********************************************************************************************* 312 * @ process : pointer on the local process descriptor. 313 * @ file_id : file descriptor index in the fd_array. 314 * @ return extended pointer on file descriptor if success / return XPTR_NULL if not found. 315 ********************************************************************************************/ 316 xptr_t process_fd_get_xptr( process_t * process, 317 uint32_t file_id ); 302 318 303 319 /********************************************************************************************* 304 320 * This function checks the number of open files for a given process. 305 ********************************************************************************************* 306 * @ process : pointer on the local process descriptor. 321 * It can be called by any thread in any cluster, because it uses portable remote access 322 * primitives to access the reference process descriptor. 323 ********************************************************************************************* 307 324 * @ returns true if file descriptor array full. 308 325 ********************************************************************************************/ 309 bool_t process_fd_array_full( process_t * process ); 310 311 /********************************************************************************************* 312 * These functions allocates a slot in the fd_array for a given process, 313 * and returns the file descriptor index. 314 ********************************************************************************************* 315 * @ process : pointer on the local process descriptor. 316 * @ file : extended pointer on the file descriptor. 317 * @ fd : [out] file descriptor index 326 bool_t process_fd_array_full(); 327 328 /********************************************************************************************* 329 * This function allocates a free slot in the fd_array of the reference process, 330 * register the <file_xp> argument in the allocated slot, and return the slot index. 331 * It can be called by any thread in any cluster, because it uses portable remote access 332 * primitives to access the reference process descriptor. 333 ********************************************************************************************* 334 * @ file_xp : extended pointer on the file descriptor to be registered. 335 * @ file_id : [out] buffer for fd_array slot index. 318 336 * @ return 0 if success / return EMFILE if array full. 319 337 ********************************************************************************************/ 320 error_t process_fd_allocate( process_t * process, 321 xptr_t file_xp, 322 uint32_t * fd ); 323 324 /********************************************************************************************* 325 * This function releases an existing file descriptor from the process fd_array. 326 ********************************************************************************************* 327 * @ process : pointer on the local process descriptor. 328 * @ return 0 if success / return EBADF if illegal file descriptor. 329 ********************************************************************************************/ 330 error_t process_fd_release( process_t * process, 331 uint32_t fd ); 332 333 /********************************************************************************************* 334 * This function copies all non-zero entries from a local <src> fd_array, 335 * embedded in a process descriptor, to another local <dst_xp> fd_array, embedded 336 * in another process descriptor. 337 * It takes the remote lock protecting the <src> fd_array during the copy. 338 * For each involved file descriptor, the refcount is incremented. 339 ********************************************************************************************* 340 * @ dst : pointer on the destination fd_array_t. 341 * @ src : pointer on the source fd_array_t. 342 ********************************************************************************************/ 343 void process_fd_local_copy( fd_array_t * dst, 344 fd_array_t * src ); 338 error_t process_fd_register( xptr_t file_xp, 339 uint32_t * file_id ); 345 340 346 341 /********************************************************************************************* … … 358 353 359 354 355 360 356 /******************** Thread Related Operations *****************************************/ 361 357 -
trunk/kernel/kern/rpc.c
r16 r23 2 2 * rpc.c - RPC related operations implementation. 3 3 * 4 * Authors Mohamed Lamine Karaoui (2015) 5 * Alain Greiner (2016) 4 * Author Alain Greiner (2016,2017) 6 5 * 7 6 * Copyright (c) UPMC Sorbonne Universites … … 40 39 #include <vfs.h> 41 40 #include <fatfs.h> 41 #include <signal.h> 42 42 #include <dev_icu.h> 43 43 #include <rpc.h> … … 55 55 &rpc_thread_user_create_server, // 4 56 56 &rpc_thread_kernel_create_server, // 5 57 &rpc_ undefined,// 657 &rpc_signal_rise_server, // 6 58 58 &rpc_undefined, // 7 59 59 &rpc_undefined, // 8 … … 64 64 &rpc_vfs_dentry_create_server, // 12 65 65 &rpc_vfs_dentry_destroy_server, // 13 66 &rpc_ undefined,// 1467 &rpc_ undefined,// 1568 &rpc_ undefined,// 1666 &rpc_vfs_file_create_server, // 14 67 &rpc_vfs_file_destroy_server, // 15 68 &rpc_fatfs_get_cluster_server, // 16 69 69 &rpc_undefined, // 17 70 70 &rpc_undefined, // 18 … … 73 73 &rpc_vmm_get_ref_vseg_server, // 20 74 74 &rpc_vmm_get_pte_server, // 21 75 &rpc_ semaphore_alloc_server,// 2276 &rpc_ semaphore_free_server,// 2375 &rpc_kcm_alloc_server, // 22 76 &rpc_kcm_free_server, // 23 77 77 &rpc_mapper_move_server, // 24 78 78 &rpc_undefined, // 25 … … 81 81 &rpc_undefined, // 28 82 82 &rpc_undefined, // 29 83 84 &rpc_fatfs_get_cluster_server // 3085 83 }; 86 84 … … 93 91 94 92 ///////////////////////////////////////////////////////////////////////////////////////// 95 // 93 // [0] Marshaling functions attached to RPC_PMEM_GET_PAGES 96 94 ///////////////////////////////////////////////////////////////////////////////////////// 97 95 … … 150 148 151 149 ///////////////////////////////////////////////////////////////////////////////////////// 152 // 150 // [1] Marshaling functions attached to RPC_PROCESS_PID_ALLOC 153 151 ///////////////////////////////////////////////////////////////////////////////////////// 154 152 … … 207 205 208 206 ///////////////////////////////////////////////////////////////////////////////////////// 209 // 207 // [2] Marshaling functions attached to RPC_PROCESS_EXEC 210 208 ///////////////////////////////////////////////////////////////////////////////////////// 211 209 … … 265 263 266 264 ///////////////////////////////////////////////////////////////////////////////////////// 267 // 265 // [3] Marshaling functions attached to RPC_PROCESS_KILL 268 266 ///////////////////////////////////////////////////////////////////////////////////////// 269 267 … … 272 270 { 273 271 // only reference cluster can send this RPC 274 if( !process->is_ref)272 if( GET_CXY( process->ref_xp ) != local_cxy ) 275 273 { 276 274 printk("PANIC in %s : caller is not the reference process\n", __FUNCTION__ ); … … 334 332 335 333 ///////////////////////////////////////////////////////////////////////////////////////// 336 // 334 // [4] Marshaling functions attached to RPC_THREAD_USER_CREATE 337 335 ///////////////////////////////////////////////////////////////////////////////////////// 338 336 339 337 ///////////////////////////////////////////////////////// 340 338 void rpc_thread_user_create_client( cxy_t cxy, 339 pid_t pid, // in 340 void * start_func, // in 341 void * start_arg, // in 341 342 pthread_attr_t * attr, // in 342 343 xptr_t * thread_xp, // out … … 356 357 357 358 // set input arguments in RPC descriptor 358 rpc.args[0] = (uint64_t)(intptr_t)attr; 359 rpc.args[0] = (uint64_t)pid; 360 rpc.args[1] = (uint64_t)(intptr_t)start_func; 361 rpc.args[2] = (uint64_t)(intptr_t)start_arg; 362 rpc.args[3] = (uint64_t)(intptr_t)attr; 359 363 360 364 // register RPC request in remote RPC fifo … … 362 366 363 367 // get output arguments from RPC descriptor 364 *thread_xp = (xptr_t)rpc.args[ 1];365 *error = (error_t)rpc.args[ 2];368 *thread_xp = (xptr_t)rpc.args[4]; 369 *error = (error_t)rpc.args[5]; 366 370 } 367 371 … … 373 377 thread_t * thread_ptr; // local pointer on thread descriptor 374 378 xptr_t thread_xp; // extended pointer on thread descriptor 379 375 380 pid_t pid; // process identifier 376 process_t * process; // local pointer on process descriptor 377 vseg_t * vseg; // local pointer on stack vseg 378 379 error_t error = 0; 381 void * start_func; 382 void * start_arg; 383 error_t error; 380 384 381 385 // get client cluster identifier and pointer on RPC descriptor … … 384 388 385 389 // get pointer on attributes structure in client cluster from RPC descriptor 386 attr_ptr = (pthread_attr_t *)(intptr_t)hal_remote_lwd( XPTR(client_cxy , &desc->args[0]) ); 390 391 // get input arguments from RPC descriptor 392 pid = (pid_t) hal_remote_lwd(XPTR(client_cxy , &desc->args[0])); 393 start_func = (void *)(intptr_t) hal_remote_lwd(XPTR(client_cxy , &desc->args[1])); 394 start_arg = (void *)(intptr_t) hal_remote_lwd(XPTR(client_cxy , &desc->args[2])); 395 attr_ptr = (pthread_attr_t *)(intptr_t)hal_remote_lwd(XPTR(client_cxy , &desc->args[3])); 387 396 388 397 // makes a local copy of attributes structure … … 391 400 sizeof(pthread_attr_t) ); 392 401 393 if( attr_copy.cxy != local_cxy ) 394 { 395 printk("\n[PANIC] in %s : target cluster = %X / local_cluster = %x\n", 396 __FUNCTION__ , attr_copy.cxy , local_cxy ); 397 hal_core_sleep(); 398 } 399 400 // get local process descriptor 401 pid = attr_copy.pid; 402 process = cluster_get_local_process_from_pid( pid ); 403 404 if( process == NULL ) 405 { 406 printk("\n[ERROR] in %s : no process descriptor in cluster %x for pid = %x\n", 407 __FUNCTION__ , local_cxy , pid ); 408 error = ENOMEM; 409 410 } 411 412 // allocate a stack from local VMM 413 vseg = vmm_create_vseg( process, 414 0, 415 0, 416 VSEG_TYPE_STACK ); 417 if( vseg == NULL ) 418 { 419 printk("\n[ERROR] in %s : cannot create stack vseg in cluster %x for pid %x\n", 420 __FUNCTION__ , local_cxy , pid ); 421 error = ENOMEM; 422 } 423 424 // create thread in local cluster 425 if( thread_user_create( &thread_ptr, 426 &attr_copy, 427 vseg->min, 428 vseg->max - vseg->min ) ) error = ENOMEM; 429 402 assert( (attr_copy.cxy == local_cxy) , __FUNCTION__ , "bad target cluster\n" ); 403 404 // call kernel function 405 error = thread_user_create( pid, 406 start_func, 407 start_arg, 408 &attr_copy, 409 &thread_ptr ); 430 410 431 411 // set output arguments … … 436 416 437 417 ///////////////////////////////////////////////////////////////////////////////////////// 438 // 418 // [5] Marshaling functions attached to RPC_THREAD_KERNEL_CREATE 439 419 ///////////////////////////////////////////////////////////////////////////////////////// 440 420 … … 502 482 503 483 ///////////////////////////////////////////////////////////////////////////////////////// 504 // Marshaling functions attached to RPC_VFS_INODE_CREATE 484 // [6] Marshaling functions attached to RPC_SIGNAL_RISE 485 ///////////////////////////////////////////////////////////////////////////////////////// 486 487 ///////////////////////////////////////////// 488 void rpc_signal_rise_client( cxy_t cxy, 489 process_t * process, // in 490 uint32_t sig_id ) // in 491 { 492 // RPC must be remote 493 if( cxy == local_cxy ) 494 { 495 printk("PANIC in %s : target is not remote\n", __FUNCTION__ ); 496 hal_core_sleep(); 497 } 498 499 // initialise RPC descriptor header 500 rpc_desc_t rpc; 501 rpc.index = RPC_SIGNAL_RISE; 502 rpc.response = 1; 503 504 // set input arguments in RPC descriptor 505 rpc.args[0] = (uint64_t)(intptr_t)process; 506 rpc.args[1] = (uint64_t)sig_id; 507 508 // register RPC request in remote RPC fifo 509 rpc_send_sync( cxy , &rpc ); 510 } 511 512 //////////////////////////////////////// 513 void rpc_signal_rise_server( xptr_t xp ) 514 { 515 process_t * process; // local pointer on process descriptor 516 uint32_t sig_id; // signal index 517 518 // get client cluster identifier and pointer on RPC descriptor 519 cxy_t client_cxy = (cxy_t)GET_CXY( xp ); 520 rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); 521 522 // get attributes from RPC descriptor 523 process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 524 sig_id = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); 525 526 // call local kernel function 527 signal_rise( process , sig_id ); 528 } 529 530 ///////////////////////////////////////////////////////////////////////////////////////// 531 // [10] Marshaling functions attached to RPC_VFS_INODE_CREATE 505 532 ///////////////////////////////////////////////////////////////////////////////////////// 506 533 … … 508 535 void rpc_vfs_inode_create_client( cxy_t cxy, 509 536 xptr_t dentry_xp, // in 510 uint32_t type, // in 537 uint32_t fs_type, // in 538 uint32_t inode_type, // in 511 539 uint32_t attr, // in 512 uint32_t mode,// in540 uint32_t rights, // in 513 541 uint32_t uid, // in 514 542 uint32_t gid, // in … … 530 558 // set input arguments in RPC descriptor 531 559 rpc.args[0] = (uint64_t)dentry_xp; 532 rpc.args[1] = (uint64_t)type; 533 rpc.args[2] = (uint64_t)attr; 534 rpc.args[3] = (uint64_t)mode; 535 rpc.args[4] = (uint64_t)uid; 536 rpc.args[5] = (uint64_t)gid; 560 rpc.args[1] = (uint64_t)fs_type; 561 rpc.args[2] = (uint64_t)inode_type; 562 rpc.args[3] = (uint64_t)attr; 563 rpc.args[4] = (uint64_t)rights; 564 rpc.args[5] = (uint64_t)uid; 565 rpc.args[6] = (uint64_t)gid; 537 566 538 567 // register RPC request in remote RPC fifo (blocking function) … … 540 569 541 570 // get output values from RPC descriptor 542 *inode_xp = (xptr_t)rpc.args[ 6];543 *error = (error_t)rpc.args[ 7];571 *inode_xp = (xptr_t)rpc.args[7]; 572 *error = (error_t)rpc.args[8]; 544 573 } 545 574 … … 548 577 { 549 578 xptr_t dentry_xp; 550 uint32_t type; 579 uint32_t fs_type; 580 uint32_t inode_type; 551 581 uint32_t attr; 552 uint32_t mode;582 uint32_t rights; 553 583 uint32_t uid; 554 584 uint32_t gid; … … 561 591 562 592 // get input arguments from client rpc descriptor 563 dentry_xp = (xptr_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 564 type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); 565 attr = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) ); 566 mode = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) ); 567 uid = (uid_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) ); 568 gid = (gid_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) ); 593 dentry_xp = (xptr_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 594 fs_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); 595 inode_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) ); 596 attr = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) ); 597 rights = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) ); 598 uid = (uid_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) ); 599 gid = (gid_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[6] ) ); 569 600 570 601 // call local kernel function 571 602 error = vfs_inode_create( dentry_xp, 572 type, 603 fs_type, 604 inode_type, 573 605 attr, 574 mode,606 rights, 575 607 uid, 576 608 gid, … … 578 610 579 611 // set output arguments 580 hal_remote_swd( XPTR( client_cxy , &desc->args[ 6] ) , (uint64_t)inode_xp );581 hal_remote_swd( XPTR( client_cxy , &desc->args[ 7] ) , (uint64_t)error );582 } 583 584 ///////////////////////////////////////////////////////////////////////////////////////// 585 // 612 hal_remote_swd( XPTR( client_cxy , &desc->args[7] ) , (uint64_t)inode_xp ); 613 hal_remote_swd( XPTR( client_cxy , &desc->args[8] ) , (uint64_t)error ); 614 } 615 616 ///////////////////////////////////////////////////////////////////////////////////////// 617 // [11] Marshaling functions attached to RPC_VFS_INODE_DESTROY 586 618 ///////////////////////////////////////////////////////////////////////////////////////// 587 619 … … 626 658 627 659 ///////////////////////////////////////////////////////////////////////////////////////// 628 // 660 // [12] Marshaling functions attached to RPC_VFS_DENTRY_CREATE 629 661 ///////////////////////////////////////////////////////////////////////////////////////// 630 662 … … 701 733 702 734 ///////////////////////////////////////////////////////////////////////////////////////// 703 // 735 // [13] Marshaling functions attached to RPC_VFS_DENTRY_DESTROY 704 736 ///////////////////////////////////////////////////////////////////////////////////////// 705 737 … … 745 777 746 778 ///////////////////////////////////////////////////////////////////////////////////////// 747 // Marshaling functions attached to RPC_VMM_GET_REF_VSEG 779 // [14] Marshaling functions attached to RPC_VFS_FILE_CREATE 780 ///////////////////////////////////////////////////////////////////////////////////////// 781 782 ////////////////////////////////////////////////////////////// 783 void rpc_vfs_file_create_client( cxy_t cxy, 784 struct vfs_inode_s * inode, // in 785 uint32_t file_attr, // in 786 xptr_t * file_xp, // out 787 error_t * error ) // out 788 { 789 // RPC must be remote 790 if( cxy == local_cxy ) 791 { 792 printk("PANIC in %s : target cluster is not remote\n", __FUNCTION__ ); 793 hal_core_sleep(); 794 } 795 796 // initialise RPC descriptor header 797 rpc_desc_t rpc; 798 rpc.index = RPC_VFS_FILE_CREATE; 799 rpc.response = 1; 800 801 // set input arguments in RPC descriptor 802 rpc.args[0] = (uint64_t)(intptr_t)inode; 803 rpc.args[1] = (uint64_t)file_attr; 804 805 // register RPC request in remote RPC fifo (blocking function) 806 rpc_send_sync( cxy , &rpc ); 807 808 // get output values from RPC descriptor 809 *file_xp = (xptr_t)rpc.args[2]; 810 *error = (error_t)rpc.args[3]; 811 } 812 813 //////////////////////////////////////////// 814 void rpc_vfs_file_create_server( xptr_t xp ) 815 { 816 uint32_t file_attr; 817 vfs_inode_t * inode; 818 xptr_t file_xp; 819 error_t error; 820 821 // get client cluster identifier and pointer on RPC descriptor 822 cxy_t client_cxy = (cxy_t)GET_CXY( xp ); 823 rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); 824 825 // get arguments "file_attr" and "inode" from client RPC descriptor 826 inode = (vfs_inode_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 827 file_attr = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); 828 829 // call local kernel function 830 error = vfs_file_create( inode, 831 file_attr, 832 &file_xp ); 833 834 // set output arguments 835 hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)file_xp ); 836 hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)error ); 837 } 838 839 ///////////////////////////////////////////////////////////////////////////////////////// 840 // [15] Marshaling functions attached to RPC_VFS_FILE_DESTROY 841 ///////////////////////////////////////////////////////////////////////////////////////// 842 843 /////////////////////////////////////////////////// 844 void rpc_vfs_file_destroy_client( cxy_t cxy, 845 vfs_file_t * file ) 846 { 847 // RPC must be remote 848 if( cxy == local_cxy ) 849 { 850 printk("PANIC in %s : target cluster is not remote\n", __FUNCTION__ ); 851 hal_core_sleep(); 852 } 853 854 // initialise RPC descriptor header 855 rpc_desc_t rpc; 856 rpc.index = RPC_VFS_FILE_DESTROY; 857 rpc.response = 1; 858 859 // set input arguments in RPC descriptor 860 rpc.args[0] = (uint64_t)(intptr_t)file; 861 862 // register RPC request in remote RPC fifo (blocking function) 863 rpc_send_sync( cxy , &rpc ); 864 } 865 866 ///////////////////////////////////////////// 867 void rpc_vfs_file_destroy_server( xptr_t xp ) 868 { 869 vfs_file_t * file; 870 871 // get client cluster identifier and pointer on RPC descriptor 872 cxy_t client_cxy = (cxy_t)GET_CXY( xp ); 873 rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); 874 875 // get arguments "dentry" from client RPC descriptor 876 file = (vfs_file_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 877 878 // call local kernel function 879 vfs_file_destroy( file ); 880 } 881 882 ///////////////////////////////////////////////////////////////////////////////////////// 883 // [16] Marshaling functions attached to RPC_FATFS_GET_CLUSTER 884 ///////////////////////////////////////////////////////////////////////////////////////// 885 886 ////////////////////////////////////////////////// 887 void rpc_fatfs_get_cluster_client( cxy_t cxy, 888 mapper_t * mapper, // in 889 uint32_t first, // in 890 uint32_t page, // in 891 uint32_t * cluster, // out 892 error_t * error ) // out 893 { 894 // RPC must be remote 895 if( cxy == local_cxy ) 896 { 897 printk("PANIC in %s : target is not remote\n", __FUNCTION__ ); 898 hal_core_sleep(); 899 } 900 901 // initialise RPC descriptor header 902 rpc_desc_t rpc; 903 rpc.index = RPC_FATFS_GET_CLUSTER; 904 rpc.response = 1; 905 906 // set input arguments in RPC descriptor 907 rpc.args[0] = (uint64_t)(intptr_t)mapper; 908 rpc.args[1] = (uint64_t)first; 909 rpc.args[2] = (uint64_t)page; 910 911 // register RPC request in remote RPC fifo 912 rpc_send_sync( cxy , &rpc ); 913 914 // get output argument from rpc descriptor 915 *cluster = (uint32_t)rpc.args[3]; 916 *error = (error_t)rpc.args[4]; 917 } 918 919 ////////////////////////////////////////////// 920 void rpc_fatfs_get_cluster_server( xptr_t xp ) 921 { 922 mapper_t * mapper; 923 uint32_t first; 924 uint32_t page; 925 uint32_t cluster; 926 error_t error; 927 928 // get client cluster identifier and pointer on RPC descriptor 929 cxy_t client_cxy = (cxy_t)GET_CXY( xp ); 930 rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); 931 932 // get input arguments 933 mapper = (mapper_t *)(intptr_t)hal_remote_lpt( XPTR( client_cxy , &desc->args[0] ) ); 934 first = (uint32_t) hal_remote_lw ( XPTR( client_cxy , &desc->args[1] ) ); 935 page = (uint32_t) hal_remote_lw ( XPTR( client_cxy , &desc->args[2] ) ); 936 937 // call the kernel function 938 error = fatfs_get_cluster( mapper , first , page , &cluster ); 939 940 // set output argument 941 hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)cluster ); 942 hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error ); 943 } 944 945 ///////////////////////////////////////////////////////////////////////////////////////// 946 // [20] Marshaling functions attached to RPC_VMM_GET_REF_VSEG 748 947 ///////////////////////////////////////////////////////////////////////////////////////// 749 948 … … 804 1003 805 1004 ///////////////////////////////////////////////////////////////////////////////////////// 806 // 1005 // [21] Marshaling functions attached to RPC_VMM_GET_PTE 807 1006 ///////////////////////////////////////////////////////////////////////////////////////// 808 1007 … … 867 1066 868 1067 ///////////////////////////////////////////////////////////////////////////////////////// 869 // Marshaling functions attached to RPC_SEMAPHORE_ALLOC 870 ///////////////////////////////////////////////////////////////////////////////////////// 871 872 ////////////////////////////////////////////// 873 void rpc_semaphore_alloc_client( cxy_t cxy, 874 xptr_t * sem_xp ) // out 1068 // [22] Marshaling functions attached to RPC_KCM_ALLOC 1069 ///////////////////////////////////////////////////////////////////////////////////////// 1070 1071 ////////////////////////////////////////// 1072 void rpc_kcm_alloc_client( cxy_t cxy, 1073 uint32_t kmem_type, // in 1074 xptr_t * buf_xp ) // out 875 1075 { 876 1076 // RPC must be remote … … 886 1086 rpc.response = 1; 887 1087 1088 // set input arguments in RPC descriptor 1089 rpc.args[0] = (uint64_t)kmem_type; 1090 888 1091 // register RPC request in remote RPC fifo 889 1092 rpc_send_sync( cxy , &rpc ); 890 1093 891 1094 // get output arguments from RPC descriptor 892 * sem_xp = (xptr_t)rpc.args[0];893 } 894 895 ////////////////////////////////////// //////896 void rpc_ semaphore_alloc_server( xptr_t xp )1095 *buf_xp = (xptr_t)rpc.args[1]; 1096 } 1097 1098 ////////////////////////////////////// 1099 void rpc_kcm_alloc_server( xptr_t xp ) 897 1100 { 898 1101 // get client cluster identifier and pointer on RPC descriptor … … 900 1103 rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); 901 1104 902 // allocates memory for semaphore 1105 // get input argument "kmem_type" from client RPC descriptor 1106 uint32_t kmem_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 1107 1108 // allocates memory for kcm 903 1109 kmem_req_t req; 904 req.type = KMEM_SEM;1110 req.type = kmem_type; 905 1111 req.flags = AF_ZERO; 906 remote_sem_t * sem_ptr = kmem_alloc( &req );1112 void * buf_ptr = kmem_alloc( &req ); 907 1113 908 1114 // set output argument 909 xptr_t sem_xp = XPTR( local_cxy , sem_ptr );910 hal_remote_swd( XPTR( client_cxy , &desc->args[ 0] ) , (uint64_t)sem_xp );1115 xptr_t buf_xp = XPTR( local_cxy , buf_ptr ); 1116 hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)buf_xp ); 911 1117 } 912 1118 913 1119 ///////////////////////////////////////////////////////////////////////////////////////// 914 // Marshaling functions attached to RPC_SEMAPHORE_FREE 915 ///////////////////////////////////////////////////////////////////////////////////////// 916 917 /////////////////////////////////////////////////// 918 void rpc_semaphore_free_client( cxy_t cxy, 919 remote_sem_t * sem ) // in 1120 // [23] Marshaling functions attached to RPC_KCM_FREE 1121 ///////////////////////////////////////////////////////////////////////////////////////// 1122 1123 ///////////////////////////////////////// 1124 void rpc_kcm_free_client( cxy_t cxy, 1125 void * buf, // in 1126 uint32_t kmem_type ) // in 920 1127 { 921 1128 // RPC must be remote … … 932 1139 933 1140 // set input arguments in RPC descriptor 934 rpc.args[0] = (uint64_t)(intptr_t)sem; 1141 rpc.args[0] = (uint64_t)(intptr_t)buf; 1142 rpc.args[1] = (uint64_t)kmem_type; 935 1143 936 1144 // register RPC request in remote RPC fifo … … 938 1146 } 939 1147 940 ///////////////////////////////////// //////941 void rpc_ semaphore_free_server( xptr_t xp )1148 ///////////////////////////////////// 1149 void rpc_kcm_free_server( xptr_t xp ) 942 1150 { 943 1151 // get client cluster identifier and pointer on RPC descriptor … … 945 1153 rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); 946 1154 947 // get input argument "sem_ptr" from client RPC descriptor 948 void * sem = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 1155 // get input arguments "buf" and "kmem_type" from client RPC descriptor 1156 void * buf = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 1157 uint32_t kmem_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); 949 1158 950 1159 // releases memory 951 1160 kmem_req_t req; 952 req.type = KMEM_SEM;953 req.ptr = sem;954 kmem_free( &req);1161 req.type = kmem_type; 1162 req.ptr = buf; 1163 kmem_free( &req ); 955 1164 } 956 1165 957 1166 ///////////////////////////////////////////////////////////////////////////////////////// 958 // Marshaling functions attached to RPC_MAPPER_MOVE 959 ///////////////////////////////////////////////////////////////////////////////////////// 960 961 ////////////////////////////////////////////// 962 void rpc_mapper_move_client( cxy_t cxy, 963 mapper_t * mapper, // in 964 bool_t read, // in 965 uint32_t nb_frags, // in 966 fragment_t * frags, // in 967 error_t * error ) // out 968 { 969 // RPC must be remote 970 if( cxy == local_cxy ) 971 { 972 printk("PANIC in %s : target is not remote\n", __FUNCTION__ ); 1167 // [24] Marshaling functions attached to RPC_MAPPER_MOVE 1168 ///////////////////////////////////////////////////////////////////////////////////////// 1169 1170 /////////////////////////////////////////// 1171 void rpc_mapper_move_client( cxy_t cxy, 1172 mapper_t * mapper, // in 1173 uint32_t to_buffer, // in 1174 uint32_t file_offset, // in 1175 void * buffer, // in 1176 uint32_t size, // in 1177 error_t * error ) // out 1178 { 1179 // RPC must be remote 1180 if( cxy == local_cxy ) 1181 { 1182 printk("PANIC in %s : target cluster is not remote\n", __FUNCTION__ ); 973 1183 hal_core_sleep(); 974 1184 } … … 981 1191 // set input arguments in RPC descriptor 982 1192 rpc.args[0] = (uint64_t)(intptr_t)mapper; 983 rpc.args[1] = (uint64_t)read; 984 rpc.args[2] = (uint64_t)nb_frags; 985 rpc.args[3] = (uint64_t)(intptr_t)frags; 986 987 // register RPC request in remote RPC fifo 988 rpc_send_sync( cxy , &rpc ); 989 990 // get output argument from rpc descriptor 991 *error = (error_t)rpc.args[4]; 1193 rpc.args[1] = (uint64_t)to_buffer; 1194 rpc.args[2] = (uint64_t)file_offset; 1195 rpc.args[3] = (uint64_t)(intptr_t)buffer; 1196 rpc.args[4] = (uint64_t)size; 1197 1198 // register RPC request in remote RPC fifo (blocking function) 1199 rpc_send_sync( cxy , &rpc ); 1200 1201 // get output values from RPC descriptor 1202 *error = (error_t)rpc.args[5]; 992 1203 } 993 1204 … … 995 1206 void rpc_mapper_move_server( xptr_t xp ) 996 1207 { 997 mapper_t * mapper; 998 bool_t read; 999 uint32_t nb; 1000 void * frags; 1001 error_t error; 1002 1003 // get client cluster identifier and pointer on RPC descriptor 1004 cxy_t client_cxy = (cxy_t)GET_CXY( xp ); 1005 rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); 1006 1007 // get input arguments 1008 mapper = (mapper_t*)(intptr_t)hal_remote_lpt( XPTR( client_cxy , &desc->args[0] ) ); 1009 read = (bool_t) hal_remote_lw ( XPTR( client_cxy , &desc->args[1] ) ); 1010 nb = (uint32_t) hal_remote_lw ( XPTR( client_cxy , &desc->args[2] ) ); 1011 frags = (void*)(intptr_t) hal_remote_lpt( XPTR( client_cxy , &desc->args[3] ) ); 1012 1013 // call the mapper_move_fragments() function 1014 error = mapper_move_fragments( mapper , read , nb , XPTR( client_cxy , frags ) ); 1015 1016 // set output argument 1017 hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error ); 1018 } 1019 1020 ///////////////////////////////////////////////////////////////////////////////////////// 1021 // Marshaling functions attached to RPC_FATFS_GET_CLUSTER 1022 ///////////////////////////////////////////////////////////////////////////////////////// 1023 1024 ////////////////////////////////////////////////// 1025 void rpc_fatfs_get_cluster_client( cxy_t cxy, 1026 mapper_t * mapper, // in 1027 uint32_t first, // in 1028 uint32_t page, // in 1029 uint32_t * cluster, // out 1030 error_t * error ) // out 1031 { 1032 // RPC must be remote 1033 if( cxy == local_cxy ) 1034 { 1035 printk("PANIC in %s : target is not remote\n", __FUNCTION__ ); 1036 hal_core_sleep(); 1037 } 1038 1039 // initialise RPC descriptor header 1040 rpc_desc_t rpc; 1041 rpc.index = RPC_FATFS_GET_CLUSTER; 1042 rpc.response = 1; 1043 1044 // set input arguments in RPC descriptor 1045 rpc.args[0] = (uint64_t)(intptr_t)mapper; 1046 rpc.args[1] = (uint64_t)first; 1047 rpc.args[2] = (uint64_t)page; 1048 1049 // register RPC request in remote RPC fifo 1050 rpc_send_sync( cxy , &rpc ); 1051 1052 // get output argument from rpc descriptor 1053 *cluster = (uint32_t)rpc.args[3]; 1054 *error = (error_t)rpc.args[4]; 1055 } 1056 1057 ////////////////////////////////////////////// 1058 void rpc_fatfs_get_cluster_server( xptr_t xp ) 1059 { 1060 mapper_t * mapper; 1061 uint32_t first; 1062 uint32_t page; 1063 uint32_t cluster; 1064 error_t error; 1065 1066 // get client cluster identifier and pointer on RPC descriptor 1067 cxy_t client_cxy = (cxy_t)GET_CXY( xp ); 1068 rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); 1069 1070 // get input arguments 1071 mapper = (mapper_t*)(intptr_t)hal_remote_lpt( XPTR( client_cxy , &desc->args[0] ) ); 1072 first = (uint32_t) hal_remote_lw ( XPTR( client_cxy , &desc->args[1] ) ); 1073 page = (uint32_t) hal_remote_lw ( XPTR( client_cxy , &desc->args[2] ) ); 1074 1075 // call the kernel function 1076 error = fatfs_get_cluster( mapper , first , page , &cluster ); 1077 1078 // set output argument 1079 hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)cluster ); 1080 hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error ); 1208 mapper_t * mapper; 1209 uint32_t to_buffer; 1210 uint32_t file_offset; 1211 void * buffer; 1212 uint32_t size; 1213 error_t error; 1214 1215 // get client cluster identifier and pointer on RPC descriptor 1216 cxy_t client_cxy = (cxy_t)GET_CXY( xp ); 1217 rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); 1218 1219 // get arguments from client RPC descriptor 1220 mapper = (mapper_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 1221 to_buffer = hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); 1222 file_offset = hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) ); 1223 buffer = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) ); 1224 size = hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) ); 1225 1226 // call local kernel function 1227 error = mapper_move( mapper, 1228 to_buffer, 1229 file_offset, 1230 buffer, 1231 size ); 1232 1233 // set output argument to client RPC descriptor 1234 hal_remote_swd( XPTR( client_cxy , &desc->args[5] ) , (uint64_t)error ); 1081 1235 } 1082 1236 -
trunk/kernel/kern/rpc.h
r16 r23 2 2 * rpc.h - RPC (Remote Procedure Call) operations definition. 3 3 * 4 * Authors Mohamed Karaoui (2015) 5 * Alain Greiner (2016) 4 * Author Alain Greiner (2016,2017) 6 5 * 7 6 * Copyright (c) UPMC Sorbonne Universites … … 43 42 struct vfs_inode_s; 44 43 struct vfs_dentry_s; 44 struct vfs_file_s; 45 45 struct thread_s; 46 46 struct mapper_s; … … 63 63 RPC_THREAD_USER_CREATE = 4, 64 64 RPC_THREAD_KERNEL_CREATE = 5, 65 RPC_SIGNAL_RISE = 6, 65 66 66 67 RPC_VFS_INODE_CREATE = 10, … … 68 69 RPC_VFS_DENTRY_CREATE = 12, 69 70 RPC_VFS_DENTRY_DESTROY = 13, 71 RPC_VFS_FILE_CREATE = 14, 72 RPC_VFS_FILE_DESTROY = 15, 73 RPC_FATFS_GET_CLUSTER = 16, 70 74 71 75 RPC_VMM_GET_REF_VSEG = 20, 72 76 RPC_VMM_GET_PTE = 21, 73 RPC_ SEMAPHORE_ALLOC= 22,74 RPC_ SEMAPHORE_FREE= 23,77 RPC_KCM_ALLOC = 22, 78 RPC_KCM_FREE = 23, 75 79 RPC_MAPPER_MOVE = 24, 76 80 77 RPC_FATFS_GET_CLUSTER = 30, 78 79 RPC_MAX_INDEX = 31, 81 RPC_MAX_INDEX = 30, 80 82 } 81 83 rpc_index_t; … … 96 98 rpc_index_t index; // index of requested RPC service 97 99 volatile uint32_t response; // response valid when 0 98 uint64_t args[ 8];// input/output arguments buffer100 uint64_t args[10]; // input/output arguments buffer 99 101 } 100 102 rpc_desc_t; … … 192 194 void __attribute__((noinline)) rpc_undefined(); 193 195 196 197 198 194 199 /**********************************************************************************/ 195 200 /******* Marshalling functions attached to the various RPCs ***********************/ … … 197 202 198 203 /*********************************************************************************** 199 * The RPC_PMEM_GET_PAGES allocates one or several pages in a remote cluster,204 * [0] The RPC_PMEM_GET_PAGES allocates one or several pages in a remote cluster, 200 205 * and returns the PPN of the first allocated page. 201 206 *********************************************************************************** … … 213 218 214 219 /*********************************************************************************** 215 * The RPC_PROCESS_PID_ALLOC allocates one new PID in a remote cluster, registers220 * [1] The RPC_PROCESS_PID_ALLOC allocates one new PID in a remote cluster, registers 216 221 * the new process in the remote cluster, and returns the PID, and an error code. 217 222 *********************************************************************************** … … 229 234 230 235 /*********************************************************************************** 231 * The RPC_PROCESS_EXEC creates a process descriptor copy, in a remote cluster236 * [2] The RPC_PROCESS_EXEC creates a process descriptor copy, in a remote cluster 232 237 * and initializes if from information found in the reference process descriptor. 233 238 * This remote cluster becomes the new reference cluster. … … 244 249 245 250 /*********************************************************************************** 246 * The RPC_PROCESS_KILL is actually a multicast RPC sent by the reference cluster251 * [3] The RPC_PROCESS_KILL is actually a multicast RPC sent by the reference cluster 247 252 * to other clusters containing a process descriptor copy, to destroy these copies. 248 253 *********************************************************************************** … … 254 259 255 260 /*********************************************************************************** 256 * The RPC_THREAD_USER_CREATE creates an user thread in the server cluster,257 * as specified by the pthread_attr_t argument. It returns the local pointer258 * on thethread descriptor in server cluster, and an error code.259 * It is called by the pthread_createsystem call.261 * [4] The RPC_THREAD_USER_CREATE creates an user thread in the server cluster, 262 * as specified by the arguments. It returns an extended pointer on the new 263 * thread descriptor in server cluster, and an error code. 264 * It is called by the sys_thread_create() system call. 260 265 *********************************************************************************** 261 266 * @ cxy : server cluster identifier. … … 265 270 **********************************************************************************/ 266 271 void rpc_thread_user_create_client( cxy_t cxy, 272 pid_t pid, 273 void * start_func, 274 void * start_arg, 267 275 struct pthread_attr_s * attr, 268 276 xptr_t * thread_xp, … … 272 280 273 281 /*********************************************************************************** 274 * The RPC_THREAD_KERNEL_CREATE creates a kernel thread in the server cluster,282 * [5] The RPC_THREAD_KERNEL_CREATE creates a kernel thread in the server cluster, 275 283 * as specified by the type, func and args arguments. It returns the local pointer 276 284 * on the thread descriptor in server cluster and an error code. 277 * It is used by the dev_init() function to cre tae the device server thread.285 * It is used by the dev_init() function to create the device server thread. 278 286 *********************************************************************************** 279 287 * @ cxy : server cluster identifier. … … 293 301 void rpc_thread_kernel_create_server( xptr_t xp ); 294 302 303 /*********************************************************************************** 304 * [6] The RPC_SIGNAL_RISE ask a target cluster to register a given signal in 305 * all threads descriptors of a given process. 306 * It is used by the sys_kill() function. 307 *********************************************************************************** 308 * @ cxy : server cluster identifier. 309 * @ process : [in] local pointer on target process descriptor in server. 310 * @ sig_id : [in] signal index. 311 **********************************************************************************/ 312 void rpc_signal_rise_client( cxy_t cxy, 313 struct process_s * process, 314 uint32_t sig_id ); 315 316 void rpc_signal_rise_server( xptr_t xp ); 317 295 318 /*********************************************************************************** 296 * The RPC_VFS_INODE_CREATE creates an inode and the associated mapper in a319 * [10] The RPC_VFS_INODE_CREATE creates an inode and the associated mapper in a 297 320 * remote cluster. The parent dentry must have been previously created. 298 321 * It returns an extended pointer on the created inode. 299 322 *********************************************************************************** 300 * @ cxy : server cluster identifier 301 * @ dentry_xp : [in] extended pointer on parent dentry. 302 * @ type : [in] file system type. 303 * @ attr : [in] TODO ??? 304 * @ mode : [in] access mode. 305 * @ uid : [in] user ID 306 * @ gid : [in] group ID 307 * @ inode_xp : [out] buffer for extended pointer on created inode. 308 * @ error : [out] error status (0 if success). 323 * @ cxy : server cluster identifier. 324 * @ dentry_xp : [in] extended pointer on parent dentry. 325 * @ fs_type : [in] file system type. 326 * @ inode_type : [in] file system type. 327 * @ attr : [in] inode attributes. 328 * @ rights : [in] access rights 329 * @ uid : [in] user ID 330 * @ gid : [in] group ID 331 * @ inode_xp : [out] buffer for extended pointer on created inode. 332 * @ error : [out] error status (0 if success). 309 333 **********************************************************************************/ 310 334 void rpc_vfs_inode_create_client( cxy_t cxy, 311 335 xptr_t dentry_xp, 312 uint32_t type, 336 uint32_t fs_type, 337 uint32_t inode_type, 313 338 uint32_t attr, 314 uint32_t mode,339 uint32_t rights, 315 340 uint32_t uid, 316 341 uint32_t gid, … … 321 346 322 347 /*********************************************************************************** 323 * The RPC_VFS_INODE_DESTROY releases memory allocated for an inode descriptor348 * [11] The RPC_VFS_INODE_DESTROY releases memory allocated for an inode descriptor 324 349 * and for the associated mapper in a remote cluster. 325 350 *********************************************************************************** … … 333 358 334 359 /*********************************************************************************** 335 * The RPC_VFS_DENTRY_CREATE creates a dentry in a remote cluster.360 * [12] The RPC_VFS_DENTRY_CREATE creates a dentry in a remote cluster. 336 361 * It returns an extended pointer on the created dentry. 337 362 *********************************************************************************** … … 353 378 354 379 /*********************************************************************************** 355 * The RPC_VFS_DENTRY_DESTROY releases memory allocated for an dentry descriptor380 * [13] The RPC_VFS_DENTRY_DESTROY releases memory allocated for an dentry descriptor 356 381 * in a remote cluster. 357 382 *********************************************************************************** … … 364 389 void rpc_vfs_dentry_destroy_server( xptr_t xp ); 365 390 366 367 368 369 /*********************************************************************************** 370 * The RPC_VMM_GET_REF_VSEG returns an extended pointer 391 /*********************************************************************************** 392 * [14] The RPC_VFS_FILE_CREATE creates a file descriptor in a remote cluster. 393 * It returns an extended pointer on the created file structure. 394 *********************************************************************************** 395 * @ cxy : server cluster identifier 396 * @ inode : [in] local pointer on parent inode. 397 * @ file_attr : [in] new file attributes. 398 * @ file_xp : [out] buffer for extended pointer on created file. 399 * @ error : [out] error status (0 if success). 400 **********************************************************************************/ 401 void rpc_vfs_file_create_client( cxy_t cxy, 402 struct vfs_inode_s * inode, 403 uint32_t file_attr, 404 xptr_t * file_xp, 405 error_t * error ); 406 407 void rpc_vfs_file_create_server( xptr_t xp ); 408 409 /*********************************************************************************** 410 * [15] The RPC_VFS_FILE_DESTROY releases memory allocated for a file descriptor 411 * in a remote cluster. 412 *********************************************************************************** 413 * @ cxy : server cluster identifier 414 * @ file : [in] local pointer on file. 415 **********************************************************************************/ 416 void rpc_vfs_file_destroy_client( cxy_t cxy, 417 struct vfs_file_s * file ); 418 419 void rpc_vfs_file_destroy_server( xptr_t xp ); 420 421 /*********************************************************************************** 422 * [16] The RPC_FATFS_GET_CLUSTER can be send by any thread running in a "client" 423 * cluster to scan the FAT mapper, stored in a remote "server" cluster, and get 424 * from the mapper the local pointer on a given page. 425 *********************************************************************************** 426 * @ cxy : server cluster identifier. 427 * @ mapper : [in] local pointer on FAT mapper. 428 * @ first : [in] FATFS cluster index allocated to first page of file. 429 * @ page : [in] page index in file. 430 * @ cluster : [out] local pointer on buffer for found FATFS cluster index. 431 * @ error : [out] local pointer on buffer for error code (in client cluster). 432 **********************************************************************************/ 433 void rpc_fatfs_get_cluster_client( cxy_t cxy, 434 struct mapper_s * mapper, 435 uint32_t first, 436 uint32_t page, 437 uint32_t * cluster, 438 error_t * error ); 439 440 void rpc_fatfs_get_cluster_server( xptr_t xp ); 441 442 /*********************************************************************************** 443 * [20] The RPC_VMM_GET_REF_VSEG returns an extended pointer 371 444 * on the vseg containing a given virtual address in a given process. 372 445 * The server cluster is supposed to be the reference cluster. … … 386 459 387 460 /*********************************************************************************** 388 * The RPC_VMM_GET_PTE returns in the "ppn" and "attr" arguments the PTE value461 * [21] The RPC_VMM_GET_PTE returns in the "ppn" and "attr" arguments the PTE value 389 462 * for a given VPN in a given process. 390 463 * The server cluster is supposed to be the reference cluster, and the vseg … … 410 483 411 484 /*********************************************************************************** 412 * The RPC_SEMAPHORE_ALLOC allocates memory for a semaphore in a remote cluster, 413 * and returns an extended pointer on the created semaphore. 414 It returns NULL if physical memory cannot be allocated. 415 *********************************************************************************** 416 * @ cxy : server cluster identifier. 417 * @ sem_xp : [out] buffer for extended pointer on semaphore. 418 **********************************************************************************/ 419 void rpc_semaphore_alloc_client( cxy_t cxy, 420 xptr_t * sem_xp ); 421 422 void rpc_semaphore_alloc_server( xptr_t xp ); 423 424 /*********************************************************************************** 425 * The RPC_SEMAPHORE_FREE releases memory allocated for a semaphore 485 * [22] The RPC_KCM_ALLOC allocates memory from a given KCM in a remote cluster, 486 * and returns an extended pointer on the allocated object. 487 It returns XPTR_NULL if physical memory cannot be allocated. 488 *********************************************************************************** 489 * @ cxy : server cluster identifier. 490 * @ kmem_type : [in] KCM object type (as defined in kmem.h). 491 * @ buf_xp : [out] buffer for extended pointer on allocated buffer. 492 **********************************************************************************/ 493 void rpc_kcm_alloc_client( cxy_t cxy, 494 uint32_t kmem_type, 495 xptr_t * buf_xp ); 496 497 void rpc_kcm_alloc_server( xptr_t xp ); 498 499 /*********************************************************************************** 500 * [23] The RPC_KCM_FREE releases memory allocated for a KCM object of a given type, 426 501 * in a remote cluster. 427 502 *********************************************************************************** 428 * @ cxy : server cluster identifier. 429 * @ sem : [in] local pointer on semaphore. 430 **********************************************************************************/ 431 void rpc_semaphore_free_client( cxy_t cxy, 432 struct remote_sem_s * sem ); 433 434 void rpc_semaphore_free_server( xptr_t xp ); 435 436 /*********************************************************************************** 437 * The RPC_MAPPER_MOVE can be send by any thread running in a "client" cluster 438 * to the "server" cluster containing the mapper of a given file. The service is 439 * to move data between the mapper and an user buffer. This user buffer is described 440 * as a set of fragments. Each fragment is contained in one single physical page. 441 * It is defined by four parameters : size / file_offset / ppn / page_offset, 442 * defined in the mapper.h file. The client thread is in charge of building 443 * the fragments array covering the user buffer. 444 * As each fragments can be stored in a different cluster, and this fragment can 445 * be stored in two successive pages in the radix tree, each fragment is moved 446 * using one or two different hal_remote_memcpy(). 447 *********************************************************************************** 448 * @ cxy : server cluster identifier. 449 * @ inode : [in] local pointer on inode (in server cluster). 450 * @ read : [in] mapper to buffer if true / buffer to mapper if false. 451 * @ nb_frags : [in] number of fragments in fragments array. 452 * @ frags : [in] local pointer on fragments array (in client cluster). 453 * @ error : [out] local pointer on buffer for error code (in client cluster). 454 **********************************************************************************/ 455 void rpc_mapper_move_client( cxy_t cxy, 456 struct mapper_s * mapper, 457 bool_t read, 458 uint32_t nb_frags, 459 struct fragment_s * frags, 460 error_t * error ); 503 * @ cxy : server cluster identifier. 504 * @ buf : [in] local pointer on allocated buffer. 505 * @ kmem_type : [in] KCM object type (as defined in kmem.h). 506 **********************************************************************************/ 507 void rpc_kcm_free_client( cxy_t cxy, 508 void * buf, 509 uint32_t kmem_type ); 510 511 void rpc_kcm_free_server( xptr_t xp ); 512 513 /*********************************************************************************** 514 * [24] The RPC_MAPPER_MOVE is called by the vfs_move() function. 515 * It allows a client thread to requires a remote mapper to move data to/from 516 * an user buffer, as specified by the arguments. 517 *********************************************************************************** 518 * @ cxy : server cluster identifier. 519 * @ mapper : [in] local pointer on mapper 520 * @ to_buffer : [in] move data from buffer to mapper if non zero. 521 * @ file_offset : [in] first byte to move in mapper 522 * @ buffer : [in] pointer on buffer in user space 523 * @ size : [in] number of bytes to move 524 * @ error : [out] error status (0 if success). 525 **********************************************************************************/ 526 void rpc_mapper_move_client( cxy_t cxy, 527 struct mapper_s * mapper, 528 uint32_t to_buffer, 529 uint32_t file_offset, 530 void * buffer, 531 uint32_t size, 532 error_t * error ); 461 533 462 534 void rpc_mapper_move_server( xptr_t xp ); 463 535 464 /*********************************************************************************** 465 * The RPC_FATFS_GET_CLUSTER can be send by any thread running in a "client" cluster 466 * to scan the FAT mapper, stored in a remote "server" cluster, and get the FATFS 467 * cluster index of a given page of a given file. 468 *********************************************************************************** 469 * @ cxy : server cluster identifier. 470 * @ mapper : [in] local pointer on FAT mapper. 471 * @ first : [in] FATFS cluster index allocated to first page of file. 472 * @ page : [in] page index in file. 473 * @ cluster : [out] local pointer on buffer for found FATFS cluster index. 474 * @ error : [out] local pointer on buffer for error code (in client cluster). 475 **********************************************************************************/ 476 void rpc_fatfs_get_cluster_client( cxy_t cxy, 477 struct mapper_s * mapper, 478 uint32_t first, 479 uint32_t page, 480 uint32_t * cluster, 481 error_t * error ); 482 483 void rpc_fatfs_get_cluster_server( xptr_t xp ); 536 537 484 538 485 539 #endif -
trunk/kernel/kern/signal.c
r5 r23 23 23 24 24 #include <hal_types.h> 25 #include <errno.h> 25 #include <hal_atomic.h> 26 #include <printk.h> 26 27 #include <thread.h> 27 #include <process.h> 28 #include <core.h> 28 #include <spinlock.h> 29 29 #include <signal.h> 30 31 ////////////////////////////////////// 32 void signal_rise( process_t * process, 33 uint32_t sig_id ) 34 { 35 // get the lock protecting the set of local threads 36 spinlock_lock( &process->th_lock ); 37 38 // loop on local threads 39 thread_t * thread; 40 uint32_t i; 41 for( i = 0 ; i < process->th_nr ; i++ ) 42 { 43 thread = process->th_tbl[i]; 44 hal_atomic_or( &thread->signals , (1 << sig_id) ); 45 46 signal_dmsg("\n[INFO] %s : thread %x in process %x received signal %d\n", 47 __FUNCTION__, thread->trdid , process->pid , sig_id ); 48 } 49 50 // release the lock 51 spinlock_unlock( &process->th_lock ); 52 53 } // end signal_rise() 54 55 /* 30 56 31 57 SIGNAL_HANDLER(kill_sigaction) 32 58 { 33 struct thread_s *this; 34 35 this = CURRENT_THREAD; 36 this->state = S_KERNEL; 59 thread_s * this = CURRENT_THREAD; 37 60 38 printk( INFO, "INFO: Recieved signal %d, pid %d, tid %x, core %d [ KILLED ]\n",61 printk("\n[INFO] %s : threadReceived signal %d, pid %d, tid %x, core %d [ KILLED ]\n", 39 62 sig, 40 63 this->process->pid, … … 45 68 } 46 69 47 /////////////////////////////////////////////// ///70 /////////////////////////////////////////////// 48 71 void signal_manager_init( process_t * process ) 49 72 { … … 53 76 } 54 77 55 ////////////////////////////////////// 56 void signal_rise( process_t * process, 57 uint32_t sig)78 79 ///////////////////////////////////// 80 void signal_notify( thread_t * this ) 58 81 { 59 thread_t * thread; 60 uint32_t i; 82 uint32_t sig_state; 83 uint32_t sig; 84 sig_mgr_t * sig_mgr; 85 uint32_t irq_state; 61 86 62 spinlock_lock( &process->th_lock ); 63 64 for( i = 0 ; i < process->th_nr ; i++ ) 65 { 66 thread = process->th_tbl[i]; 67 hal_atomic_or( &thread->signals , (1 << sig) ); 68 } 69 70 spinlock_unlock( &process->th_lock ); 71 72 sig_dmsg("\n[INFO] %s : %d threads have been signaled for process %d\n", 73 __FUNCTION__, process->th_nr , process->pid ); 74 75 } // end signal_rise() 76 77 /////////////////////////////////////////// 78 RPC_DECLARE( __signal_rise, \ 79 RPC_RET( RPC_RET_PTR(error_t, err)), \ 80 RPC_ARG( RPC_ARG_VAL(pid_t, pid), \ 81 RPC_ARG_VAL(uint32_t, sig)) \ 82 ) 83 { 84 process_t * process; 85 struct hnode_s *hnode; 86 87 /* Avoid killing process0 and init */ 88 /* FIXME: Zero should not be hard-coded but obtains with something like MAIN_KERN */ 89 if( ((pid == PID_MIN_GLOBAL) || (pid == PID_MIN_GLOBAL+1)) 90 && (current_cid == 0) ) 91 { 92 *err = EPERM; 93 sig_dmsg(1, "%s: can't kill process %u on cluster %u\n", \ 94 __FUNCTION__, PID_GET_LOCAL(pid), current_cid); 95 goto SYS_RISE_ERR_PID; 96 } 97 98 /* Step 1 : lock the process manager */ 99 processs_manager_lock(); 100 101 /* Step 2 : Get the process' address */ 102 /* Case 1 : current cluster is the anchor and the owner. */ 103 if ( PID_GET_CLUSTER(pid) == current_cid ) 104 { 105 sig_dmsg(1, "%s: process %u is in the processs manager array of cluster %u\n", \ 106 __FUNCTION__, pid, current_cid); 107 process = process_lookup(pid)->process; 108 109 } 110 else /* Case 2 : current cluster is not the anchor, so the struct 111 * process_s is in its hash table. 112 */ 113 { 114 sig_dmsg(1, "%s: process %u is in the processs manager hash table of cluster %u\n", \ 115 __FUNCTION__, pid, current_cid); 116 hnode = hfind(processs_manager_get_htable(), (void*)pid); 117 process = ( process_t*) container_of(hnode, \ 118 process_t, t_hnode); 119 } 120 121 /* Step 4 : check process' address */ 122 if ( process == NULL ) 123 { 124 *err = ESRCH; 125 goto SYS_RISE_ERR; 126 } 127 128 /* Step 5 : deliver signal */ 129 if((sig == SIGTERM) || (sig == SIGKILL)) 130 *err = signal_rise_all(process, sig); 131 else 132 *err = signal_rise_one(process, sig); 133 134 /* Step 6 : unlock processs manager */ 135 processs_manager_unlock(); 136 137 return; 138 139 SYS_RISE_ERR: 140 processs_manager_unlock(); 141 SYS_RISE_ERR_PID: 142 sig_dmsg(1, "%s: Cluster %u has not deliver signal %u to process %u (err %u)\n", \ 143 __FUNCTION__, current_cid, sig, err ); 144 145 return; 146 } 147 148 /////////////////////////////// 149 error_t sys_kill( pid_t pid, 150 uint32_t sig) 151 { 152 cxy_t owner_cxy; // process owner cluster 153 lpid_t owner_lpid; // local process identifier 154 xptr_t root_xp; // extended pointer on root of xlist of process copies 155 xptr_t lock_xp; // extended pointer on remote_spinlock protecting this list 156 xptr_t iter_xp; // iterator for process copies list 157 xptr_t process_xp; // local pointer on process copy 158 cxy_t process_cxy; // cluster of process copy 159 process_t * process_ptr; // local pointer on process copy 160 error_t error; 161 162 // get local pointer on local cluster manager 163 cluster_t * cluster = LOCAL_CLUSTER; 164 165 // get owner process cluster and lpid 166 owner_cxy = CXY_FROM_PID( pid ); 167 owner_lpid = LPID_FROM_PID( pid ); 168 169 // get extended pointers on copies root and lock 170 root_xp = XPTR( owner_cxy , &cluster->copies_root[lpid] ); 171 lock_xp = XPTR( owner_cxy , &cluster->copies_lock[lpid] ); 172 173 // take the lock protecting the copies 174 remote_spinlock_lock( lock_xp ); 175 176 // TODO the loop below sequencialize the RPCs 177 // they could be pipelined... 178 179 // traverse the list of copies 180 XLIST_FOREACH( root_xp , iter_xp ) 181 { 182 process_xp = XLIST_ELEMENT( iter_xp , process_t , copies_list ); 183 process_cxy = GET_CXY( process_xp ); 184 process_ptr = (process_t *)GET_PTR( process_xp ); 185 186 if( process_xy == local_cxy ) // process copy is local 187 { 188 error = signal_rise( process_ptr , sig ); 189 } 190 else // process copy is remote 191 { 192 rpc_signal_rise_client( process_cxy , process_ptr , sig ); 193 } 194 } 195 196 return 0; 197 } 198 199 //////////////////////////////////// 200 void signal_notify( thread_s * this) 201 { 202 register uint32_t sig_state; 203 register uint32_t sig; 204 register struct sig_mgr_s *sig_mgr; 205 uint32_t irq_state; 206 207 sig_state = this->info.sig_state & this->info.sig_mask; 87 sig_state = this->signals; 208 88 sig = 0; 209 89 … … 242 122 } 243 123 } 124 */ -
trunk/kernel/kern/signal.h
r16 r23 4 4 * Author Ghassan Almaless (2008,2009,2010,2011,2012) 5 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016 )6 * Alain Greiner (2016,2017) 7 7 * 8 8 * Copyright (c) UPMC Sorbonne Universites … … 33 33 #define SIG_ERROR -1L 34 34 35 #define SIGHUP 1 /*! hangup */36 #define SIGINT 2 /*! interrupt */37 #define SIGQUIT 3 /*! quit */38 #define SIGILL 4 /*! illegal instruction (not reset when caught) */39 #define SIGTRAP 5 /*! trace trap (not reset when caught) */40 #define SIGIOT 6 /*! IOT instruction */41 #define SIGABRT 6 /*! used by abort, replace SIGIOT in the future */42 #define SIGEMT 7 /*! EMT instruction */43 #define SIGFPE 8 /*! floating point exception */44 #define SIGKILL 9 /*! kill (cannot be caught or ignored) */45 #define SIGBUS 10 /*! bus error */46 #define SIGSEGV 11 /*! segmentation violation */47 #define SIGSYS 12 /*! bad argument to system call */48 #define SIGPIPE 13 /*! write on a pipe with no one to read it */49 #define SIGALRM 14 /*! alarm clock */50 #define SIGTERM 15 /*! software termination signal from kill */51 #define SIGURG 16 /*! urgent condition on IO channel */52 #define SIGSTOP 17 /*! sendable stop signal not from tty */53 #define SIGTSTP 18 /*! stop signal from tty */54 #define SIGCONT 19 /*! continue a stopped process */55 #define SIGCHLD 20 /*! to parent on child stop or exit */56 #define SIGCLD 20 /*! System V name for SIGCHLD */57 #define SIGTTIN 21 /*! to readers pgrp upon background tty read */58 #define SIGTTOU 22 /*! like TTIN for output if (tp->t_local<OSTOP) */59 #define SIGIO 23 /*! input/output possible signal */60 #define SIGPOLL SIGIO /*! System V name for SIGIO */61 #define SIGXCPU 24 /*! exceeded CPU time limit */62 #define SIGXFSZ 25 /*! exceeded file size limit */63 #define SIGVTALRM 26 /*! virtual time alarm */64 #define SIGPROF 27 /*! profiling time alarm */65 #define SIGWINCH 28 /*! window changed */66 #define SIGLOST 29 /*! resource lost (eg, record-lock lost) */67 #define SIGUSR1 30 /*! user defined signal 1 */68 #define SIGUSR2 31 /*! user defined signal 2 */69 #define SIG_NR 32 /*! signal 0 implied */35 #define SIGHUP 1 /*! hangup */ 36 #define SIGINT 2 /*! interrupt */ 37 #define SIGQUIT 3 /*! quit */ 38 #define SIGILL 4 /*! illegal instruction (not reset when caught) */ 39 #define SIGTRAP 5 /*! trace trap (not reset when caught) */ 40 #define SIGIOT 6 /*! IOT instruction */ 41 #define SIGABRT 6 /*! used by abort, replace SIGIOT in the future */ 42 #define SIGEMT 7 /*! EMT instruction */ 43 #define SIGFPE 8 /*! floating point exception */ 44 #define SIGKILL 9 /*! kill (cannot be caught or ignored) */ 45 #define SIGBUS 10 /*! bus error */ 46 #define SIGSEGV 11 /*! segmentation violation */ 47 #define SIGSYS 12 /*! bad argument to system call */ 48 #define SIGPIPE 13 /*! write on a pipe with no one to read it */ 49 #define SIGALRM 14 /*! alarm clock */ 50 #define SIGTERM 15 /*! software termination signal from kill */ 51 #define SIGURG 16 /*! urgent condition on IO channel */ 52 #define SIGSTOP 17 /*! sendable stop signal not from tty */ 53 #define SIGTSTP 18 /*! stop signal from tty */ 54 #define SIGCONT 19 /*! continue a stopped process */ 55 #define SIGCHLD 20 /*! to parent on child stop or exit */ 56 #define SIGCLD 20 /*! System V name for SIGCHLD */ 57 #define SIGTTIN 21 /*! to readers pgrp upon background tty read */ 58 #define SIGTTOU 22 /*! like TTIN for output if (tp->t_local<OSTOP) */ 59 #define SIGIO 23 /*! input/output possible signal */ 60 #define SIGPOLL SIGIO /*! System V name for SIGIO */ 61 #define SIGXCPU 24 /*! exceeded CPU time limit */ 62 #define SIGXFSZ 25 /*! exceeded file size limit */ 63 #define SIGVTALRM 26 /*! virtual time alarm */ 64 #define SIGPROF 27 /*! profiling time alarm */ 65 #define SIGWINCH 28 /*! window changed */ 66 #define SIGLOST 29 /*! resource lost (eg, record-lock lost) */ 67 #define SIGUSR1 30 /*! user defined signal 1 */ 68 #define SIGUSR2 31 /*! user defined signal 2 */ 69 #define SIG_NR 32 /*! signal 0 implied */ 70 70 71 71 #define SIG_DEFAULT_MASK 0xFFEEFFFF … … 81 81 82 82 /******************************************************************************************* 83 * This structure ... 83 * This structure ... TODO 84 84 ******************************************************************************************/ 85 85 … … 104 104 105 105 /******************************************************************************************* 106 * This structure ... 106 * This structure ... TODO 107 107 ******************************************************************************************/ 108 108 … … 122 122 123 123 /******************************************************************************************* 124 * This structure TODO124 * This structure ... TODO 125 125 ******************************************************************************************/ 126 126 … … 132 132 sig_mgr_t; 133 133 134 135 134 /******************************************************************************************* 136 * This function TODO 137 ******************************************************************************************/ 138 int sys_signal ( uint32_t sig, 139 sa_handler_t * handler ); 140 141 /******************************************************************************************* 142 * This function TODO 135 * This function ... TODO 143 136 ******************************************************************************************/ 144 137 int sys_sigreturn_setup( void * sigreturn_func ); 145 138 146 /*******************************************************************************************147 * This function register the signal <sig> in the bit_vector of all threads of a given148 * process identified by its <pid>, in all clusters containing threads for this process.149 * It can be executed by any thread running in any cluster, as this function uses150 * remote access to traverse the list of process copies, and the RPC_RISE_SIGNAL151 * to deliver the signal to all involved clusters.152 * The list of process copies is rooted in the owner cluster.153 ******************************************************************************************/154 int sys_kill( pid_t pid,155 uint32_t sig );156 139 157 140 /******************************************************************************************* 158 * This function TODO141 * This function ... TODO 159 142 ******************************************************************************************/ 160 error_tsignal_manager_init( struct process_s * process );143 void signal_manager_init( struct process_s * process ); 161 144 162 145 /******************************************************************************************* … … 165 148 * It must be executed by a thread running in the same cluster as the target threads 166 149 * (can be a local thread or a RPC thread). 150 ******************************************************************************************* 151 * @ process : local pointer on local target process. 152 * @ sig_id : signal type. 167 153 ******************************************************************************************/ 168 error_tsignal_rise( struct process_s * process,169 uint32_t sig);154 void signal_rise( struct process_s * process, 155 uint32_t sig_id ); 170 156 171 157 /******************************************************************************************* -
trunk/kernel/kern/thread.c
r16 r23 3 3 * 4 4 * Author Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016) 5 * Alain Greiner (2016,2017) 7 6 * 8 7 * Copyright (c) UPMC Sorbonne Universites … … 74 73 static thread_t * thread_alloc() 75 74 { 76 page_t * page; 77 kmem_req_t req; 75 page_t * page; // pointer on page descriptor containing thread descriptor 76 kmem_req_t req; // kmem request 78 77 79 78 // allocates memory for thread descriptor + kernel stack … … 84 83 85 84 // return pointer on new thread descriptor 86 if( page == NULL ) 87 { 88 printk("\n[ERROR] in %s : no memory for thread descriptor\n", __FUNCTION__ ); 89 return NULL; 90 } 91 else 92 { 93 return (thread_t *)ppm_page2base( page ); 94 } 95 } // end thread_alloc() 85 if( page == NULL ) return NULL; 86 else return (thread_t *)ppm_page2base( page ); 87 } 88 89 ///////////////////////////////////////////////////////////////////////////////////// 90 // This static function releases the physical memory for a thread descriptor. 91 // It can be called by the three functions: 92 // - thread_user_create() 93 // - thread_user_fork() 94 // - thread_kernel_create() 95 ///////////////////////////////////////////////////////////////////////////////////// 96 // @ thread : pointer on thread descriptor. 97 ///////////////////////////////////////////////////////////////////////////////////// 98 static void thread_release( thread_t * thread ) 99 { 100 kmem_req_t req; 101 102 req.type = KMEM_PAGE; 103 req.ptr = ppm_base2page( thread ); 104 kmem_free( &req ); 105 } 96 106 97 107 ///////////////////////////////////////////////////////////////////////////////////// … … 194 204 195 205 ///////////////////////////////////////////////////////// 196 error_t thread_user_create( thread_t ** new_thread, 206 error_t thread_user_create( pid_t pid, 207 void * start_func, 208 void * start_arg, 197 209 pthread_attr_t * attr, 198 intptr_t u_stack_base, 199 uint32_t u_stack_size ) 210 thread_t ** new_thread ) 200 211 { 201 212 error_t error; … … 203 214 process_t * process; // pointer to local process descriptor 204 215 lid_t core_lid; // selected core local index 205 kmem_req_t req; // kmem request (for release) 206 207 thread_dmsg("\n[INFO] %s : enters\n", __FUNCTION__ ); 208 209 cluster_t * local_cluster = LOCAL_CLUSTER; 216 vseg_t * vseg; // stack vseg 217 218 thread_dmsg("\n[INFO] %s : enters for process %x\n", __FUNCTION__ , pid ); 219 220 // get process descriptor local copy 221 process = process_get_local_copy( pid ); 222 223 if( process == NULL ) 224 { 225 printk("\n[ERROR] in %s : cannot get process descriptor %x\n", 226 __FUNCTION__ , pid ); 227 return ENOMEM; 228 } 210 229 211 230 // select a target core in local cluster 212 if( attr-> flags & PT_FLAG_CORE_DEFINED ) core_lid = attr->lid;213 else core_lid = cluster_select_local_core();231 if( attr->attributes & PT_ATTR_CORE_DEFINED ) core_lid = attr->lid; 232 else core_lid = cluster_select_local_core(); 214 233 215 234 // check core local index 216 if( core_lid >= local_cluster->cores_nr ) return EINVAL; 217 218 // get process descriptor local copy 219 process = process_get_local_copy( attr->pid ); 220 if( process == NULL ) return ENOMEM; 235 if( core_lid >= LOCAL_CLUSTER->cores_nr ) 236 { 237 printk("\n[ERROR] in %s : illegal core index attribute = %d\n", 238 __FUNCTION__ , core_lid ); 239 240 return EINVAL; 241 } 242 243 // allocate a stack from local VMM 244 vseg = vmm_create_vseg( process, 0 , 0 , VSEG_TYPE_STACK ); 245 246 if( vseg == NULL ); 247 { 248 printk("\n[ERROR] in %s : cannot create stack vseg\n", __FUNCTION__ ); 249 return ENOMEM; 250 } 221 251 222 252 // allocates memory tor thread descriptor 223 253 thread = thread_alloc(); 224 254 225 if( thread == NULL ) return ENOMEM; 255 if( thread == NULL ) 256 { 257 printk("\n[ERROR] in %s : cannot create new thread\n", __FUNCTION__ ); 258 vmm_remove_vseg( vseg ); 259 return ENOMEM; 260 } 226 261 227 262 // initializes thread descriptor … … 229 264 process, 230 265 THREAD_USER, 231 attr->entry_func,232 attr->entry_args,266 start_func, 267 start_arg, 233 268 core_lid, 234 u_stack_base,235 u_stack_size);236 237 if( error ) // release allocated memory for thread descriptor238 { 239 req.type = KMEM_PAGE;240 req.ptr = ppm_base2page( thread);241 kmem_free( &req);269 vseg->min, 270 vseg->max - vseg->min ); 271 272 if( error ) 273 { 274 printk("\n[ERROR] in %s : cannot initialize new thread\n", __FUNCTION__ ); 275 vmm_remove_vseg( vseg ); 276 thread_release( thread ); 242 277 return EINVAL; 243 278 } … … 247 282 248 283 // set DETACHED flag if required 249 if( attr-> flags & PT_FLAG_DETACH ) thread->flags |= THREAD_FLAG_DETACHED;284 if( attr->attributes & PT_ATTR_DETACH ) thread->flags |= THREAD_FLAG_DETACHED; 250 285 251 286 // allocate & initialise CPU context 252 287 error = hal_cpu_context_create( thread ); 253 if( error ) return ENOMEM; 288 289 if( error ) 290 { 291 printk("\n[ERROR] in %s : cannot create CPU context\n", __FUNCTION__ ); 292 vmm_remove_vseg( vseg ); 293 thread_release( thread ); 294 return ENOMEM; 295 } 254 296 255 297 // allocate & initialise FPU context 256 298 error = hal_fpu_context_create( thread ); 257 if( error ) return ENOMEM; 258 299 300 if( error ) 301 { 302 printk("\n[ERROR] in %s : cannot create FPU context\n", __FUNCTION__ ); 303 vmm_remove_vseg( vseg ); 304 thread_release( thread ); 305 return ENOMEM; 306 } 307 259 308 thread_dmsg("\n[INFO] %s : exit / trdid = %x / process %x / core = %d\n", 260 309 __FUNCTION__ , thread->trdid , process->pid , core_lid ); … … 266 315 267 316 268 ///////////////////////////////////////////////// 269 error_t thread_user_fork( thread_t ** new_thread, 270 process_t * process, 271 intptr_t u_stack_base, 272 uint32_t u_stack_size ) 317 ////////////////////////////////////////////// 318 error_t thread_user_fork( process_t * process, 319 thread_t ** new_thread ) 273 320 { 274 321 error_t error; 275 322 thread_t * thread; // pointer on new thread descriptor 276 323 lid_t core_lid; // selected core local index 277 kmem_req_t req; // kmem request (for release)324 vseg_t * vseg; // stack vseg 278 325 279 326 thread_dmsg("\n[INFO] %s : enters\n", __FUNCTION__ ); 327 328 // allocate a stack from local VMM 329 vseg = vmm_create_vseg( process, 0 , 0 , VSEG_TYPE_STACK ); 330 331 if( vseg == NULL ); 332 { 333 printk("\n[ERROR] in %s : cannot create stack vseg\n", __FUNCTION__ ); 334 return ENOMEM; 335 } 280 336 281 337 // select a target core in local cluster … … 288 344 thread = thread_alloc(); 289 345 290 if( thread == NULL ) return ENOMEM; 346 if( thread == NULL ) 347 { 348 printk("\n[ERROR] in %s : cannot allocate new thread\n", __FUNCTION__ ); 349 vmm_remove_vseg( vseg ); 350 return ENOMEM; 351 } 291 352 292 353 // initializes thread descriptor … … 297 358 this->entry_args, 298 359 core_lid, 299 u_stack_base,300 u_stack_size);301 302 if( error ) // release allocated memory for thread descriptor303 { 304 req.type = KMEM_PAGE;305 req.ptr = ppm_base2page( thread);306 kmem_free( &req);360 vseg->min, 361 vseg->max - vseg->min ); 362 363 if( error ) 364 { 365 printk("\n[ERROR] in %s : cannot initialize new thread\n", __FUNCTION__ ); 366 vmm_remove_vseg( vseg ); 367 thread_release( thread ); 307 368 return EINVAL; 308 369 } … … 313 374 // allocate & initialise CPU context from calling thread 314 375 error = hal_cpu_context_copy( thread , this ); 315 if( error ) return ENOMEM; 376 377 if( error ) 378 { 379 printk("\n[ERROR] in %s : cannot create CPU context\n", __FUNCTION__ ); 380 vmm_remove_vseg( vseg ); 381 thread_release( thread ); 382 return ENOMEM; 383 } 316 384 317 385 // allocate & initialise FPU context from calling thread 318 386 error = hal_fpu_context_copy( thread , this ); 319 if( error ) return ENOMEM; 320 321 thread_dmsg("INFO : %s thread %x for process %x on core %d in cluster %x\n", 387 388 if( error ) 389 { 390 printk("\n[ERROR] in %s : cannot create CPU context\n", __FUNCTION__ ); 391 vmm_remove_vseg( vseg ); 392 thread_release( thread ); 393 return ENOMEM; 394 } 395 396 thread_dmsg("\n[INFO] %s : exit / thread %x for process %x on core %d in cluster %x\n", 322 397 __FUNCTION__, thread->trdid, process->pid, core_lid, local_cxy ); 323 398 … … 473 548 spinlock_unlock( &process->th_lock ); 474 549 550 // update local DQDT 551 dqdt_local_update_threads( -1 ); 552 475 553 // invalidate thread descriptor 476 554 thread->signature = 0; 477 555 478 556 // release memory for thread descriptor 479 kmem_req_t req; 480 req.type = KMEM_PAGE; 481 req.ptr = ppm_base2page( thread ); 482 kmem_free(&req); 557 thread_release( thread ); 483 558 484 559 tm_end = hal_time_stamp(); … … 706 781 707 782 //////////////////////////////////////////////// 708 void thread_signals_handle r( thread_t * thread )783 void thread_signals_handle( thread_t * thread ) 709 784 { 710 785 // TODO … … 712 787 } 713 788 714 789 ///////////////////////////////////// 790 xptr_t thread_get_xptr( pid_t pid, 791 trdid_t trdid ) 792 { 793 cxy_t target_cxy; // target thread cluster identifier 794 ltid_t target_thread_ltid; // target thread local index 795 thread_t * target_thread_ptr; // target thread local pointer 796 xptr_t target_process_xp; // extended pointer on target process descriptor 797 process_t * target_process_ptr; // local pointer on target process descriptor 798 pid_t target_process_pid; // target process identifier 799 xlist_entry_t root; // root of list of process in target cluster 800 xptr_t lock_xp; // extended pointer on lock protecting this list 801 802 // get target cluster identifier and local thread identifier 803 target_cxy = CXY_FROM_TRDID( trdid ); 804 target_thread_ltid = LTID_FROM_TRDID( trdid ); 805 806 // get root of list of process descriptors in target cluster 807 hal_remote_memcpy( XPTR( local_cxy , &root ), 808 XPTR( target_cxy , &LOCAL_CLUSTER->pmgr.local_root ), 809 sizeof(xlist_entry_t) ); 810 811 // get extended pointer on lock protecting the list of processes 812 lock_xp = XPTR( target_cxy , &LOCAL_CLUSTER->pmgr.local_lock ); 813 814 // take the lock protecting the list of processes in target cluster 815 remote_spinlock_lock( lock_xp ); 816 817 // loop on list of process in target cluster to find the PID process 818 xptr_t iter; 819 bool_t found = false; 820 XLIST_FOREACH( XPTR( target_cxy , &LOCAL_CLUSTER->pmgr.local_root ) , iter ) 821 { 822 target_process_xp = XLIST_ELEMENT( iter , process_t , local_list ); 823 target_process_ptr = (process_t *)GET_PTR( target_process_xp ); 824 target_process_pid = hal_remote_lw( XPTR( target_cxy , &target_process_ptr->pid ) ); 825 if( target_process_pid == pid ) 826 { 827 found = true; 828 break; 829 } 830 } 831 832 // release the lock protecting the list of processes in target cluster 833 remote_spinlock_unlock( lock_xp ); 834 835 // check target thread found 836 if( found == false ) 837 { 838 return XPTR_NULL; 839 } 840 841 // get target thread local pointer 842 xptr_t xp = XPTR( target_cxy , &target_process_ptr->th_tbl[target_thread_ltid] ); 843 target_thread_ptr = (thread_t *)hal_remote_lpt( xp ); 844 845 if( target_thread_ptr == NULL ) 846 { 847 return XPTR_NULL; 848 } 849 850 return XPTR( target_cxy , target_thread_ptr ); 851 852 } // end thread_get_xptr() 853 -
trunk/kernel/kern/thread.h
r16 r23 3 3 * 4 4 * Author Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Mohamed Lamine Karaoui (2015)6 5 * Alain Greiner (2016) 7 6 * … … 43 42 44 43 /*************************************************************************************** 45 * This defines the various pthread_attr_t flags. 46 **************************************************************************************/ 47 48 #define PT_FLAG_DETACH 0x001 // user defined not joinable 49 #define PT_FLAG_CLUSTER_DEFINED 0x002 // user defined target cluster 50 #define PT_FLAG_CORE_DEFINED 0x004 // user defined core cluster 51 52 /*************************************************************************************** 53 * This structure defines the input argument of the pthread_create() system call. 54 * It contains all informations required to initialize an user thread, and is passed 55 * as input argument to the thread_user_create() function. 56 * It is partly set by the kernel, partly set by the user application itself, 57 * using the pthread_attr_***() functions. 44 * These macros are used to compose or decompose global thread identifier (TRDID) 45 * to or from cluster identifier / local thread index (CXY , LTID) 46 **************************************************************************************/ 47 48 #define LTID_FROM_TRDID( trdid ) (ltid_t)(trdid & 0x0000FFFF) 49 #define CXY_FROM_TRDID( trdid ) (cxy_t)(trdid >> 16) 50 #define TRDID( cxy , ltid ) (trdid_t)((cxy << 16) | ltid ) 51 52 /*************************************************************************************** 53 * This defines the various pthread_attr_t attributes bit-vector. 54 **************************************************************************************/ 55 56 /*************************************************************************************** 57 * This opaque structure contains the user defined attributes for an user thread. 58 * It is passed as input argument to the thread_user_create() function. 59 * It is set by the user application itself, using the pthread_attr_***() functions. 60 * The currently supported attributes are defined below. 58 61 **************************************************************************************/ 59 62 60 63 typedef struct pthread_attr_s 61 64 { 62 pid_t pid; /*! owner process identifier */ 63 void * entry_func; /*! pointer on entry function */ 64 void * entry_args; /*! pointer on entry function arguments */ 65 uint32_t flags; /*! pthread flags (entirely user specified) */ 66 cxy_t cxy; /*! target cluster (can be user specified) */ 67 lid_t lid; /*! target core (can be user specified) */ 65 uint32_t attributes; /*! user defined attributes bit vector */ 66 cxy_t cxy; /*! target cluster identifier */ 67 lid_t lid; /*! target core index */ 68 68 } 69 69 pthread_attr_t; 70 70 71 typedef enum 72 { 73 PT_ATTR_DETACH = 0x0001, /*! user defined not joinable */ 74 PT_ATTR_CLUSTER_DEFINED = 0x0002, /*! user defined target cluster */ 75 PT_ATTR_CORE_DEFINED = 0x0004, /*! user defined core index in cluster */ 76 } 77 pt_attributes_t; 71 78 72 79 /*************************************************************************************** … … 86 93 87 94 /*************************************************************************************** 88 * This defines the masks associated to the thread flags.95 * This defines the thread flags bit-vector. 89 96 **************************************************************************************/ 90 97 91 98 #define THREAD_FLAG_LOADABLE 0x0001 /*! This thread has not been executed yet */ 92 #define THREAD_FLAG_DETACHED 0x0002 /*! This user thread is detached from parent */ 99 #define THREAD_FLAG_DETACHED 0x0002 /*! This thread is detached from parent */ 100 #define THREAD_FLAG_JOIN 0x0004 /*! Parent thread made a join */ 101 #define THREAD_FLAG_EXIT 0x0008 /*! This thread made an exit */ 93 102 94 103 /*************************************************************************************** … … 102 111 **************************************************************************************/ 103 112 104 #define THREAD_BLOCKED_GLOBAL 0x0001 /*! thread global blocking*/113 #define THREAD_BLOCKED_GLOBAL 0x0001 /*! thread desactivated / wait activation */ 105 114 #define THREAD_BLOCKED_IO 0x0002 /*! thread wait IO operation completion */ 106 115 #define THREAD_BLOCKED_MAPPER 0x0004 /*! thread wait mapper */ 107 #define THREAD_BLOCKED_EXIT 0x0010 /*! thread requested exit */ 116 #define THREAD_BLOCKED_JOIN 0x0008 /*! thread blocked in join / wait exit */ 117 #define THREAD_BLOCKED_EXIT 0x0010 /*! thread blocked in exit / wait join i */ 108 118 #define THREAD_BLOCKED_KILL 0x0020 /*! thread received kill signal */ 109 119 #define THREAD_BLOCKED_SEM 0x0040 /*! thread wait semaphore */ 110 120 #define THREAD_BLOCKED_PAGE 0x0080 /*! thread wait page access */ 121 #define THREAD_BLOCKED_USERSYNC 0x0100 /*! thread wait POSIX (cond/mutex/barrier) */ 122 111 123 #define THREAD_BLOCKED_IDLE 0x1000 /*! thread RPC wait activation */ 112 124 #define THREAD_BLOCKED_DEV_QUEUE 0x2000 /*! thread DEV wait queue */ … … 141 153 * that is returned by the kernel to the user: 142 154 * - The TRDID 16 LSB bits contain the LTID (Local Thread Index). 143 * - The TRDID 16 MSB bits contain the owner cluster CXY.155 * - The TRDID 16 MSB bits contain the CXY of cluster containing the thread. 144 156 * - The LTID is used to index the th_tbl[] array in the local process descriptor. 145 157 * This TRDID is computed by the process_register_thread() function, when the user … … 155 167 void * fpu_context; /*! used for dynamic FPU allocation */ 156 168 157 uint32_t trdid; /*! thread index ( in THTBL) */169 uint32_t trdid; /*! thread index (cxy.ltid) */ 158 170 thread_type_t type; /*! thread type */ 159 171 uint32_t quantum; /*! number of clock ticks given to thread */ … … 162 174 core_t * core; /*! pointer to the owner core */ 163 175 process_t * process; /*! pointer on local process descriptor */ 164 176 xptr_t parent; /*! extended pointer on parent thread */ 177 178 void * exit_value; /*! exit_value used in case of join */ 179 165 180 uint32_t local_locks; /*! number of local locks owned by thread */ 166 181 list_entry_t locks_root; /*! root of local locks list */ 182 183 remote_spinlock_t * flags_lock; /*! lock protecting the flags */ 167 184 168 185 uint32_t remote_locks; /*! number of local locks owned by thread */ … … 182 199 183 200 error_t errno; /*! errno value set by last system call */ 201 uint32_t utls; /*! user thread local storage */ 184 202 185 203 bool_t fork_user; /*! user defined placement for next fork() */ … … 231 249 /*************************************************************************************** 232 250 * This function allocates memory for an user thread descriptor in the local cluster, 233 * and initializes it from information contained in the "attr" argument.234 * It is used by the pthread_create system call, the CPU context is initialised from235 * scratch, and the "loadable" field is set.236 * The new thread is attached to the core specified in the "attr"argument.237 * It is registered in the local process descriptor for the process specified in "attr".251 * and initializes it from information contained in the arguments. 252 * It is used by the "pthread_create" system call. 253 * The CPU context is initialised from scratch, and the "loadable" field is set. 254 * The new thread is attached to the core specified in the <attr> argument. 255 * It is registered in the local process descriptor specified by the <pid> argument. 238 256 * The thread descriptor pointer is returned to allow the parent thread to register it 239 257 * in its children list. 240 * The THREAD_BLOCKED_GLOBAL bit is set, and the thread must be activated to start. 241 *************************************************************************************** 242 * @ new_thread : address of buffer for new thread descriptor pointer. 258 * The THREAD_BLOCKED_GLOBAL bit is set => the thread must be activated to start. 259 *************************************************************************************** 260 * @ pid : process identifier. 261 * @ start_func : pointer on entry function. 262 * @ start_args : pointer on function argument (can be NULL). 243 263 * @ attr : pointer on pthread attributes descriptor. 244 * @ u_stack_base : actual user stack size. 245 * @ u_stack_size : actual user stack base. 264 * @ new_thread : [out] address of buffer for new thread descriptor pointer. 246 265 * @ returns 0 if success / returns ENOMEM if error. 247 266 **************************************************************************************/ 248 error_t thread_user_create( thread_t ** new_thread, 267 error_t thread_user_create( pid_t pid, 268 void * start_func, 269 void * start_arg, 249 270 pthread_attr_t * attr, 250 intptr_t u_stack_base, 251 uint32_t u_stack_size ); 271 thread_t ** new_thread ); 252 272 253 273 /*************************************************************************************** … … 261 281 * The THREAD_BLOCKED_GLOBAL bit is set, and the thread must be activated to start. 262 282 *************************************************************************************** 263 * @ new_thread : address of buffer for new thread descriptor pointer.264 283 * @ process : local pointer on owner process descriptor. 265 * @ u_stack_base : actual user stack size. 266 * @ u_stack_size : actual user stack base. 284 * @ new_thread : [out] address of buffer for new thread descriptor pointer. 267 285 * @ returns 0 if success / returns ENOMEM if error. 268 286 **************************************************************************************/ 269 error_t thread_user_fork( thread_t ** new_thread, 270 process_t * process, 271 intptr_t u_stack_base, 272 uint32_t u_stack_size ); 287 error_t thread_user_fork( process_t * process, 288 thread_t ** new_thread ); 273 289 274 290 /*************************************************************************************** … … 343 359 * This function removes an user thread from the parent thread global list 344 360 * of attached children threads. 345 * It does take the lock, as this function can be called by the child thread.346 * In this case, it uses the extended pointer on the parent thread contained347 * in the pthread_attr_t embedded in the child thread descriptor.348 361 *************************************************************************************** 349 362 * @ xp_parent : extended pointer on the parent thread descriptor. … … 352 365 void thread_child_parent_unlink( xptr_t xp_parent, 353 366 xptr_t xp_child ); 354 355 367 356 368 /*************************************************************************************** … … 475 487 void thread_signals_handle( thread_t * thread ); 476 488 489 /*************************************************************************************** 490 * This function returns the extended pointer on a thread descriptor identified 491 * by its thread identifier, and process identifier. 492 * It can be called by any thread running in any cluster. 493 *************************************************************************************** 494 * @ pid : process identifier. 495 * @ trdid : thread identifier. 496 * @ return the extended pointer if thread found / return XPTR_NULL if not found. 497 **************************************************************************************/ 498 xptr_t thread_get_xptr( pid_t pid, 499 trdid_t trdid ); 477 500 478 501 -
trunk/kernel/kern/time.h
r1 r23 1 1 /* 2 * time.h : thread time related management2 * time.h - Structure used by gettimeofday. 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ … … 24 25 #define _TIME_H_ 25 26 26 #include <types.h> 27 #include <list.h> 28 #include <device.h> 27 #include <hal_types.h> 29 28 30 struct event_s;31 29 32 struct alarm_info_s30 struct timeval 33 31 { 34 uint_t signature; 35 36 /* Public members */ 37 struct event_s *event; 38 39 /* Private members */ 40 uint_t tm_wakeup; 41 struct list_entry list; 32 uint32_t tv_sec; /* secondes */ 33 uint32_t tv_usec; /* microsecondes */ 42 34 }; 43 35 44 struct alarm_s 45 { 46 struct list_entry wait_queue; 47 }; 48 49 50 struct timeb { 51 time_t time; 52 unsigned short millitm; 53 short timezone; 54 short dstflag; 55 }; 56 57 struct timeval { 58 clock_t tv_sec; /* secondes */ 59 clock_t tv_usec; /* microsecondes */ 60 }; 61 62 struct timezone { 36 struct timezone 37 { 63 38 int tz_minuteswest; /* minutes west of Greenwich */ 64 39 int tz_dsttime; /* type of DST correction */ 65 40 }; 66 41 67 68 struct tms69 {70 clock_t tms_utime; /* user time */71 clock_t tms_stime; /* system time */72 clock_t tms_cutime; /* user time of children */73 clock_t tms_cstime; /* system time of children */74 };75 76 77 error_t alarm_manager_init(struct alarm_s *alarm);78 error_t alarm_wait(struct alarm_info_s *info, uint_t msec);79 80 void alarm_clock(struct alarm_s *alarm, uint_t ticks_nr);81 82 int sys_clock (uint64_t *val);83 int sys_alarm (unsigned nb_sec);84 int sys_ftime (struct timeb *utime);85 int sys_times(struct tms *utms);86 int sys_gettimeofday(struct timeval *tv, struct timezone *tz);87 88 #if CONFIG_THREAD_TIME_STAT89 struct thread_s;90 inline void tm_sleep_compute(struct thread_s *thread);91 inline void tm_usr_compute(struct thread_s *thread);92 inline void tm_sys_compute(struct thread_s *thread);93 inline void tm_wait_compute(struct thread_s *thread);94 inline void tm_exit_compute(struct thread_s *thread);95 inline void tm_born_compute(struct thread_s *thread);96 inline void tm_create_compute(struct thread_s *thread);97 98 #else99 100 #define tm_sleep_compute(thread)101 #define tm_usr_compute(thread)102 #define tm_sys_compute(thread)103 #define tm_wait_compute(thread)104 #define tm_exit_compute(thread)105 #define tm_born_compute(thread)106 #define tm_create_compute(thread)107 108 #endif /* CONFIG_SCHED_STAT */109 110 42 #endif /* _TIME_H_ */ -
trunk/kernel/libk/bits.c
r11 r23 25 25 #include <hal_types.h> 26 26 #include <bits.h> 27 28 //////////////////////////////////// 29 void bitmap_init( bitmap_t * bitmap, 30 uint32_t len ) 31 { 32 uint32_t word; 33 uint32_t nwords = BITMAP_SIZE( len ); 34 for( word = 0 ; word < nwords ; word++ ) 35 { 36 bitmap[word] = 0; 37 } 38 } // end bitmap_init() 27 39 28 40 ////////////////////////////////////////// -
trunk/kernel/libk/bits.h
r14 r23 78 78 79 79 /********************************************************************************************** 80 * This macro returns the number of 32 bits words required to register sizeentries.80 * This macro returns the number of 32 bits words required to register <size> entries. 81 81 *********************************************************************************************/ 82 82 83 83 #define BITMAP_SIZE(size) ( ((size) & 31) ? (((size)>>5) + 1) : ((size)>>5) ) 84 85 /**********************************************************************************************86 * This macro declare a bitmap data structure. It is actually an array of uint32_t.87 * size is the total number of entries in the bitmap.88 *********************************************************************************************/89 90 #define BITMAP( name , size ) uint32_t name[BITMAP_SIZE(size)]91 84 92 85 typedef uint32_t bitmap_t; 93 86 94 /********************************************************************************************** 87 /********************************************************************************************* 88 * This function reset all bits in a bitmap. (array ot 32 bits words). 89 ********************************************************************************************* 90 * @ bitmap : pointer on first word in the bitmap. 91 * @ len : number of bits to reset. 92 ********************************************************************************************/ 93 void bitmap_init( bitmap_t * bitmap, 94 uint32_t len ); 95 96 /********************************************************************************************* 95 97 * This function set a specific bit in a bitmap. 96 ********************************************************************************************* *98 ********************************************************************************************* 97 99 * @ bitmap : pointer on the bitmap 98 100 * @ index : bit index in the bitmap 99 ******************************************************************************************** */101 ********************************************************************************************/ 100 102 extern inline void bitmap_set( bitmap_t * bitmap, 101 103 uint32_t index ); 102 104 103 /********************************************************************************************* *105 /********************************************************************************************* 104 106 * This function clear a specific bit in a bitmap. 105 ********************************************************************************************* *107 ********************************************************************************************* 106 108 * @ bitmap : pointer on the bitmap 107 109 * @ index : bit index in the bitmap 108 ******************************************************************************************** */110 ********************************************************************************************/ 109 111 extern inline void bitmap_clear( bitmap_t * bitmap, 110 112 uint32_t index ); 111 113 112 /********************************************************************************************* *114 /********************************************************************************************* 113 115 * This function returns a specific bit in a bitmap. 114 ********************************************************************************************* *116 ********************************************************************************************* 115 117 * @ bitmap : pointer on the bitmap 116 118 * @ index : bit index in the bitmap 117 * @ returns tru if bitmap[index] is set118 ******************************************************************************************** */119 * @ returns true if bitmap[index] is set 120 ********************************************************************************************/ 119 121 extern inline bool_t bitmap_state( bitmap_t * bitmap, 120 122 uint32_t index ); 121 123 122 /********************************************************************************************* *124 /********************************************************************************************* 123 125 * This function set a range of bits in a bitmap : [index ... (index + len)[ 124 ********************************************************************************************* *126 ********************************************************************************************* 125 127 * @ bitmap : pointer on the bitmap 126 128 * @ index : first bit index in the bitmap 127 129 * @ len : number of bits to set 128 ******************************************************************************************** */130 ********************************************************************************************/ 129 131 extern void bitmap_set_range( bitmap_t * bitmap, 130 132 uint32_t index, 131 133 uint32_t len ); 132 134 133 /********************************************************************************************* *135 /********************************************************************************************* 134 136 * This function reset a range of bits in a bitmap : [index ... (index + len)[ 135 ********************************************************************************************* *137 ********************************************************************************************* 136 138 * @ bitmap : pointer on the bitmap 137 139 * @ index : first bit index in the bitmap 138 140 * @ len : number of bits to clear 139 ******************************************************************************************** */141 ********************************************************************************************/ 140 142 extern void bitmap_clear_range( bitmap_t * bitmap, 141 143 uint32_t index, 142 144 uint32_t len ); 143 145 144 /********************************************************************************************* *146 /********************************************************************************************* 145 147 * This function returns the index of first bit set in a bitmap, starting from index. 146 ********************************************************************************************* *148 ********************************************************************************************* 147 149 * @ bitmap : pointer on the bitmap 148 150 * @ index : first bit to analyse in the bitmap 149 151 * @ size : number of bits to analyse in bitmap 150 152 * @ returns index if found / returns 0xFFFFFFFF if bit not found 151 ******************************************************************************************** */153 ********************************************************************************************/ 152 154 extern uint32_t bitmap_ffs2( bitmap_t * bitmap, 153 155 uint32_t index, 154 156 uint32_t size ); 155 157 156 /********************************************************************************************* *158 /********************************************************************************************* 157 159 * This function returns the index of first bit cleared in a bitmap, starting from index. 158 ********************************************************************************************* *160 ********************************************************************************************* 159 161 * @ bitmap : pointer on the bitmap 160 162 * @ index : first bit to analyse in the bitmap 161 163 * @ size : number of bits to analyse in bitmap 162 164 * @ returns index if found / returns 0xFFFFFFFF if bit not found 163 ******************************************************************************************** */165 ********************************************************************************************/ 164 166 extern uint32_t bitmap_ffc2( bitmap_t * bitmap, 165 167 uint32_t index, 166 168 uint32_t size ); 167 169 168 /********************************************************************************************* *170 /********************************************************************************************* 169 171 * This function returns the index of first bit set in a bitmap, starting from bit 0. 170 ********************************************************************************************* *172 ********************************************************************************************* 171 173 * @ bitmap : pointer on the bitmap 172 174 * @ size : number of bits to analyse in bitmap 173 175 * @ returns index if found / returns 0xFFFFFFFF if bit not found 174 ******************************************************************************************** */176 ********************************************************************************************/ 175 177 extern uint32_t bitmap_ffs( bitmap_t * bitmap, 176 178 uint32_t size ); 177 179 178 /********************************************************************************************* *180 /********************************************************************************************* 179 181 * This function returns the index of first bit cleared in a bitmap, starting from bit 0. 180 ********************************************************************************************* *182 ********************************************************************************************* 181 183 * @ bitmap : pointer on the bitmap 182 184 * @ size : number of bits to alalyse in bitmap 183 185 * @ returns index if found / returns 0xFFFFFFFF if bit not found 184 ******************************************************************************************** */186 ********************************************************************************************/ 185 187 extern uint32_t bitmap_ffc( bitmap_t * bitmap, 186 188 uint32_t size ); 187 189 188 /********************************************************************************************* *190 /********************************************************************************************* 189 191 * This function returns the number of bits to code a non-zero unsigned integer value. 190 ********************************************************************************************* *192 ********************************************************************************************* 191 193 * @ val : value to analyse 192 194 * @ returns number of bits 193 ******************************************************************************************** */195 ********************************************************************************************/ 194 196 static inline uint32_t bits_nr( uint32_t val ) 195 197 { … … 202 204 } 203 205 204 /********************************************************************************************* *206 /********************************************************************************************* 205 207 * This function takes an unsigned integer value as input argument, and returns another 206 208 * unsigned integer, that is the (base 2) logarithm of the smallest power of 2 contained 207 209 * in the input value. 208 ********************************************************************************************* *210 ********************************************************************************************* 209 211 * @ val : value to analyse 210 212 * @ returns logarithm value 211 ******************************************************************************************** */213 ********************************************************************************************/ 212 214 static inline uint32_t bits_log2( uint32_t val ) 213 215 { -
trunk/kernel/libk/elf.c
r14 r23 31 31 #include <vfs.h> 32 32 #include <elf.h> 33 #include <syscalls.h> 33 34 34 35 … … 85 86 86 87 // load .elf header 87 count = vfs_read( file_xp , buffer , size ); 88 count = vfs_move( true , 89 file_xp, 90 buffer, 91 size ); 88 92 89 93 if( count != size ) … … 163 167 164 168 // set seek on segment base in file 165 error = vfs_lseek( file_xp , offset , VFS_SEEK_SET , NULL ); 169 error = vfs_lseek( file_xp, 170 offset, 171 SEEK_SET, 172 NULL ); 166 173 167 174 if( error ) … … 210 217 process_t * process) 211 218 { 219 char path_copy[CONFIG_VFS_MAX_PATH_LENGTH]; 212 220 kmem_req_t req; // kmem request for program header 213 char path_copy[256]; // local copy of pathname214 221 uint32_t length; // actual path length 215 222 Elf32_Ehdr header; // local buffer for .elf header … … 217 224 uint32_t segs_size; // size of buffer for segment descriptors array 218 225 xptr_t file_xp; // extended pointer on created file descriptor 226 uint32_t file_id; // file descriptor index (unused) 219 227 uint32_t count; // bytes counter 220 228 error_t error; … … 223 231 length = hal_strlen_from_uspace( pathname ); 224 232 225 if( length > 255)233 if( length >= CONFIG_VFS_MAX_PATH_LENGTH ) 226 234 { 227 235 printk("\n[ERROR] in %s : pathname length too long\n", __FUNCTION__ ); … … 234 242 // open file 235 243 file_xp = XPTR_NULL; // avoid GCC warning 244 file_id = -1; 236 245 237 246 error = vfs_open( process->vfs_cwd_xp, 238 247 path_copy, 239 VFS_O_RDONLY, 240 &file_xp ); 248 O_RDONLY, 249 0, 250 &file_xp, 251 &file_id ); 241 252 if( error ) 242 253 { … … 252 263 if( error ) 253 264 { 254 vfs_close( file_xp , &count);265 vfs_close( file_xp , file_id ); 255 266 return -1; 256 267 } … … 261 272 { 262 273 printk("\n[ERROR] in %s : no segments found\n", __FUNCTION__ ); 263 vfs_close( file_xp , &count);274 vfs_close( file_xp , file_id ); 264 275 return -1; 265 276 } … … 277 288 { 278 289 printk("\n[ERROR] in %s : no memory for segment descriptors\n", __FUNCTION__ ); 279 vfs_close( file_xp , &count);290 vfs_close( file_xp , file_id ); 280 291 return -1; 281 292 } 282 293 283 294 // set seek pointer in file descriptor to access segment descriptors array 284 error = vfs_lseek( file_xp , header.e_phoff, VFS_SEEK_SET , NULL );295 error = vfs_lseek( file_xp , header.e_phoff, SEEK_SET , NULL ); 285 296 286 297 if( error ) 287 298 { 288 299 printk("\n[ERROR] in %s : cannot seek for descriptors array\n", __FUNCTION__ ); 289 vfs_close( file_xp , &count);300 vfs_close( file_xp , file_id ); 290 301 req.ptr = segs_base; 291 302 kmem_free( &req ); … … 294 305 295 306 // load seg descriptors array to local buffer 296 count = vfs_read( file_xp, 307 count = vfs_move( true, 308 file_xp, 297 309 segs_base, 298 310 segs_size ); … … 301 313 { 302 314 printk("\n[ERROR] in %s : cannot read segments descriptors\n", __FUNCTION__ ); 303 vfs_close( file_xp , &count);315 vfs_close( file_xp , file_id ); 304 316 req.ptr = segs_base; 305 317 kmem_free( &req ); … … 316 328 if( error ) 317 329 { 318 vfs_close( file_xp , &count);330 vfs_close( file_xp , file_id ); 319 331 req.ptr = segs_base; 320 332 kmem_free( &req ); -
trunk/kernel/libk/htab.c
r1 r23 2 2 * htable.c - Generic, embedded hash table implementation. 3 3 * 4 * Author Ghassan Almalles (2008,2009,2010,2011,2012) 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016) 4 * Author Alain Greiner (2016,2017) 7 5 * 8 6 * Copyright (c) UPMC Sorbonne Universites … … 10 8 * This file is part of ALMOS-MKH. 11 9 * 12 * ALMOS-MKH .is free software; you can redistribute it and/or modify it10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 13 11 * under the terms of the GNU General Public License as published by 14 12 * the Free Software Foundation; version 2.0 of the License. 15 13 * 16 * ALMOS-MKH .is distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 17 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 18 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 20 18 * 21 19 * You should have received a copy of the GNU General Public License 22 * along with ALMOS-MKH .; if not, write to the Free Software Foundation,20 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 23 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 22 */ 25 23 26 #include <htable.h> 27 #include <kmem.h> 28 #include <ppm.h> 29 30 /////////////////////////////////////////////// 31 error_t ht_header_init( ht_header_t * header, 32 ht_hash_t * hash, 33 ht_compare_t * compare ) 24 #include <kernel_config.h> 25 #include <hal_types.h> 26 #include <hal_special.h> 27 #include <htab.h> 28 #include <rwlock.h> 29 #include <list.h> 30 #include <printk.h> 31 #include <vfs.h> 32 33 /////////////////////////////////////////////////////////////////////////////////////////// 34 // Item type specific (static) functions (two functions for each item type). 35 // Example below if for <vhs_inode_t>, where the identifier is the inum field. 36 /////////////////////////////////////////////////////////////////////////////////////////// 37 38 /////////////////////////////////////////////////////////////////////////////////////////// 39 // These static functions compute the hash index from the key. 40 /////////////////////////////////////////////////////////////////////////////////////////// 41 // @ key : local pointer on key. 42 // @ return the index value, from 0 to (HASHTAB_SIZE - 1) 43 /////////////////////////////////////////////////////////////////////////////////////////// 44 45 static uint32_t htab_inode_index( void * key ) 46 { 47 uint32_t * inum = key; 48 return (((*inum) >> 16) ^ ((*inum) & 0xFFFF)) % HASHTAB_SIZE; 49 } 50 51 /////////////////////////////////////////////////////////////////////////////////////// 52 // These static functions are used by htab_lookup(), htab_insert(), and htab_remove(). 53 // They scan one sub-list identified by <index> to find an item identified by <key>. 54 // The sub-list is not modified, but the lock must have been taken by the caller. 55 /////////////////////////////////////////////////////////////////////////////////////// 56 // @ htab : pointer on hash table. 57 // @ index : index of sub-list to be scanned. 58 // @ key : pointer on item identifier. 59 // @ return pointer on item if found / return NULL if not found. 60 /////////////////////////////////////////////////////////////////////////////////////// 61 62 static void * htab_inode_scan( htab_t * htab, 63 uint32_t index, 64 void * key ) 65 { 66 list_entry_t * list_entry; // pointer on list_entry_t (iterator) 67 vfs_inode_t * inode; // pointer on item 68 69 LIST_FOREACH( &htab->roots[index] , list_entry ) 70 { 71 inode = (vfs_inode_t *)LIST_ELEMENT( list_entry , vfs_inode_t , list ); 72 if( inode->inum == *(uint32_t *)key ) return inode; 73 } 74 75 // no matching item found 76 return NULL; 77 } 78 79 //////////////////////////////////////////////////////////////////////////////////////// 80 // Generic access functions 81 //////////////////////////////////////////////////////////////////////////////////////// 82 83 //////////////////////////////////////// 84 void htab_init( htab_t * htab, 85 htab_item_type_t type ) 34 86 { 35 87 uint32_t i; 36 kmem_req_t req; 37 page_t * page; 38 39 req.type = KMEM_PAGE; 40 req.size = 0; 41 req.flags = AF_ZERO; 42 page = kmem_alloc( &req ); 43 44 if( page == NULL ) return ENOMEM; 45 46 header->nb_buckets = CONFIG_PPM_PAGE_SIZE/sizeof( list_entry_t ); 47 header->buckets = ppm_page2base( page ); 48 header->hash = hash; 49 header->compare = compare; 50 51 for( i=0 ; i < header->nb_buckets ; i++ ) 52 { 53 list_root_init( &header->buckets[i] ); 54 } 55 56 return 0; 57 } 58 59 //////////////////////////////////////// 60 error_t ht_node_init( ht_node_t * node ) 61 { 62 node->index = (uint32_t) -1; 63 list_entry_init( &node->list ); 64 65 return 0; 66 } 67 68 ///////////////////////////////////////////////// 69 static ht_node_t * __hfind( ht_header_t * header, 70 uint32_t index, 71 void * key) 72 { 73 ht_node_t * node; 74 list_entry_t * root, 75 list_entry_t * iter; 76 77 root = &header->buckets[index % header->nb_buckets]; 78 79 LIST_FOREACH( root , iter ) 80 { 81 node = LIST_ELEMENT( iter , ht_node_t , list ); 82 if( node->index == index ) 83 { 84 if( header->compare( node , key ) ) return node; 85 } 86 } 87 88 return NULL; 89 } 90 91 ////////////////////////////////////////// 92 ht_node_t * ht_find( ht_header_t * header, 93 void * key ) 94 { 95 uint32_t index = header->hash( key ); 96 97 return __ht_find( header , index , key ); 98 } 99 100 //////////////////////////////////////// 101 error_t ht_insert( ht_header_t * header, 102 ht_node_t * node, 103 void * key ) 104 { 105 uint32_t index = header->hash( key ); 106 107 ht_node_t * node = __ht_find( header , index , key ); 108 109 if( node != NULL ) return EINVAL; 110 111 list_entry_t * root = &header->buckets[index % header->nb_buckets]; 112 113 list_add_first( root , &node->list); 114 115 node->index = index; 116 117 return 0; 118 } 119 120 //////////////////////////////////////// 121 error_t ht_remove( ht_header_t * header, 122 void * key ) 123 { 124 uint32_t index = header->hash( key ); 125 126 ht_node_t * node = __ht_find( header , index , key ); 127 128 if( node == NULL ) return EINVAL; 129 130 list_unlink( &node->list ); 131 132 return 0; 133 } 134 88 89 // initialize readlock 90 rwlock_init( &htab->lock ); 91 92 htab->items = 0; 93 94 if( type == HTAB_INODE_TYPE ) 95 { 96 htab->scan = &htab_inode_scan; 97 htab->index = &htab_inode_index; 98 } 99 else 100 { 101 printk("\n[PANIC] in %s : undefined item type\n", __FUNCTION__ ); 102 hal_core_sleep(); 103 } 104 105 // initialize partial lists 106 for( i = 0 ; i < HASHTAB_SIZE ; i++ ) 107 { 108 list_root_init( &htab->roots[i] ); 109 } 110 } 111 112 ///////////////////////////////////////// 113 error_t htab_insert( htab_t * htab, 114 void * key, 115 list_entry_t * list_entry ) 116 { 117 // compute index from key 118 uint32_t index = htab->index( key ); 119 120 // take the lock in write mode 121 rwlock_wr_lock( &htab->lock ); 122 123 // scan sub-list to check if item exist 124 void * item = htab->scan( htab , index , key ); 125 126 if( item != NULL ) // item exist => return error 127 { 128 // release lock 129 rwlock_wr_unlock( &htab->lock ); 130 131 return -1; 132 } 133 else // item doesn't exist => register 134 { 135 // register item in hash table 136 list_add_last( &htab->roots[index] , list_entry ); 137 138 // update items number 139 htab->items++; 140 141 // release lock 142 rwlock_wr_unlock( &htab->lock ); 143 144 return 0; 145 } 146 } 147 148 ///////////////////////////////////////// 149 error_t htab_remove( htab_t * htab, 150 void * key, 151 list_entry_t * list_entry ) 152 { 153 // compute index from key 154 uint32_t index = htab->index( key ); 155 156 // take the lock in write mode 157 rwlock_wr_lock( &htab->lock ); 158 159 // scan sub-list to chek if item exist 160 void * item = htab->scan( htab , index , key ); 161 162 if( item == NULL ) // item doesn't exist 163 { 164 // release lock 165 rwlock_wr_unlock( &htab->lock ); 166 167 return -1; 168 } 169 else // item exist => remove it 170 { 171 // remove item from hash table 172 list_unlink( list_entry ); 173 174 // update items number 175 htab->items--; 176 177 // release lock 178 rwlock_wr_unlock( &htab->lock ); 179 180 return 0; 181 } 182 } 183 184 ////////////////////////////////// 185 void * htab_lookup( htab_t * htab, 186 void * key ) 187 { 188 // compute index from key 189 uint32_t index = htab->index( key ); 190 191 // take the lock in read mode 192 rwlock_rd_lock( &htab->lock ); 193 194 // scan sub-list 195 void * item = htab->scan( htab , index , key ); 196 197 // release lock 198 rwlock_rd_unlock( &htab->lock ); 199 200 return item; 201 } 202 203 204 -
trunk/kernel/libk/htab.h
r1 r23 2 2 * htab.h - Generic embedded hash table definition. 3 3 * 4 * Author Ghassan Almalles (2008,2009,2010,2011,2012) 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016) 4 * Authors Alain Greiner (2016,2017) 7 5 * 8 6 * Copyright (c) UPMC Sorbonne Universites … … 29 27 30 28 #include <hal_types.h> 29 #include <rwlock.h> 31 30 #include <list.h> 32 31 32 ///////////////////////////////////////////////////////////////////////////////////////// 33 // This file define a generic, embedded, hash table. 34 // 35 // It can only be accessed by threads running in the local cluster. 36 // It is generic as it can be used to register various types of items. 37 // The main goal is to provide fast retrieval for a large number of items of same type. 38 // For this purpose the set of all registered items is split in several subsets. 39 // Each subset is organised as a double linked lists. 40 // - an item is uniquely identified by a <key>, that can be a single uint32_t, 41 // a character string, or a more complex structure. 42 // - From the pointer on <key>, we use an item type specific htab_index() function, 43 // to compute an <index> value, defining a subset of registered items. 44 // - As several items can have the same <index>, we use the item type specific defined 45 // htab_scan() function for a final associative search on the subset. 46 // - Each registered item is a structure, that must contain an embedded list_entry_t, 47 // that is part of a rooted double linked list. 48 // 49 // Implementation Note: for each supported item type ***, you must define the two 50 // htab_***_index() and htab_***_scan() functions, and 51 // update the htab_init() function. 52 ///////////////////////////////////////////////////////////////////////////////////////// 53 54 #define HASHTAB_SIZE 64 // number of subsets 55 33 56 /**************************************************************************************** 34 * This file define a generic, embedded, hash table. 35 * The main goal is to provide fast retrieval for a large number of items of same type 36 * in a given cluster. For this purpose the set of all registered items is split 37 * in several subsets. Each subset is organised as a double linked lists. 38 * - an item is uniquely identified by a <key>, that can be a single uint32_t, 39 * a character string, or a more complex structure. 40 * - From the pointer on the <key>, the hash table uses an user defined ht_hash() 41 * function, to compute an <index> value, defining a subset of registered 42 * items, to restrict the associative search. 43 * - As several items can have the same <index>, the hash table uses the user defined 44 * ht_compare() function for a final associative search on the subset. 45 * - Each registered item is a structure, that must contain an embedded ht_node_t, 46 * This ht_node_t is part of a rooted double linked list, and contains the <index>. 47 * - Finally, the hash table returns a pointer on the embedded ht_node_t, and the 48 * pointer on the searched item can be obtained by a simple offset. 57 * These typedef define the two item type specific function prototypes. 49 58 ***************************************************************************************/ 50 59 60 struct htab_s; 61 62 typedef void * htab_scan_t( struct htab_s * htab , uint32_t index , void * key ); 63 64 typedef uint32_t htab_index_t( void * key ); 65 51 66 /**************************************************************************************** 52 * This define the generic, user defined, functiontypes.67 * This define the supported item types. 53 68 ***************************************************************************************/ 54 69 55 struct ht_node_s; 56 57 typedef bool_t ht_compare_t( struct ht_node_s * node , void * key ); 58 typedef uint32_t ht_hash_t( void * key ); 70 typedef enum 71 { 72 HTAB_INODE_TYPE = 1, /*! item is a vfs_inode_t */ 73 } 74 htab_item_type_t; 59 75 60 76 /**************************************************************************************** 61 * This structure defines the hash table header.77 * This structure defines the the root of a local hash table. 62 78 ***************************************************************************************/ 63 79 64 typedef struct ht _header_s80 typedef struct htab_s 65 81 { 66 uint32_t nb_buckets; /*! number of subsets (one linked list per subset) */ 67 ht_hash_t * hash; /*! user defined hash function */ 68 ht_compare_t * compare; /*! user defined compare function */ 69 list_entry_t * buckets; /*! array of root of partial lists of ht_node_t */ 82 list_entry_t roots[HASHTAB_SIZE]; /*! array of roots of partial lists */ 83 htab_index_t * index; /*! item type specific function */ 84 htab_scan_t * scan; /*! item type specific function */ 85 uint32_t items; /*! number of registered items */ 86 rwlock_t lock; /*! lock protecting hash table accesses */ 70 87 } 71 ht _header_t;88 htab_t; 72 89 73 90 /**************************************************************************************** 74 * This structure defines one hash table node. 91 * This function initialises an empty hash table (zero registered item). 92 **************************************************************************************** 93 * @ htab : pointer on hash table. 94 * @ type : item type. 75 95 ***************************************************************************************/ 76 77 typedef struct ht_node_s 78 { 79 uint32_t index; /*! integer value computed from the key */ 80 list_entry_t list; /*! member of list of all nodes in same bucket */ 81 } 82 ht_node_t; 96 void htab_init( htab_t * htab, 97 htab_item_type_t type ); 83 98 84 99 /**************************************************************************************** 85 * This function initialises one hash table node.100 * This function register a new item in the hash table. 86 101 **************************************************************************************** 87 ccccc 102 * @ htab : pointer on the hash table. 103 * @ key : pointer on the item identifier. 104 * @ list_entry : pointer on list_entry_t embedded in item to be registered. 105 * @ return 0 if success / return EINVAL if item already registered. 88 106 ***************************************************************************************/ 89 void ht_node_init( ht_node_t * node ); 107 error_t htab_insert( htab_t * htab, 108 void * key, 109 list_entry_t * list_entry ); 90 110 91 111 /**************************************************************************************** 92 * This function allocates memory for the buckets array, and initializes the header. 93 * The number of buckets (number of subsets) is PAGE_SIZE / sizeof(list_entry_t) 112 * This function remove an item from the hash table. 94 113 **************************************************************************************** 95 * @ header : pointer on the hash table header.96 * @ ht_hash : pointer on the user defined hash function.97 * @ ht_compare : pointer on the user defined compare function.98 * @ return 0 if success / return E NOMEM if error.114 * @ header : pointer on the hash table. 115 * @ key : pointer on the item identifier. 116 * @ list_entry : pointer on list_entry_t embedded in item to be removed. 117 * @ return 0 if success / return EINVAL if item not found. 99 118 ***************************************************************************************/ 100 error_t ht_header_init( ht_header_t * header, 101 ht_hash_t * ht_hash, 102 ht_compare_t * ht_compare ); 103 104 /**************************************************************************************** 105 * This function register a new node in the hash table. 106 **************************************************************************************** 107 * @ header : pointer on the hash table header. 108 * @ node : pointer on the node to be registered (embedded in item). 109 * @ key : pointer on the item identifier. 110 * @ return 0 if success / return EINVAL if node already registered... 111 ***************************************************************************************/ 112 error_t ht_insert( ht_header_t * header, 113 ht_node_t * node, 114 void * key ); 119 error_t htab_remove( htab_t * htab, 120 void * key, 121 list_entry_t * list_entry ); 115 122 116 123 /**************************************************************************************** … … 118 125 * identified by its key. 119 126 **************************************************************************************** 120 * @ h eader : pointer on the hash table header.121 * @ key 122 * @ return pointer on nodeif found / return NULL if not found.127 * @ htab : pointer on the hash table. 128 * @ key : pointer on the item identifier. 129 * @ return pointer on item if found / return NULL if not found. 123 130 ***************************************************************************************/ 124 ht_node_t * ht_find( ht_header_t * header,125 void* key);131 void * htab_lookup( htab_t * htab, 132 void * key); 126 133 127 /****************************************************************************************128 * This function remove an item from the hash table.129 ****************************************************************************************130 * @ header : pointer on the hash table header.131 * @ key : pointer on the item identifier.132 * @ return 0 if success / return EINVAL if not found.133 ***************************************************************************************/134 error_t ht_remove( ht_header_t * header,135 void * key );136 134 137 #endif /* _HTAB LE_H_ */135 #endif /* _HTAB_H_ */ -
trunk/kernel/libk/remote_barrier.c
r14 r23 1 1 /* 2 * remote_barrier.c - distributed kernel barrier implementaion2 * remote_barrier.c - Access a POSIX barrier. 3 3 * 4 * Author Alain Greiner (2016 )4 * Author Alain Greiner (2016,2017) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 24 24 #include <hal_types.h> 25 25 #include <hal_remote.h> 26 #include <hal_irqmask.h> 27 #include <remote_spinlock.h> 28 #include <thread.h> 29 #include <kmem.h> 30 #include <printk.h> 31 #include <process.h> 32 #include <vmm.h> 26 33 #include <remote_barrier.h> 27 34 28 ///////////////////////////////////////// 29 inline void remote_barrier( xptr_t xp,35 ///////////////////////////////////////////////// 36 inline void remote_barrier( xptr_t barrier_xp, 30 37 uint32_t count ) 31 38 { 32 39 uint32_t expected; 33 40 34 remote_barrier_t * ptr = (remote_barrier_t *)GET_PTR( xp );35 cxy_t cxy = GET_CXY( xp );41 remote_barrier_t * ptr = (remote_barrier_t *)GET_PTR( barrier_xp ); 42 cxy_t cxy = GET_CXY( barrier_xp ); 36 43 37 44 // get barrier sense value … … 57 64 } 58 65 59 66 /////////////////////////////////////////////////// 67 xptr_t remote_barrier_from_ident( intptr_t ident ) 68 { 69 // get pointer on local process_descriptor 70 process_t * process = CURRENT_THREAD->process; 71 72 // get extended pointer on reference process 73 xptr_t ref_xp = process->ref_xp; 74 75 // get cluster and local pointer on reference process 76 cxy_t ref_cxy = GET_CXY( ref_xp ); 77 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 78 79 // get extended pointer on root of barriers list 80 xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->barrier_root ); 81 82 // scan reference process barriers list 83 xptr_t iter_xp; 84 xptr_t barrier_xp; 85 cxy_t barrier_cxy; 86 remote_barrier_t * barrier_ptr; 87 intptr_t current; 88 bool_t found = false; 89 90 XLIST_FOREACH( root_xp , iter_xp ) 91 { 92 barrier_xp = XLIST_ELEMENT( iter_xp , remote_barrier_t , list ); 93 barrier_cxy = GET_CXY( barrier_xp ); 94 barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp ); 95 current = (intptr_t)hal_remote_lpt( XPTR( barrier_cxy , &barrier_ptr->ident ) ); 96 if( ident == current ) 97 { 98 found = true; 99 break; 100 } 101 } 102 103 if( found == false ) return XPTR_NULL; 104 else return barrier_xp; 105 106 } // end remote_barrier_from_ident() 107 108 ////////////////////////////////////////////// 109 error_t remote_barrier_create( intptr_t ident, 110 uint32_t count ) 111 { 112 xptr_t barrier_xp; 113 remote_barrier_t * barrier_ptr; 114 115 // get pointer on local process descriptor 116 process_t * process = CURRENT_THREAD->process; 117 118 // get extended pointer on reference process 119 xptr_t ref_xp = process->ref_xp; 120 121 // get reference process cluster and local pointer 122 cxy_t ref_cxy = GET_CXY( ref_xp ); 123 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 124 125 // allocate memory for barrier descriptor 126 if( ref_cxy == local_cxy ) // local cluster is the reference 127 { 128 kmem_req_t req; 129 req.type = KMEM_BARRIER; 130 req.flags = AF_ZERO; 131 barrier_ptr = kmem_alloc( &req ); 132 barrier_xp = XPTR( local_cxy , barrier_ptr ); 133 } 134 else // reference is remote 135 { 136 rpc_kcm_alloc_client( ref_cxy , KMEM_BARRIER , &barrier_xp ); 137 barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp ); 138 } 139 140 if( barrier_ptr == NULL ) return ENOMEM; 141 142 // initialise barrier 143 hal_remote_sw ( XPTR( ref_cxy , &barrier_ptr->nb_threads ) , count ); 144 hal_remote_sw ( XPTR( ref_cxy , &barrier_ptr->current ) , 0 ); 145 hal_remote_sw ( XPTR( ref_cxy , &barrier_ptr->sense ) , 0 ); 146 hal_remote_spt( XPTR( ref_cxy , &barrier_ptr->ident ) , (void*)ident ); 147 148 xlist_entry_init( XPTR( ref_cxy , &barrier_ptr->list ) ); 149 150 // register barrier in reference process xlist 151 xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->barrier_root ); 152 xptr_t entry_xp = XPTR( ref_cxy , &barrier_ptr->list ); 153 154 remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 155 xlist_add_first( root_xp , entry_xp ); 156 remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 157 158 return 0; 159 160 } // end remote_barrier_create() 161 162 //////////////////////////////////////////////// 163 void remote_barrier_destroy( xptr_t barrier_xp ) 164 { 165 // get pointer on local process descriptor 166 process_t * process = CURRENT_THREAD->process; 167 168 // get extended pointer on reference process 169 xptr_t ref_xp = process->ref_xp; 170 171 // get reference process cluster and local pointer 172 cxy_t ref_cxy = GET_CXY( ref_xp ); 173 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 174 175 // get barrier cluster and local pointer 176 cxy_t barrier_cxy = GET_CXY( barrier_xp ); 177 remote_barrier_t * barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp ); 178 179 // remove barrier from reference process xlist 180 remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 181 xlist_unlink( XPTR( barrier_cxy , &barrier_ptr->list ) ); 182 remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 183 184 // release memory allocated for barrier descriptor 185 if( barrier_cxy == local_cxy ) // reference is local 186 { 187 kmem_req_t req; 188 req.type = KMEM_BARRIER; 189 req.ptr = barrier_ptr; 190 kmem_free( &req ); 191 } 192 else // reference is remote 193 { 194 rpc_kcm_free_client( barrier_cxy , barrier_ptr , KMEM_BARRIER ); 195 } 196 197 } // end remote_barrier_destroy() 198 199 ///////////////////////////////////////////// 200 void remote_barrier_wait( xptr_t barrier_xp ) 201 { 202 uint32_t expected; 203 uint32_t current; 204 uint32_t count; 205 uint32_t sense; 206 uint32_t irq_state; 207 xptr_t root_xp; 208 209 // get cluster and local pointer on calling thread 210 cxy_t thread_cxy = local_cxy; 211 thread_t * thread_ptr = CURRENT_THREAD; 212 213 // get cluster and local pointer on remote barrier 214 remote_barrier_t * barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp ); 215 cxy_t barrier_cxy = GET_CXY( barrier_xp ); 216 217 // get count and root fields from barrier descriptor 218 count = hal_remote_lw ( XPTR( barrier_cxy , &barrier_ptr->nb_threads ) ); 219 root_xp = hal_remote_lwd( XPTR( barrier_cxy , &barrier_ptr->root ) ); 220 221 // get barrier sense value 222 sense = hal_remote_lw( XPTR( barrier_cxy , &barrier_ptr->sense ) ); 223 224 // compute expected value 225 if ( sense == 0 ) expected = 1; 226 else expected = 0; 227 228 // atomically increment current 229 current = hal_remote_atomic_add( XPTR( barrier_cxy , &barrier_ptr->current ) , 1 ); 230 231 // last thread reset current, toggle sense, and activate all waiting threads 232 // other threads block, register in queue, and deschedule 233 234 if( current == (count-1) ) // last thread 235 { 236 hal_remote_sw( XPTR( barrier_cxy , &barrier_ptr->current) , 0 ); 237 hal_remote_sw( XPTR( barrier_cxy , &barrier_ptr->sense ) , expected ); 238 239 // activate waiting threads if required 240 if( xlist_is_empty( root_xp ) == false ) 241 { 242 // disable interrupts 243 hal_disable_irq( &irq_state ); 244 245 xptr_t iter_xp; 246 xptr_t thread_xp; 247 XLIST_FOREACH( root_xp , iter_xp ) 248 { 249 // get extended pointer on waiting thread 250 thread_xp = XLIST_ELEMENT( iter_xp , thread_t , wait_list ); 251 252 // remove waiting thread from queue 253 remote_spinlock_lock( XPTR( barrier_cxy , &barrier_ptr->lock ) ); 254 xlist_unlink( XPTR( barrier_cxy , &barrier_ptr->list ) ); 255 remote_spinlock_unlock( XPTR( barrier_cxy , &barrier_ptr->lock ) ); 256 257 // unblock waiting thread 258 thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC ); 259 } 260 261 // restore interrupts 262 hal_restore_irq( irq_state ); 263 } 264 } 265 else // not the last thread 266 { 267 // disable interrupts 268 hal_disable_irq( &irq_state ); 269 270 // register calling thread in barrier waiting queue 271 xptr_t entry_xp = XPTR( thread_cxy , &thread_ptr->wait_list ); 272 273 remote_spinlock_lock( XPTR( barrier_cxy , &barrier_ptr->lock ) ); 274 xlist_add_last( root_xp , entry_xp ); 275 remote_spinlock_unlock( XPTR( barrier_cxy , &barrier_ptr->lock ) ); 276 277 // block & deschedule the calling thread 278 thread_block( thread_ptr , THREAD_BLOCKED_USERSYNC ); 279 sched_yield(); 280 281 // restore interrupts 282 hal_restore_irq( irq_state ); 283 } 284 } // end remote_barrier_wait() -
trunk/kernel/libk/remote_barrier.h
r14 r23 1 1 /* 2 * remote_barrier.h - distributed kernel barrier definition2 * remote_barrier.h - Access a POSIX barrier. 3 3 * 4 4 * Author Alain Greiner (2016) … … 10 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 11 11 * under the terms of the GNU General Public License as published by 12 err* the Free Software Foundation; version 2.0 of the License.12 * the Free Software Foundation; version 2.0 of the License. 13 13 * 14 14 * ALMOS-MKH is distributed in the hope that it will be useful, but … … 27 27 #include <kernel_config.h> 28 28 #include <hal_types.h> 29 #include <remote_spinlock.h> 30 #include <xlist.h> 31 32 /*************************************************************************************** 33 * This file defines a POSIX compliant barrier. 34 * 35 * It is used by multi-threaded applications to synchronise threads running in 36 * different clusters, as all access functions uses hal_remote_lw() / hal_remote_sw() 37 * portable remote access primitives. 38 * 39 * A barrier is declared by a given user process as a "pthread_barrier_t" global variable. 40 * This user type is implemented as an unsigned long, but the value is not used by the 41 * kernel. ALMOS-MKH uses only the barrier virtual address as an identifier. 42 * For each user barrier, ALMOS-MKH creates a kernel "remote_barrier_t" structure, 43 * dynamically allocated in the reference cluster by the remote_barrier_create() function, 44 * and destroyed by the remote_barrier_destroy() function, using RPC if the calling thread 45 * is not running in the reference cluster. 46 * 47 * The blocking "remote_barrier_wait()" function implements a descheduling policy when 48 * the calling thread is not the last expected thread: the calling thread is registered 49 * in a waiting queue, rooted in the barrier structure, and the the calling thread 50 * is blocked on the THREAD_BLOCKED_USERSYNC condition. The last arrived thread 51 * unblocks all registtered waiting threads. 52 * 53 * Implementation note: 54 * This barrier is also used by the kernel in the parallel kernel_init phase, as the 55 * remote_barrier() function does not require barrier initialisation, when the barrier 56 * is statically allocated by the compiler in the kdata segment. 57 * **************************************************************************************/ 29 58 30 59 /***************************************************************************************** 31 * This structure defines a distributed "rendez-vous" barrier, that can be used 32 * to synchronise several kernel threads running in different clusters 33 * It is used in the parallel kernel_init phase. 34 * It does not need to be initialised, but it must be statically allocated 35 * in the KDATA segment to be properly initialised by the compiler/loader. 60 * This structure defines the barrier descriptor. 61 * - It contains an xlist of all barriers dynamically created by a given process, 62 * rooted in the reference process descriptor. 63 * - It contains the root of another xlist to register all arrived threads. 36 64 ****************************************************************************************/ 37 65 38 66 typedef struct remote_barrier_s 39 67 { 40 uint32_t current; // number of arrived threads 41 uint32_t sense; // barrier state (toggle) 42 uint32_t pad[(CONFIG_CACHE_LINE_SIZE>>2)-2]; 68 remote_spinlock_t lock; /*! lock protecting list of arrived threads */ 69 intptr_t ident; /*! virtual address in user space == identifier */ 70 uint32_t current; /*! number of arrived threads */ 71 uint32_t sense; /*! barrier state (toggle) */ 72 uint32_t nb_threads; /*! number of expected threads */ 73 xlist_entry_t list; /*! member of list of barriers in same process */ 74 xlist_entry_t root; /*! root of list of arrived threads */ 43 75 } 44 76 remote_barrier_t; 45 77 46 78 /***************************************************************************************** 47 * This blocking function implements a toggle barrier. It returns only when all48 * expected threads reach the barrier. It can be used several times without49 * specific initialisation.50 * It is portable, as it uses the remote_lw() & remote_sw() access functions.51 * @ xp : extended pointer on barrier in remote cluster52 * @ count : number of expected thread79 * This function is directly used by the kernel in the kernel_init phase, 80 * because it does not require barrier state initialisation. 81 * It returns only when the <count> expected threads reach the barrier. 82 ***************************************************************************************** 83 * @ barrier_xp : extended pointer on barrier descriptor. 84 * @ count : number of expected threads. 53 85 ****************************************************************************************/ 54 inline void remote_barrier( xptr_t xp,86 inline void remote_barrier( xptr_t barrier_xp, 55 87 uint32_t count ); 56 88 57 89 90 /***************************************************************************************** 91 * This function returns an extended pointer on the remote barrier identified 92 * by its virtual address in a given user process. It makes an associative search, 93 * scanning the list of barriers rooted in the reference process descriptor. 94 ***************************************************************************************** 95 * @ ident : barrier virtual address, used as identifier. 96 * @ returns extended pointer on barrier if success / returns XPTR_NULL if not found. 97 ****************************************************************************************/ 98 xptr_t remote_barrier_from_ident( intptr_t ident ); 99 100 /***************************************************************************************** 101 * This function implement the pthread_barrier_init() syscall. 102 * It allocates memory for the barrier descriptor in the reference cluster for 103 * the calling process, it initializes the barrier state, and register it in the 104 * list of barriers owned by the reference process. 105 ***************************************************************************************** 106 * @ count : number of expected threads. 107 * @ ident : barrier identifier (virtual address in user space). 108 * @ return 0 if success / return ENOMEM if failure. 109 ****************************************************************************************/ 110 error_t remote_barrier_create( intptr_t ident, 111 uint32_t count ); 112 113 /***************************************************************************************** 114 * This function implement the pthread_barrier_destroy() syscall. 115 * It releases thr memory allocated for the barrier descriptor, and remove the barrier 116 * from the list of barriers owned by the reference process. 117 ***************************************************************************************** 118 * @ barrier_xp : extended pointer on barrier descriptor. 119 ****************************************************************************************/ 120 void remote_barrier_destroy( xptr_t barrier_xp ); 121 122 /***************************************************************************************** 123 * This function implement the pthread_barrier_wait() syscall. 124 * It returns only when the number of expected threads (registered in the barrier 125 * dexcriptor) reach the barrier. 126 ***************************************************************************************** 127 * @ barrier_xp : extended pointer on barrier descriptor. 128 ****************************************************************************************/ 129 void remote_barrier_wait( xptr_t barrier_xp ); 130 131 58 132 #endif /* _REMOTE_BARRIER_H_ */ -
trunk/kernel/libk/remote_rwlock.c
r1 r23 2 2 * remote_rwlock.c - kernel remote rwlock implementation. 3 3 * 4 * Authors Mohamed Karaoui (2015) 5 * Alain Greiner (2016) 4 * Authors Alain Greiner (2016,2017) 6 5 * 7 6 * Copyright (c) UPMC Sorbonne Universites … … 67 66 68 67 // get next free ticket 69 ticket = hal_remote_ lw( ticket_xp);70 71 // loop to take the lock68 ticket = hal_remote_atomic_add( ticket_xp , 1 ); 69 70 // busy waiting loop to take the lock 72 71 while( ticket != hal_remote_lw( current_xp ) ) 73 72 { … … 147 146 148 147 // get next free ticket 149 ticket = hal_remote_ lw( ticket_xp);148 ticket = hal_remote_atomic_add( ticket_xp , 1 ); 150 149 151 150 // loop to take the lock -
trunk/kernel/libk/remote_rwlock.h
r14 r23 30 30 31 31 /*************************************************************************************** 32 * This structure defines a remote rwdlock,that supports several simultaneous read32 * This file defines a remote kernel lock, that supports several simultaneous read 33 33 * accesses, but only one write access. It implements a ticket based allocation policy. 34 34 * It can be used to synchronize threads running in different clusters, because … … 41 41 * When the lock is taken by another thread, the new-comers use a busy waiting policy. 42 42 * 43 * TODO This could be replaced by a descheduling policy and a threads waiting queue 44 * implemented in the lock itself: each thread releasing the lock (i.e. incrementing 45 * the current field) activates the first waiting thread... 43 * It uses a busy-waiting policy if the lock is already allocated to another thread. 46 44 **************************************************************************************/ 47 45 -
trunk/kernel/libk/remote_sem.c
r15 r23 23 23 24 24 #include <hal_types.h> 25 #include <hal_remote.h> 25 26 #include <thread.h> 26 27 #include <kmem.h> … … 35 36 { 36 37 // get pointer on local process_descriptor 37 process_t * process = CURRENT_ PROCESS;38 process_t * process = CURRENT_THREAD->process; 38 39 39 40 // get extended pointer on reference process … … 57 58 XLIST_FOREACH( root_xp , iter_xp ) 58 59 { 59 sem_xp = XLIST_ELEMENT( iter_xp , remote_sem_t , sem_list );60 sem_xp = XLIST_ELEMENT( iter_xp , remote_sem_t , list ); 60 61 sem_cxy = GET_CXY( sem_xp ); 61 62 sem_ptr = (remote_sem_t *)GET_PTR( sem_xp ); 62 ident = hal_remote_lw( XPTR( sem_cxy , &sem_ptr->ident ) );63 ident = (intptr_t)hal_remote_lpt( XPTR( sem_cxy , &sem_ptr->ident ) ); 63 64 if( ident == vaddr ) 64 65 { … … 73 74 } // end remote_sem_from_vaddr() 74 75 75 ///////////////////////////////////////// 76 error_t remote_sem_ init( intptr_t vaddr,77 uint32_t value )76 /////////////////////////////////////////// 77 error_t remote_sem_create( intptr_t vaddr, 78 uint32_t value ) 78 79 { 79 80 xptr_t sem_xp; … … 81 82 82 83 // get pointer on local process descriptor 83 process_t * process = CURRENT_ PROCESS;84 process_t * process = CURRENT_THREAD->process; 84 85 85 86 // get extended pointer on reference process 86 87 xptr_t ref_xp = process->ref_xp; 87 88 89 // get reference process cluster and local pointer 88 90 cxy_t ref_cxy = GET_CXY( ref_xp ); 89 91 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); … … 100 102 else // reference is remote 101 103 { 102 rpc_ semaphore_alloc_client( ref_cxy, &sem_xp );104 rpc_kcm_alloc_client( ref_cxy , KMEM_SEM , &sem_xp ); 103 105 sem_ptr = (remote_sem_t *)GET_PTR( sem_xp ); 104 106 } … … 106 108 if( sem_xp == XPTR_NULL ) return ENOMEM; 107 109 108 // initialise semaphore lock 110 // initialise semaphore 111 hal_remote_sw ( XPTR( ref_cxy , &sem_ptr->count ) , value ); 112 hal_remote_spt( XPTR( ref_cxy , &sem_ptr->ident ) , (void *)vaddr ); 113 109 114 remote_spinlock_init( XPTR( ref_cxy , &sem_ptr->lock ) ); 110 111 // initialise semaphore count 112 hal_remote_sw( XPTR( ref_cxy , &sem_ptr->count ) , value ); 113 114 // initialise vaddr 115 hal_remote_spt( XPTR( ref_cxy , &sem_ptr->ident ) , (void *)vaddr ); 116 117 // initialise waiting threads queue 118 xlist_root_init( XPTR( ref_cxy , &sem_ptr->wait_queue ) ); 119 120 // register new semaphore in reference process xlist 115 xlist_root_init( XPTR( ref_cxy , &sem_ptr->root ) ); 116 xlist_entry_init( XPTR( ref_cxy , &sem_ptr->list ) ); 117 118 // register semaphore in reference process xlist 121 119 xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->sem_root ); 122 xptr_t xp_list = XPTR( ref_cxy , &sem_ptr->sem_list ); 120 xptr_t xp_list = XPTR( ref_cxy , &sem_ptr->list ); 121 122 remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 123 123 xlist_add_first( root_xp , xp_list ); 124 remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 124 125 125 126 return 0; … … 127 128 } // en remote_sem_init() 128 129 130 //////////////////////////////////////// 131 void remote_sem_destroy( xptr_t sem_xp ) 132 { 133 // get pointer on local process descriptor 134 process_t * process = CURRENT_THREAD->process; 135 136 // get extended pointer on reference process 137 xptr_t ref_xp = process->ref_xp; 138 139 // get reference process cluster and local pointer 140 cxy_t ref_cxy = GET_CXY( ref_xp ); 141 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 142 143 // get semaphore cluster and local pointer 144 cxy_t sem_cxy = GET_CXY( sem_xp ); 145 remote_sem_t * sem_ptr = (remote_sem_t *)GET_PTR( sem_xp ); 146 147 // get lock protecting semaphore 148 remote_spinlock_lock( XPTR( sem_cxy , &sem_ptr->lock ) ); 149 150 // get remote pointer on waiting queue 151 xptr_t root_xp = (xptr_t)hal_remote_lwd( XPTR( sem_cxy , &sem_ptr->root ) ); 152 153 if( !xlist_is_empty( root_xp ) ) // user error 154 { 155 printk("WARNING in %s for thread %x in process %x : " 156 "destroy semaphore, but waiting threads queue not empty\n", 157 __FUNCTION__ , CURRENT_THREAD->trdid , CURRENT_THREAD->process->pid ); 158 } 159 160 // reset semaphore count 161 hal_remote_sw( XPTR( sem_cxy , &sem_ptr->count ) , 0 ); 162 163 // remove semaphore from reference process xlist 164 remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 165 xlist_unlink( XPTR( sem_cxy , &sem_ptr->list ) ); 166 remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 167 168 // release lock 169 remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) ); 170 171 // release memory allocated for semaphore descriptor 172 if( sem_cxy == local_cxy ) // reference is local 173 { 174 kmem_req_t req; 175 req.type = KMEM_SEM; 176 req.ptr = sem_ptr; 177 kmem_free( &req ); 178 } 179 else // reference is remote 180 { 181 rpc_kcm_free_client( sem_cxy , sem_ptr , KMEM_SEM ); 182 } 183 184 } // end remote_sem_destroy() 185 129 186 ////////////////////////////////// 130 187 void remote_sem_wait( xptr_t sem_xp ) … … 153 210 154 211 // register thread in waiting queue 155 xptr_t root_xp = (xptr_t)hal_remote_lwd( XPTR( sem_cxy , &sem_ptr-> wait_queue) );212 xptr_t root_xp = (xptr_t)hal_remote_lwd( XPTR( sem_cxy , &sem_ptr->root ) ); 156 213 xptr_t thread_xp = XPTR( local_cxy , this ); 157 214 xlist_add_last( root_xp , thread_xp ); … … 177 234 178 235 // get remote pointer on waiting queue root 179 xptr_t queue_xp = (xptr_t)hal_remote_lwd( XPTR( sem_cxy , &sem_ptr->wait_queue) );180 181 if( xlist_is_empty( queue_xp ) ) // no waiting thread236 xptr_t root_xp = (xptr_t)hal_remote_lwd( XPTR( sem_cxy , &sem_ptr->root ) ); 237 238 if( xlist_is_empty( root_xp ) ) // no waiting thread 182 239 { 183 240 // get semaphore current value … … 190 247 { 191 248 // get first waiting thread from queue 192 xptr_t thread_xp = XLIST_FIRST_ELEMENT( queue_xp , thread_t , wait_list );249 xptr_t thread_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list ); 193 250 194 251 // get thread cluster and local poiner … … 206 263 } // end remote_sem_post() 207 264 208 ////////////////////////////////////////209 void remote_sem_destroy( xptr_t sem_xp )210 {211 // get semaphore cluster and local pointer212 cxy_t sem_cxy = GET_CXY( sem_xp );213 remote_sem_t * sem_ptr = (remote_sem_t *)GET_PTR( sem_xp );214 215 // get lock protecting semaphore216 remote_spinlock_lock( XPTR( sem_cxy , &sem_ptr->lock ) );217 218 // get remote pointer on waiting queue219 xptr_t queue_xp = (xptr_t)hal_remote_lwd( XPTR( sem_cxy , &sem_ptr->wait_queue ) );220 221 if( !xlist_is_empty( queue_xp ) ) // user error222 {223 printk("WARNING in %s for thread %x in process %x : "224 "destroy semaphore, but waiting threads queue not empty\n",225 __FUNCTION__ , CURRENT_THREAD->trdid , CURRENT_PROCESS->pid );226 }227 228 // reset semaphore count229 hal_remote_sw( XPTR( sem_cxy , &sem_ptr->count ) , 0 );230 231 // remove semaphore from process232 xptr_t xp_list = (xptr_t)hal_remote_lwd( XPTR( sem_cxy , &sem_ptr->sem_list ) );233 xlist_unlink( xp_list );234 235 // release lock236 remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) );237 238 // release memory allocated239 if( sem_cxy == local_cxy ) // reference is local240 {241 kmem_req_t req;242 req.type = KMEM_SEM;243 req.ptr = sem_ptr;244 kmem_free( &req );245 }246 else // reference is remote247 {248 rpc_semaphore_free_client( sem_cxy , sem_ptr );249 }250 251 } // end remote_sem_destroy()252 265 253 266 ////////////////////////////////////////////// -
trunk/kernel/libk/remote_sem.h
r15 r23 30 30 31 31 /********************************************************************************************* 32 * This file defines the thePOSIX compliant unnamed semaphore.32 * This file defines a POSIX compliant unnamed semaphore. 33 33 * 34 34 * A semaphore is declared by a given user process as a "sem_t" global variable. … … 46 46 47 47 /********************************************************************************************* 48 * This structure defines the kernel remote_sem_t structure.49 * It contains the root of a waiting threads queue, implemented as a distributed xlist.50 * It contains an xlist of all semaphores, rooted in the reference process descriptor.51 * It contains a lock protecting both the semaphore value and the waiting queue.48 * This structure defines the kernel semaphore descriptor. 49 * - It contains the root of a waiting threads queue, implemented as a distributed xlist. 50 * - It contains an xlist of all semaphores, rooted in the reference process descriptor. 51 * - It contains a lock protecting both the semaphore value and the waiting queue. 52 52 ********************************************************************************************/ 53 53 … … 57 57 uint32_t count; /*! current value */ 58 58 intptr_t ident; /*! virtual address in user space == identifier */ 59 xlist_entry_t wait_queue;/*! root of waiting thread queue */60 xlist_entry_t sem_list;/*! member of list of semaphores in same process */59 xlist_entry_t root; /*! root of waiting thread queue */ 60 xlist_entry_t list; /*! member of list of semaphores in same process */ 61 61 } 62 62 remote_sem_t; 63 64 /*********************************************************************************************65 * This enum defines the semaphore operation types supported by the sys_sem() function.66 * It must be consistent with the values defined in the semaphore.c file (user library).67 ********************************************************************************************/68 69 typedef enum70 {71 SEM_INIT,72 SEM_GETVALUE,73 SEM_WAIT,74 SEM_POST,75 SEM_DESTROY76 }77 sem_operation_t;78 79 63 80 64 81 65 /********************************************************************************************* 82 66 * This function returns an extended pointer on the remote semaphore identified 83 * by its virtual address in a given user process. It makes an associative search, scanning84 * the list of semaphores rooted in the reference process descriptor.67 * by its virtual address in a given user process. It makes an associative search, 68 * scanning the list of semaphores rooted in the reference process descriptor. 85 69 ********************************************************************************************* 86 70 * @ process : pointer on local process descriptor. … … 99 83 * @ returns 0 if success / returns ENOMEM if error. 100 84 ********************************************************************************************/ 101 error_t remote_sem_ init( intptr_t vaddr,102 uint32_t value );85 error_t remote_sem_create( intptr_t vaddr, 86 uint32_t value ); 103 87 88 /****************************yy*************************************************************** 89 * This function implements the SEM_DESTROY operation. 90 * It desactivates the semaphore, and releases the physical memory allocated in the 91 * reference cluster, using a RPC if required. 92 ********************************************************************************************* 93 * @ sem_xp : extended pointer on semaphore. 94 ********************************************************************************************/ 95 void remote_sem_destroy( xptr_t sem_xp ); 96 104 97 /****************************yy*************************************************************** 105 98 * This blocking function implements the SEM_WAIT operation. … … 123 116 124 117 /****************************yy*************************************************************** 125 * This function implements the SEM_DESTROY operation.126 * It desactivates the semaphore, and releases the physical memory allocated in the127 * reference cluster, using a RPC if required.128 *********************************************************************************************129 * @ sem_xp : extended pointer on semaphore.130 ********************************************************************************************/131 void remote_sem_destroy( xptr_t sem_xp );132 133 /****************************yy***************************************************************134 118 * This function implements the SEM_GETVALUE operation. 135 119 * It returns in the <data> buffer the semaphore current value. -
trunk/kernel/libk/rwlock.c
r14 r23 86 86 87 87 // decrement number of readers 88 hal_atomic_ dec( &lock->count);88 hal_atomic_add( &lock->count , -1 ); 89 89 this->local_locks--; 90 90 -
trunk/kernel/libk/string.h
r1 r23 83 83 84 84 /******************************************************************************************** 85 * TODO85 * this function copies the <src> buffer to the <dst> buffer, including the terminating NUL. 86 86 ******************************************************************************************** 87 * @ dst : pointer on destination buffer. 88 * @ src : pointer on source buffer. 87 89 *******************************************************************************************/ 88 char * strcpy ( char * d est,90 char * strcpy ( char * dst, 89 91 char * src ); 90 92 91 93 /******************************************************************************************** 92 * T ODO94 * This function copies <n> characters from the <sr> buffer to the <dst> buffer. 93 95 ******************************************************************************************** 96 * @ dst : pointer on destination buffer. 97 * @ src : pointer on source buffer. 98 * @ n : number of characters to be copied. 94 99 *******************************************************************************************/ 95 char * strncpy ( char * d est,100 char * strncpy ( char * dst, 96 101 char * src, 97 102 uint32_t n ); 98 103 99 104 /******************************************************************************************** 100 * T ODO105 * This function locates the first occurence of the <c> character in the <s> string. 101 106 ******************************************************************************************** 107 * @ s : string to be analysed. 108 * @ c : searched character value (casted to a char) 109 * @ return pointer on the found character / return NULL if not found. 102 110 *******************************************************************************************/ 103 111 char * strchr ( const char * s, … … 105 113 106 114 /******************************************************************************************** 107 * T ODO115 * This function locates the last occurence of the <c> character in the <s> string. 108 116 ******************************************************************************************** 117 * @ s : string to be analysed. 118 * @ c : searched character value (casted to a char) 119 * @ return pointer on the found character / return NULL if not found. 109 120 *******************************************************************************************/ 110 121 char * strrchr ( const char * t, -
trunk/kernel/libk/xhtab.c
r14 r23 2 2 * xhtab.c - Remote access embedded hash table implementation. 3 3 * 4 * Author Alain Greiner (2016 )4 * Author Alain Greiner (2016,2017) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 34 34 35 35 36 /////////////////////////////////////////////////////////////////////////////////////// 37 // This static function s called by the xhtab_lookup() and xhtab_register() functions. 38 // It scan one sub-list identified by <index> to find an item identified by <key>. 39 // The hash table is identified by <cxy> and local pointer <xhtab>. 36 /////////////////////////////////////////////////////////////////////////////////////////// 37 // Item type specific (static) functions (two functions for each item type). 38 // - for type <vfs_dentry_t>, identifier is the name field. 39 /////////////////////////////////////////////////////////////////////////////////////////// 40 41 /////////////////////////////////////////////////////////////////////////////////////////// 42 // These static functions compute the hash index from the key. 43 /////////////////////////////////////////////////////////////////////////////////////////// 44 // @ key : local pointer on key. 45 // @ return the index value, from 0 to (HASHTAB_SIZE - 1) 46 /////////////////////////////////////////////////////////////////////////////////////////// 47 48 ///////////////////////////////////////// 49 uint32_t xhtab_dentry_index( void * key ) 50 { 51 char * name = key; 52 uint32_t index = 0; 53 while( *name ) 54 { 55 index = index + (*(name++) ^ index); 56 } 57 return index % HASHTAB_SIZE; 58 } 59 60 //////////////////////////////////////////////////////////////////////////////////////////// 61 // These static function are used by xhtab_lookup(), xhtab_insert(), xhtab_remove(). 62 // They scan one sub-list identified by <index> to find an item identified by <key>. 40 63 // The sub-list is not modified, but the readlock must have been taken by the caller. 41 /////////////////////////////////////////////////////////////////////////////////////// 42 // @ cxy : hash table cluster. 43 // @ xhtab_xp : hash table local pointer. 64 //////////////////////////////////////////////////////////////////////////////////////////// 65 // @ xhtab_xp : extended pointer on hash table. 44 66 // @ index : index of sub-list to be scanned. 45 67 // @ key : local pointer on item identifier. 46 /////////////////////////////////////////////////////////////////////////////////////// 47 static xptr_t xhtab_scan( cxy_t cxy, 48 xhtab_t * xhtab, 49 uint32_t index, 50 void * key ) 51 { 52 xptr_t xlist_xp; // extended pointer on xlist_entry_t (iterator) 53 xptr_t item_xp; // extended pointer on found item (return value) 68 // return an extended pointer on item if found / return XPTR_NULL if not found. 69 //////////////////////////////////////////////////////////////////////////////////////////// 70 71 //////////////////////////////////////////////////// 72 static xptr_t xhtab_dentry_scan( xptr_t xhtab_xp, 73 uint32_t index, 74 void * key ) 75 { 76 xptr_t xlist_xp; // xlist_entry_t (iterator) 77 xhtab_t * xhtab_ptr; // hash table local pointer 78 cxy_t xhtab_cxy; // hash table cluster 79 char local_name[CONFIG_VFS_MAX_NAME_LENGTH]; // local copy of dentry name 80 81 // get hash table cluster and local pointer 82 xhtab_cxy = GET_CXY( xhtab_xp ); 83 xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp ); 84 85 // scan sub-list[index] 86 XLIST_FOREACH( XPTR( xhtab_cxy , &xhtab_ptr->roots[index] ) , xlist_xp ) 87 { 88 // get extended pointer on dentry containing the xlist_entry_t 89 xptr_t dentry_xp = XLIST_ELEMENT( xlist_xp , vfs_dentry_t , xlist ); 90 91 // get dentry cluster and local pointer 92 cxy_t dentry_cxy = GET_CXY( dentry_xp ); 93 vfs_dentry_t * dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp ); 54 94 55 // scan the sub-list[index] 56 XLIST_FOREACH( XPTR( cxy , &xhtab->roots[index] ) , xlist_xp ) 57 { 58 if ( xhtab->compare( xlist_xp , key , &item_xp ) ) return item_xp; 59 } 60 61 // no matching item found 62 return XPTR_NULL; 95 // make a local copy of dentry name 96 hal_remote_memcpy( XPTR( local_cxy , local_name ) , 97 XPTR( dentry_cxy , dentry_ptr->name ), 98 CONFIG_VFS_MAX_NAME_LENGTH ); 99 100 // check matching 101 if( strcmp( local_name , (char *)key ) == 0 ) return dentry_xp; 102 } 103 104 // No matching item found 105 return XPTR_NULL; 63 106 } 64 107 65 ///////////////////////////////// 66 void xhtab_init( xhtab_t * xhtab, 67 uint32_t type ) 108 //////////////////////////////////////////////////////////////////////////////////////// 109 // Generic access functions 110 //////////////////////////////////////////////////////////////////////////////////////// 111 112 ////////////////////////////////////////// 113 void xhtab_init( xhtab_t * xhtab, 114 xhtab_item_type_t type ) 68 115 { 69 116 uint32_t i; … … 76 123 if( type == XHTAB_DENTRY_TYPE ) 77 124 { 78 hal_remote_spt( XPTR( local_cxy , &xhtab->compare ) , &xhtab_dentry_compare );79 hal_remote_spt( XPTR( local_cxy , &xhtab->index ) , &xhtab_dentry_index );125 xhtab->scan = &xhtab_dentry_scan; 126 xhtab->index = &xhtab_dentry_index; 80 127 } 81 128 else … … 92 139 93 140 /////////////////////////////////////// 94 void xhtab_register( xptr_t xhtab_xp, 95 void * key, 96 xptr_t xlist_xp ) 97 { 141 error_t xhtab_insert( xptr_t xhtab_xp, 142 void * key, 143 xptr_t xlist_xp ) 144 { 145 146 printk("\n @@@ xhtab_insert : 0 / name = %s / xhtab_xp = %l / xlist_xp = %l\n", 147 key , xhtab_xp , xlist_xp ); 148 98 149 // get xhtab cluster and local pointer 99 150 cxy_t xhtab_cxy = GET_CXY( xhtab_xp ); … … 103 154 uint32_t index = xhtab_ptr->index( key ); 104 155 156 printk("\n @@@ xhtab_insert : 1 / name = %s / index = %d\n", 157 key , index ); 158 105 159 // take the lock protecting hash table 106 160 remote_rwlock_wr_lock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); 107 161 108 // register item in hash table 109 xlist_add_last( XPTR( xhtab_cxy , &xhtab_ptr->roots[index] ) , xlist_xp ); 110 111 // update number of registered items 112 hal_remote_atomic_add( XPTR( xhtab_cxy , &xhtab_ptr->items ) , 1 ); 113 114 // release the lock protecting hash table 115 remote_rwlock_wr_unlock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); 116 117 } // end xhtab_register() 162 // search a matching item 163 xptr_t item_xp = xhtab_ptr->scan( xhtab_xp , index , key ); 164 165 if( item_xp != XPTR_NULL ) // error if found 166 { 167 // release the lock protecting hash table 168 remote_rwlock_wr_unlock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); 169 170 printk("\n @@@ xhtab_insert : 2 / name = %s / item_xp = %l\n", 171 key , item_xp ); 172 173 return EINVAL; 174 } 175 else // insert item if not found 176 { 177 // register item in hash table 178 xlist_add_last( XPTR( xhtab_cxy , &xhtab_ptr->roots[index] ) , xlist_xp ); 179 180 // update number of registered items 181 hal_remote_atomic_add( XPTR( xhtab_cxy , &xhtab_ptr->items ) , 1 ); 182 183 // release the lock protecting hash table 184 remote_rwlock_wr_unlock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); 185 186 printk("\n @@@ xhtab_insert : 3 / name = %s / item_xp = %l\n", 187 key , xhtab_ptr->scan( xhtab_xp , index , key ) ); 188 189 return 0; 190 } 191 } // end xhtab_insert() 118 192 119 193 ///////////////////////////////////// 120 void xhtab_remove( xptr_t xhtab_xp, 121 void * key ) 194 error_t xhtab_remove( xptr_t xhtab_xp, 195 void * key, 196 xptr_t xlist_entry_xp ) 122 197 { 123 198 // get xhtab cluster and local pointer … … 125 200 xhtab_t * xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp ); 126 201 202 // compute index from key 203 uint32_t index = xhtab_ptr->index( key ); 204 127 205 // take the lock protecting hash table 128 206 remote_rwlock_wr_lock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); 129 207 130 // compute index from key131 uint32_t index = xhtab_ptr->index( key );132 133 208 // get extended pointer on item to remove 134 xptr_t item_xp = xhtab_scan( xhtab_cxy , xhtab_ptr , index , key ); 135 136 if( item_xp == XPTR_NULL ) // do nothing if not found 137 { 138 // release the lock protecting hash table 139 remote_rwlock_wr_unlock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); 209 xptr_t item_xp = xhtab_ptr->scan( xhtab_xp , index , key ); 210 211 if( item_xp == XPTR_NULL ) // error if not found 212 { 213 // release the lock protecting hash table 214 remote_rwlock_wr_unlock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); 215 216 return EINVAL; 140 217 } 141 218 else // remove item if found 142 219 { 143 // get item cluster and local pointer144 cxy_t item_cxy = GET_CXY( item_xp );145 vfs_dentry_t * item_ptr = (vfs_dentry_t *)GET_PTR( item_xp );146 147 220 // remove item from hash table <=> unlink xlist_entry_t 148 xlist_unlink( XPTR( item_cxy , &item_ptr->xlist ));221 xlist_unlink( xlist_entry_xp ); 149 222 150 223 // update number of registered items … … 153 226 // release the lock protecting hash table 154 227 remote_rwlock_wr_unlock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) ); 155 } 156 } // end xhtab_unregister() 228 229 return 0; 230 } 231 } // end xhtab_remove() 157 232 158 233 ///////////////////////////////////////// … … 173 248 174 249 // scan sub-list 175 item_xp = xhtab_ scan( xhtab_cxy , xhtab_ptr, index , key );250 item_xp = xhtab_ptr->scan( xhtab_xp , index , key ); 176 251 177 252 // release the lock protecting hash table … … 183 258 184 259 185 186 /////////////////////////////////////////187 uint32_t xhtab_dentry_index( void * key )188 {189 char * str = key;190 uint32_t index = 0;191 192 while( *str ) index = index + (*(str++) ^ index);193 194 return index % HASHTAB_SIZE;195 }196 197 ///////////////////////////////////////////////198 bool_t xhtab_dentry_compare( xptr_t xlist_xp,199 void * key,200 xptr_t * item_xp )201 {202 char tested_name[256]; // local copy of name stored in remote hash table203 204 char * searched_name = key; // local pointer on searched name205 206 // compute name length207 uint32_t length = strlen( searched_name );208 209 // get extended pointer on dentry containing the xlist_entry_t210 xptr_t dentry_xp = XLIST_ELEMENT( xlist_xp , vfs_dentry_t , xlist );211 212 // get dentry cluster and local pointer213 cxy_t dentry_cxy = GET_CXY( dentry_xp );214 vfs_dentry_t * dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp );215 216 // make a local copy of remote dentry name217 hal_remote_memcpy( XPTR( local_cxy , tested_name ) ,218 XPTR( dentry_cxy , dentry_ptr->name ) , length );219 220 // check matching / return if match221 if( strcmp( tested_name , searched_name ) == 0 )222 {223 return true;224 *item_xp = dentry_xp;225 }226 else227 {228 return false;229 }230 }231 232 233 234 ////////////////////////////////////////235 uint32_t xhtab_inode_index( void * key )236 {237 uint32_t * inum = key;238 239 return (((*inum) >> 16) ^ ((*inum) & 0xFFFF)) % HASHTAB_SIZE;240 }241 242 ///////////////////////////////////////////////243 bool_t xhtab_inode_compare( xptr_t xlist_xp,244 void * key,245 xptr_t * item_xp )246 {247 uint32_t * searched_inum = key;248 uint32_t tested_inum;249 250 // get extended pointer on inode containing the xlist_entry_t251 xptr_t inode_xp = XLIST_ELEMENT( xlist_xp , vfs_inode_t , xlist );252 253 // get inode cluster and local pointer254 cxy_t inode_cxy = GET_CXY( inode_xp );255 vfs_inode_t * inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );256 257 // get tested inode inum258 tested_inum = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->inum ) );259 260 // check matching / return if match261 if( tested_inum == *searched_inum )262 {263 return true;264 *item_xp = inode_xp;265 }266 else267 {268 return false;269 }270 }271 -
trunk/kernel/libk/xhtab.h
r14 r23 2 2 * xhtab.h - Remote access embedded hash table definition. 3 3 * 4 * Author Alain Greiner (2016)4 * Author Alain Greiner (2016,2017) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 31 31 32 32 33 /****************************************************************************************** 34 * This file define a generic, embedded, hash table that can be remotely accessed by 35 * any thread running in any cluster. 36 * The main goal is to speedup search by key in a set of items identified by their key. 37 * For this purpose the set of all registered items is split in several subsets: 38 * Each subset is organised an embedded double linked lists. 39 * - an item is uniquely identified by a <key>, that can be a single uint32_t, 40 * a name (character string), or a more complex structure. 41 * - From the <key>, the hash table uses an item type specific "xhtab_index()" function, 42 * to compute an <index> value, defining a subset of registered items. 43 * - to discriminate between items that have the same <index>, the hash table uses another 44 * item type specific "xhtab_compare()" function for the associative search in subset. 45 * - Each registered item is a structure, that must contain an embedded xlist_entry, 46 * that is part of the xlist implementing the subset. 47 * - The xhtab header contains an array indexed by <index> and containing the roots 48 * of the various xlists implementing the subsets. 49 * pointer on the searched item can be obtained by a simple offset. 50 * Implementation note: 51 * to use this generic infrastructure for a new type of item, you must define a new 52 * type in the xhtan_item_type_t" below, and to define the two associated 53 * "xhtab_compare() and xhtab_index(). 54 *****************************************************************************************/ 33 /////////////////////////////////////////////////////////////////////////////////////////// 34 // This file define a generic, embedded, remotely accessible hash table. 35 // 36 // It can be accessed by any thread, running in any cluster. 37 // It is generic as it can be used to register various types of items. 38 // The main goal is to speedup search by key for a large number of items of same type. 39 // For this purpose the set of all registered items is split in several subsets. 40 // Each subset is organised an embedded double linked lists. 41 // - an item is uniquely identified by a <key>, that can be a single uint32_t, 42 // a name (character string), or a more complex structure. 43 // - From the pointer on <key>, we use an item type specific xhtab_index() function, 44 // to compute an <index> value, defining a subset of registered items. 45 // - to discriminate between items that have the same <index>, the hash table uses another 46 // item type specific "xhtab_scan()" function for the associative search in subset. 47 // - Each registered item is a structure, that must contain an embedded xlist_entry, 48 // that is part of the xlist implementing the subset. 49 // 50 // Implementation Note: for each supported item type ***, you must define the two 51 // xhtab_***_index() and xhtab_***_scan() functions, and 52 // update the xhtab_init() function. 53 /////////////////////////////////////////////////////////////////////////////////////////// 55 54 56 55 #define HASHTAB_SIZE 64 // number of subsets 57 56 58 57 /****************************************************************************************** 59 * These typedef define the generic xhtab_compare() and xhtab_index() function prototypes. 60 * It must exist a specific couple of functions for each item type. 61 * @ entry_xp : extended pointer on an xlist_entry_t in a partial xlist. 62 * @ key : local pointer on the searched item key. 63 * @ item_xp : buffer to store extended pointer on found item. 58 * These typedef define the two item type specific function prototypes. 64 59 *****************************************************************************************/ 65 60 66 typedef bool_t xhtab_compare_t( xptr_t entry_xp , void * key , xptr_t * item_xp ); 61 typedef xptr_t xhtab_scan_t( xptr_t xhtab_xp , uint32_t index , void * key ); 62 67 63 typedef uint32_t xhtab_index_t( void * key ); 68 64 … … 73 69 typedef enum 74 70 { 75 XHTAB_DENTRY_TYPE = 1, /*! item is a vfs_dentry_t */ 76 XHTAB_INODE_TYPE = 2, /*! item is a vfs_inode_t */ 71 XHTAB_DENTRY_TYPE = 0, /*! item is a vfs_dentry_t */ 77 72 } 78 73 xhtab_item_type_t; 79 74 80 75 /****************************************************************************************** 81 * This structure define the root of a generic, remote accessible,hash table.76 * This structure define the root of the remote accessible hash table. 82 77 *****************************************************************************************/ 83 78 … … 85 80 { 86 81 xlist_entry_t roots[HASHTAB_SIZE]; /*! array of roots of xlist */ 87 xhtab_ compare_t * compare; /*! item specific index function*/88 xhtab_ index_t * index; /*! item specific compare function*/82 xhtab_index_t * index; /*! item specific function */ 83 xhtab_scan_t * scan; /*! item specific function */ 89 84 uint32_t items; /*! number of registered items */ 90 remote_rwlock_t lock; /*! lock protecting hash table modifs*/85 remote_rwlock_t lock; /*! lock protecting hash table accesses */ 91 86 } 92 87 xhtab_t; 93 88 94 89 /****************************************************************************************** 95 * This function initializes an empty hash table (zero children).90 * This function initializes an empty hash table (zero registered item). 96 91 * The initialisation must be done by a thread running in cluster containing the table. 97 92 ****************************************************************************************** … … 99 94 * @ type : item type (see above). 100 95 *****************************************************************************************/ 101 void xhtab_init( xhtab_t * xhtab,102 uint32_ttype );96 void xhtab_init( xhtab_t * xhtab, 97 xhtab_item_type_t type ); 103 98 104 99 /****************************************************************************************** … … 108 103 * @ key : local pointer on item identifier. 109 104 * @ xlist_xp : extended pointer on xlist_entry_t embedded in item to be registered. 105 * @ return 0 if success / return EINVAL if item already registered. 110 106 *****************************************************************************************/ 111 void xhtab_register( xptr_t xhtab_xp,112 void * key,113 xptr_t xlist_xp );107 error_t xhtab_insert( xptr_t xhtab_xp, 108 void * key, 109 xptr_t xlist_xp ); 114 110 115 111 /****************************************************************************************** 116 112 * This function safely remove an item from the hash table, using the lock protecting it. 117 113 ****************************************************************************************** 118 * @ xhtab_xp : extended pointer on hash table. 119 * @ key : local pointer on item identifier. 114 * @ xhtab_xp : extended pointer on hash table. 115 * @ key : local pointer on item identifier. 116 * @ xlist_entry_xp : extended pointer on xlist_entry embedded in item to be removed. 117 * @ return 0 if success / return EINVAL if item not found. 120 118 *****************************************************************************************/ 121 void xhtab_remove( xptr_t xhtab_xp, 122 void * key ); 119 error_t xhtab_remove( xptr_t xhtab_xp, 120 void * key, 121 xptr_t xlist_entry_xp ); 123 122 124 123 /****************************************************************************************** … … 133 132 134 133 135 /************************ vfs_dentry_t specific functions ******************************/136 137 /******************************************************************************************138 * This function compute the hash index from the key, when the item is a vhs_dentry_t.139 ******************************************************************************************140 * @ key : local pointer on dentry name.141 * @ return the index value, from 0 to (HASHTAB_SIZE - 1)142 *****************************************************************************************/143 uint32_t xhtab_dentry_index( void * key );144 145 /******************************************************************************************146 * This function check the key value for a given item, when the item is a vhs_dentry_t.147 ******************************************************************************************148 * @ xlist_xp : extended pointer on xlist_entry_t contained in a vfs_dentry_t.149 * @ key : local pointer on searched dentry name.150 * @ return true if the item name matches the searched name.151 *****************************************************************************************/152 bool_t xhtab_dentry_compare( xptr_t xlist_xp,153 void * key,154 xptr_t * item_xp );155 156 157 /************************ vfs_inode_t specific functions *******************************/158 159 /******************************************************************************************160 * This function compute the hash index from the key, when the item is a vhs_inode_t.161 ******************************************************************************************162 * @ key : local pointer on dentry name.163 * @ return the index value, from 0 to (HASHTAB_SIZE - 1)164 *****************************************************************************************/165 uint32_t xhtab_inode_index( void * key );166 167 /******************************************************************************************168 * This function check the key value for a given item, when the item is a vhs_inode_t.169 ******************************************************************************************170 * @ xlist_xp : extended pointer on xlist_entry_t contained in a vfs_dentry_t.171 * @ key : local pointer on searched dentry name.172 * @ return true if the item name matches the searched name.173 *****************************************************************************************/174 bool_t xhtab_inode_compare( xptr_t xlist_xp,175 void * key,176 xptr_t * item_xp );177 178 134 #endif /* _XHTAB_H_ */ -
trunk/kernel/mm/kcm.h
r18 r23 70 70 typedef struct kcm_page_s 71 71 { 72 BITMAP ( bitmap , CONFIG_KCM_BLOCKS_MAX );72 uint32_t bitmap[BITMAP_SIZE(CONFIG_KCM_BLOCKS_MAX)]; 73 73 uint8_t * base; /*! pointer on first block in page */ 74 74 kcm_t * kcm; /*! owner KCM allocator */ -
trunk/kernel/mm/kmem.c
r18 r23 44 44 #include <remote_sem.h> 45 45 #include <remote_barrier.h> 46 #include <remote_mutex.h> 47 #include <remote_condvar.h> 46 48 #include <mapper.h> 47 49 #include <grdxt.h> … … 89 91 else if( type == KMEM_CPU_CTX ) return sizeof( hal_cpu_context_t ); 90 92 else if( type == KMEM_FPU_CTX ) return sizeof( hal_fpu_context_t ); 93 else if( type == KMEM_BARRIER ) return sizeof( remote_barrier_t ); 91 94 92 95 else if( type == KMEM_FATFS_INODE ) return sizeof( fatfs_inode_t ); 93 96 else if( type == KMEM_FATFS_CTX ) return sizeof( fatfs_ctx_t ); 94 else if( type == KMEM_ RAMFS_INODE ) return sizeof( ramfs_inode_t );95 else if( type == KMEM_ RAMFS_CTX ) return sizeof( ramfs_ctx_t );97 else if( type == KMEM_DEVFS_INODE ) return sizeof( devfs_inode_t ); 98 else if( type == KMEM_MUTEX ) return sizeof( remote_mutex_t ); 96 99 else if( type == KMEM_VFS_CTX ) return sizeof( vfs_ctx_t ); 97 100 else if( type == KMEM_VFS_INODE ) return sizeof( vfs_inode_t ); … … 99 102 else if( type == KMEM_VFS_FILE ) return sizeof( vfs_file_t ); 100 103 else if( type == KMEM_SEM ) return sizeof( remote_sem_t ); 104 else if( type == KMEM_CONDVAR ) return sizeof( remote_condvar_t ); 101 105 else return 0; 102 106 } … … 114 118 else if( type == KMEM_CPU_CTX ) return "KMEM_CPU_CTX"; 115 119 else if( type == KMEM_FPU_CTX ) return "KMEM_FPU_CTX"; 120 else if( type == KMEM_BARRIER ) return "KMEM_BARRIER"; 116 121 117 122 else if( type == KMEM_FATFS_INODE ) return "KMEM_FATFS_INODE"; 118 123 else if( type == KMEM_FATFS_CTX ) return "KMEM_FATFS_CTX"; 119 else if( type == KMEM_ RAMFS_INODE ) return "KMEM_RAMFS_INODE";120 else if( type == KMEM_ RAMFS_CTX ) return "KMEM_RAMFS_CTX";124 else if( type == KMEM_DEVFS_INODE ) return "KMEM_DEVFS_INODE"; 125 else if( type == KMEM_MUTEX ) return "KMEM_MUTEX"; 121 126 else if( type == KMEM_VFS_CTX ) return "KMEM_VFS_CTX"; 122 127 else if( type == KMEM_VFS_INODE ) return "KMEM_VFS_INODE"; … … 124 129 else if( type == KMEM_VFS_FILE ) return "KMEM_VFS_FILE"; 125 130 else if( type == KMEM_SEM ) return "KMEM_SEM"; 131 else if( type == KMEM_SEM ) return "KMEM_CONDVAR"; 126 132 else return "undefined"; 127 133 } -
trunk/kernel/mm/kmem.h
r18 r23 31 31 32 32 /************************************************************************************* 33 * This enum defines the Kernel Memory Types for dynamically allocated objectsn. 33 * This enum defines the Kernel Memory Types for dynamically allocated objects. 34 * WARNING : this enum must be kepts consistent with use in kmem.c file. 34 35 ************************************************************************************/ 35 36 … … 45 46 KMEM_CPU_CTX = 7, /*! hal_cpu_context_t */ 46 47 KMEM_FPU_CTX = 8, /*! hal_fpu_context_t */ 47 KMEM_ TBD_9 = 9,48 KMEM_BARRIER = 9, /*! remote_barrier_t */ 48 49 49 50 KMEM_FATFS_INODE = 10, /*! fatfs_inode_t */ 50 51 KMEM_FATFS_CTX = 11, /*! fatfs_ctx_t */ 51 KMEM_ RAMFS_INODE = 12, /* ramfs_inode_t */52 KMEM_ RAMFS_CTX = 13, /*! ramfs_ctx_t*/52 KMEM_DEVFS_INODE = 12, /* devfs_inode_t */ 53 KMEM_MUTEX = 13, /*! remote_mutex_t */ 53 54 KMEM_VFS_CTX = 14, /*! vfs_context_t */ 54 55 KMEM_VFS_INODE = 15, /*! vfs_inode_t */ … … 56 57 KMEM_VFS_FILE = 17, /*! vfs_file_t */ 57 58 KMEM_SEM = 18, /*! remote_sem_t */ 58 KMEM_ TBD_19 = 19,59 KMEM_CONDVAR = 19, /*! remote_condvar_t */ 59 60 60 KMEM_TYPES_NR = 20,61 KMEM_TYPES_NR = 19, 61 62 }; 62 63 -
trunk/kernel/mm/mapper.c
r18 r23 26 26 #include <hal_types.h> 27 27 #include <hal_special.h> 28 #include <hal_uspace.h> 28 29 #include <grdxt.h> 29 30 #include <rwlock.h> … … 108 109 { 109 110 // remove page from mapper and release to PPM 110 error = mapper_release_page( mapper , found_index ,page );111 error = mapper_release_page( mapper , page ); 111 112 112 113 if ( error ) return error; … … 148 149 149 150 // test if page available in mapper 150 if( ( page == NULL) || page_is_flag( page , PG_INLOAD ) ) // page not available /151 if( ( page == NULL) || page_is_flag( page , PG_INLOAD ) ) // page not available 151 152 { 152 153 // release the lock in READ_MODE and take it in WRITE_MODE … … 194 195 printk("\n[ERROR] in %s : thread %x cannot insert page in mapper\n", 195 196 __FUNCTION__ , this->trdid ); 196 mapper_release_page( mapper , index ,page );197 mapper_release_page( mapper , page ); 197 198 page_clear_flag( page , PG_ALL ); 198 199 req.ptr = page; … … 203 204 204 205 // launch I/O operation to load page from file system 205 error = mapper_updt_page( mapper , index ,page );206 error = vfs_move_page_to_mapper( page ); 206 207 207 208 if( error ) … … 209 210 printk("\n[ERROR] in %s : thread %x cannot load page from device\n", 210 211 __FUNCTION__ , this->trdid ); 211 mapper_release_page( mapper , index ,page );212 mapper_release_page( mapper , page ); 212 213 page_clear_flag( page , PG_ALL ); 213 214 req.ptr = page; … … 255 256 /////////////////////////////////////////////// 256 257 error_t mapper_release_page( mapper_t * mapper, 257 uint32_t index,258 258 page_t * page ) 259 259 { … … 261 261 262 262 // lauch IO operation to update page to file system 263 error = mapper_sync_page( mapper , index ,page );263 error = vfs_move_page_from_mapper( page ); 264 264 265 265 if( error ) … … 288 288 } // end mapper_release_page() 289 289 290 //////////////////////////////////////////// 291 error_t mapper_updt_page( mapper_t * mapper, 292 uint32_t index, 293 page_t * page ) 294 { 295 uint32_t type; 296 vfs_inode_t * inode; 297 error_t error = 0; 298 299 if( page == NULL ) 300 { 301 printk("\n[PANIC] in %s : page pointer is NULL\n", __FUNCTION__ ); 302 hal_core_sleep(); 303 } 304 305 if( mapper == NULL ) 306 { 307 printk("\n[PANIC] in %s : no mapper for this page\n", __FUNCTION__ ); 308 hal_core_sleep(); 309 } 310 311 // get file system type and inode pointer 312 inode = mapper->inode; 313 type = inode->ctx->type; 314 315 // get page lock 316 page_lock( page ); 317 318 // get mapper lock in WRITE_MODE 319 rwlock_wr_lock( &mapper->lock ); 320 321 // call proper I/O operation to update file system 322 if ( type == FS_TYPE_FATFS ) error = fatfs_read_page( page ); 323 else if( type == FS_TYPE_RAMFS ) error = ramfs_read_page( page ); 324 else 325 { 326 printk("\n[PANIC] in %s : undefined file system type\n", __FUNCTION__ ); 327 hal_core_sleep(); 328 } 329 330 // release mapper lock from WRITE_MODE 331 rwlock_wr_unlock( &mapper->lock ); 332 333 // release page lock 334 page_unlock( page ); 335 336 if( error ) 337 { 338 printk("\n[PANIC] in %s : cannot access file system\n", __FUNCTION__ ); 339 return EIO; 340 } 341 342 return 0; 343 } // end mapper_updt_page 344 345 //////////////////////////////////////////// 346 error_t mapper_sync_page( mapper_t * mapper, 347 uint32_t index, 348 page_t * page ) 349 { 350 uint32_t type; 351 vfs_inode_t * inode; 352 error_t error = 0; 353 354 if( page == NULL ) 355 { 356 printk("\n[PANIC] in %s : page pointer is NULL\n", __FUNCTION__ ); 357 hal_core_sleep(); 358 } 359 360 if( mapper == NULL ) 361 { 362 printk("\n[PANIC] in %s : no mapper for this page\n", __FUNCTION__ ); 363 hal_core_sleep(); 364 } 365 366 if( page_is_flag( page , PG_DIRTY ) ) 367 { 368 // get file system type and inode pointer 369 inode = mapper->inode; 370 type = inode->ctx->type; 371 372 // get page lock 373 page_lock( page ); 374 375 // get mapper lock in READ_MODE 376 rwlock_rd_lock( &mapper->lock ); 377 378 // call proper I/O operation to update file system 379 if ( type == FS_TYPE_FATFS ) error = fatfs_write_page( page ); 380 else if( type == FS_TYPE_RAMFS ) error = ramfs_write_page( page ); 381 else 382 { 383 printk("\n[PANIC] in %s : undefined file system type\n", __FUNCTION__ ); 384 hal_core_sleep(); 385 } 386 387 // release mapper lock from READ_MODE 388 rwlock_rd_unlock( &mapper->lock ); 389 390 // release page lock 391 page_unlock( page ); 392 393 if( error ) 394 { 395 printk("\n[PANIC] in %s : cannot update file system\n", __FUNCTION__ ); 396 return EIO; 397 } 398 399 // clear dirty bit 400 page_undo_dirty( page ); 401 } 402 403 return 0; 404 405 } // end mapper_sync_page() 406 407 /////////////////////////////////////////////////////////////////////////////////////// 408 // This static function is called by the mapper_move fragments() function. 409 // It moves one fragment between an user buffer and the kernel mapper. 410 // Implementation Note: It can require access to one or two pages in mapper: 411 // [max_page_index == min_page_index] <=> fragment fit in one mapper page 412 // [max_page index == min_page_index + 1] <=> fragment spread on two mapper pages 413 /////////////////////////////////////////////////////////////////////////////////////// 414 static error_t mapper_move_one_fragment( mapper_t * mapper, 415 bool_t to_buffer, 416 fragment_t * fragment ) 417 { 418 uint32_t size; // number of bytes in fragment 419 cxy_t buf_cxy; // cluster identifier for user buffer 420 uint8_t * buf_ptr; // local pointer on first byte in user buffer 421 422 xptr_t xp_buf; // extended pointer on byte in user buffer 423 xptr_t xp_map; // extended pointer on byte in kernel mapper 424 425 uint32_t min_file_offset; // offset of first byte in file 426 uint32_t max_file_offset; // offset of last byte in file 427 428 uint32_t first_page_index; // index of first page in mapper 429 uint32_t first_page_offset; // offset of first byte in first page in mapper 430 uint32_t first_page_size; // offset of first byte in first page in mapper 431 432 uint32_t second_page_index; // index of last page in mapper 433 uint32_t second_page_offset; // offset of last byte in last page in mapper 434 uint32_t second_page_size; // offset of last byte in last page in mapper 435 436 page_t * page; // pointer on one page descriptor in mapper 437 uint8_t * map_ptr; // local pointer on first byte in mapper 438 439 // get fragment attributes in user buffer 440 buf_cxy = fragment->buf_cxy; 441 buf_ptr = fragment->buf_ptr; 442 size = fragment->size; 443 444 if( size > CONFIG_PPM_PAGE_SIZE ) 445 { 446 printk("\n[PANIC] in %s : illegal fragment size = %d\n", 447 __FUNCTION__ , size ); 448 return EINVAL; 449 } 290 ///////////////////////////////////////// 291 error_t mapper_move( mapper_t * mapper, 292 bool_t to_buffer, 293 uint32_t file_offset, 294 void * buffer, 295 uint32_t size ) 296 { 297 uint32_t page_offset; // first byte to move to/from a mapper page 298 uint32_t page_count; // number of bytes to move to/from a mapper page 299 uint32_t index; // current mapper page index 300 uint32_t done; // number of moved bytes 301 page_t * page; // current mapper page descriptor 302 uint8_t * map_ptr; // current mapper address 303 uint8_t * buf_ptr; // current buffer address 450 304 451 305 // compute offsets of first and last bytes in file 452 min_file_offset = fragment->file_offset;453 max_file_offset = min_file_offset + size;306 uint32_t min_byte = file_offset; 307 uint32_t max_byte = file_offset + size -1; 454 308 455 309 // compute indexes of pages for first and last byte in mapper 456 first_page_index = min_file_offset >> CONFIG_PPM_PAGE_SHIFT; 457 second_page_index = max_file_offset >> CONFIG_PPM_PAGE_SHIFT; 458 459 if ( first_page_index == second_page_index ) // only one page in mapper 460 { 461 // compute offset and size for page in mapper 462 first_page_offset = min_file_offset & (1<<CONFIG_PPM_PAGE_SHIFT); 463 first_page_size = size; 464 465 // get pointer on first page in mapper 466 page = mapper_get_page( mapper , first_page_index ); 310 uint32_t first = min_byte >> CONFIG_PPM_PAGE_SHIFT; 311 uint32_t last = max_byte >> CONFIG_PPM_PAGE_SHIFT; 312 313 done = 0; 314 315 // loop on pages in mapper 316 for( index = first ; index <= last ; index++ ) 317 { 318 // compute page_offset 319 if( index == first ) page_offset = min_byte & CONFIG_PPM_PAGE_MASK; 320 else page_offset = 0; 321 322 // compute page_count 323 if ( first == last ) page_count = size; 324 else if ( index == first ) page_count = CONFIG_PPM_PAGE_SIZE - page_offset; 325 else if ( index == last ) page_count = (max_byte & CONFIG_PPM_PAGE_MASK) + 1; 326 else page_count = CONFIG_PPM_PAGE_SIZE; 327 328 // get page descriptor 329 page = mapper_get_page( mapper , index ); 467 330 468 331 if ( page == NULL ) return EINVAL; 469 332 470 // compute pointer on fragment first byte in mapper 471 map_ptr = (uint8_t *)ppm_page2base( page ) + first_page_offset; 472 473 // compute extended pointers in mapper and in buffer 474 xp_map = XPTR( local_cxy , map_ptr ); 475 xp_buf = XPTR( buf_cxy , buf_ptr ); 333 // compute pointer in mapper 334 map_ptr = (uint8_t *)ppm_page2base( page ) + page_offset; 335 336 // compute pointer in buffer 337 buf_ptr = (uint8_t *)buffer + done; 476 338 477 339 // move fragment 478 340 if( to_buffer ) 479 341 { 480 hal_ remote_memcpy( xp_buf , xp_map , first_page_size);342 hal_copy_to_uspace( buf_ptr , map_ptr , page_count ); 481 343 } 482 344 else 483 345 { 484 346 page_do_dirty( page ); 485 hal_remote_memcpy( xp_map , xp_buf , first_page_size ); 486 } 487 } 488 else // two pages in mapper 489 { 490 // compute offset and size for first page in mapper 491 first_page_offset = min_file_offset & (1<<CONFIG_PPM_PAGE_SHIFT); 492 first_page_size = CONFIG_PPM_PAGE_SIZE - first_page_offset; 493 494 // get pointer on first page descriptor in mapper 495 page = mapper_get_page( mapper , first_page_index ); 496 497 if ( page == NULL ) return EINVAL; 498 499 // compute local pointer on first byte in first page in mapper 500 map_ptr = (uint8_t *)ppm_page2base(page) + first_page_offset; 501 502 // compute extended pointers 503 xp_map = XPTR( local_cxy , map_ptr ); 504 xp_buf = XPTR( buf_cxy , buf_ptr ); 505 506 // move fragment to/from first page 507 if( to_buffer ) 508 { 509 hal_remote_memcpy( xp_buf , xp_map , first_page_size ); 510 } 511 else 512 { 513 page_do_dirty( page ); 514 hal_remote_memcpy( xp_map , xp_buf , first_page_size ); 515 } 516 517 // compute offset and size for second page in mapper 518 second_page_offset = 0; 519 second_page_size = size - first_page_size; 520 521 // get pointer on second page in mapper 522 page = mapper_get_page( mapper , second_page_index ); 523 524 if ( page == NULL ) return EINVAL; 525 526 // compute local pointer on first byte in second page in mapper 527 map_ptr = (uint8_t *)ppm_page2base( page ) + second_page_offset; 528 529 // compute extended pointers 530 xp_map = XPTR( local_cxy , map_ptr ); 531 xp_buf = XPTR( buf_cxy , buf_ptr + first_page_offset ); 532 533 // move fragment to/from second page 534 if( to_buffer ) 535 { 536 hal_remote_memcpy( xp_buf , xp_map , second_page_size ); 537 } 538 else 539 { 540 page_do_dirty( page ); 541 hal_remote_memcpy( xp_map , xp_buf , second_page_size ); 542 } 347 hal_copy_from_uspace( map_ptr , buf_ptr , page_count ); 348 } 349 350 done += page_count; 543 351 } 544 352 545 353 return 0; 546 } // end mapper_move_one_fragment() 547 548 ///////////////////////////////////////////////// 549 error_t mapper_move_fragments( mapper_t * mapper, 550 bool_t read, 551 uint32_t nb_frags, 552 xptr_t xp_frags ) 553 { 554 uint32_t index; 555 error_t error; 556 fragment_t local_frags[CONFIG_MAPPER_MAX_FRAGMENTS]; // local copy of fragments array 557 fragment_t * frags_array; // pointer on fragments array 558 559 // check nb_frags 560 if( nb_frags > CONFIG_MAPPER_MAX_FRAGMENTS ) 561 { 562 printk("\n[PANIC] in %s : number of fragments cannot be larger than %d\n", 563 __FUNCTION__ , CONFIG_MAPPER_MAX_FRAGMENTS ); 564 return EINVAL; 565 } 566 567 // get client cluster and local pointer on fragments array 568 cxy_t client_cxy = GET_CXY( xp_frags ); 569 fragment_t * client_frags = (fragment_t *)GET_PTR( xp_frags ); 570 571 if ( local_cxy == client_cxy ) // use the local fragments array if possible 572 { 573 frags_array = client_frags; 574 } 575 else // make a local copy of fragments array 576 { 577 hal_remote_memcpy( XPTR( local_cxy , local_frags ) , xp_frags , 578 sizeof(fragment_t) * nb_frags ); 579 frags_array = local_frags; 580 } 581 582 // loop on fragments 583 for( index = 0 ; index < nb_frags ; index ++ ) 584 { 585 error = mapper_move_one_fragment( mapper , read , &frags_array[index] ); 586 if ( error ) return error; 587 } 588 589 return 0; 590 591 } // end mapper_move_fragments() 592 593 354 355 } // end mapper_move() 356 357 358 -
trunk/kernel/mm/mapper.h
r18 r23 39 39 /******************************************************************************************* 40 40 * The mapper implements the kernel cache for a given file or directory. 41 * There is one mapper per file . It is implemented as a three levels radix tree,41 * There is one mapper per file/dir. It is implemented as a three levels radix tree, 42 42 * entirely stored in the same cluster as the inode representing the file/dir. 43 43 * - The fast retrieval key is the page index in the file. … … 49 49 * - The mapper is protected by a blocking "rwlock", to support several simultaneous 50 50 * readers, and only one writer. This lock implement a busy waiting policy. 51 * - The two functions mapper_sync_page() and mapper_updt_page() define the generic API52 * used to move pages to or from the relevant file system on IOC device.53 * - the mapper_move fragments() function is used to move data to or from adistributed54 * user buffer .51 * - The two functions vfs_move_page_to_mapper() and vfs_move_page_from_mapper() define 52 * the generic API used to move pages to or from the relevant file system on IOC device. 53 * - the mapper_move() function is used to move data to or from a, possibly distributed 54 * user buffer in user space. 55 55 * - The mapper_get_page() function that return a page descriptor pointer from a page 56 56 * index in file is in charge of handling the miss on the mapper cache. 57 57 * - In the present implementation the cache size increases on demand, and the 58 * allocated memory is only released when the mapper is destroyed.58 * allocated memory is only released when the mapper/inode is destroyed. 59 59 ******************************************************************************************/ 60 60 … … 66 66 typedef struct mapper_s 67 67 { 68 struct vfs_inode_s * inode; /*! owner file inode*/68 struct vfs_inode_s * inode; /*! owner inode */ 69 69 grdxt_t radix; /*! pages cache implemented as a radix tree */ 70 70 rwlock_t lock; /*! several readers / only one writer */ … … 89 89 uint32_t size; /*! number of bytes in fragment */ 90 90 cxy_t buf_cxy; /*! user buffer cluster identifier */ 91 uint8_t* buf_ptr; /*! local pointer on first byte in user buffer */91 void * buf_ptr; /*! local pointer on first byte in user buffer */ 92 92 } 93 93 fragment_t; … … 114 114 115 115 /******************************************************************************************* 116 * This function moves all fragments covering a distributed user buffer between 117 * a mapper (associated to a local inode), and the user buffer. 118 * [See the fragment definition in the mapper.h file] 119 * It must be executed by a thread running in the cluster containing the mapper. 120 * The lock protecting the mapper must have been taken in WRITE_MODE or READ_MODE 121 * by the caller thread, depending on the transfer direction. 116 * This function move data between a kernel mapper and an user buffer. 117 * It must be called by a thread running in the cluster containing the mapper. 118 * It split the data in fragments : one fragment is a set of contiguous bytes 119 * stored in the same mapper page. 120 * It uses "hal_uspace" accesses to move fragments to/from the user buffer. 122 121 * In case of write, the dirty bit is set for all pages written in the mapper. 123 122 * The offset in the file descriptor is not modified by this function. 124 * Implementation note:125 * For each fragment, this function makes ONE hal_remote_memcpy() when the fragment is126 * fully contained in one single page of the mapper. It makes TWO hal_remote_memcpy()127 * if the fragment spread on two contiguous pages in the mapper.128 123 ******************************************************************************************* 129 * @ mapper : local pointer on the local mapper. 130 * @ to_buffer : mapper to buffer if true / buffer to mapper if false. 131 * @ nb_frags : number of fragments covering the user buffer (one per page). 132 * @ frags_xp : extended pointer on array of fragments. 133 FAT * returns O if success / returns EINVAL if error. 124 * @ mapper : extended pointer on local mapper. 125 * @ to_buffer : move data from mapper to buffer if true. 126 * @ file_offset : first byte to move in file. 127 * @ buffer : buffer address in user space. 128 * @ size : number of bytes to move. 129 * returns O if success / returns EINVAL if error. 134 130 ******************************************************************************************/ 135 error_t mapper_move _fragments( mapper_t * mapper,136 137 uint32_t nb_frags,138 xptr_t frags_xp );139 131 error_t mapper_move( mapper_t * mapper, 132 bool_t to_buffer, 133 uint32_t file_offset, 134 void * buffer, 135 uint32_t size ); 140 136 141 137 /******************************************************************************************* … … 146 142 ******************************************************************************************* 147 143 * @ mapper : local pointer on the mapper. 148 * @ index : page index in file149 144 * @ page : pointer on page to remove. 150 145 * @ return 0 if success / return EIO if a dirty page cannot be copied to FS. 151 146 ******************************************************************************************/ 152 147 error_t mapper_release_page( mapper_t * mapper, 153 uint32_t index,154 148 struct page_s * page ); 155 149 … … 167 161 uint32_t index ); 168 162 169 /******************************************************************************************* 170 * This function makes an I/O operation to move one page from FS to mapper. 171 * Depending on the file system type, it calls the proper, FS specific function. 172 * It must be executed by a thread running in the cluster containing the mapper. 173 ******************************************************************************************* 174 * @ mapper : local pointer on the mapper. 175 * @ index : page index in file. 176 * @ page : local pointer on the page descriptor in mapper. 177 * @ returns 0 if success / return EINVAL if it cannot access the device. 178 ******************************************************************************************/ 179 error_t mapper_updt_page( mapper_t * mapper, 180 uint32_t index, 181 struct page_s * page ); 182 183 /******************************************************************************************* 184 * This function makes an I/0 operation to move one page from mapper to FS. 185 * Depending on the file system type, it calls the proper, FS specific function. 186 * It must be executed by a thread running in the cluster containing the mapper. 187 * It does nothing if the page is not dirty. If the page is dirty, it takes 188 * the page lock before launching the IO operation, clear the page dirty bit, 189 * and remove the page from the PPM dirty list. It does nothing if the page is not dirty. 190 ******************************************************************************************* 191 * @ mapper : local pointer on the mapper. 192 * @ index : page index in file. 193 * @ page : local pointer on the page descriptor in mapper. 194 * @ returns 0 if success / return EINVAL if it cannot access the device. 195 ******************************************************************************************/ 196 error_t mapper_sync_page( mapper_t * mapper, 197 uint32_t index, 198 struct page_s * page ); 163 199 164 200 165 #endif /* _MAPPER_H_ */ -
trunk/kernel/mm/page.c
r22 r23 3 3 * 4 4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016 )5 * Alain Greiner (2016,2017) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 44 44 page->flags = 0; 45 45 page->order = 0; 46 page->mapper = NULL; 46 47 page->index = 0; 47 page->mapper = NULL; 48 page->private = 0; 48 page->fork_nr = 0; 49 49 page->refcount = 0; 50 50 51 spinlock_init( &page->lock ); 51 52 list_entry_init( &page->list ); 53 xlist_root_init( XPTR( local_cxy , &page->wait_root ) ); 52 54 } 53 55 54 56 //////////////////////////////////////////// 55 57 inline void page_set_flag( page_t * page, 56 uint 16_t value )58 uint32_t value ) 57 59 { 58 60 hal_atomic_or( (uint32_t *)&page->flags , (uint32_t)value ); … … 61 63 ////////////////////////////////////////////// 62 64 inline void page_clear_flag( page_t * page, 63 uint 16_t value )65 uint32_t value ) 64 66 { 65 67 hal_atomic_and( (uint32_t *)&page->flags , ~((uint32_t)value) ); … … 68 70 ////////////////////////////////////////////// 69 71 inline bool_t page_is_flag( page_t * page, 70 uint 16_t value )71 { 72 return (bool_t)(page->flags & value);72 uint32_t value ) 73 { 74 return ( (page->flags & value) ? 1 : 0 ); 73 75 } 74 76 … … 150 152 151 153 // sync the page 152 mapper_sync_page( mapper , index ,page );154 vfs_move_page_from_mapper( page ); 153 155 154 156 // unlock the page … … 226 228 inline void page_refcount_up( page_t *page ) 227 229 { 228 hal_atomic_inc( &page->refcount);230 hal_atomic_add( &page->refcount , +1 ); 229 231 } 230 232 … … 232 234 inline void page_refcount_down( page_t *page ) 233 235 { 234 hal_atomic_dec( &page->refcount);236 hal_atomic_add( &page->refcount , -1 ); 235 237 } 236 238 -
trunk/kernel/mm/page.h
r22 r23 49 49 #define PG_DIRTY 0x0040 // page has been written 50 50 #define PG_LOCKED 0x0080 // page is locked 51 #define PG_COW 0x0100 // page is copy-on-write 51 52 52 53 #define PG_ALL 0xFFFF // All flags … … 54 55 /************************************************************************************* 55 56 * This structure defines a physical page descriptor. 56 * Size is 6 0bytes for a 32 bits core...57 * Size is 64 bytes for a 32 bits core... 57 58 ************************************************************************************/ 58 59 59 60 typedef struct page_s 60 61 { 61 uint16_t flags; /*! flags defined above (2) */ 62 uint16_t order; /*! log2( number of 4Kbytes pages) (2) */ 63 62 uint32_t flags; /*! flags defined above (4) */ 63 uint32_t order; /*! log2( number of 4Kbytes pages) (4) */ 64 64 struct mapper_s * mapper; /*! local pointer on associated mapper (4) */ 65 65 uint32_t index; /*! page index in mapper (4) */ 66 67 union /*! (4) */68 {69 uint32_t private; /*! TODO ??? [AG] */70 void * data; /*! TODO ??? [AG] */71 slist_entry_t root; /*! TODO ??? [AG] */72 };73 74 66 list_entry_t list; /*! for both dirty pages and free pages (8) */ 75 76 67 xlist_entry_t wait_root; /*! root of list of waiting threads (16) */ 77 78 68 uint32_t refcount; /*! reference counter (4) */ 69 uint32_t fork_nr; /*! number of forked processes (4) */ 79 70 spinlock_t lock; /*! only used to set the PG_LOCKED flag (16) */ 80 71 } … … 83 74 /************************************************************************************* 84 75 * This function initializes one page descriptor. 76 ************************************************************************************* 85 77 * @ page : pointer to page descriptor 86 78 ************************************************************************************/ … … 88 80 89 81 /************************************************************************************* 90 * This function sets one or several flags in page descriptor flags. 82 * This function atomically set one or several flags in page descriptor flags. 83 ************************************************************************************* 91 84 * @ page : pointer to page descriptor. 92 85 * @ value : all non zero bits in value will be set. 93 86 ************************************************************************************/ 94 87 inline void page_set_flag( page_t * page, 95 uint 16_t value );88 uint32_t value ); 96 89 97 90 /************************************************************************************* 98 * This function clears one or several flags in page descriptor flags. 91 * This function atomically reset one or several flags in page descriptor flags. 92 ************************************************************************************* 99 93 * @ page : pointer to page descriptor. 100 94 * @ value : all non zero bits in value will be cleared. 101 95 ************************************************************************************/ 102 96 inline void page_clear_flag( page_t * page, 103 uint 16_t value );97 uint32_t value ); 104 98 105 99 /************************************************************************************* 106 100 * This function tests the value of one or several flags in page descriptor flags. 101 ************************************************************************************* 107 102 * @ page : pointer to page descriptor. 108 103 * @ value : all non zero bits will be tested. … … 110 105 ************************************************************************************/ 111 106 inline bool_t page_is_flag( page_t * page, 112 uint 16_t value );107 uint32_t value ); 113 108 114 109 /************************************************************************************* … … 121 116 * This function sets the PG_DIRTY flag in the page descriptor, 122 117 * and registers the page in the dirty list in PPM. 118 ************************************************************************************* 123 119 * @ page : pointer on page descriptor. 124 120 * @ returns true if page was not dirty / returns false if page was dirty … … 129 125 * This function resets the PG_DIRTY flag in the page descriptor, 130 126 * and removes the page from the dirty list in PPM. 127 ************************************************************************************* 131 128 * @ page : pointer on page descriptor. 132 129 * @ returns true if page was dirty / returns false if page was not dirty … … 136 133 /************************************************************************************* 137 134 * This function makes a local copy of the content of a src page to a dst page. 135 ************************************************************************************* 138 136 * @ dst : pointer on destination page descriptor. 139 137 * @ src : pointer on source page descriptor. … … 144 142 /************************************************************************************* 145 143 * This function resets to 0 all bytes in a given page. 144 ************************************************************************************* 146 145 * @ page : pointer on page descriptor. 147 146 ************************************************************************************/ … … 152 151 * It deschedule if the page has already been locked by another thread, 153 152 * and returns only when the flag has been successfully set. 153 ************************************************************************************* 154 154 * @ page : pointer on page descriptor. 155 155 ************************************************************************************/ … … 160 160 * other waiting thread. If there is waiting thread(s), it activates the first 161 161 * waiting thread without modifying the PG_LOCKED flag. 162 ************************************************************************************* 162 163 * @ page : pointer on page descriptor. 163 164 ************************************************************************************/ … … 166 167 /************************************************************************************* 167 168 * This blocking function atomically increments the page refcount. 169 ************************************************************************************* 168 170 * @ page : pointer on page descriptor. 169 171 ************************************************************************************/ … … 172 174 /************************************************************************************* 173 175 * This blocking function atomically decrements the page refcount. 176 ************************************************************************************* 174 177 * @ page : pointer on page descriptor. 175 178 ************************************************************************************/ … … 178 181 /************************************************************************************* 179 182 * This function display the values contained in a page descriptor. 183 ************************************************************************************* 184 * @ page : pointer on page descriptor. 180 185 ************************************************************************************/ 181 186 void page_print( page_t * page ); -
trunk/kernel/mm/vmm.c
r21 r23 29 29 #include <hal_gpt.h> 30 30 #include <printk.h> 31 #include <memcpy.h> 31 32 #include <rwlock.h> 32 33 #include <list.h> … … 94 95 95 96 // initialize local list of vsegs and radix-tree 97 vmm->vsegs_nr = 0; 96 98 list_root_init( &vmm->vsegs_root ); 97 vmm->vsegs_nr = 0;98 99 error = grdxt_init( &vmm->grdxt, 99 100 CONFIG_VMM_GRDXT_W1, … … 182 183 183 184 } // end vmm_init() 185 186 ////////////////////////////////////////// 187 error_t vmm_copy( process_t * dst_process, 188 process_t * src_process ) 189 { 190 error_t error; 191 192 vmm_t * src_vmm = &src_process->vmm; 193 vmm_t * dst_vmm = &dst_process->vmm; 194 195 // take the src_vmm vsegs_lock 196 rwlock_wr_lock( &src_vmm->vsegs_lock ); 197 198 // initialise dst_vmm vsegs_lock 199 rwlock_init( &dst_vmm->vsegs_lock ); 200 201 // initialise the dst_vmm vsegs list and the radix tree 202 dst_vmm->vsegs_nr = 0; 203 list_root_init( &dst_vmm->vsegs_root ); 204 error = grdxt_init( &dst_vmm->grdxt, 205 CONFIG_VMM_GRDXT_W1, 206 CONFIG_VMM_GRDXT_W2, 207 CONFIG_VMM_GRDXT_W3 ); 208 if( error ) 209 { 210 printk("\n[ERROR] in %s : cannot initialise radix tree for process %x\n", 211 __FUNCTION__ , dst_process->pid ); 212 return ENOMEM; 213 } 214 215 // loop on src_vmm list of vsegs to create 216 // and register vsegs copies in dst_vmm 217 list_entry_t * iter; 218 vseg_t * src_vseg; 219 vseg_t * dst_vseg; 220 LIST_FOREACH( &src_vmm->vsegs_root , iter ) 221 { 222 // get pointer on current src_vseg 223 src_vseg = LIST_ELEMENT( iter , vseg_t , list ); 224 225 // allocate memory for a new dst_vseg 226 dst_vseg = vseg_alloc(); 227 228 if( dst_vseg == NULL ) 229 { 230 // release all allocated vsegs 231 LIST_FOREACH( &dst_vmm->vsegs_root , iter ) 232 { 233 dst_vseg = LIST_ELEMENT( iter , vseg_t , list ); 234 vseg_free( dst_vseg ); 235 } 236 return ENOMEM; 237 } 238 239 // copy src_vseg to dst_vseg 240 vseg_init_from_ref( dst_vseg , XPTR( local_cxy , src_vseg ) ); 241 242 // register dst_vseg in dst_vmm 243 vseg_attach( dst_vmm , dst_vseg ); 244 } 245 246 // release the src_vmm vsegs_lock 247 rwlock_wr_unlock( &src_vmm->vsegs_lock ); 248 249 // initialize generic page table 250 error = hal_gpt_create( &dst_vmm->gpt ); 251 252 if( error ) 253 { 254 printk("\n[ERROR] in %s : cannot initialize page table\n", __FUNCTION__ ); 255 return ENOMEM; 256 } 257 258 // initialize STACK allocator 259 dst_vmm->stack_mgr.bitmap = 0; 260 dst_vmm->stack_mgr.vpn_base = CONFIG_VMM_STACK_BASE; 261 262 // initialize MMAP allocator 263 dst_vmm->mmap_mgr.vpn_base = CONFIG_VMM_MMAP_BASE; 264 dst_vmm->mmap_mgr.vpn_size = CONFIG_VMM_STACK_BASE - CONFIG_VMM_MMAP_BASE; 265 dst_vmm->mmap_mgr.first_free_vpn = CONFIG_VMM_MMAP_BASE; 266 uint32_t i; 267 for( i = 0 ; i < 32 ; i++ ) list_root_init( &dst_vmm->mmap_mgr.zombi_list[i] ); 268 269 // initialise instrumentation counters 270 dst_vmm->pgfault_nr = 0; 271 dst_vmm->u_err_nr = 0; 272 dst_vmm->m_err_nr = 0; 273 274 // copy base addresses 275 dst_vmm->kent_vpn_base = src_vmm->kent_vpn_base; 276 dst_vmm->args_vpn_base = src_vmm->args_vpn_base; 277 dst_vmm->envs_vpn_base = src_vmm->envs_vpn_base; 278 dst_vmm->heap_vpn_base = src_vmm->heap_vpn_base; 279 dst_vmm->code_vpn_base = src_vmm->code_vpn_base; 280 dst_vmm->data_vpn_base = src_vmm->data_vpn_base; 281 282 dst_vmm->entry_point = src_vmm->entry_point; 283 284 // HEAP TODO : new heap for child ??? 285 dst_vmm->heap_vseg = src_vmm->heap_vseg; 286 287 // initialize generic page table 288 error = hal_gpt_create( &dst_vmm->gpt ); 289 290 if( error ) 291 { 292 printk("\n[ERROR] in %s : cannot initialize page table\n", __FUNCTION__ ); 293 return ENOMEM; 294 } 295 296 // copy GPT content from src_vmm to dst_vmm, activating "Copy-On-Write" 297 // TODO register Copy-On_Write in page descriptors 298 bool_t cow = true; 299 hal_gpt_copy( &dst_vmm->gpt , &src_vmm->gpt , cow ); 300 301 hal_wbflush(); 302 303 return 0; 304 305 } // end vmm_copy() 184 306 185 307 /////////////////////////////////////// … … 659 781 error_t error; 660 782 661 // this function must be called by in the reference cluster662 if( process->is_ref == false);783 // this function must be called by a thread running in the reference cluster 784 if( GET_CXY( process->ref_xp ) != local_cxy ); 663 785 { 664 786 printk("\n[PANIC] in %s : not called in the reference cluster\n", __FUNCTION__ ); … … 796 918 paddr_t * paddr ) 797 919 { 798 uint32_t vaddr = (uint32_t)ptr; 799 800 thread_t * this = CURRENT_THREAD; 801 process_t * process = this->process; 920 process_t * process = CURRENT_THREAD->process; 802 921 803 922 if( ident ) // identity mapping 804 923 { 805 *paddr = (paddr_t)PADDR( local_cxy , vaddr );924 *paddr = (paddr_t)PADDR( local_cxy , (lpa_t)ptr ); 806 925 return 0; 807 926 } … … 814 933 uint32_t offset; 815 934 816 vpn = (vpn_t)( vaddr >> CONFIG_PPM_PAGE_SHIFT );817 offset = (uint32_t)( vaddr& CONFIG_PPM_PAGE_MASK );818 819 if( process->is_ref) // calling process is reference process935 vpn = (vpn_t)( (intptr_t)ptr >> CONFIG_PPM_PAGE_SHIFT ); 936 offset = (uint32_t)( ((intptr_t)ptr) & CONFIG_PPM_PAGE_MASK ); 937 938 if( local_cxy == GET_CXY( process->ref_xp) ) // calling process is reference process 820 939 { 821 940 error = vmm_get_pte( process, vpn , &attr , &ppn ); 822 941 } 823 else // use a RPC942 else // use a RPC 824 943 { 825 944 cxy_t ref_cxy = GET_CXY( process->ref_xp ); … … 828 947 } 829 948 830 if( error ) 831 { 832 printk("\n[ERROR] in %s : cannot get physical address for vaddr = %x\n", 833 __FUNCTION__ , vaddr ); 834 return error; 835 } 836 837 // return paddr 949 // set paddr 838 950 *paddr = (((paddr_t)ppn) << CONFIG_PPM_PAGE_SHIFT) | offset; 839 return 0; 951 952 return error; 840 953 841 954 } // end vmm_v2p_translate() 955 956 ////////////////////////////////////////////// 842 957 843 958 -
trunk/kernel/mm/vmm.h
r18 r23 4 4 * Authors Ghassan Almaless (2008,2009,2010,2011, 2012) 5 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016 )6 * Alain Greiner (2016,2017) 7 7 * 8 8 * Copyright (c) UPMC Sorbonne Universites … … 103 103 rwlock_t vsegs_lock; /*! lock protecting the vsegs list & radix tree */ 104 104 list_entry_t vsegs_root; /*! all vsegs in same process and same cluster */ 105 uint32_t vsegs_nr; /*! total number of vsegs */ 106 105 uint32_t vsegs_nr; /*! total number of local vsegs */ 107 106 grdxt_t grdxt; /*! embedded generic vsegs radix tree (key is vpn) */ 108 107 … … 110 109 111 110 stack_mgr_t stack_mgr; /*! embedded STACK vsegs allocator */ 112 113 111 mmap_mgr_t mmap_mgr; /*! embedded MMAP vsegs allocator */ 114 112 … … 158 156 159 157 /********************************************************************************************* 158 * This function copies the content of a source VMM to a destination VMM. 159 ********************************************************************************************* 160 * @ dst_process : pointer on destination process descriptor. 161 * @ src_process : pointer on source process descriptor. 162 * @ return 0 if success / return ENOMEM if failure. 163 ********************************************************************************************/ 164 error_t vmm_copy( struct process_s * dst_process, 165 struct process_s * src_process ); 166 167 /********************************************************************************************* 160 168 * This function removes all vsegs registered in in a virtual memory manager, 161 169 * and releases the memory allocated to the local generic page table. 162 170 ********************************************************************************************* 163 * @ vmm: pointer on process descriptor.171 * @ process : pointer on process descriptor. 164 172 ********************************************************************************************/ 165 173 void vmm_destroy( struct process_s * process ); … … 265 273 266 274 /********************************************************************************************* 267 * This function is called by the architecture specific exception handler when a268 * page fault has been detected in a given cluster.275 * This function is called by the generic exception handler when a page fault 276 * has been detected in a given cluster. 269 277 * If the local cluster is not the reference cluster, it send a RPC_VMM_GET_PTE 270 278 * to the reference cluster to get the missing PTE attributes and PPN, and update … … 305 313 * This function makes the virtual to physical address translation, using the calling 306 314 * process page table. It uses identity mapping if required by the ident flag. 307 * This address translation is required to configure the devices308 * that have a DMA capability, or to implement the software L2/L3 cache cohérence,309 * using the MMC devicesynchronisation primitives.310 * WARNING : the <ident> value must be defined by the CONFIG_KERNEL_IDENT parameter.315 * This address translation is required to configure the peripherals having a DMA 316 * capability, or to implement the software L2/L3 cache cohérence, using the MMC device 317 * synchronisation primitives. 318 * WARNING : the <ident> value must be defined by the CONFIG_KERNEL_IDENTITY_MAP parameter. 311 319 ********************************************************************************************* 312 320 * @ ident : [in] uses identity mapping if true. … … 321 329 322 330 /********************************************************************************************* 323 * Pas a sa place ici [AG]324 ********************************************************************************************/325 int sys_mmap( mmap_attr_t * mattr );326 327 /*********************************************************************************************328 331 ********************************************************************************************/ 329 332 int sys_madvise( void * start, -
trunk/kernel/syscalls/sys_alarm.c
r1 r23 1 1 /* 2 * kern/sys_alarm.c - timed sleep/wakeup2 * sys_alarm.c - timed sleep/wakeup 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 5 * 6 * Copyright (c) UPMC Sorbonne Universites 6 7 * 7 * This file is part of ALMOS- kernel.8 * This file is part of ALMOS-MKH. 8 9 * 9 * ALMOS- kernelis free software; you can redistribute it and/or modify it10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include < types.h>24 #include <hal_types.h> 24 25 #include <thread.h> 26 #include <printk.h> 25 27 #include <cluster.h> 26 #include <task.h> 27 #include <time.h> 28 #include <process.h> 28 29 #include <scheduler.h> 29 #include <cpu.h> 30 #include <cpu-trace.h> 30 #include <core.h> 31 31 32 EVENT_HANDLER(sys_alarm_event_handler) 32 //////////////////////////////// 33 int sys_alarm( uint64_t cycles ) 33 34 { 34 struct thread_s *thread; 35 thread_t * this = CURRENT_THREAD; 36 process_t * process = this->process; 35 37 36 thread = event_get_argument(event); 37 sched_wakeup(thread); 38 return 0; 39 } 40 41 int sys_alarm (unsigned nb_sec) 42 { 43 struct thread_s *this; 44 struct event_s event; 45 struct alarm_info_s info; 46 47 if( nb_sec == 0) 48 return 0; 49 50 this = current_thread; 51 event_set_handler(&event, &sys_alarm_event_handler); 52 event_set_priority(&event, E_FUNC); 53 event_set_argument(&event,this); 54 info.event = &event; 55 56 alarm_wait(&info, nb_sec * 4); 57 sched_sleep(this); 58 return 0; 38 printk("\n[ERROR] in %s for thread %x in process %x : not implemented yet\n", 39 __FUNCTION__ , this->trdid , process->pid ); 40 this->errno = EFAULT; 41 return -1; 59 42 } 60 43 61 44 45 -
trunk/kernel/syscalls/sys_barrier.c
r1 r23 1 1 /* 2 * kern/sys_barrier.c - barrier service interface for userland2 * sys_barrier.c - Access a POSIX barrier. 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * authors Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include <types.h> 24 #include <hal_types.h> 25 #include <hal_special.h> 24 26 #include <errno.h> 25 27 #include <thread.h> 26 #include <task.h> 27 #include <kmem.h> 28 #include <printk.h> 28 29 #include <vmm.h> 29 #include < kmagics.h>30 #include < barrier.h>30 #include <syscalls.h> 31 #include <remote_barrier.h> 31 32 32 int sys_barrier(struct barrier_s **barrier, uint_t operation, uint_t count) 33 ////////////////////////////////// 34 int sys_barrier( void * vaddr, 35 uint32_t operation, 36 uint32_t count ) 33 37 { 34 kmem_req_t req; 35 struct barrier_s *ibarrier; 36 error_t err = EINVAL; 38 error_t error; 39 paddr_t paddr; 37 40 38 if((err = vmm_check_address("usr barrier ptr", 39 current_task, 40 barrier, 41 sizeof(struct barrier_s*)))) 42 goto SYS_BARRIER_END; 41 thread_t * this = CURRENT_THREAD; 43 42 44 if((err = cpu_copy_from_uspace(&ibarrier, barrier, sizeof(struct barrier_s *)))) 45 goto SYS_BARRIER_END; 43 // check vaddr in user vspace 44 error = vmm_v2p_translate( false , vaddr , &paddr ); 45 if( error ) 46 { 47 printk("\n[ERROR] in %s : illegal barrier virtual address = %x\n", 48 __FUNCTION__ , (intptr_t)vaddr ); 49 this->errno = error; 50 return -1; 51 } 46 52 47 switch(operation) 53 // execute requested operation 54 switch( operation ) 48 55 { 49 case BARRIER_INIT_PRIVATE: 50 case BARRIER_INIT_SHARED: 51 req.type = KMEM_BARRIER; 52 req.size = sizeof(*ibarrier); 53 req.flags = AF_USER; 56 ////////////////// 57 case BARRIER_INIT: 58 { 59 error = remote_barrier_create( (intptr_t)vaddr , count ); 60 61 if( error ) 62 { 63 printk("\n[ERROR] in %s : cannot create barrier = %x\n", 64 __FUNCTION__ , (intptr_t)vaddr ); 65 this->errno = error; 66 return -1; 67 } 68 break; 69 } 70 ////////////////// 71 case BARRIER_WAIT: 72 { 73 xptr_t barrier_xp = remote_barrier_from_ident( (intptr_t)vaddr ); 54 74 55 if((ibarrier = kmem_alloc(&req)) == NULL) 56 { 57 err = ENOMEM; 58 break; 59 } 60 61 if((err = barrier_init(ibarrier, count, operation))) 62 break; 63 64 if((err = cpu_copy_to_uspace(barrier, &ibarrier, sizeof(struct barrier_s *)))) 65 { 66 req.ptr = ibarrier; 67 kmem_free(&req); 68 } 69 break; 75 if( barrier_xp == XPTR_NULL ) // user error 76 { 77 printk("\n[ERROR] in %s : barrier %x not registered\n", 78 __FUNCTION__ , (intptr_t)vaddr ); 79 this->errno = EINVAL; 80 return -1; 81 } 82 else // success 83 { 84 remote_barrier_wait( barrier_xp ); 85 } 86 break; 87 } 88 ///////////////////// 89 case BARRIER_DESTROY: 90 { 91 xptr_t barrier_xp = remote_barrier_from_ident( (intptr_t)vaddr ); 70 92 71 case BARRIER_WAIT: 93 if( barrier_xp == XPTR_NULL ) // user error 94 { 95 printk("\n[ERROR] in %s : barrier %x not registered\n", 96 __FUNCTION__ , (intptr_t)vaddr ); 97 this->errno = EINVAL; 98 return -1; 99 } 100 else // success 101 { 102 remote_barrier_destroy( barrier_xp ); 103 } 104 break; 105 } 106 //////// 107 default: 108 { 109 printk("\n[PANIC] in %s : illegal operation type\n", __FUNCTION__ ); 110 hal_core_sleep(); 111 } 112 } // end switch 72 113 73 if((err = vmm_check_object(ibarrier, struct barrier_s, BARRIER_ID))) 74 break; 114 return 0; 75 115 76 err = barrier_wait(ibarrier); 77 break; 116 } // end sys_barrier() 78 117 79 case BARRIER_DESTROY:80 81 if((err = vmm_check_object(ibarrier, struct barrier_s, BARRIER_ID)))82 break;83 84 if((err = barrier_destroy(ibarrier)))85 break;86 87 req.type = KMEM_BARRIER;88 req.ptr = ibarrier;89 kmem_free(&req);90 return 0;91 92 default:93 err = EINVAL;94 }95 96 SYS_BARRIER_END:97 current_thread->info.errno = err;98 return err;99 }100 101 KMEM_OBJATTR_INIT(barrier_kmem_init)102 {103 attr->type = KMEM_BARRIER;104 attr->name = "KCM Barrier";105 attr->size = sizeof(struct barrier_s);106 attr->aligne = 0;107 attr->min = CONFIG_BARRIER_MIN;108 attr->max = CONFIG_BARRIER_MAX;109 attr->ctor = NULL;110 attr->dtor = NULL;111 return 0;112 } -
trunk/kernel/syscalls/sys_chdir.c
r11 r23 1 1 /* 2 * sys_chdir: change process current work directory2 * sys_chdir: change process current working directory 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 4 * Author Alain Greiner (2016,2017) 5 * 5 6 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 6 7 * 7 * This file is part of ALMOS- kernel.8 * This file is part of ALMOS-MKH. 8 9 * 9 * ALMOS- kernelis free software; you can redistribute it and/or modify it10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include <cpu.h> 24 #include <hal_types.h> 25 #include <hal_uspace.h> 24 26 #include <chdev.h> 25 #include <driver.h>26 27 #include <rwlock.h> 27 28 #include <vfs.h> 28 #include < sys-vfs.h>29 #include <errno.h> 29 30 #include <thread.h> 30 #include < ku_transfert.h>31 #include < task.h>31 #include <printk.h> 32 #include <process.h> 32 33 33 int sys_chdir (char *pathname) 34 ///////////////////////////////// 35 int sys_chdir ( char * pathname ) 34 36 { 35 register error_t err = 0;36 register struct thread_s *this;37 register struct task_s *task;38 struct ku_obj ku_path;37 error_t error; 38 paddr_t paddr; 39 uint32_t length; 40 char kbuf[CONFIG_VFS_MAX_PATH_LENGTH]; 39 41 40 th is = current_thread;41 task = current_task;42 thread_t * this = CURRENT_THREAD; 43 process_t * process = this->process; 42 44 43 if(!pathname) 45 // check pathname in user space 46 error = vmm_v2p_translate( false , pathname , &paddr ); 47 48 if( error ) 44 49 { 45 this->info.errno = EINVAL; 50 printk("\n[ERROR] in %s : user buffer unmapped for thread %x in process %x\n", 51 __FUNCTION__ , this->trdid , process->pid ); 52 this->errno = EINVAL; 46 53 return -1; 47 54 } 48 55 49 KU_BUFF(ku_path, pathname); 50 rwlock_wrlock(&task->cwd_lock); 56 // get pathname length 57 length = hal_strlen_from_uspace( pathname ); 58 59 if( length >= CONFIG_VFS_MAX_PATH_LENGTH ) 60 { 61 printk("\n[ERROR] in %s : pathname too long for thread %x in process %x\n", 62 __FUNCTION__ , this->trdid , process->pid ); 63 this->errno = ENFILE; 64 return -1; 65 } 66 67 // get pathname copy in kernel space 68 hal_copy_from_uspace( kbuf, pathname, length ); 69 70 // get cluster and local pointer on reference process 71 xptr_t ref_xp = process->ref_xp; 72 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 73 cxy_t ref_cxy = GET_CXY( ref_xp ); 74 75 // get extended pointer on cwd lock in reference process 76 xptr_t lock_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 51 77 52 if((err = vfs_chdir(&ku_path, &task->vfs_cwd))) 78 // get cwd lock in read mode 79 remote_rwlock_rd_lock( lock_xp ); 80 81 // call relevant VFS function 82 error = vfs_chdir( process->vfs_cwd_xp , kbuf ); 83 84 // release cwd lock 85 remote_rwlock_rd_unlock( lock_xp ); 86 87 if( error ) 53 88 { 54 rwlock_unlock(&task->cwd_lock);55 this-> info.errno = (err < 0) ? -err : err;89 printk("\n[ERROR] in %s : cannot change current directory\n", __FUNCTION__ ); 90 this->errno = error; 56 91 return -1; 57 92 } 58 93 59 rwlock_unlock(&task->cwd_lock);60 94 return 0; 61 95 } -
trunk/kernel/syscalls/sys_chmod.c
r11 r23 1 1 /* 2 * sys_chmod : change file mode2 * sys_chmod.c - Change file access rights. 3 3 * 4 * Author Alain Greiner (2016,2017) 5 * 4 6 * Copyright (c) 2015 UPMC Sorbonne Universites 5 7 * 6 * This file is part of ALMOS- kernel.8 * This file is part of ALMOS-MKH. 7 9 * 8 * ALMOS- kernelis free software; you can redistribute it and/or modify it10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 9 11 * under the terms of the GNU General Public License as published by 10 12 * the Free Software Foundation; version 2.0 of the License. 11 13 * 12 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 13 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 16 18 * 17 19 * You should have received a copy of the GNU General Public License 18 * along with ALMOS- kernel; if not, write to the Free Software Foundation,20 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 19 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 22 */ 21 23 22 #include <cpu.h> 23 #include <chdev.h> 24 #include <driver.h> 25 #include <rwlock.h> 24 #include <hal_types.h> 25 #include <hal_uspace.h> 26 26 #include <vfs.h> 27 #include <sys-vfs.h> 27 #include <vmm.h> 28 #include <printk.h> 28 29 #include <thread.h> 29 #include <ku_transfert.h> 30 #include <task.h> 30 #include <process.h> 31 31 32 int sys_chmod (char *pathname, uint_t mode) 32 ////////////////////////////////// 33 int sys_chmod( char * pathname, 34 uint32_t rights ) 33 35 { 34 register error_t err = 0; 35 register struct thread_s *this; 36 register struct task_s *task; 37 struct ku_obj ku_path; 36 error_t error; 37 paddr_t paddr; 38 uint32_t length; 39 char kbuf[CONFIG_VFS_MAX_PATH_LENGTH]; 40 41 thread_t * this = CURRENT_THREAD; 42 process_t * process = this->process; 38 43 39 this = current_thread; 40 task = current_task;44 // check pathname in user space 45 error = vmm_v2p_translate( false , pathname , &paddr ); 41 46 42 if( !pathname || NOT_IN_USPACE(pathname))47 if( error ) 43 48 { 44 this->info.errno = EINVAL; 49 printk("\n[ERROR] in %s : user pathname unmapped for thread %x in process %x\n", 50 __FUNCTION__ , this->trdid , process->pid ); 51 this->errno = EINVAL; 45 52 return -1; 46 53 } 47 48 49 KU_BUFF(ku_path, pathname); 50 rwlock_wrlock(&task->cwd_lock); 51 52 if((err = vfs_chmod(&ku_path, &task->vfs_cwd, mode))) 54 55 // get pathname length 56 length = hal_strlen_from_uspace( pathname ); 57 58 if( length >= CONFIG_VFS_MAX_PATH_LENGTH ) 59 { 60 printk("\n[ERROR] in %s : pathname too long\n", __FUNCTION__ ); 61 this->errno = ENFILE; 62 return -1; 63 } 64 65 // get pathname copy in kernel space 66 hal_copy_from_uspace( kbuf, pathname, length ); 67 68 // get cluster and local pointer on reference process 69 xptr_t ref_xp = process->ref_xp; 70 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 71 cxy_t ref_cxy = GET_CXY( ref_xp ); 72 73 // get extended pointer on cwd inode 74 xptr_t cwd_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_cwd_xp ) ); 75 76 // get the cwd lock in read mode from reference process 77 remote_rwlock_rd_lock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 78 79 // call the relevant VFS function 80 error = vfs_chmod( cwd_xp, 81 kbuf, 82 rights ); 83 84 // release the cwd lock 85 remote_rwlock_rd_unlock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 86 87 if( error ) 53 88 { 54 rwlock_unlock(&task->cwd_lock); 55 this->info.errno = (err < 0) ? -err : err; 89 printk("\n[ERROR] in %s : cannot remove directory %s\n", 90 __FUNCTION__ , kbuf ); 91 this->errno = error; 56 92 return -1; 57 93 } 58 94 59 rwlock_unlock(&task->cwd_lock);60 95 return 0; 61 } 96 97 } // end sys_chmod() -
trunk/kernel/syscalls/sys_clock.c
r1 r23 1 1 /* 2 * sys_clock: get system current time2 * sys_clock: get calling core cycles count 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 5 * 6 * Copyright (c) UPMC Sorbonne Universites 6 7 * 7 * This file is part of ALMOS- kernel.8 * This file is part of ALMOS-MKH. 8 9 * 9 * ALMOS- kernelis free software; you can redistribute it and/or modify it10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 24 #include <hal_types.h> 25 #include <hal_uspace.h> 23 26 #include <errno.h> 24 #include <config.h> 25 #include <cpu.h> 27 #include <core.h> 26 28 #include <thread.h> 29 #include <process.h> 30 #include <vmm.h> 31 #include <printk.h> 27 32 28 int sys_clock(uint64_t *val) 33 ////////////////////////////////// 34 int sys_clock (uint64_t * cycles ) 29 35 { 30 error_t err; 31 uint64_t cycles; 36 error_t error; 37 paddr_t paddr; 38 uint64_t k_cycles; 32 39 33 if((val == NULL) || NOT_IN_USPACE((uint_t)val)) 40 thread_t * this = CURRENT_THREAD; 41 process_t * process = this->process; 42 43 // check buffer in user space 44 error = vmm_v2p_translate( false , cycles , &paddr ); 45 46 if( error ) 34 47 { 35 err = EINVAL; 36 goto fail_inval; 48 printk("\n[ERROR] in %s : user buffer unmapped for thread %x in process %x\n", 49 __FUNCTION__ , this->trdid , process->pid ); 50 this->errno = EFAULT; 51 return -1; 37 52 } 38 53 39 cycles = cpu_get_cycles(current_cpu); 40 err = cpu_copy_to_uspace(val, &cycles, sizeof(cycles));54 // call relevant core function 55 k_cycles = core_get_cycles( this->core ); 41 56 42 fail_inval: 43 current_thread->info.errno = err; 44 return err; 45 } 57 // copy to user space 58 hal_copy_to_uspace( cycles , &k_cycles , sizeof(uint64_t) ); 59 60 return 0; 61 62 } // end sys_clock() -
trunk/kernel/syscalls/sys_close.c
r11 r23 1 1 /* 2 * sys_close.c close a processopen file2 * sys_close.c close an open file 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include < cpu.h>24 #include < chdev.h>25 #include < driver.h>24 #include <kernel_config.h> 25 #include <hal_types.h> 26 #include <hal_special.h> 26 27 #include <vfs.h> 27 #include <sys-vfs.h>28 28 #include <process.h> 29 29 #include <thread.h> 30 #include < config.h>30 #include <printk.h> 31 31 32 ///////////////////////////// 33 int sys_close ( uint32_t f d )32 ////////////////////////////////// 33 int sys_close ( uint32_t file_id ) 34 34 { 35 register process_t * process = current_process; 36 register thread_t * this = current_thread; 37 struct vfs_file_s * file = NULL; 38 error_t err; 39 40 if(( fd >= CONFIG_TASK_FILE_MAX_NR ) || (process_fd_lookup( process , fd , &file ))) 35 error_t error; 36 xptr_t file_xp; 37 38 thread_t * this = CURRENT_THREAD; 39 process_t * process = this->process; 40 41 // check file_id argument 42 if( file_id >= CONFIG_PROCESS_FILE_MAX_NR ) 41 43 { 42 this->info.errno = EBADFD; 44 printk("\n[ERROR] in %s : illegal file descriptor index = %d\n", 45 __FUNCTION__ , file_id ); 46 this->errno = EBADFD; 43 47 return -1; 44 48 } 45 49 46 err = vfs_close( file , NULL ); 47 if( err ) 50 // get extended pointer on remote file descriptor 51 file_xp = process_fd_get_xptr( process , file_id ); 52 53 if( file_xp == XPTR_NULL ) 54 { 55 printk("\n[ERROR] in %s : undefined file descriptor = %d\n", 56 __FUNCTION__ , file_id ); 57 this->errno = EBADFD; 58 return -1; 59 } 60 61 // call the relevant VFS function 62 error = vfs_close( file_xp , file_id ); 63 64 if( error ) 48 65 { 49 this->info.errno = err; 66 printk("\n[ERROR] in %s : cannot close file descriptor = %d\n", 67 __FUNCTION__ , file_id ); 68 this->errno = error; 50 69 return -1; 51 70 } 52 71 53 process_fd_release( process , fd);54 cpu_wbflush(); 72 hal_wbflush(); 73 55 74 return 0; 56 75 } -
trunk/kernel/syscalls/sys_closedir.c
r1 r23 1 1 /* 2 * sys_closedir.c close a process open directory2 * sys_closedir.c - Close an open directory. 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016, 2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 24 #include <hal_types.h> 23 25 #include <vfs.h> 24 #include <sys-vfs.h>25 26 #include <thread.h> 27 #include <printk.h> 26 28 #include <process.h> 27 29 28 //////////////////////////////// 29 int sys_closedir ( uint32_t f d )30 ///////////////////////////////////// 31 int sys_closedir ( uint32_t file_id ) 30 32 { 31 register thread_t * this = current-thread; 32 register process_t * process = current_process; 33 struct vfs_file_s * file = NULL; 34 error_t err; 33 error_t error; 34 xptr_t file_xp; // extended pointer on searched directory file descriptor 35 35 36 if(( fd >= CONFIG_TASK_FILE_MAX_NR ) || (process_fd_lookup( process , fd , &file ))) 36 thread_t * this = CURRENT_THREAD; 37 process_t * process = this->process; 38 39 // check file_id argument 40 if( file_id >= CONFIG_PROCESS_FILE_MAX_NR ) 37 41 { 38 this->info.errno = EBADFD; 42 printk("\n[ERROR] in %s : illegal file descriptor index %d\n", 43 __FUNCTION__ , file_id ); 44 this->errno = EBADFD; 39 45 return -1; 40 46 } 41 47 42 err = vfs_closedir( file , NULL ); 43 if(err) 48 // get extended pointer on remote file descriptor 49 file_xp = process_fd_get_xptr( process , file_id ); 50 51 if( file_xp == XPTR_NULL ) 52 { 53 printk("\n[ERROR] in %s : undefined file descriptor index = %d\n", 54 __FUNCTION__ , file_id ); 55 this->errno = EBADFD; 56 return -1; 57 } 58 59 // call relevant VFS function 60 error = vfs_close( file_xp , file_id ); 61 62 if( error ) 44 63 { 45 this->info.errno = (err < 0) ? -err : err; 64 printk("\n[ERROR] in %s : cannot close the directory = %d\n", 65 __FUNCTION__ , file_id ); 66 this->errno = error; 46 67 return -1; 47 68 } 48 69 49 process_fd_release( process , fd );50 70 return 0; 51 } 71 72 } // end sys_closedir() -
trunk/kernel/syscalls/sys_condvar.c
r15 r23 1 1 /* 2 * sys_cond _var: interface to access condition vraibles service2 * sys_condvar.c - Access a POSIX condvar. 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include <types.h> 24 #include <hal_types.h> 25 #include <hal_special.h> 24 26 #include <errno.h> 25 27 #include <thread.h> 26 #include <kmem.h> 27 #include <task.h> 28 #include <printk.h> 28 29 #include <vmm.h> 29 #include <kmagics.h> 30 #include <semaphore.h> 31 #include <cond_var.h> 30 #include <syscalls.h> 31 #include <remote_condvar.h> 32 32 33 static inline bool_t isBadSem(struct semaphore_s *sem) 34 { 35 return vmm_check_object(sem, struct semaphore_s, SEMAPHORE_ID); 36 } 33 //////////////////////////////////////// 34 int sys_condvar( void * condvar, 35 uint32_t operation, 36 void * mutex ) 37 { 38 error_t error; 39 paddr_t paddr; 40 41 thread_t * this = CURRENT_THREAD; 37 42 38 static inline bool_t isBadCV(struct cv_s *cv) 39 { 40 return vmm_check_object(cv, struct cv_s, COND_VAR_ID); 41 } 43 // check condvar in user vspace 44 error = vmm_v2p_translate( false , condvar , &paddr ); 45 if( error ) 46 { 47 printk("\n[ERROR] in %s : illegal condvar virtual address = %x\n", 48 __FUNCTION__ , (intptr_t)condvar ); 49 this->errno = error; 50 return -1; 51 } 42 52 43 int sys_cond_var(struct cv_s **cv, uint_t operation, struct semaphore_s **sem) 44 { 45 kmem_req_t req; 46 struct cv_s *icv; 47 struct semaphore_s *isem; 48 error_t err = EINVAL; 49 50 if((err = vmm_check_address("usr cv ptr", current_task,cv,sizeof(struct cv_s*)))) 51 goto SYS_COND_END; 53 // execute requested operation 54 switch( operation ) 55 { 56 ////////////////// 57 case CONDVAR_INIT: 58 { 59 error = remote_condvar_create( (intptr_t)condvar ); 60 61 if( error ) 62 { 63 printk("\n[ERROR] in %s : cannot create condvar = %x\n", 64 __FUNCTION__ , (intptr_t)condvar ); 65 this->errno = error; 66 return -1; 67 } 68 break; 69 } 70 ////////////////// 71 case CONDVAR_WAIT: 72 { 73 // check mutex in user vspace 74 error = vmm_v2p_translate( false , mutex , &paddr ); 52 75 53 if((err = cpu_copy_from_uspace(&icv, cv, sizeof(struct cv_s *)))) 54 goto SYS_COND_END; 76 if( error ) 77 { 78 printk("\n[ERROR] in %s : illegal condvar virtual address = %x\n", 79 __FUNCTION__ , (intptr_t)condvar ); 80 this->errno = error; 81 return -1; 82 } 55 83 56 switch(operation) 57 { 58 case CV_INIT: 59 req.type = KMEM_CV; 60 req.size = sizeof(*icv); 61 req.flags = AF_USER; 84 xptr_t condvar_xp = remote_condvar_from_ident( (intptr_t)condvar ); 85 86 if( condvar_xp == XPTR_NULL ) // user error 87 { 88 printk("\n[ERROR] in %s : condvar %x not registered\n", 89 __FUNCTION__ , (intptr_t)condvar ); 90 this->errno = EINVAL; 91 return -1; 92 } 62 93 63 if((icv = kmem_alloc(&req)) == NULL) 64 { 65 err = ENOMEM; 66 break; 94 xptr_t mutex_xp = remote_condvar_from_ident( (intptr_t)condvar ); 95 if( mutex_xp == XPTR_NULL ) // user error 96 { 97 printk("\n[ERROR] in %s : mutex %x not registered\n", 98 __FUNCTION__ , (intptr_t)condvar ); 99 this->errno = EINVAL; 100 return -1; 101 } 102 103 remote_condvar_wait( condvar_xp , mutex_xp ); 104 105 break; 106 } 107 //////////////////// 108 case CONDVAR_SIGNAL: 109 { 110 xptr_t condvar_xp = remote_condvar_from_ident( (intptr_t)condvar ); 111 112 if( condvar_xp == XPTR_NULL ) // user error 113 { 114 printk("\n[ERROR] in %s : condvar %x not registered\n", 115 __FUNCTION__ , (intptr_t)condvar ); 116 this->errno = EINVAL; 117 return -1; 118 } 119 120 remote_condvar_signal( condvar_xp ); 121 122 break; 123 } 124 /////////////////////// 125 case CONDVAR_BROADCAST: 126 { 127 xptr_t condvar_xp = remote_condvar_from_ident( (intptr_t)condvar ); 128 129 if( condvar_xp == XPTR_NULL ) // user error 130 { 131 printk("\n[ERROR] in %s : condvar %x not registered\n", 132 __FUNCTION__ , (intptr_t)condvar ); 133 this->errno = EINVAL; 134 return -1; 135 } 136 137 remote_condvar_broadcast( condvar_xp ); 138 139 break; 140 } 141 ///////////////////// 142 case CONDVAR_DESTROY: 143 { 144 xptr_t condvar_xp = remote_condvar_from_ident( (intptr_t)condvar ); 145 146 if( condvar_xp == XPTR_NULL ) // user error 147 { 148 printk("\n[ERROR] in %s : condvar %x not registered\n", 149 __FUNCTION__ , (intptr_t)condvar ); 150 this->errno = EINVAL; 151 return -1; 152 } 153 154 remote_condvar_destroy( condvar_xp ); 155 156 break; 67 157 } 68 69 if((err = cv_init(icv))) 70 break; 71 72 if((err = cpu_copy_to_uspace(cv, &icv, sizeof(struct cv_s *)))) 73 { 74 req.ptr = icv; 75 kmem_free(&req); 76 } 158 ///////// 159 default: 160 { 161 printk("\n[PANIC] in %s : illegal operation type\n", __FUNCTION__ ); 162 hal_core_sleep(); 163 } 164 } // end switch 77 165 78 break;166 return 0; 79 167 80 case CV_WAIT: 81 err = vmm_check_address("usr sem ptr", 82 current_task, 83 sem, sizeof(struct semaphore_s*)); 168 } // enc sys_condvar() 84 169 85 if(err) break;86 87 if((err = cpu_copy_from_uspace(&isem, sem, sizeof(struct semaphore_s *))))88 break;89 90 if(isBadSem(isem))91 break;92 93 if(isBadCV(icv))94 break;95 96 return cv_wait(icv, isem);97 98 case CV_SIGNAL:99 if(isBadCV(icv))100 break;101 102 return cv_signal(icv);103 104 case CV_BROADCAST:105 if(isBadCV(icv))106 break;107 108 return cv_broadcast(icv);109 110 case CV_DESTROY:111 if(isBadCV(icv))112 break;113 114 if((err = cv_destroy(icv)))115 break;116 117 req.type = KMEM_CV;118 req.ptr = icv;119 kmem_free(&req);120 return 0;121 122 default:123 err = EINVAL;124 }125 126 SYS_COND_END:127 current_thread->info.errno = err;128 return err;129 }130 131 KMEM_OBJATTR_INIT(cv_kmem_init)132 {133 attr->type = KMEM_CV;134 attr->name = "KCM Condition Variable";135 attr->size = sizeof(struct cv_s);136 attr->aligne = 0;137 attr->min = CONFIG_CONDTION_VAR_MIN;138 attr->max = CONFIG_CONDTION_VAR_MAX;139 attr->ctor = NULL;140 attr->dtor = NULL;141 142 return 0;143 } -
trunk/kernel/syscalls/sys_creat.c
r1 r23 1 1 /* 2 * kern/sys_creat.c - create a file2 * sys_creat.c - create a file 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 5 * 6 * Copyright (c) UPMC Sorbonne Universites 6 7 * 7 8 * This file is part of ALMOS-kernel. … … 21 22 */ 22 23 23 #include < config.h>24 #include <hal_types.h> 24 25 #include <vfs.h> 25 #include <sys-vfs.h> 26 #include <spinlock.h> 27 #include <process.h> 28 #include <thread.h> 26 #include <syscalls.h> 29 27 30 28 //////////////////////////////////// 31 int sys_creat 32 29 int sys_creat( char * pathname, 30 uint32_t mode ) 33 31 { 34 CPU_HW_TRACE(sys_creat);32 uint32_t flags = O_CREAT; 35 33 36 register error_t err; 37 register uint32_t flags; 38 register thread_t * this = durrent_thread; 39 register process_t * process = current_process; 40 struct vfs_file_s file; 41 struct ku_obj ku_path; 42 uint32_t fd = (uint32_t)-1; 43 44 if( process_fd_array_full( process ) ) 45 { 46 this->info.errno = ENFILE; 47 CPU_HW_TRACE(sys_creat); 48 return fd; 49 } 50 51 flags = 0; 52 KU_BUFF( ku_path , pathname ); 53 54 // get the cwd lock 55 rwlock_rdlock( &process->cwd_lock ); 56 57 err = vfs_create( &process->vfs_cwd , &ku_path , flags , mode , &file ); 58 if( err ) 59 { 60 this->info.errno = (err < 0 ) ? -err : err; 61 rwlock_unlock( &process->cwd_lock ); 62 CPU_HW_TRACE(sys_creat); 63 return fd; 64 } 65 66 err = process_fd_set( process , &file , &fd ); 67 if( err ) 68 { 69 vfs_close( &file , NULL ); 70 this->info.errno = err; 71 } 72 73 rwlock_unlock( &process->cwd_lock ); 74 CPU_HW_TRACE(sys_creat); 75 return fd; 34 return sys_open( pathname , flags , mode ); 76 35 } -
trunk/kernel/syscalls/sys_exec.c
r14 r23 1 1 /* 2 * sys_exec.c - Kernel function implementing the "exec" sys call2 * sys_exec.c - Kernel function implementing the "exec" system call. 3 3 * 4 * Authors Mohamed Lamine Karaoui (2015) 5 * Alain Greiner (2016) 4 * Authors Alain Greiner (2016,2017) 6 5 * 7 6 * Copyright (c) UPMC Sorbonne Universites … … 25 24 #include <kernel_config.h> 26 25 #include <hal_types.h> 26 #include <hal_uspace.h> 27 27 #include <errno.h> 28 28 #include <printk.h> … … 51 51 52 52 // get string length 53 hal_strlen_from_uspace( pathname , &length ); 54 if( length > 255 ) 55 { 56 printk(ERROR, "%s: elf file pathname larger than 255 bytes\n", __FUNCTION__ ); 57 return EINVAL; 58 } 53 length = hal_strlen_from_uspace( pathname ); 54 55 if( length >= CONFIG_VFS_MAX_PATH_LENGTH ) return EINVAL; 59 56 60 57 // copy string to exec_info … … 75 72 // The max number of strings is 1024 (for both args and envs). The numbers of pages 76 73 // to store the (args) and (envs) strings are configuration parameters. 77 //////////////////////////////////////////////// i//////////////////////////////////////74 /////////////////////////////////////////////////////////////////////////////////////// 78 75 // @ exec_info : pointer on the exec_info structure. 79 76 // @ is_args : true if called for (args) / false if called for (envs). … … 88 85 uint32_t found_null; // NULL pointer found in array of pointers 89 86 uint32_t length; // string length 90 uint32_t strings; // actual number of strings91 87 kmem_req_t req; // kmem request 92 88 page_t * page; // page descriptor 93 89 uint32_t order; // ln2( number of pages to store strings ) 94 char ** k_pointers; // base of kernel buffer containingarray of pointers95 char * buf_ptr;// pointer on first empty slot in kernel strings buffer96 char * buf_base;// base address of the kernel strings buffer90 char ** k_pointers; // base of kernel array of pointers 91 char * k_buf_ptr; // pointer on first empty slot in kernel strings buffer 92 char * k_buf_base; // base address of the kernel strings buffer 97 93 98 94 // compute ln2( number of pages for kernel strings buffer ) 99 if( is_args ) order = CONFIG_PROCESS_ARGS_ORDER;100 else order = CONFIG_PROCESS_ENVS_ORDER;95 if( is_args ) order = bits_log2( CONFIG_VMM_ARGS_SIZE ); 96 else order = bits_log2( CONFIG_VMM_ENVS_SIZE ); 101 97 102 98 req.type = KMEM_PAGE; … … 106 102 req.type = 0; 107 103 page = kmem_alloc( &req ); 108 if( page == NULL ) 109 { 110 printk("ERROR in %s : cannot allocate memory for pointers\n", __FUNCTION__ ); 111 return ENOMEM; 112 } 104 105 if( page == NULL ) return ENOMEM; 106 113 107 k_pointers = ppm_page2base( page ); 114 108 … … 116 110 req.type = order; 117 111 page = kmem_alloc( &req ); 118 if( page == NULL ) 119 { 120 printk("ERROR in %s : cannot allocate memory for strings\n", __FUNCTION__ ); 121 return ENOMEM; 122 } 123 buf_base = ppm_page2base( page ); 112 113 if( page == NULL ) return ENOMEM; 114 115 k_buf_base = ppm_page2base( page ); 124 116 125 117 // copy the array of pointers to kernel buffer … … 128 120 CONFIG_PPM_PAGE_SIZE ); 129 121 130 // scan local copy ofarray of pointers to copy the strings122 // scan kernel array of pointers to copy the strings 131 123 found_null = 0; 132 buf_ptr =buf_base;124 k_buf_ptr = k_buf_base; 133 125 for( index = 0 ; index < 1024 ; index++ ) 134 126 { … … 140 132 141 133 // compute string length 142 hal_strlen_from_uspace( k_pointers[index] , &length);134 length = hal_strlen_from_uspace( k_pointers[index] ); 143 135 144 136 // copy the user string to kernel buffer 145 hal_copy_from_uspace( k_ strings,146 k_pointers[index] ;137 hal_copy_from_uspace( k_buf_ptr, 138 k_pointers[index], 147 139 length ); 148 140 149 141 // update k_pointer[index] entry 150 k_pointers[index] = buf_ptr;142 k_pointers[index] = k_buf_ptr; 151 143 152 144 // increment pointer on kernel strings buffer 153 buf_ptr += (length + 1);145 k_buf_ptr += (length + 1); 154 146 } 155 147 … … 158 150 { 159 151 exec_info->args_pointers = k_pointers; 160 exec_info->args_buf_base = buf_base;152 exec_info->args_buf_base = k_buf_base; 161 153 exec_info->args_nr = index; 162 154 } … … 164 156 { 165 157 exec_info->envs_pointers = k_pointers; 166 exec_info->envs_buf_base = buf_base;167 exec_info->envs_buf_free = buf_ptr;158 exec_info->envs_buf_base = k_buf_base; 159 exec_info->envs_buf_free = k_buf_ptr; 168 160 exec_info->envs_nr = index; 169 161 } 170 162 else 171 163 { 172 printk("ERROR in %s : number of strings larger than 1024\n", __FUNCTION__ );173 164 return EINVAL; 174 165 } … … 177 168 } // end process_exec_get_strings() 178 169 179 /////////////////////////////////////////////////////////////////////////////////////////180 // This function is executed in a "client" cluster by a process whose PID can belong181 // to another "server" cluster (defined by the MSB bits of the calling process PID).182 // A new process descriptor, and the associated main thread descriptor must be created183 // in the "server" cluster, using directly the process_make_exec() function if local,184 // or the rpc_process_exec_client() function if server is remote.185 170 ///////////////////////////////////////////////////////////////////////////////////////// 186 171 // Implementation note: … … 189 174 // It calls the static process_exec_get_path() and process_exec_get_strings() functions 190 175 // to copy the .elf pathname, the main() arguments and the environment variables from 191 // user buffers to the exec_info_t , and calls the staticprocess_make_exec() function.176 // user buffers to the exec_info_t structure, and call the process_make_exec() function. 192 177 ///////////////////////////////////////////////////////////////////////////////////////// 193 178 int sys_exec( char * filename, // .elf file pathname 194 char ** arg v, // process arguments195 char ** env p) // environment variables179 char ** args, // process arguments 180 char ** envs ) // environment variables 196 181 { 197 182 exec_info_t exec_info; // structure to pass to process_make_exec() 198 thread_t * thread; // pointer on thread created in server cluster 199 error_t error = 0; 200 process_t * process = CURRENT_PROCESS; 201 202 // check arguments 203 if((filename == NULL) || (argv == NULL) || (envp == NULL)) 204 { 205 printk("\n[ERROR] in %s : missing arguments / file = %x / argv = %x / envp = %x\n", 206 __FUNCTION__ , filename , argv , envp ); 207 return EINVAL; 183 error_t error; 184 paddr_t paddr; 185 186 thread_t * this = CURRENT_THREAD; 187 process_t * process = this->process; 188 189 // check argument fileme 190 error = vmm_v2p_translate( false , filename , &paddr ); 191 192 if( error ) 193 { 194 printk("\n[ERROR] in %s : filename unmapped\n", __FUNCTION__ ); 195 this->errno = EINVAL; 196 return -1; 197 } 198 199 // check argument fileme 200 error = vmm_v2p_translate( false , args , &paddr ); 201 202 if( error ) 203 { 204 printk("\n[ERROR] in %s : args unmapped\n", __FUNCTION__ ); 205 this->errno = EINVAL; 206 return -1; 207 } 208 209 // check argument fileme 210 error = vmm_v2p_translate( false , envs , &paddr ); 211 212 if( error ) 213 { 214 printk("\n[ERROR] in %s : envs unmapped\n", __FUNCTION__ ); 215 this->errno = EINVAL; 216 return -1; 208 217 } 209 218 … … 218 227 cxy_client, cxy_server, hal_time_stamp()); 219 228 220 // Change process's state to prevent any concurent access TODO ??? [AG]221 222 229 // initialize exec_info structure 223 exec_info ->pid= process->pid;224 exec_info ->ppid= process->ppid;225 exec_info ->fd_array = &process->fd_array;226 exec_info ->vfs_root = &process->vfs_root;227 exec_info ->vfs_cwd = &process->vfs_cwd;228 exec_info ->vfs_bin = &process->vfs_bin;230 exec_info.pid = process->pid; 231 exec_info.ppid = process->ppid; 232 exec_info.fd_array_xp = XPTR( local_cxy , &process->fd_array ); 233 exec_info.vfs_root_xp = process->vfs_root_xp; 234 exec_info.vfs_cwd_xp = process->vfs_cwd_xp; 235 exec_info.vfs_bin_xp = process->vfs_bin_xp; 229 236 230 237 // check pathname and store it in exec_info structure 231 238 error = process_exec_get_path( &exec_info , filename ); 232 if ( error ) return EINVAL; 233 234 // check and store argv in exec_info structure 235 error = process_exec_get_strings( &exec_info , true , argv ); 236 if( error ) return EINVAL; 239 240 if ( error ) 241 { 242 printk("\n[ERROR] in %s : elf pathname too long\n", __FUNCTION__ ); 243 this->errno = error; 244 return -1; 245 } 246 247 // check and store args in exec_info structure 248 error = process_exec_get_strings( &exec_info , true , args ); 249 250 if( error ) 251 { 252 printk("\n[ERROR] in %s : cannot access args\n", __FUNCTION__ ); 253 this->errno = error; 254 return -1; 255 } 237 256 238 // check and store envp in exec_info structure 239 error = process_exec_get_strings( &exec_info , false , envp ); 240 if( error ) return EINVAL; 257 // check and store envs in exec_info structure 258 error = process_exec_get_strings( &exec_info , false , envs ); 259 260 if( error ) 261 { 262 printk("\n[ERROR] in %s : cannot access envs\n", __FUNCTION__ ); 263 this->errno = error; 264 return -1; 265 } 241 266 242 if( is_local ) ////////////// local exec ////////////////////////// 243 { 244 exec_dmsg("\n[INFO] %s starts local exec for process %x at cycle %d\n", 245 __FUNCTION__, process->pid, hal_time_stamp()); 246 247 // call directly the local process_make_exec() function 248 error = process_make_exec( &exec_info , &thread ); 249 if error 250 { 251 printk("\n[ERROR] in %s : failed in local exec for process %x\n", 252 __FUNCTION__ , process->pid ); 253 return EINVAL; 254 } 255 256 exec_dmsg("\n[INFO] %s completes local exec for process %x at cycle %d\n", 257 __FUNCTION__, process->pid , hal_time_stamp() ); 258 } 259 else ///////////// remote exec ///////////////////////// 260 { 261 exec_dmsg("\n[INFO] %s starts remote exec for process %x at cycle %d\n", 262 __FUNCTION__, process->pid, hal_time_stamp() ); 263 264 // call the rpc_process_exec_client() function 265 rpc_process_exec_client( cxy_server , &exec_info , &thread , &error ); 266 267 if( error ) 268 { 269 printk("\n[ERROR] in %s : failed in remote exec for process %x\n", 270 __FUNCTION__ , process->pid ); 271 return EINVAL; 272 } 273 274 exec_dmsg("\n[INFO] %s completes remote exec for process %x at cycle %d\n", 275 __FUNCTION__, process->pid , hal_time_stamp() ); 276 } 277 278 // If no error, delete the current thread an process descriptors. 267 exec_dmsg("\n[INFO] %s starts exec for process %x at cycle %d\n", 268 __FUNCTION__, process->pid, hal_time_stamp() ); 269 270 if( is_local ) error = process_make_exec( &exec_info ); 271 else rpc_process_exec_client( cxy_server , &exec_info , &error ); 272 273 if( error ) 274 { 275 printk("\n[ERROR] in %s : cannot create new process %x\n", 276 __FUNCTION__ , process->pid ); 277 this->errno = error; 278 return -1; 279 } 280 281 exec_dmsg("\n[INFO] %s completes exec for process %x at cycle %d\n", 282 __FUNCTION__, process->pid , hal_time_stamp() ); 283 284 // delete the calling thread an process 279 285 thread_kill( CURRENT_THREAD ); 280 process_kill( CURRENT_ PROCESS);286 process_kill( CURRENT_THREAD->process ); 281 287 282 288 return 0; 289 283 290 } // end sys_exec() 284 291 -
trunk/kernel/syscalls/sys_fork.c
r1 r23 1 1 /* 2 * sys_fork.c - fork the current process2 * sys_fork.c - Fork the current process. 3 3 * 4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016) 4 * Authors Alain Greiner (2016,2017) 7 5 * 8 6 * Copyright (c) UPMC Sorbonne Universites … … 24 22 */ 25 23 24 #include <kernel_config.h> 25 #include <hal_types.h> 26 #include <hal_atomic.h> 26 27 #include <errno.h> 27 #include < config.h>28 #include <c pu.h>28 #include <printk.h> 29 #include <core.h> 29 30 #include <cluster.h> 30 #include <event.h>31 31 #include <list.h> 32 32 #include <thread.h> … … 36 36 #include <process.h> 37 37 38 #if CONFIG_FORK_DEBUG 39 #define fork_debug(...) printk(__VA_ARGS__) 40 #else 41 #define fork_debug(...) /**/ 42 #endif 43 44 /*********************************************************************************************** 45 * This kernel function implement the "fork" system call. 46 * The calling process descriptor (parent process), and the associated thread descriptor are 47 * replicated in the same cluster as the calling thread, but the new process (child process) 48 * is registered in another target cluster, that will become the process owner. 49 * The child process and the associated main thread will be migrated to the target cluster 50 * later, when the child process makes an "exec" or any other system call. 51 * The target cluster depends on the "fork_user" flag and "fork_cxy" variable that can be 52 * stored in the calling thread descriptor by the specific fork_place() system call. 53 * If not, the sys_fork() function makes a query to the DQDT to select the target cluster. 54 * @ returns child process PID if success / returns -1 if failure 55 **********************************************************************************************/ 56 int sys_fork(); 38 ////////////// 39 int sys_fork() 57 40 { 58 41 process_t * parent_process; // pointer on parent process descriptor … … 63 46 thread_t * child_thread; // pointer on child main thread descriptor 64 47 trdid_t child_trdid; // child main thread identifier 65 core_t * child_core; // pointer on core for child main thread66 48 lid_t child_core_lid; // core local index for the child main thread 67 49 cxy_t target_cxy; // final target cluster for forked child process 68 50 error_t error; 69 51 70 cluster_t * parent_cluster = LOCAL_CLUSTER;71 72 52 // get pointers on parent process and thread 73 53 parent_thread = CURRENT_THREAD; 74 54 parent_process = parent_thread->process; 55 parent_pid = parent_process->pid; 75 56 76 57 // check parent process children number 77 if( hal_atomic_add( &parent_process->child s_nr , 1 ) >= CONFIG_PROCESS_CHILDS_MAX_NR)78 { 79 printk(" ERRORin %s : too much children processes\n", __FUNCTION__);80 hal_atomic_add ( &parent_process->child s_nr , -1 );81 return EAGAIN; 82 } 83 84 fork_d ebug("INFO : %senters for process %d at cycle [%d]\n",58 if( hal_atomic_add( &parent_process->children_nr , 1 ) >= CONFIG_PROCESS_MAX_CHILDREN ) 59 { 60 printk("\n[ERROR] in %s : too much children processes\n", __FUNCTION__); 61 hal_atomic_add ( &parent_process->children_nr , -1 ); 62 return EAGAIN; 63 } 64 65 fork_dmsg("\n[INFO] %s : enters for process %d at cycle [%d]\n", 85 66 __FUNCTION__, parent_process->pid, hal_time_stamp()); 86 67 … … 90 71 { 91 72 hal_fpu_context_save( parent_thread ); 92 fork_d ebug("INFO : %ssave FPU\n", __FUNCTION__);73 fork_dmsg("\n[INFO] %s : save FPU\n", __FUNCTION__); 93 74 } 94 75 95 76 // Select target cluster for future migration of child process and main thread. 96 // The placement can be specified by user. If placement is not user-defined,97 // the placement is defined by the DQDT.98 // The two first processes ("init" and "sh") on boot cluster will not migrate. 99 if( parent_thread s->fork_user )77 // If placement is not user-defined, the placement is defined by the DQDT. 78 // The two first processes ("init" and "sh") on boot cluster do not migrate. 79 80 if( parent_thread->fork_user ) 100 81 { 101 82 // user defined placement 102 target_cxy = parent->thread.fork_cxy; 103 parent->thread.fork_cxy = false; 104 } 105 else if( (LPID_FROM_PID(parent_process->pid) < 2 ) 106 && ( parent_cluster->cxy == parent_cluster->boot_cxy ) ) 83 target_cxy = parent_thread->fork_cxy; 84 parent_thread->fork_user = false; 85 } 86 else if( (LPID_FROM_PID(parent_process->pid) < 2) && (local_cxy == 0) ) 107 87 { 108 88 // 2 first process stay in boot cluster 109 target_cxy = parent_cluster->cxy;89 target_cxy = local_cxy; 110 90 } 111 91 else … … 115 95 } 116 96 117 fork_d ebug("INFO : %s select target_cluster = %x\n",97 fork_dmsg("INFO : %s select target_cluster = %x\n", 118 98 __FUNCTION__ , target_cxy ); 119 99 120 100 // allocates memory in local cluster for the child process descriptor 121 101 child_process = process_alloc(); 102 122 103 if( child_process == NULL ) 123 104 { 124 printk("ERROR in %s : cannot allocate memory for child process\n", __FUNCTION__ ); 125 hal_atomic_add ( &parent_process->childs_nr , -1 ); 126 return EAGAIN; 127 } 128 129 // get a new PID for child process 130 // it requires an RPC if target cluster is remote 131 xptr_t xp = XPTR( target_cxy , child_process ); 132 if( target_cxy == parent_cluster->cxy ) // local cluster 133 { 134 error = process_pid_alloc( xp , &child_pid ); 135 } 136 else // remote cluster 137 { 138 rpc_process_pid_alloc_server( target_cxy , xp , &error , &child_pid ); 139 } 105 printk("\n[ERROR] in %s : cannot allocate child process\n", __FUNCTION__ ); 106 hal_atomic_add ( &parent_process->children_nr , -1 ); 107 return EAGAIN; 108 } 109 110 // get a new PID for child process, 111 if( target_cxy == local_cxy ) // target cluster is local 112 { 113 error = cluster_pid_alloc( XPTR( target_cxy , child_process ) , &child_pid ); 114 } 115 else // target cluster is remote 116 { 117 rpc_process_pid_alloc_client( target_cxy , child_process , &error , &child_pid ); 118 } 119 140 120 if( error ) 141 121 { 142 printk(" ERRORin %s : cannot allocate PID\n", __FUNCTION__ );143 atomic_add ( &parent_process->childs_nr , -1 );122 printk("\n[ERROR] in %s : cannot allocate PID\n", __FUNCTION__ ); 123 hal_atomic_add ( &parent_process->children_nr , -1 ); 144 124 process_destroy( child_process ); 145 125 return EAGAIN; … … 147 127 148 128 // initialize and register the child process descriptor 149 error = process_reference_init( child_process , child_pid , parent_pid ); 150 if( error ) 151 { 152 printk("ERROR in %s : cannot initialise child process\n", __FUNCTION__ ); 153 atomic_add ( &parent_process->childs_nr , -1 ); 154 process_destroy( child_process ); 155 return EAGAIN; 156 } 157 158 fork_debug("INFO : %s created child process : pid = %x / ppid = %x\n", 129 process_reference_init( child_process , child_pid , parent_pid ); 130 131 fork_dmsg("\n[INFO] : %s created child process : pid = %x / ppid = %x\n", 159 132 __FUNCTION__, child_pid , parent_pid ); 160 161 // set IS_REFERENCE flag in child process descriptor162 child_process->flags = PDF_IS_REFERENCE;163 133 164 134 // initialises child process standard files structures 165 135 // ( root / cwd / bin ) from parent process descriptor 166 spinlock_lock( &parent_process->cwd_lock ); 167 168 vfs_file_count_up( &parent_process->vfs_root ); 169 child_process->vfs_root = parent_process->vfs_root; 170 171 vfs_file_count_up( &parent_process->vfs_cwd ); 172 child_process->vfs_cwd = parent_process->vfs_cwd; 173 174 vfs_file_count_up( &parent_process->vfs_bin ); 175 child_process->vfs_bin = parent_process->vfs_bin; 176 177 spinlock_unlock( &parent_process->cwd_lock ); 136 137 vfs_file_count_up( parent_process->vfs_root_xp ); 138 child_process->vfs_root_xp = parent_process->vfs_root_xp; 139 140 vfs_file_count_up( parent_process->vfs_cwd_xp ); 141 child_process->vfs_cwd_xp = parent_process->vfs_cwd_xp; 142 143 vfs_file_count_up( parent_process->vfs_bin_xp ); 144 child_process->vfs_bin_xp = parent_process->vfs_bin_xp; 145 146 // copy the parent process fd_array to the child process fd_array 147 process_fd_remote_copy( XPTR( local_cxy , &child_process->fd_array ), 148 XPTR( local_cxy , &parent_process->fd_array ) ); 149 150 fork_dmsg("\n[INFO] %s : duplicated child process from parent process\n", 151 __FUNCTION__ ); 152 153 // replicates virtual memory manager 154 error = vmm_copy( child_process , parent_process ); 155 156 if( error ) 157 { 158 printk("\n[ERROR] in %s : cannot duplicate VMM\n", __FUNCTION__ ); 159 hal_atomic_add ( &parent_process->children_nr , -1 ); 160 process_destroy( child_process ); 161 return ENOMEM; 162 } 178 163 179 // copy the parent process fd_array to the child process fd_array 180 process_fd_fork( child_process , parent_process ); 181 182 // initialise child process signal manager TODO ??? 183 signal_manager_init( child_process ); 184 185 fork_debug("INFO : %s duplicated child process from parent process\n", 186 __FUNCTION__ ); 187 188 // replicates virtual memory manager 189 error = vmm_dup( &child_process->vmm , &parent_process->vmm ); 164 fork_dmsg("\n[INFO] %s : parent vmm duplicated in child process\n", __FUNCTION__ ); 165 166 // create child main thread descriptor in local cluster 167 error = thread_user_fork( parent_process , &child_thread ); 168 190 169 if( error ) 191 170 { 192 printk("ERROR in %s : cannot duplicate VMM\n", __FUNCTION__ ); 193 atomic_add ( &parent_process->childs_nr , -1 ); 194 process_destroy( child_process ); 195 return EAGAIN; 196 } 197 198 fork_debug("INFO : %s: parent vmm duplicated in child process\n", __FUNCTION__ ); 199 200 // create child main thread descriptor in local cluster TODO stack ??? 201 error = thread_user_fork( &child_thread , process , parent_thread ); 202 if( error ) 203 { 204 printk("ERROR in %s : cannot duplicate thread\n", __FUNCTION__ ); 205 atomic_add ( &parent_process->childs_nr , -1 ); 206 process_destroy( child_process ); 207 return EAGAIN; 171 printk("\n[ERROR] in %s : cannot duplicate thread\n", __FUNCTION__ ); 172 hal_atomic_add( &parent_process->children_nr , -1 ); 173 process_destroy( child_process ); 174 return ENOMEM; 208 175 } 209 176 210 177 // register child thread in child process, and get a TRDID 211 spinlock_lock( &child ->process->th_lock );212 error = process_register_thread( child ->process, child->thread , &child_trdid );213 spinlock_unlock( & process->th_lock );178 spinlock_lock( &child_process->th_lock ); 179 error = process_register_thread( child_process, child_thread , &child_trdid ); 180 spinlock_unlock( &child_process->th_lock ); 214 181 215 182 if( error ) 216 183 { 217 printk(" ERRORin %s : cannot register thread\n", __FUNCTION__ );218 atomic_add ( &parent_process->childs_nr , -1 );184 printk("\n[ERROR] in %s : cannot register thread\n", __FUNCTION__ ); 185 hal_atomic_add ( &parent_process->children_nr , -1 ); 219 186 thread_destroy( child_thread ); 220 187 process_destroy( child_process ); … … 226 193 227 194 // Update child thread descriptor 228 child_thread->core = process->core_tbl[child_core_lid];195 child_thread->core = &LOCAL_CLUSTER->core_tbl[child_core_lid]; 229 196 child_thread->process = child_process; 230 child_thread->trdid = chi d_trdid;231 232 fork_d ebug("INFO : %sinitialised child main thread\n", __FUNCTION__ );197 child_thread->trdid = child_trdid; 198 199 fork_dmsg("\n[INFO] %s : initialised child main thread\n", __FUNCTION__ ); 233 200 234 201 // register local child thread into local child process th_tbl[] 235 202 // we don't use the th_lock because there is no concurrent access 236 ltid_t ltid = LTID_FROM_TRDID( trdid );237 child_process->th_tbl[ltid] = XPTR( local_cxy , child_thread );238 child_process->th reads_nr = 1;203 ltid_t ltid = LTID_FROM_TRDID( child_trdid ); 204 child_process->th_tbl[ltid] = child_thread; 205 child_process->th_nr = 1; 239 206 240 207 // register child thread in scheduler 241 sched_register ( child_thread->core , child_thread );208 sched_register_thread( child_thread->core , child_thread ); 242 209 243 fork_d ebug("INFO : %sregistered main thread in scheduler\n", __FUNCTION__);210 fork_dmsg("\n[INFO] %s : registered main thread in scheduler\n", __FUNCTION__); 244 211 245 212 // update DQDT for the child thread 246 dqdt_ update_threads_number( 1 );247 248 fork_d ebug("INFO :%scompleted / parent pid = %x / child pid = %x / at cycle [%d]\n",213 dqdt_local_update_threads( 1 ); 214 215 fork_dmsg("\n[INFO] %s : completed / parent pid = %x / child pid = %x / at cycle [%d]\n", 249 216 __FUNCTION__, parent_process->pid, child_process->pid, hal_time_stamp() ); 250 217 -
trunk/kernel/syscalls/sys_getcwd.c
r1 r23 1 1 /* 2 * kern/sys_getcwd.c - get process current work directory2 * sys_getcwd.c - get process current work directory 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include <libk.h> 24 #include <kernel_config.h> 25 #include <hal_types.h> 26 #include <hal_uspace.h> 27 #include <hal_special.h> 28 #include <errno.h> 24 29 #include <vfs.h> 25 #include <sys-vfs.h> 26 #include <task.h> 27 #include <kmem.h> 28 #include <ppm.h> 30 #include <vmm.h> 31 #include <process.h> 29 32 #include <thread.h> 33 #include <printk.h> 30 34 31 /* TODO: user page need to be locked as long as its region*/35 /* TODO: user page(s) need to be locked [AG] */ 32 36 33 int sys_getcwd (char *buff, size_t size) 37 //////////////////////////////// 38 int sys_getcwd ( char * buf, 39 uint32_t nbytes ) 34 40 { 35 register struct thread_s *this; 36 register struct task_s *task; 37 register error_t err; 38 struct ku_obj ku_buff; 41 error_t error; 42 paddr_t paddr; 43 char kbuf[CONFIG_VFS_MAX_PATH_LENGTH]; 39 44 40 th is = current_thread;41 task = current_task;45 thread_t * this = CURRENT_THREAD; 46 process_t * process = this->process; 42 47 43 if((size < VFS_MAX_NAME_LENGTH) || (!buff)) 48 // check buffer size 49 if( nbytes < CONFIG_VFS_MAX_PATH_LENGTH ) 44 50 { 45 err = ERANGE; 46 goto SYS_GETCWD_ERROR; 51 printk("\n[ERROR] in %s : buffer too small\n", __FUNCTION__ ); 52 this->errno = ERANGE; 53 return -1; 47 54 } 48 55 49 if(vmm_check_address("usr cwd buffer", task, buff, size)) 56 // check buffer in user space 57 error = vmm_v2p_translate( false , buf , &paddr ); 58 59 if( error ) 50 60 { 51 err = EFAULT; 52 goto SYS_GETCWD_ERROR; 61 printk("\n[ERROR] in %s : user buffer unmapped\n", __FUNCTION__ ); 62 this->errno = EFAULT; 63 return -1; 53 64 } 54 65 55 KU_SZ_BUFF(ku_buff, buff, size); 66 // get reference process cluster and local pointer 67 xptr_t ref_xp = process->ref_xp; 68 cxy_t ref_cxy = GET_CXY( ref_xp ); 69 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 56 70 57 rwlock_rdlock(&task->cwd_lock); 71 // get CWD lock in read mode 72 remote_rwlock_rd_lock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 58 73 59 err = vfs_get_path(&task->vfs_cwd, &ku_buff); 74 // call relevant VFS function 75 error = vfs_get_path( XPTR( ref_cxy , &ref_ptr->vfs_cwd_xp ) , 76 kbuf , CONFIG_VFS_MAX_PATH_LENGTH ); 60 77 61 rwlock_unlock(&task->cwd_lock); 78 // release CWD lock 79 remote_rwlock_rd_unlock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 62 80 81 // copy kernel buffer to user space 82 hal_copy_to_uspace( buf , kbuf , CONFIG_VFS_MAX_PATH_LENGTH ); 63 83 64 SYS_GETCWD_ERROR: 65 this->info.errno = err; 66 return (int)buff; 67 } 84 hal_wbflush(); 85 86 return 0; 87 88 } // end sys_getcwd() -
trunk/kernel/syscalls/sys_getpid.c
r1 r23 2 2 * kern/sys_getpid.c - get process id 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include <task.h>24 24 #include <thread.h> 25 25 26 //////////////// 26 27 int sys_getpid() 27 28 { 28 return current_task->pid;29 return CURRENT_THREAD->process->pid; 29 30 } -
trunk/kernel/syscalls/sys_gettimeofday.c
r1 r23 1 1 /* 2 * sys_gettimeofday: get current time 3 * 4 * Copyright (c) 2015 UPMC Sorbonne Universites 2 * sys_gettimeofday.c - Get current time 5 3 * 6 * This file is part of ALMOS-kernel.4 * Author Alain Greiner (2016,2017) 7 5 * 8 * ALMOS-kernel is free software; you can redistribute it and/or modify it 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 9 11 * under the terms of the GNU General Public License as published by 10 12 * the Free Software Foundation; version 2.0 of the License. 11 13 * 12 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 13 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 16 18 * 17 19 * You should have received a copy of the GNU General Public License 18 * along with ALMOS- kernel; if not, write to the Free Software Foundation,20 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 19 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 22 */ 21 23 22 #include <cpu.h> 24 #include <hal_types.h> 25 #include <hal_uspace.h> 23 26 #include <thread.h> 27 #include <printk.h> 28 #include <errno.h> 29 #include <process.h> 30 #include <vmm.h> 31 #include <core.h> 24 32 #include <time.h> 25 33 26 int sys_gettimeofday(struct timeval *tv, struct timezone *tz) 34 /////////////////////////////////////////// 35 int sys_gettimeofday( struct timeval * tv, 36 struct timezone * tz ) 27 37 { 28 error_t err; 29 uint_t tm_ms, tm_us; 30 struct timeval time; 38 error_t error; 39 paddr_t paddr; 31 40 32 if((tv == NULL) || NOT_IN_USPACE(tv) || NOT_IN_USPACE(tv+sizeof(*tv))) 33 { 34 err = EINVAL; 35 goto fail_inval; 36 } 41 uint32_t tm_s; 42 uint32_t tm_us; 37 43 38 if(tz) 39 return ENOTSUPPORTED; 44 struct timeval k_tv; 40 45 41 cpu_get_time(current_cpu, &tm_ms, &tm_us); 42 time.tv_sec = tm_ms/1000; 43 time.tv_usec = ((tm_ms%1000)*1000)+tm_us; 46 thread_t * this = CURRENT_THREAD; 47 process_t * process = this->process; 44 48 45 //printk(INFO, "%s: [%d] (%u ms) sec %u, usec %u\n", __FUNCTION__, 46 //current_cpu->gid, tm_ms, (uint32_t)time.tv_sec, (uint32_t)time.tv_usec); 49 // check tz (non supported / must be null) 50 if( tz ) 51 { 52 printk("\n[ERROR] in %s for thread %x in process %x : tz argument must be NULL\n", 53 __FUNCTION__ , this->trdid , process->pid ); 54 this->errno = EINVAL; 55 return -1; 56 } 57 58 // check tv 59 error = vmm_v2p_translate( false , tv , &paddr ); 47 60 48 err = cpu_copy_to_uspace(tv, &time, sizeof(time)); 61 if( error ) 62 { 63 printk("\n[ERROR] in %s for thread %x in process %x : tv argument unmapped\n", 64 __FUNCTION__ , this->trdid , process->pid ); 65 this->errno = EINVAL; 66 return -1; 67 } 49 68 50 fail_inval: 51 current_thread->info.errno = err; 52 return err; 53 } 69 // get time from calling core descriptor 70 core_get_time( this->core , &tm_s , &tm_us ); 71 k_tv.tv_sec = tm_s; 72 k_tv.tv_usec = tm_us; 73 74 // copy values to user space 75 hal_copy_to_uspace( tv , &k_tv , sizeof(struct timeval) ); 76 77 hal_wbflush(); 78 79 return 0; 80 81 } // end sys_timeofday() -
trunk/kernel/syscalls/sys_lseek.c
r1 r23 21 21 */ 22 22 23 #include <types.h> 23 #include <kernel_config.h> 24 #include <hal_types.h> 25 #include <hal_uspace.h> 26 #include <errno.h> 24 27 #include <vfs.h> 28 #include <vmm.h> 25 29 #include <thread.h> 26 #include < sys-vfs.h>27 #include < task.h>30 #include <printk.h> 31 #include <process.h> 28 32 29 int sys_lseek (uint_t fd, off_t offset, int whence) 33 //////////////////////////////// 34 int sys_lseek (uint32_t file_id, 35 uint32_t offset, 36 uint32_t whence ) 30 37 { 31 error_t err = 0; 32 size_t new_offset; 33 struct thread_s *this; 34 struct task_s *task; 35 struct vfs_file_s *file; 38 error_t error; 39 xptr_t file_xp; 40 uint32_t new_offset; 36 41 37 file = NULL; 38 this = current_thread; 39 task = current_task; 42 thread_t * this = CURRENT_THREAD; 43 process_t * process = this->process; 44 45 // check file_id argument 46 if( file_id >= CONFIG_PROCESS_FILE_MAX_NR ) 47 { 48 printk("\n[ERROR] in %s : illegal file descriptor index = %d\n", 49 __FUNCTION__ , file_id ); 50 this->errno = EBADFD; 51 return -1; 52 } 53 54 // get extended pointer on remote file descriptor 55 file_xp = process_fd_get_xptr( process , file_id ); 56 57 if( file_xp == XPTR_NULL ) 58 { 59 printk("\n[ERROR] in %s : undefined file descriptor index = %d\n", 60 __FUNCTION__ , file_id ); 61 this->errno = EBADFD; 62 return -1; 63 } 40 64 41 65 /* FIXME: file may be closed in parallel 42 66 * of seek/read/write/mmap ..etc 43 67 * so file may be NULL or invalid */ 44 if((fd >= CONFIG_TASK_FILE_MAX_NR) || (task_fd_lookup(task, fd, &file))) 68 69 // call relevant VFS function 70 error = vfs_lseek( file_xp , offset , whence , &new_offset ); 71 72 if( error ) 45 73 { 46 this->info.errno = EBADFD; 47 return -1; 48 } 49 50 if((err = vfs_lseek(file, offset, whence, &new_offset))) 51 { 52 this->info.errno = (err < 0) ? -err : err; 74 printk("\n[ERROR] in %s : cannot seek file = %d\n", 75 __FUNCTION__ , file_id ); 76 this->errno = error; 53 77 return -1; 54 78 } -
trunk/kernel/syscalls/sys_mkdir.c
r1 r23 1 1 /* 2 * kern/sys_mkdir.c - createsnew directory2 * sys_mkdir.c - Create a new directory 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 24 #include <hal_types.h> 25 #include <hal_uspace.h> 23 26 #include <vfs.h> 24 #include <sys-vfs.h> 25 #include <task.h> 27 #include <vmm.h> 28 #include <errno.h> 29 #include <process.h> 26 30 #include <thread.h> 31 #include <printk.h> 27 32 28 int sys_mkdir (char *pathname, uint_t mode) 33 /////////////////////////////////// 34 int sys_mkdir( char * pathname, 35 uint32_t mode ) 29 36 { 30 register error_t err = 0; 31 struct task_s *task = current_task; 32 struct ku_obj ku_path; 37 error_t error; 38 paddr_t paddr; 39 uint32_t length; 40 char kbuf[CONFIG_VFS_MAX_PATH_LENGTH]; 33 41 34 KU_BUFF(ku_path, pathname);35 rwlock_rdlock(&task->cwd_lock);42 thread_t * this = CURRENT_THREAD; 43 process_t * process = this->process; 36 44 37 if((err = vfs_mkdir(&task->vfs_cwd, &ku_path, mode))) 45 // check pathname in user space 46 error = vmm_v2p_translate( false , pathname , &paddr ); 47 48 if( error ) 38 49 { 39 current_thread->info.errno = (err < 0) ? -err : err; 40 rwlock_unlock(&task->cwd_lock); 50 printk("\n[ERROR] in %s : user buffer unmapped for thread %x in process %x\n", 51 __FUNCTION__ , this->trdid , process->pid ); 52 this->errno = EINVAL; 53 return -1; 54 } 55 56 // check fd_array not full 57 if( process_fd_array_full() ) 58 { 59 printk("\n[ERROR] in %s : file descriptor array full for process %x\n", 60 __FUNCTION__ , process->pid ); 61 this->errno = ENFILE; 62 return -1; 63 } 64 65 // get pathname length 66 length = hal_strlen_from_uspace( pathname ); 67 68 if( length >= CONFIG_VFS_MAX_PATH_LENGTH ) 69 { 70 printk("\n[ERROR] in %s : pathname too long\n", __FUNCTION__ ); 71 this->errno = ENFILE; 72 return -1; 73 } 74 75 // get pathname copy in kernel space 76 hal_copy_from_uspace( kbuf, pathname, length ); 77 78 // get cluster and local pointer on reference process 79 xptr_t ref_xp = process->ref_xp; 80 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 81 cxy_t ref_cxy = GET_CXY( ref_xp ); 82 83 // get extended pointer on cwd inode 84 xptr_t cwd_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_cwd_xp ) ); 85 86 // get the cwd lock in read mode from reference process 87 remote_rwlock_rd_lock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 88 89 // call the relevant VFS function 90 error = vfs_mkdir( cwd_xp, 91 kbuf, 92 mode ); 93 94 // release the cwd lock 95 remote_rwlock_rd_unlock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 96 97 if( error ) 98 { 99 printk("\n[ERROR] in %s : cannot create directory %s\n", 100 __FUNCTION__ , kbuf ); 101 this->errno = error; 41 102 return -1; 42 103 } 43 104 44 rwlock_unlock(&task->cwd_lock);45 105 return 0; 46 106 } -
trunk/kernel/syscalls/sys_mkfifo.c
r1 r23 1 1 /* 2 * kern/sys_mkfifo.c - creates a FIFO named file2 * sys_mkfifo.c - creates a named FIFO file. 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include <kdmsg.h> 24 #include <hal_types.h> 25 #include <hal_uspace.h> 26 #include <printk.h> 24 27 #include <vfs.h> 25 #include <sys-vfs.h> 26 #include <task.h> 28 #include <process.h> 27 29 #include <thread.h> 28 30 29 int sys_mkfifo (char *pathname, uint_t mode) 31 //////////////////////////////////// 32 int sys_mkfifo ( char * pathname, 33 uint32_t mode ) 30 34 { 31 register error_t err = 0;32 struct task_s *task = current_task; 33 struct ku_obj ku_path;35 error_t error; 36 uint32_t length; // pathname length (bytes) 37 char kbuf[CONFIG_VFS_MAX_PATH_LENGTH]; 34 38 35 current_thread->info.errno = ENOSYS;36 return -1;39 thread_t * this = CURRENT_THREAD; 40 process_t * process = this->process; 37 41 38 KU_BUFF(ku_path, pathname); 39 rwlock_rdlock(&task->cwd_lock); 40 if((err = vfs_mkfifo(&task->vfs_cwd, &ku_path, mode))) 42 if( pathname == NULL ) 41 43 { 42 printk(INFO, "INFO: sys_mkfifo: Thread %x, CPU %d, Error Code %d\n", 43 current_thread,44 cpu_get_id(),45 err);44 printk("\n[ERROR] in %s : pathname is NULL\n", __FUNCTION__ ); 45 this->errno = EINVAL; 46 return -1; 47 } 46 48 47 rwlock_unlock(&task->cwd_lock); 49 // check fd_array not full 50 if( process_fd_array_full() ) 51 { 52 printk("\n[ERROR] in %s : file descriptor array full for process %x\n", 53 __FUNCTION__ , process->pid ); 54 this->errno = ENFILE; 55 return -1; 56 } 57 58 // get pathname length 59 length = hal_strlen_from_uspace( pathname ); 60 61 if( length >= CONFIG_VFS_MAX_PATH_LENGTH ) 62 { 63 printk("\n[ERROR] in %s : pathname too long\n", __FUNCTION__ ); 64 this->errno = ENFILE; 65 return -1; 66 } 67 68 // get pathname copy in kernel space 69 hal_copy_from_uspace( kbuf, pathname, length ); 70 71 // get cluster and local pointer on reference process 72 xptr_t ref_xp = process->ref_xp; 73 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 74 cxy_t ref_cxy = GET_CXY( ref_xp ); 75 76 // get extended pointer on cwd inode 77 xptr_t cwd_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_cwd_xp ) ); 78 79 // get the cwd lock in read mode from reference process 80 remote_rwlock_rd_lock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 81 82 // call the relevant VFS function 83 error = vfs_mkfifo( cwd_xp, 84 kbuf, 85 mode ); 86 87 // release the cwd lock 88 remote_rwlock_rd_unlock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 89 90 if( error ) 91 { 92 printk("\n[ERROR] in %s : cannot create named FIFO %s\n", 93 __FUNCTION__ , kbuf ); 94 this->errno = error; 48 95 return -1; 49 96 } 50 rwlock_unlock(&task->cwd_lock);51 97 52 98 return 0; 53 } 99 100 } // end sys_mkfifo() -
trunk/kernel/syscalls/sys_mmap.c
r1 r23 1 1 /* 2 * kern/sys_mmap.c - map files, memory or devices into process's 3 * virtual address space 2 * sys_mmap.c - map files, memory or devices into process virtual address space 4 3 * 5 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless6 * Copyright (c) 2011,2012 UPMC Sorbonne Universites4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016,2017) 7 6 * 8 * This file is part of ALMOS-kernel.7 * Copyright (c) UPMC Sorbonne Universites 9 8 * 10 * ALMOS-kernel is free software; you can redistribute it and/or modify it 9 * This file is part of ALMOS-MKH. 10 * 11 * ALMOS-MKH is free software; you can redistribute it and/or modify it 11 12 * under the terms of the GNU General Public License as published by 12 13 * the Free Software Foundation; version 2.0 of the License. 13 14 * 14 * ALMOS- kernelis distributed in the hope that it will be useful, but15 * ALMOS-MKH is distributed in the hope that it will be useful, but 15 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 18 19 * 19 20 * You should have received a copy of the GNU General Public License 20 * along with ALMOS- kernel; if not, write to the Free Software Foundation,21 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 21 22 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 23 */ 23 24 25 #include <hal_types.h> 24 26 #include <errno.h> 25 27 #include <thread.h> 28 #include <printk.h> 26 29 #include <vfs.h> 27 #include <sys-vfs.h>28 30 #include <process.h> 29 31 #include <vmm.h> 30 32 31 33 /////////////////////////////////// 32 int sys_mmap( mmap_attr_t * mattr )34 int sys_mmap( mmap_attr_t * attr ) 33 35 { 36 printk("\n[WARNING] function %s not implemented\n", __FUNCTION__ ); 37 return 0; 38 /* 34 39 error_t err; 35 40 uint_t count; … … 46 51 file = NULL; 47 52 48 if((err = cpu_copy_from_uspace(&attr, mattr, sizeof(mmap_attr_t))))53 if((err = cpu_copy_from_uspace(&attr, attr, sizeof(mmap_attr_t)))) 49 54 { 50 55 printk(INFO, "%s: failed, copying from uspace @%x\n", 51 56 __FUNCTION__, 52 mattr);57 attr); 53 58 54 59 this->info.errno = EFAULT; … … 82 87 else 83 88 { 84 / * FIXEME: possible concurent delete of file from another bugy thread closing it */89 // FIXME: possible concurent delete of file from another bugy thread closing it 85 90 if((attr.fd >= CONFIG_TASK_FILE_MAX_NR) || (process_fd_lookup(process, attr.fd, &file))) 86 91 { … … 145 150 146 151 return (int)VM_FAILED; 147 } 152 */ 153 } // end sys_mmap() -
trunk/kernel/syscalls/sys_mutex.c
r15 r23 1 1 /* 2 * kern/sys_rwlock.c - interface to access Read-Write locks service2 * sys_mutex.c - Access a POSIX mutex. 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include <types.h> 24 #include <hal_types.h> 25 #include <hal_special.h> 24 26 #include <errno.h> 25 27 #include <thread.h> 26 #include <kmem.h> 27 #include <task.h> 28 #include <printk.h> 28 29 #include <vmm.h> 29 #include < kmagics.h>30 #include <r wlock.h>30 #include <syscalls.h> 31 #include <remote_mutex.h> 31 32 32 33 33 static inline bool_t isBadLock(struct rwlock_s *rwlock) 34 { 35 return vmm_check_object(rwlock, struct rwlock_s, RWLOCK_ID); 36 } 34 ///////////////////////////////// 35 int sys_mutex( void * vaddr, 36 uint32_t operation, 37 uint32_t attr ) 38 { 39 error_t error; 40 paddr_t paddr; 37 41 38 int sys_rwlock(struct rwlock_s **rwlock, uint_t operation) 39 { 40 kmem_req_t req; 41 struct rwlock_s *irwlock; 42 error_t err; 43 44 err = vmm_check_address("usr rwlock ptr", 45 current_task, 46 rwlock, 47 sizeof(struct rwlock_s*)); 48 if(err) 49 goto SYS_RWLOCK_END; 42 thread_t * this = CURRENT_THREAD; 50 43 51 if((err = cpu_copy_from_uspace(&irwlock, rwlock, sizeof(struct rwlock_s *)))) 52 goto SYS_RWLOCK_END;53 54 switch(operation) 55 { 56 case RWLOCK_INIT: 57 req.type = KMEM_RWLOCK;58 req.size = sizeof(*irwlock);59 req.flags = AF_USER; 44 // check vaddr in user vspace 45 error = vmm_v2p_translate( false , vaddr , &paddr ); 46 if( error ) 47 { 48 printk("\n[ERROR] in %s : illegal virtual address = %x\n", 49 __FUNCTION__ , (intptr_t)vaddr ); 50 this->errno = error; 51 return -1; 52 } 60 53 61 if((irwlock = kmem_alloc(&req)) == NULL) 62 { 63 err = ENOMEM; 64 break; 54 // execute requested operation 55 switch( operation ) 56 { 57 //////////////// 58 case MUTEX_INIT: 59 { 60 if( attr != 0 ) 61 { 62 printk("\n[ERROR] in %s : mutex attributes non supported yet\n", 63 __FUNCTION__ ); 64 this->errno = error; 65 return -1; 66 } 67 68 error = remote_mutex_create( (intptr_t)vaddr ); 69 70 if( error ) 71 { 72 printk("\n[ERROR] in %s : cannot create mutex\n", 73 __FUNCTION__ ); 74 this->errno = error; 75 return -1; 76 } 77 break; 65 78 } 66 67 if((err = rwlock_init(irwlock))) 68 break; 69 70 if((err = cpu_copy_to_uspace(rwlock, &irwlock, sizeof(struct rwlock_s *)))) 71 { 72 req.ptr = irwlock; 73 kmem_free(&req); 74 } 75 break; 79 /////////////////// 80 case MUTEX_DESTROY: 81 { 82 xptr_t mutex_xp = remote_mutex_from_ident( (intptr_t)vaddr ); 76 83 77 case RWLOCK_WRLOCK: 78 if(isBadLock(irwlock)) 79 break; 80 81 return rwlock_wrlock(irwlock); 84 if( mutex_xp == XPTR_NULL ) // user error 85 { 86 printk("\n[ERROR] in %s : mutex %x not registered\n", 87 __FUNCTION__ , (intptr_t)vaddr ); 88 this->errno = EINVAL; 89 return -1; 90 } 91 else // success 92 { 93 remote_mutex_destroy( mutex_xp ); 94 } 95 break; 96 } 97 //////////////// 98 case MUTEX_LOCK: 99 { 100 xptr_t mutex_xp = remote_mutex_from_ident( (intptr_t)vaddr ); 82 101 83 case RWLOCK_RDLOCK: 84 if(isBadLock(irwlock)) 85 break; 86 87 return rwlock_rdlock(irwlock); 102 if( mutex_xp == XPTR_NULL ) // user error 103 { 104 printk("\n[ERROR] in %s : mutex %x not registered\n", 105 __FUNCTION__ , (intptr_t)vaddr ); 106 this->errno = EINVAL; 107 return -1; 108 } 109 else // success 110 { 111 remote_mutex_lock( mutex_xp ); 112 } 113 break; 114 } 115 ////////////////// 116 case MUTEX_UNLOCK: 117 { 118 xptr_t mutex_xp = remote_mutex_from_ident( (intptr_t)vaddr ); 88 119 89 case RWLOCK_TRYWRLOCK: 90 if(isBadLock(irwlock)) 91 break; 92 93 return rwlock_trywrlock(irwlock); 94 95 case RWLOCK_TRYRDLOCK: 96 if(isBadLock(irwlock)) 97 break; 98 99 return rwlock_tryrdlock(irwlock); 100 101 case RWLOCK_UNLOCK: 102 if(isBadLock(irwlock)) 103 break; 104 105 if((err = rwlock_unlock(irwlock))) 106 break; 107 108 case RWLOCK_DESTROY: 109 if(isBadLock(irwlock)) 110 break; 111 112 if((err = rwlock_destroy(irwlock))) 113 break; 114 115 req.type = KMEM_RWLOCK; 116 req.ptr = irwlock; 117 kmem_free(&req); 118 return 0; 119 120 default: 121 err = EINVAL; 120 if( mutex_xp == XPTR_NULL ) // user error 121 { 122 printk("\n[ERROR] in %s : mutex %x not registered\n", 123 __FUNCTION__ , (intptr_t)vaddr ); 124 this->errno = EINVAL; 125 return -1; 126 } 127 else // success 128 { 129 remote_mutex_unlock( mutex_xp ); 130 } 131 break; 132 } 133 //////// 134 default: 135 { 136 printk("\n[PANIC] in %s : illegal operation type\n", __FUNCTION__ ); 137 hal_core_sleep(); 138 } 122 139 } 123 140 124 SYS_RWLOCK_END: 125 current_thread->info.errno = err; 126 return err; 127 } 141 return 0; 128 142 129 KMEM_OBJATTR_INIT(rwlock_kmem_init) 130 { 131 attr->type = KMEM_RWLOCK; 132 attr->name = "KCM RWLOCK"; 133 attr->size = sizeof(struct rwlock_s); 134 attr->aligne = 0; 135 attr->min = CONFIG_RWLOCK_MIN; 136 attr->max = CONFIG_RWLOCK_MAX; 137 attr->ctor = NULL; 138 attr->dtor = NULL; 139 140 return 0; 141 } 143 } // end sys_mutex() 144 -
trunk/kernel/syscalls/sys_open.c
r1 r23 1 1 /* 2 * kern/sys_open.c - open a named file2 * sys_open.c - open a file. 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 24 #include <kernel_config.h> 25 #include <hal_types.h> 26 #include <hal_uspace.h> 23 27 #include <errno.h> 24 28 #include <thread.h> 29 #include <printk.h> 25 30 #include <vfs.h> 26 #include <sys-vfs.h>27 31 #include <process.h> 28 #include < spinlock.h>29 #include < cpu-trace.h>32 #include <remote_spinlock.h> 33 #include <remote_rwlock.h> 30 34 31 35 /////////////////////////////////// … … 34 38 uint32_t mode ) 35 39 { 36 CPU_HW_TRACE(sys_open);37 40 38 error_t err; 39 struct vfs_file_s file; 40 struct ku_obj ku_path; 41 thread_t * this = current_thread; 42 process_t * process = current_process; 43 uint32_t fd = (uint32_t)-1; 41 error_t error; 42 xptr_t file_xp; // extended pointer on vfs_file_t 43 uint32_t file_id; // file descriptor index 44 uint32_t length; // pathname length (bytes) 45 char kbuf[CONFIG_VFS_MAX_PATH_LENGTH]; 44 46 45 cpu_trace_write(current_cpu, sys_open); 47 thread_t * this = CURRENT_THREAD; 48 process_t * process = this->process; 46 49 47 if( p rocess_fd_aray_full( process ))50 if( pathname == NULL ) 48 51 { 49 this->info.errno = ENFILE; 50 CPU_HW_TRACE(sys_open); 51 return fd; 52 printk("\n[ERROR] in %s : pathname is NULL\n", __FUNCTION__ ); 53 this->errno = EINVAL; 54 return -1; 55 } 56 57 // check fd_array not full 58 if( process_fd_array_full() ) 59 { 60 printk("\n[ERROR] in %s : file descriptor array full for process %x\n", 61 __FUNCTION__ , process->pid ); 62 this->errno = ENFILE; 63 return -1; 52 64 } 53 65 54 if( VFS_IS( flags , VFS_O_DIRECTORY ) ) VFS_SET( flags , VFS_DIR ); 66 // get pathname length 67 length = hal_strlen_from_uspace( pathname ); 55 68 56 KU_BUFF( ku_path , pathname ); 69 if( length >= CONFIG_VFS_MAX_PATH_LENGTH ) 70 { 71 printk("\n[ERROR] in %s : pathname too long\n", __FUNCTION__ ); 72 this->errno = ENFILE; 73 return -1; 74 } 75 76 // get pathname copy in kernel space 77 hal_copy_from_uspace( kbuf, pathname, length ); 57 78 58 // get the cwd lock 59 rwlock_rdlock( &process->cwd_lock ); 79 // get cluster and local pointer on reference process 80 xptr_t ref_xp = process->ref_xp; 81 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 82 cxy_t ref_cxy = GET_CXY( ref_xp ); 83 84 // get extended pointer on cwd inode 85 xptr_t cwd_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_cwd_xp ) ); 60 86 61 err = vfs_open( &process->vfs_cwd , &ku_path , flags , mode , &file ); 62 if( err ) 87 // get the cwd lock in read mode from reference process 88 remote_rwlock_rd_lock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 89 90 // call the relevant VFS function 91 error = vfs_open( cwd_xp, 92 kbuf, 93 flags, 94 mode, 95 &file_xp, 96 &file_id ); 97 98 // release the cwd lock 99 remote_rwlock_rd_unlock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 100 101 if( error ) 63 102 { 64 this->info.errno = (err < 0 ) ? -err : err; 65 rwlock_unlock( &process->cwd_lock ); 66 CPU_HW_TRACE(sys_open); 67 return fd; 68 } 69 70 err = process_fd_set( process , &file , &fd ); 71 if( err ) 72 { 73 vfs_close(&file, NULL); 74 this->info.errno = err; 103 printk("\n[ERROR] in %s : cannot create file descriptor\n", __FUNCTION__ ); 104 this->errno = ENFILE; 105 return -1; 75 106 } 76 107 77 rwlock_unlock( &process->cwd_lock ); 78 CPU_HW_TRACE(sys_open); 79 return fd; 108 // update local fd_array 109 remote_spinlock_lock( XPTR( local_cxy , &process->fd_array.lock ) ); 110 process->fd_array.array[file_id] = file_xp; 111 remote_spinlock_unlock( XPTR( local_cxy , &process->fd_array.lock ) ); 112 113 return file_id; 80 114 } -
trunk/kernel/syscalls/sys_opendir.c
r1 r23 1 1 /* 2 * kern/sys_opendir.c - open a directory2 * sys_opendir.c - open a directory. 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 24 #include <hal_types.h> 23 25 #include <vfs.h> 24 #include <sys-vfs.h> 25 #include <process.h> 26 #include <thread.h> 27 #include <spinlock.h> 26 #include <syscalls.h> 28 27 29 28 /////////////////////////////////// 30 29 int sys_opendir ( char * pathname ) 31 30 { 32 error_t err; 33 struct vfs_file_s file; 34 struct ku_obj ku_path; 35 thread_t * this = current_thread; 36 process_t * process = current_process; 37 uint32_t fd = (uint32_t)-1; 38 uint32_t mode = 0; 39 40 if( process_fd_array_full( process ) ) 41 { 42 this->info.errno = ENFILE; 43 return fd; 44 } 31 uint32_t mode = 0; 32 uint32_t flags = O_DIR; 45 33 46 KU_BUFF(ku_path, pathname); 47 48 rwlock_rdlock( &process->cwd_lock ); 49 50 err = vfs_opendir( &process->vfs_cwd , &ku_path , mode , &file ); 51 if( err ) 52 { 53 this->info.errno = (err < 0 ) ? -err : err; 54 rwlock_unlock( &process->cwd_lock ); 55 return fd; 56 } 57 58 err = process_fd_set( process , &file , &fd); 59 if( err ) 60 { 61 vfs_close(&file, NULL); 62 this->info.errno = err; 63 } 64 65 rwlock_unlock( &process->cwd_lock ); 66 return fd; 34 return sys_open( pathname , flags , mode ); 67 35 } -
trunk/kernel/syscalls/sys_pipe.c
r1 r23 1 1 /* 2 * kern/sys_pipe.c - open a pipe communication channel2 * sys_pipe.c - open a pipe communication channel 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,1017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 24 #include <hal_types.h> 23 25 #include <vfs.h> 24 #include <sys-vfs.h> 25 #include <task.h> 26 #include <process.h> 26 27 #include <thread.h> 27 #include < spinlock.h>28 #include <printk.h> 28 29 29 int sys_pipe (uint_t *pipefd) 30 ////////////////////////////////////// 31 int sys_pipe ( uint32_t * file_fd[2] ) 30 32 { 31 current_thread->info.errno = ENOSYS; 32 return -1; 33 thread_t * this = CURRENT_THREAD; 34 35 printk("\n[ERROR] in %d : not implemented yet\n", __FUNCTION__ ); 36 this->errno = ENOSYS; 37 return -1; 38 33 39 } -
trunk/kernel/syscalls/sys_read.c
r1 r23 1 1 /* 2 * kern/sys_read.c - read bytes from an openedfile2 * sys_read.c - read bytes from a file 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 24 #include <kernel_config.h> 25 #include <hal_types.h> 26 #include <hal_uspace.h> 27 #include <hal_special.h> 23 28 #include <errno.h> 29 #include <vfs.h> 30 #include <vmm.h> 24 31 #include <thread.h> 25 #include <vfs.h> 26 #include <sys-vfs.h> 27 #include <task.h> 32 #include <printk.h> 33 #include <process.h> 28 34 29 int sys_read (uint_t fd, void *buf, size_t count) 35 /* TODO: user page(s) need to be locked [AG] */ 36 37 ///////////////////////////////// 38 int sys_read( uint32_t file_id, 39 void * buf, 40 uint32_t count ) 30 41 { 31 struct ku_obj kub; 32 ssize_t err; 33 struct thread_s *this; 34 struct task_s *task; 35 struct vfs_file_s *file; 42 error_t error; 43 paddr_t paddr; 44 char kbuf[CONFIG_VFS_KBUF_SIZE]; 36 45 37 file = NULL; 38 this = current_thread; 39 task = current_task; 46 xptr_t file_xp; // remote file extended pointer 47 uint32_t nbytes; // number of bytes in one iteration 40 48 41 if((fd >= CONFIG_TASK_FILE_MAX_NR) || (task_fd_lookup(task, fd, &file))) 49 thread_t * this = CURRENT_THREAD; 50 process_t * process = this->process; 51 52 // check file_id argument 53 if( file_id >= CONFIG_PROCESS_FILE_MAX_NR ) 42 54 { 43 this->info.errno = EBADFD; 55 printk("\n[ERROR] in %s : illegal file descriptor index = %d\n", 56 __FUNCTION__ , file_id ); 57 this->errno = EBADFD; 44 58 return -1; 45 59 } 46 60 47 KU_SLICE_BUFF(kub, buf, count); 48 if((err = vfs_read(file, &kub)) < 0) 61 // check user buffer in user space 62 error = vmm_v2p_translate( false , buf , &paddr ); 63 64 if ( error ) 65 { 66 printk("\n[ERROR] in %s : user buffer unmapped = %x\n", 67 __FUNCTION__ , (intptr_t)buf ); 68 this->errno = EINVAL; 69 return -1; 70 } 71 72 // get extended pointer on remote file descriptor 73 file_xp = process_fd_get_xptr( process , file_id ); 74 75 if( file_xp == XPTR_NULL ) 76 { 77 printk("\n[ERROR] in %s : undefined file descriptor index = %d\n", 78 __FUNCTION__ , file_id ); 79 this->errno = EBADFD; 80 return -1; 81 } 82 83 // get file descriptor cluster and local pointer 84 vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 85 cxy_t file_cxy = GET_CXY( file_xp ); 86 87 // check file readable 88 uint32_t attr = hal_remote_lw( XPTR( file_cxy , &file_ptr->attr ) ); 89 if( (attr & FD_ATTR_READ_ENABLE) == 0 ) 49 90 { 50 this->info.errno = -err; 51 printk(INFO, "INFO: sys_read: Error %d\n", this->info.errno); 91 printk("\n[ERROR] in %s : file %d not readable\n", 92 __FUNCTION__ , file_id ); 93 this->errno = EBADFD; 52 94 return -1; 53 95 } 54 96 55 return err; 56 } 97 // transfer at most CONFIG_VFS_KBUF_SIZE bytes per iteration 98 while( count ) 99 { 100 if( count <= CONFIG_VFS_KBUF_SIZE ) 101 { 102 nbytes = count; 103 count = 0; 104 } 105 else 106 { 107 nbytes = CONFIG_VFS_KBUF_SIZE; 108 count = count - CONFIG_VFS_KBUF_SIZE; 109 } 110 111 // transfer nbytes to kernel buffer 112 error = vfs_move( true, // read => (to_buffer = true) 113 file_xp , 114 kbuf , 115 nbytes ); 116 117 if( error ) 118 { 119 printk("\n[ERROR] in %s cannot read data from file %d\n", 120 __FUNCTION__ , file_id ); 121 this->errno = error; 122 return -1; 123 } 124 125 // copy kernel buffer to user space 126 hal_copy_to_uspace( buf , kbuf , nbytes ); 127 } 128 129 hal_wbflush(); 130 131 return 0; 132 133 } // end sys_read() -
trunk/kernel/syscalls/sys_readdir.c
r1 r23 1 1 /* 2 * sys_read.c: read entries from an opened directory 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 2 * sys_readdir.c - Read one entry from an open directory. 6 3 * 7 * This file is part of ALMOS-kernel.4 * Author Alain Greiner (2016,2017) 8 5 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 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 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 24 #include <kernel_config.h> 25 #include <hal_types.h> 26 #include <hal_uspace.h> 27 #include <errno.h> 28 #include <thread.h> 29 #include <printk.h> 23 30 #include <vfs.h> 24 #include <sys-vfs.h> 25 #include <task.h> 26 #include <thread.h> 31 #include <process.h> 32 #include <syscalls.h> 27 33 28 /* FIXEME: reading dirent from user without any protection */ 34 ////////////////////////////////////////// 35 int sys_readdir ( uint32_t file_id, 36 vfs_dirent_t * dirent ) 37 { 38 error_t error; 39 paddr_t paddr; 40 xptr_t file_xp; // extended pointer on searched directory file descriptor 41 vfs_dirent_t k_dirent; // kernel copy of dirent 29 42 30 int sys_readdir (uint_t fd, struct vfs_usp_dirent_s *dirent) 31 { 32 error_t err; 33 struct ku_obj dir; 34 struct task_s *task; 35 struct thread_s *this; 36 struct vfs_file_s *file; 37 38 file = NULL; 39 task = current_task; 40 this = current_thread; 43 thread_t * this = CURRENT_THREAD; 44 process_t * process = this->process; 41 45 42 if((dirent == NULL) || 43 (fd >= CONFIG_TASK_FILE_MAX_NR) || 44 (task_fd_lookup(task, fd, &file))) 46 // check file_id argument 47 if( file_id >= CONFIG_PROCESS_FILE_MAX_NR ) 45 48 { 46 this->info.errno = EBADFD; 49 printk("\n[ERROR] in %s : illegal file descriptor index\n", __FUNCTION__ ); 50 this->errno = EBADFD; 47 51 return -1; 48 52 } 49 53 50 KU_OBJ(dir, dirent); 51 if((err = vfs_readdir(file, &dir))) 54 // check dirent structure in user space 55 error = vmm_v2p_translate( false , dirent , &paddr ); 56 57 if ( error ) 58 { 59 printk("\n[ERROR] in %s : user buffer for dirent unmapped = %x\n", 60 __FUNCTION__ , (intptr_t)dirent ); 61 this->errno = EFAULT; 62 return -1; 63 } 64 65 // get extended pointer on remote file descriptor 66 file_xp = process_fd_get_xptr( process , file_id ); 67 68 if( file_xp == XPTR_NULL ) 69 { 70 printk("\n[ERROR] in %s : undefined file descriptor index = %d\n", 71 __FUNCTION__ , file_id ); 72 this->errno = EBADFD; 73 return -1; 74 } 75 76 // call the relevant VFS function 77 error = vfs_readdir( file_xp , &k_dirent ); 78 79 if( error ) 52 80 { 53 this->info.errno = (err < 0) ? -err : err; 81 printk("\n[ERROR] in %s : cannot access directory %d\n", 82 __FUNCTION__ , file_id ); 83 this->errno = error; 54 84 return -1; 55 85 } 56 86 87 // copy dirent to user space 88 hal_copy_to_uspace( dirent , &k_dirent , sizeof(vfs_dirent_t) ); 89 57 90 return 0; 58 } 91 92 } // end sys_readdir() -
trunk/kernel/syscalls/sys_rmdir.c
r1 r23 1 1 /* 2 * sys_rmdir: remove a directory 2 * sys_rmdir.c - Remove a directory from file system. 3 * 4 * Author Alain Greiner (2016,2017) 3 5 * 4 6 * Copyright (c) 2015 UPMC Sorbonne Universites 5 7 * 6 * This file is part of ALMOS- kernel.8 * This file is part of ALMOS-MKH. 7 9 * 8 * ALMOS- kernelis free software; you can redistribute it and/or modify it10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 9 11 * under the terms of the GNU General Public License as published by 10 12 * the Free Software Foundation; version 2.0 of the License. 11 13 * 12 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 13 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 16 18 * 17 19 * You should have received a copy of the GNU General Public License 18 * along with ALMOS- kernel; if not, write to the Free Software Foundation,20 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 19 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 22 */ 21 23 22 #include <cpu.h> 24 #include <hal_types.h> 25 #include <hal_uspace.h> 26 #include <printk.h> 27 #include <errno.h> 23 28 #include <vfs.h> 24 #include < sys-vfs.h>29 #include <vmm.h> 25 30 #include <thread.h> 26 #include < task.h>31 #include <process.h> 27 32 33 //////////////////////////////// 34 int sys_rmdir( char * pathname ) 35 { 36 error_t error; 37 paddr_t paddr; 38 uint32_t length; 39 char kbuf[CONFIG_VFS_MAX_PATH_LENGTH]; 40 41 thread_t * this = CURRENT_THREAD; 42 process_t * process = this->process; 28 43 29 int sys_rmdir (char *pathname) 30 { 31 register struct thread_s *this; 32 register struct task_s *task; 33 struct ku_obj ku_path; 34 error_t err = 0; 35 36 this = current_thread; 37 task = current_task; 44 // check pathname in user space 45 error = vmm_v2p_translate( false , pathname , &paddr ); 38 46 39 if( !pathname)47 if( error ) 40 48 { 41 this->info.errno = EINVAL; 49 printk("\n[ERROR] in %s : user buffer unmapped for thread %x in process %x\n", 50 __FUNCTION__ , this->trdid , process->pid ); 51 this->errno = EINVAL; 52 return -1; 53 } 54 55 // get pathname length 56 length = hal_strlen_from_uspace( pathname ); 57 58 if( length >= CONFIG_VFS_MAX_PATH_LENGTH ) 59 { 60 printk("\n[ERROR] in %s : pathname too long\n", __FUNCTION__ ); 61 this->errno = ENFILE; 62 return -1; 63 } 64 65 // get pathname copy in kernel space 66 hal_copy_from_uspace( kbuf, pathname, length ); 67 68 // get cluster and local pointer on reference process 69 xptr_t ref_xp = process->ref_xp; 70 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 71 cxy_t ref_cxy = GET_CXY( ref_xp ); 72 73 // get extended pointer on cwd inode 74 xptr_t cwd_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_cwd_xp ) ); 75 76 // get the cwd lock in read mode from reference process 77 remote_rwlock_rd_lock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 78 79 // call the relevant VFS function 80 error = vfs_rmdir( cwd_xp, 81 kbuf ); 82 83 // release the cwd lock 84 remote_rwlock_rd_unlock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 85 86 if( error ) 87 { 88 printk("\n[ERROR] in %s : cannot remove directory %s\n", 89 __FUNCTION__ , kbuf ); 90 this->errno = error; 42 91 return -1; 43 92 } 93 94 return 0; 44 95 45 KU_BUFF(ku_path, pathname); 46 rwlock_wrlock(&task->cwd_lock); 47 48 if((err = vfs_rmdir(¤t_task->vfs_cwd, &ku_path))) 49 { 50 current_thread->info.errno = (err < 0) ? -err : err; 51 rwlock_unlock(&task->cwd_lock); 52 return -1; 53 } 54 55 rwlock_unlock(&task->cwd_lock); 56 return 0; 57 } 96 } // end sys_rmdir() -
trunk/kernel/syscalls/sys_sem.c
r1 r23 2 2 * sys_sem.c - Acces a POSIX unamed semaphore. 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Authors Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 24 #include <hal_types.h> 24 #include <hal_uspace. 25 #include <hal_uspace.h> 26 #include <errno.h> 27 #include <thread.h> 28 #include <printk.h> 29 #include <vmm.h> 25 30 #include <remote_sem.h> 31 #include <syscalls.h> 26 32 27 33 ////////////////////////////////// … … 31 37 { 32 38 uint32_t data; 33 error_t error; 39 paddr_t paddr; 40 error_t error; 34 41 35 thread_t * this = CURRENT_THREAD; 36 process_t * process = CURRENT_PROCESS; 42 thread_t * this = CURRENT_THREAD; 37 43 38 44 // check vaddr in user vspace 39 error = vmm_ check_address( process , vaddr , sizeof(unsigned long));40 if( error ) 45 error = vmm_v2p_translate( false , vaddr , &paddr ); 46 if( error ) 41 47 { 48 printk("\n[ERROR] in %s : illegal semaphore virtual address = %x\n", 49 __FUNCTION__ , (intptr_t)vaddr ); 42 50 this->errno = error; 43 51 return -1; … … 45 53 46 54 // check value in user vspace 47 error = vmm_check_address( process , value , sizeof(int*));48 if( error ) 55 error = vmm_v2p_translate( false , value , &paddr ); 56 if( error ) 49 57 { 58 printk("\n[ERROR] in %s : illegal argument virtual address = %x\n", 59 __FUNCTION__ , (intptr_t)value ); 50 60 this->errno = error; 51 61 return -1; … … 62 72 63 73 // call init function 64 error = remote_sem_ init( (intptr_t)vaddr , data );74 error = remote_sem_create( (intptr_t)vaddr , data ); 65 75 66 76 if ( error ) 67 77 { 78 printk("\n[ERROR] in %s : cannot create semaphore = %x\n", 79 __FUNCTION__ , (intptr_t)value ); 68 80 this->errno = error; 69 81 return -1; … … 79 91 if( sem_xp == XPTR_NULL ) // user error 80 92 { 93 printk("\n[ERROR] in %s : semaphore %x not registered\n", 94 __FUNCTION__ , (intptr_t)value ); 81 95 this->errno = EINVAL; 82 96 return -1; … … 100 114 if( sem_xp == XPTR_NULL ) // user error 101 115 { 116 printk("\n[ERROR] in %s : semaphore %x not registered\n", 117 __FUNCTION__ , (intptr_t)value ); 102 118 this->errno = EINVAL; 103 119 return -1; … … 118 134 if( sem_xp == XPTR_NULL ) // user error 119 135 { 136 printk("\n[ERROR] in %s : semaphore %x not registered\n", 137 __FUNCTION__ , (intptr_t)value ); 120 138 this->errno = EINVAL; 121 139 return -1; … … 136 154 if( sem_xp == XPTR_NULL ) // user error 137 155 { 156 printk("\n[ERROR] in %s : semaphore %x not registered\n", 157 __FUNCTION__ , (intptr_t)value ); 138 158 this->errno = EINVAL; 139 159 return -1; … … 149 169 default: // undefined operation 150 170 { 151 this->errno = EINVAL;152 return -1;171 printk("\n[PANIC] in %s : illegal operation type\n", __FUNCTION__ ); 172 hal_core_sleep(); 153 173 } 154 174 } -
trunk/kernel/syscalls/sys_signal.c
r1 r23 1 1 /* 2 * sys_s em.c: interface to access signal service2 * sys_signal.c - associate a specific signal handler to a given signal. 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012,2013,2014,2015 UPMC Sorbonne Universites 4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016,2017) 6 * 7 * Copyright (c) UPMC Sorbonne Universites 6 8 * 7 9 * This file is part of ALMOS-kernel. … … 21 23 */ 22 24 23 #include < types.h>25 #include <hal_types.h> 24 26 #include <errno.h> 25 27 #include <thread.h> 26 #include <task.h> 27 #include <pid.h> 28 #include <printk.h> 28 29 #include <signal.h> 29 30 31 ////////////////////////////////// 32 int sys_signal( uint32_t sig_id, 33 void * handler ) 34 { 35 thread_t * this = CURRENT_THREAD; 30 36 31 int sys_signal(uint_t sig, sa_handler_t *handler) 32 { 33 register struct thread_s *this; 34 int retval; 35 36 this = current_thread; 37 38 if((sig == 0) || (sig >= SIG_NR) || (sig == SIGKILL) || (sig == SIGSTOP)) 37 if((sig_id == 0) || (sig_id >= SIG_NR) || (sig_id == SIGKILL) || (sig_id == SIGSTOP)) 39 38 { 40 this->info.errno = EINVAL; 41 return SIG_ERROR; 39 printk("\n[ERROR] in %s : illega signal index = %d\n", __FUNCTION__ , sig_id ); 40 this->errno = EINVAL; 41 return -1; 42 42 } 43 43 44 retval = (int) this->task->sig_mgr.sigactions[sig];45 this-> task->sig_mgr.sigactions[sig] = handler;44 // register handler in signal manager for the calling process 45 this->process->sig_mgr.sigactions[sig_id] = handler; 46 46 47 sig_dmsg(1, "%s: handler @%x has been registred for signal %d\n", 48 __FUNCTION__, 49 handler, 50 sig); 47 signal_dmsg("\n[INFO] %s : handler @%x has been registred for signal %d\n", 48 __FUNCTION__ , handler , sig_id ); 51 49 52 return retval;53 }54 55 56 int sys_sigreturn_setup(void *sigreturn_func)57 {58 struct thread_s *this;59 60 this = current_thread;61 this->info.attr.sigreturn_func = sigreturn_func;62 cpu_context_set_sigreturn(&this->pws, sigreturn_func);63 50 return 0; 64 51 } 65 52 66 67 int sys_kill(pid_t pid, uint_t sig)68 {69 cid_t location;70 error_t err;71 72 if((sig == 0) || (sig >= SIG_NR))73 {74 err = EINVAL;75 }76 else77 {78 if ( PID_GET_CLUSTER(pid) == current_cid )79 location = current_cid;80 else81 location = task_whereis(pid);82 83 err = signal_rise(pid, location, sig);84 85 /* No error, return 0 */86 if (!err)87 return 0;88 }89 90 /* Error. Set errno and return */91 current_thread->info.errno = err;92 return -1;93 } -
trunk/kernel/syscalls/sys_stat.c
r1 r23 1 1 /* 2 * kern/sys_stat.c - stats a file or directory2 * sys_stat.c - Return statistics on a file or directory. 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 24 #include <hal_types.h> 25 #include <hal_uspace.h> 26 #include <hal_special.h> 23 27 #include <errno.h> 24 28 #include <thread.h> 29 #include <printk.h> 25 30 #include <vfs.h> 26 #include <sys-vfs.h> 27 #include <task.h> 28 #include <spinlock.h> 29 #include <cpu-trace.h> 31 #include <vmm.h> 32 #include <process.h> 30 33 34 ////////////////////////////////////////// 35 int sys_stat( uint32_t file_id, 36 struct vfs_stat_s * stat ) 37 { 38 error_t error; 39 paddr_t paddr; 40 struct vfs_stat_s k_stat; 41 xptr_t file_xp; 42 43 thread_t * this = CURRENT_THREAD; 44 process_t * process = this->process; 31 45 32 int sys_stat(char *pathname, struct vfs_stat_s *buff, int fd) 33 { 34 CPU_HW_TRACE(sys_stat); 35 struct thread_s *this; 36 register error_t err = 0; 37 struct vfs_file_s *file; 38 struct ku_obj ku_path; 39 struct task_s *task; 46 // check stat structure in user space 47 error = vmm_v2p_translate( false , stat , &paddr ); 40 48 41 file = NULL; 42 this = current_thread; 43 task = current_task; 49 if( error ) 50 { 51 printk("\n[ERROR] in %s : stat structure unmapped for thread %x in process %x\n", 52 __FUNCTION__ , this->trdid , process->pid ); 53 this->errno = EINVAL; 54 return -1; 55 } 44 56 45 if((buff == NULL) || ((pathname == NULL) && (fd == -1))) 57 // get extended pointer on remote file descriptor 58 file_xp = process_fd_get_xptr( process , file_id ); 59 60 if( file_xp == XPTR_NULL ) 61 { 62 printk("\n[ERROR] in %s : undefined file descriptor for thread %x in process %x\n", 63 __FUNCTION__ , this->trdid , process->pid ); 64 this->errno = EBADFD; 65 return -1; 66 } 67 68 // call the relevant VFS function 69 error = vfs_stat( file_xp, 70 &k_stat ); 71 if( error ) 46 72 { 47 this->info.errno = EINVAL; 48 CPU_HW_TRACE(sys_stat); 73 printk("\n[ERROR] in %s : cannot access file %d for thread %x in process %x\n", 74 __FUNCTION__ , file_id , this->trdid , process->pid ); 75 this->errno = error; 49 76 return -1; 50 77 } 78 79 // copy stat to user space 80 hal_copy_to_uspace( stat , &k_stat , sizeof(struct vfs_stat_s) ); 51 81 52 if(NOT_IN_USPACE((uint_t)buff)) 53 { 54 this->info.errno = EPERM; 55 CPU_HW_TRACE(sys_stat); 56 return -1; 57 } 82 hal_wbflush(); 58 83 59 if(pathname == NULL)60 {61 if((fd >= CONFIG_TASK_FILE_MAX_NR) || (task_fd_lookup(task, fd, &file)))62 {63 CPU_HW_TRACE(sys_stat);64 return EBADFD;65 }66 67 err = vfs_stat(&task->vfs_cwd, NULL, buff, file);68 }69 else70 {71 KU_BUFF(ku_path, pathname);72 rwlock_rdlock(&task->cwd_lock);73 err = vfs_stat(&task->vfs_cwd, &ku_path, buff, NULL);74 rwlock_unlock(&task->cwd_lock);75 }76 77 this->info.errno = err;78 CPU_HW_TRACE(sys_stat);79 84 return 0; 80 } 85 86 } // end sys_stat() 87 -
trunk/kernel/syscalls/sys_thread_create.c
r14 r23 2 2 * sys_thread_create.c - creates a new user thread 3 3 * 4 * Author Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Mohamed lamine Karaoui (2015) 6 * Alain Greiner (2016) 4 * Author Alain Greiner (2016,2017) 7 5 * 8 6 * Copyright (c) UPMC Sorbonne Universites … … 26 24 #include <kernel_config.h> 27 25 #include <hal_types.h> 26 #include <hal_uspace.h> 28 27 #include <printk.h> 29 28 #include <errno.h> … … 38 37 #include <spinlock.h> 39 38 #include <dqdt.h> 39 #include <rpc.h> 40 40 41 41 … … 46 46 pthread_attr_t * user_attr, // [in] argument 47 47 void * start_func, // [in] argument 48 void * start_arg s )// [in] argument48 void * start_arg ) // [in] argument 49 49 { 50 pthread_attr_t attr;// copy of pthread attributes in kernel space50 pthread_attr_t k_attr; // copy of pthread attributes in kernel space 51 51 thread_t * parent; // pointer on thread executing the pthread_create 52 xptr_t xp_parent; // extended pointer on created thread53 thread_t * child ;// pointer on created child thread54 xptr_t xp_child; // extended pointer on created thread52 xptr_t parent_xp; // extended pointer on created thread 53 thread_t * child_ptr; // pointer on created child thread 54 xptr_t child_xp; // extended pointer on created thread 55 55 trdid_t trdid; // created thread identifier 56 56 process_t * process; // pointer on local process descriptor 57 paddr_t paddr; // unused, required by vmm_v2p_translate() 57 58 error_t error; 58 59 … … 64 65 // get parent thead pointer, extended pointer, and process pointer 65 66 parent = CURRENT_THREAD; 66 xp_parent= XPTR( local_cxy , parent );67 parent_xp = XPTR( local_cxy , parent ); 67 68 process = parent->process; 68 69 69 // check user_attr & start_func arguments 70 if( user_attr == NULL ) 70 // check user_attr in user space 71 error = vmm_v2p_translate( false , user_attr , &paddr ); 72 73 if( error ) 71 74 { 72 printk("\n[ERROR] in %s : user_attr is NULL\n", __FUNCTION__ ); 73 return EINVAL; 74 } 75 if( start_func== NULL ) 76 { 77 printk("\n[ERROR] in %s : start_func is NULL\n", __FUNCTION__ ); 78 return EINVAL; 75 printk("\n[ERROR] in %s : user_attr unmapped\n", __FUNCTION__ ); 76 parent->errno = EINVAL; 77 return -1; 79 78 } 80 79 81 // copy user_attr structure to kernel space 82 hal_copy_from_uspace( &attr , user_attr , sizeof(pthread_attr_t) ); 80 // check start_func in user space 81 error = vmm_v2p_translate( false , start_func , &paddr ); 82 83 if( error ) 84 { 85 printk("\n[ERROR] in %s : start_func unmapped\n", __FUNCTION__ ); 86 parent->errno = EINVAL; 87 return -1; 88 } 89 90 // check start_arg in user space 91 if( start_arg != NULL ) error = vmm_v2p_translate( false , start_arg , &paddr ); 92 93 if( error ) 94 { 95 printk("\n[ERROR] in %s : start_arg unmapped\n", __FUNCTION__ ); 96 parent->errno = EINVAL; 97 return -1; 98 } 99 100 // copy user_attr structure from user space to kernel space 101 hal_copy_from_uspace( &k_attr , user_attr , sizeof(pthread_attr_t) ); 83 102 84 103 // check/set "cxy" attribute 85 if( attr.flags & PT_FLAG_CLUSTER_DEFINED )104 if( k_attr.attributes & PT_ATTR_CLUSTER_DEFINED ) 86 105 { 87 if( cluster_is_undefined( attr.cxy ) )106 if( cluster_is_undefined( k_attr.cxy ) ) 88 107 { 89 printk("\n[ERROR] in %s : illegal target cluster = %x\n", 90 __FUNCTION__ , attr.cxy ); 91 return = EINVAL; 108 printk("\n[ERROR] in %s : illegal target cluster attribute = %x\n", 109 __FUNCTION__ , k_attr.cxy ); 110 parent->errno = EINVAL; 111 return -1; 92 112 } 93 113 } 94 114 else 95 115 { 96 attr.cxy = dqdt_get_cluster_for_process();116 k_attr.cxy = dqdt_get_cluster_for_process(); 97 117 } 98 118 99 // set "pid", "start_func" & "start_args" attributes100 attr.pid = process->pid;101 attr.start_func = start_func;102 attr.start_args = start_args;103 104 119 // create the thread, using a RPC if required 105 // this returns "error", "child", and "xp_child" 106 if( attr.cxy == local_cxy ) // target cluster is local 120 // this returns "error", "child", and "child_xp" 121 122 if( k_attr.cxy == local_cxy ) // target cluster is local 107 123 { 108 // allocate a stack from local VMM109 vseg_t * vseg = vmm_create_vseg( process,110 0,111 0,112 VSEG_TYPE_STACK,113 local_cxy );114 if( vseg == NULL )115 {116 printk("\n[ERROR] in %s for : cannot create stack vseg\n", __FUNCTION__ );117 return = EINVAL;118 }119 124 120 125 // create thread in local cluster 121 error = thread_user_create( &child, 122 &attr, 123 vseg->min, 124 vseg->max - vseg->min ); 126 error = thread_user_create( process->pid, 127 start_func, 128 start_arg, 129 &k_attr, 130 &child_ptr ); 125 131 126 xp_child = XPTR( local_cxy , thread);132 child_xp = XPTR( local_cxy , child_ptr ); 127 133 } 128 134 else // target cluster is remote 129 135 { 130 rpc_thread_user_create( attr.cxy , &attr , &error , &xp_child ); 131 child = (thread_t *)GET_PTR( xp_child ); 136 rpc_thread_user_create_client( k_attr.cxy, 137 process->pid, 138 start_func, 139 start_arg, 140 &k_attr, 141 &child_xp, 142 &error ); 143 144 child_ptr = (thread_t *)GET_PTR( child_xp ); 132 145 } 133 146 … … 140 153 141 154 // returns trdid to user space 142 trdid = hal_remote_lw( XPTR( attr.cxy , &child->trdid ) );155 trdid = hal_remote_lw( XPTR( k_attr.cxy , &child_ptr->trdid ) ); 143 156 hal_copy_to_uspace( new_thread , &trdid , sizeof(pthread_t) ); 144 157 145 158 // register new-thread in parent-thread children list if required 146 if( attr.flags & PT_FLAG_DETACH == 0 ) thread_child_parent_link( xp_parent , xp_child ); 159 if( (k_attr.attributes & PT_ATTR_DETACH) == 0 ) 160 thread_child_parent_link( parent_xp , child_xp ); 147 161 148 162 tm_end = hal_time_stamp(); … … 150 164 thread_dmsg("\n[INFO] %s created thread %x for process %x in cluster %x\n" 151 165 " start_cycle = %d / end_cycle = %d\n", 152 trdid , process->pid , attr.cxy , tm_start , tm_end );166 trdid , process->pid , k_attr.cxy , tm_start , tm_end ); 153 167 return 0; 154 168 -
trunk/kernel/syscalls/sys_thread_detach.c
r1 r23 1 1 /* 2 * kern/sys_thread_detach.c - detach a joinable thread2 * sys_thread_detach.c - detach a joinable thread 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 4 * Authors Alain Greiner (2016,2017) 5 * 5 6 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 6 7 * 7 * This file is part of ALMOS- kernel.8 * This file is part of ALMOS-MKH. 8 9 * 9 * ALMOS- kernelis free software; you can redistribute it and/or modify it10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include <list.h> 24 #include <hal_types.h> 25 #include <hal_remote.h> 26 #include <hal_special.h> 24 27 #include <thread.h> 25 #include <kmem.h>26 #include <kmagics.h>27 28 #include <errno.h> 28 #include <task.h> 29 #include <spinlock.h> 29 #include <printk.h> 30 30 31 int sys_thread_detach (pthread_t tid) 31 ////////////////////////////////////// 32 int sys_thread_detach( trdid_t trdid ) 32 33 { 33 register struct task_s *task; 34 struct thread_s *target_th; 35 uint_t state; 36 error_t err; 34 xptr_t target_xp; 35 thread_t * target_ptr; 36 cxy_t target_cxy; 37 ltid_t target_ltid; 38 uint32_t flags; 37 39 38 task = current_task; 40 thread_t * this = CURRENT_THREAD; 41 process_t * process = this->process; 39 42 40 if(tid > task->max_order) 43 // get target thread ltid and cxy 44 target_ltid = LTID_FROM_TRDID( trdid ); 45 target_cxy = CXY_FROM_TRDID( trdid ); 46 47 // check trdid argument 48 if( (target_ltid >= CONFIG_THREAD_MAX_PER_CLUSTER) || cluster_is_undefined( target_cxy ) ) 41 49 { 42 err = EINVAL; 43 goto fail_arg; 44 } 45 46 spinlock_lock(&task->th_lock); 47 48 target_th = task->th_tbl[tid]; 49 50 if((target_th == NULL) || 51 (target_th->signature != THREAD_ID) || 52 (target_th->info.attr.key != tid)) 53 { 54 err = ESRCH; 55 goto fail_srch; 56 } 57 58 if(!(thread_isJoinable(target_th))) 59 { 60 err = EINVAL; 61 goto fail_not_joinable; 62 } 63 64 err = 0; 65 66 spinlock_lock(&target_th->lock); 67 68 thread_clear_joinable(target_th); 69 70 if((target_th->info.join == NULL) && 71 !(state = wait_queue_isEmpty(&target_th->info.wait_queue))) 72 { 73 wakeup_one(&target_th->info.wait_queue, WAIT_ANY); 50 printk("\n[ERROR] in %s : illegal trdid argument\n", __FUNCTION__ ); 51 this->errno = EINVAL; 52 return -1; 74 53 } 75 54 76 spinlock_unlock(&target_th->lock); 77 78 fail_not_joinable: 79 fail_srch: 80 spinlock_unlock(&task->lock); 55 // get extended pointer on target thread 56 target_xp = thread_get_xptr( process->pid , trdid ); 81 57 82 fail_arg: 83 current_thread->info.errno = err; 84 return err; 85 } 58 if( target_xp == XPTR_NULL ) 59 { 60 printk("\n[ERROR] in %s : target thread not found\n", __FUNCTION__ ); 61 this->errno = ESRCH; 62 return -1; 63 } 64 65 // get local pointer on target thread 66 target_ptr = (thread_t *)GET_PTR( target_xp ); 67 68 // get target thread flags 69 flags = hal_remote_lw( XPTR( target_cxy , &target_ptr->flags ) ); 70 71 // check target thread joinable 72 if( flags & THREAD_FLAG_DETACHED ) 73 { 74 printk("\n[ERROR] in %s : target thread not joinable\n", __FUNCTION__ ); 75 this->errno = EINVAL; 76 return -1; 77 } 78 79 // atomically set the thread DETACHED flag 80 hal_remote_atomic_or( XPTR( target_cxy , &target_ptr->flags ) , THREAD_FLAG_DETACHED ); 81 82 return 0; 83 84 } // end sys_thread_detach() -
trunk/kernel/syscalls/sys_thread_exit.c
r16 r23 1 1 /* 2 * kern/sys_thread_exit.c - terminates the execution of current thread2 * sys_thread_exit.c - terminates the execution of current thread 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016,2017) 6 6 * 7 * This file is part of ALMOS-kernel.7 * Copyright (c) UPMC Sorbonne Universites 8 8 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 9 * This file is part of ALMOS-MKH. 10 * 11 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 12 * under the terms of the GNU General Public License as published by 11 13 * the Free Software Foundation; version 2.0 of the License. 12 14 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but15 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 19 * 18 20 * 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,21 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 22 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 23 */ 22 24 23 #include <list.h> 25 #include <hal_types.h> 26 #include <hal_irqmask.h> 24 27 #include <thread.h> 28 #include <core.h> 25 29 #include <scheduler.h> 26 #include <wait_queue.h> 27 #include <cluster.h> 28 #include <dqdt.h> 29 #include <process.h> 30 #include <printk.h> 30 31 31 /////////////////////////////////////// 32 int sys_thread_exit ( void * exit_val ) 32 33 //////////////////////////////////////// 34 int sys_thread_exit( void * exit_value ) 33 35 { 34 36 thread_t * this = CURRENT_THREAD; 35 37 core_t * core = this->core; 36 bool_t isEmpty;37 bool_t isReleased;38 38 uint32_t irq_state; 39 39 40 // update DQDT TODO must be done by thread destroy 41 if(this->process->pid != 1) dqdt_local_update_threads( -1 );40 // register the exit_value in thread descriptor 41 this->exit_value = exit_value; 42 42 43 spinlock_lock( &this->lock ); 43 // we enter the join loop to wait the join 44 // only if thread is joinable 45 if( (this->flags & THREAD_FLAG_DETACHED) == 0 ) 46 { 47 while( 1 ) 48 { 49 // take the lock protecting the flags 50 remote_spinlock_lock( XPTR( local_cxy, &this->flags_lock ) ); 44 51 45 if(!(thread_isJoinable(this))) 46 { 47 goto exit_dead; 52 // check the JOIN flag 53 if( this->flags & THREAD_FLAG_JOIN ) // parent made a join 54 { 55 // unblock the parent thread 56 thread_unblock( this->parent , THREAD_BLOCKED_JOIN ); 57 58 // release the lock protecting the flags 59 remote_spinlock_unlock( XPTR( local_cxy, &this->flags_lock ) ); 60 61 // exit while 62 break; 63 } 64 else // no join done by parent thread 65 { 66 // set the EXIT flag 67 this->flags |= THREAD_FLAG_EXIT; 68 69 // block this thread 70 thread_block( this , THREAD_BLOCKED_EXIT ); 71 72 // release the lock protecting the flags 73 remote_spinlock_unlock( XPTR( local_cxy, &this->flags_lock ) ); 74 75 // deschedule 76 sched_yield(); 77 } 78 } 48 79 } 49 50 // Check if there's a thread waiting the end of calling thread51 isEmpty = wait_queue_isEmpty(&this->info.wait_queue);52 53 if(isEmpty)54 {55 this->info.exit_value = exit_val;56 wait_on(&this->info.wait_queue, WAIT_ANY);57 spinlock_unlock_nosched(&this->lock);58 sched_sleep(this);59 }60 else61 {62 this->info.join->info.exit_value = exit_val;63 wakeup_one(&this->info.wait_queue, WAIT_ANY);64 spinlock_unlock_nosched(&this->lock);65 }66 67 exit_dead:68 69 isReleased = false;70 80 71 81 // Release FPU if required 72 82 hal_disable_irq( &irq_state ); 73 if(core->fpu_owner == this) 74 { 75 core->fpu_owner = NULL; 76 isReleased = true; 77 } 83 if( core->fpu_owner == this ) core->fpu_owner = NULL; 78 84 hal_restore_irq( irq_state ); 79 85 80 if(isReleased) 81 { 82 thread_dmsg(1, "INFO: Thread %x has released FPU on CPU %d\n", 83 this, 84 current_cpu->gid); 85 } 86 // suicide 87 thread_kill( this ); 88 return 0; 86 89 87 sched_exit(this); 88 89 PANIC ("Thread %x, CPU %d must never return", this, current_cpu->gid); 90 return -1; /* Fake return ! */ 91 } 90 } // end sys_thread_exit() -
trunk/kernel/syscalls/sys_thread_join.c
r1 r23 1 1 /* 2 * kern/sys_thread_join.c - passive wait on the end of a given thread2 * sys_thread_join.c - passive wait on the end of a given thread. 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 4 * Authors Alain Greiner (2016,2017) 5 * 5 6 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 6 7 * 7 * This file is part of ALMOS- kernel.8 * This file is part of ALMOS-MKH. 8 9 * 9 * ALMOS- kernelis free software; you can redistribute it and/or modify it10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include <list.h> 24 #include <hal_types.h> 25 #include <hal_remote.h> 26 #include <hal_special.h> 24 27 #include <thread.h> 28 #include <vmm.h> 25 29 #include <scheduler.h> 26 #include <kmem.h>27 30 #include <errno.h> 28 #include < task.h>29 #include < spinlock.h>31 #include <printk.h> 32 #include <remote_spinlock.h> 30 33 31 int sys_thread_join (pthread_t tid, void **thread_return) 34 /////////////////////////////////////// 35 int sys_thread_join ( trdid_t trdid, 36 void ** exit_value ) 32 37 { 33 register struct task_s *task; 34 register struct thread_s *this; 35 register struct thread_s *target_th; 36 register uint_t state = 0; 37 void *retval; 38 int err; 38 xptr_t target_xp; 39 thread_t * target_ptr; 40 cxy_t target_cxy; 41 ltid_t target_ltid; 42 uint32_t flags; // target thread flags 43 intptr_t value; // value returned by target thread 44 paddr_t paddr; // required for vmm_v2p_translate() 39 45 40 this = current_thread; 41 task = this->task; 42 retval = 0; 46 thread_t * this = CURRENT_THREAD; 47 process_t * process = this->process; 43 48 44 if((tid > task->max_order) || 45 ((thread_return != NULL) && 46 (NOT_IN_USPACE((uint_t)thread_return + sizeof(void*))))) 49 // get target thread ltid and cxy 50 target_ltid = LTID_FROM_TRDID( trdid ); 51 target_cxy = CXY_FROM_TRDID( trdid ); 52 53 // check trdid argument 54 if( (target_ltid >= CONFIG_THREAD_MAX_PER_CLUSTER) || cluster_is_undefined( target_cxy ) ) 47 55 { 48 err = EINVAL; 49 goto fail_arg; 56 printk("\n[ERROR] in %s : illegal trdid argument\n", __FUNCTION__ ); 57 this->errno = EINVAL; 58 return -1; 50 59 } 51 60 52 /* try to write to userland address */ 53 if( thread_return)61 // check exit_value argument 62 if( (exit_value != NULL) && (vmm_v2p_translate( false , exit_value , &paddr ) != 0 ) ) 54 63 { 55 if((err = cpu_copy_to_uspace(thread_return, &retval, sizeof(void *)))) 56 goto fail_uspace_ret; 64 printk("\n[ERROR] in %s : illegal exit_value argument\n", __FUNCTION__ ); 65 this->errno = EINVAL; 66 return -1; 57 67 } 58 68 59 spinlock_lock(&task->th_lock); 60 target_th = task->th_tbl[tid]; 69 // check target thread != this thread 70 if( this->trdid == trdid ) 71 { 72 printk("\n[ERROR] in %s : this thread == target thread\n", __FUNCTION__ ); 73 this->errno = EDEADLK; 74 return -1; 75 } 61 76 62 if((target_th == NULL) || 63 (target_th->signature != THREAD_ID) || 64 (target_th->info.attr.key != tid)) 65 { 66 err = ESRCH; 67 goto fail_srch; 68 } 77 // get extended pointer on target thread 78 target_xp = thread_get_xptr( process->pid , trdid ); 69 79 70 if(target_th == this) 71 { 72 err = EDEADLK; 73 goto fail_deadlock; 74 } 80 if( target_xp == XPTR_NULL ) 81 { 82 printk("\n[ERROR] in %s : target thread not found\n", __FUNCTION__ ); 83 this->errno = ESRCH; 84 return -1; 85 } 75 86 76 if(!(thread_isJoinable(target_th))) 77 { 78 err = EINVAL; 79 goto fail_joinable; 80 } 81 82 spinlock_lock(&target_th->lock); 83 84 if(target_th->info.join != NULL) 85 { 86 spinlock_unlock(&target_th->lock); 87 err = EINVAL; 88 goto fail_joined; 89 } 87 // get cluster and local pointer on target thread 88 target_ptr = (thread_t *)GET_PTR( target_xp ); 90 89 91 // Get the exit code of the target thread 92 if ((state=wait_queue_isEmpty(&target_th->info.wait_queue))) 93 { 94 target_th->info.join = this; 95 wait_on(&target_th->info.wait_queue, WAIT_ANY); 96 spinlock_unlock(&target_th->lock); 97 spinlock_unlock_nosched(&task->th_lock); 98 sched_sleep(this); 99 retval = this->info.exit_value; 100 } 101 else 102 { 103 retval = target_th->info.exit_value; 104 wakeup_one(&target_th->info.wait_queue, WAIT_ANY); 105 spinlock_unlock(&target_th->lock); 106 spinlock_unlock(&task->th_lock); 107 } 90 // check target thread joinable 91 flags = hal_remote_lw( XPTR( target_cxy , &target_ptr->flags ) ); 92 if( flags & THREAD_FLAG_DETACHED ) 93 { 94 printk("\n[ERROR] in %s : target thread not joinable\n", __FUNCTION__ ); 95 this->errno = EINVAL; 96 return -1; 97 } 108 98 109 /* Probably will not fail */ 110 if(thread_return)111 112 if((err = cpu_copy_to_uspace(thread_return, &retval, sizeof(void *)))) 113 goto fail_uspace;114 99 // check kernel stack overflow 100 if( target_ptr->signature != THREAD_SIGNATURE ) 101 { 102 printk("\n[PANIC] in %s : kernel stack overflow\n", __FUNCTION__ ); 103 hal_core_sleep(); 104 } 115 105 116 return 0; 106 // wait target thread exit 107 while( 1 ) 108 { 109 // take the target thread lock protecting flags 110 remote_spinlock_lock( XPTR( target_cxy , &target_ptr->flags_lock ) ); 117 111 118 fail_joined: 119 fail_joinable: 120 fail_deadlock: 121 fail_srch: 122 spinlock_unlock(&task->th_lock); 112 // get the remote thread flags 113 flags = hal_remote_lw( XPTR( target_cxy , &target_ptr->flags ) ); 123 114 124 fail_uspace: 125 fail_uspace_ret: 126 fail_arg: 127 this->info.errno = err; 128 return err; 129 } 115 // check the EXIT flag 116 if( flags & THREAD_FLAG_EXIT ) // target made an exit 117 { 118 // unblock the target thread 119 thread_unblock( target_xp , THREAD_BLOCKED_EXIT ); 120 121 // release the target thread lock protecting flags 122 remote_spinlock_unlock( XPTR( target_cxy , &target_ptr->flags_lock ) ); 123 124 // exit while 125 break; 126 } 127 else // no exit done by target thread 128 { 129 // set the JOIN flag in target thread 130 hal_remote_atomic_or( XPTR( target_xp , &target_ptr->flags ) , 131 THREAD_BLOCKED_JOIN ); 132 133 // block this thread 134 thread_block( this , THREAD_BLOCKED_JOIN ); 135 136 // release the target thread lock protecting flags 137 remote_spinlock_unlock( XPTR( target_cxy , &target_ptr->flags_lock ) ); 138 139 // deschedule 140 sched_yield(); 141 } 142 } 143 144 // return exit_value from target thread descriptor 145 value = (intptr_t)hal_remote_lpt( XPTR( target_cxy , &target_ptr->exit_value ) ); 146 *exit_value = (void *)value; 147 return 0; 148 149 } // end sys_thread_join() -
trunk/kernel/syscalls/sys_thread_sleep.c
r1 r23 1 1 /* 2 * kern/sys_thread_sleep.c - puts the currentthread in sleep state2 * sys_thread_sleep.c - put the calling thread in sleep state 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 24 #include <hal_special.h> 23 25 #include <scheduler.h> 24 26 #include <thread.h> 25 #include < task.h>27 #include <printk.h> 26 28 29 ////////////////////// 27 30 int sys_thread_sleep() 28 31 { 29 struct thread_s *this;32 thread_t * this = CURRENT_THREAD; 30 33 31 this = current_thread; 34 thread_dmsg("\n[INFO] %s : thread %x in process %x goes to sleep at cycle %d\n", 35 __FUNCTION__ , this->trdid , this->process->pid , hal_time_stamp() ); 32 36 33 if(this->info.isTraced == true) 34 { 35 printk(INFO, "%s: cpu %d, pid %d, tid %d, asked to go sleep [%d]\n", 36 __FUNCTION__, 37 cpu_get_id(), 38 this->task->pid, 39 this->info.order, 40 cpu_time_stamp()); 41 } 37 thread_block( CURRENT_THREAD , THREAD_BLOCKED_GLOBAL ); 38 sched_yield(); 42 39 43 thread_set_cap_wakeup(this); 44 sched_sleep(this); 45 46 if(this->info.isTraced == true) 47 { 48 printk(INFO, "%s: cpu %d, pid %d, tid %d, resuming [%d]\n", 49 __FUNCTION__, 50 cpu_get_id(), 51 this->task->pid, 52 this->info.order, 53 cpu_time_stamp()); 54 } 40 thread_dmsg("\n[INFO] %s : thread %x in process %x resume at cycle\n", 41 __FUNCTION__ , this->trdid , this->process->pid , hal_time_stamp() ); 55 42 56 43 return 0; 57 } 44 } // end sys_thread_sleep() -
trunk/kernel/syscalls/sys_thread_wakeup.c
r1 r23 1 1 /* 2 * kern/sys_thread_wakeup.c - wakeup all indicated threads2 * sys_thread_wakeup.c - wakeup all indicated threads 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 24 #include <hal_types.h> 25 #include <thread.h> 26 #include <printk.h> 27 #include <process.h> 23 28 #include <errno.h> 24 #include <kmagics.h>25 #include <cpu.h>26 #include <kdmsg.h>27 #include <cluster.h>28 #include <task.h>29 #include <scheduler.h>30 #include <thread.h>31 29 32 /* 33 * FIXME: define spinlock_rdlock() so all locking on task->th_lock 34 * becoms rdlock but on join/detach/destroy 35 */ 36 int sys_thread_wakeup(pthread_t tid, pthread_t *tid_tbl, uint_t count) 30 ////////////////////////////////////// 31 int sys_thread_wakeup( trdid_t trdid ) 37 32 { 38 struct task_s *task; 39 struct thread_s *this; 40 struct thread_s *target; 41 pthread_t tbl[100]; 42 void *listner; 43 uint_t event; 44 sint_t i; 45 error_t err; 33 thread_t * this = CURRENT_THREAD; 34 process_t * process = this->process; 46 35 47 this = current_thread; 48 task = this->task;49 i = -1;36 // get target thread ltid and cxy 37 ltid_t target_ltid = LTID_FROM_TRDID( trdid ); 38 cxy_t target_cxy = CXY_FROM_TRDID( trdid ); 50 39 51 if(tid_tbl != NULL) 40 // check trdid argument 41 if( (target_ltid >= CONFIG_THREAD_MAX_PER_CLUSTER) || cluster_is_undefined( target_cxy ) ) 52 42 { 53 if((NOT_IN_USPACE((uint_t)tid_tbl + (count*sizeof(pthread_t)))) || 54 (count == 0) || (count > 100)) 55 { 56 err = -1; 57 goto fail_tid_tbl; 58 } 59 60 if((err = cpu_copy_from_uspace(&tbl[0], tid_tbl, sizeof(pthread_t*) * count))) 61 goto fail_usapce; 62 63 if(tbl[0] != tid) 64 { 65 err = -2; 66 goto fail_first_tid; 67 } 68 } 69 else 70 { 71 count = 1; 72 tbl[0] = tid; 43 printk("\n[ERROR] in %s : illegal trdid argument\n", __FUNCTION__ ); 44 this->errno = EINVAL; 45 return -1; 73 46 } 74 47 75 for(i = 0; i < count; i++) 76 { 77 tid = tbl[i]; 48 // get extended pointer on target thread 49 xptr_t thread_xp = thread_get_xptr( process->pid , trdid ); 78 50 79 if(tid > task->max_order) 80 { 81 err = -3; 82 goto fail_tid; 83 } 51 if( thread_xp == XPTR_NULL ) 52 { 53 printk("\n[ERROR] in %s : cannot find thread %x in process %x/n", 54 __FUNCTION__ , trdid , CURRENT_THREAD->process->pid ); 55 CURRENT_THREAD->errno = EINVAL; 56 return -1; 57 } 84 58 85 target = task->th_tbl[tid]; 86 87 if((target == NULL) || (target->signature != THREAD_ID)) 88 { 89 err = -4; 90 goto fail_target; 91 } 59 // unblock target thread 60 thread_unblock( thread_xp , THREAD_BLOCKED_GLOBAL ); 92 61 93 listner = sched_get_listner(target, SCHED_OP_UWAKEUP); 94 event = sched_event_make(target,SCHED_OP_UWAKEUP); 95 96 if(this->info.isTraced == true) 97 { 98 printk(INFO,"%s: tid %d --> tid %d [%d][%d]\n", 99 __FUNCTION__, 100 this->info.order, 101 tid, 102 cpu_time_stamp(), 103 i); 104 } 105 106 sched_event_send(listner,event); 107 cpu_wbflush(); 108 } 109 110 return 0; 111 112 fail_target: 113 fail_tid: 114 fail_first_tid: 115 fail_usapce: 116 fail_tid_tbl: 117 118 printk(INFO, "%s: cpu %d, pid %d, tid %x, i %d, count %d, ttid %x, request has failed with err %d [%d]\n", 119 __FUNCTION__, 120 cpu_get_id(), 121 task->pid, 122 this, 123 i, 124 count, 125 tid, 126 err, 127 cpu_time_stamp()); 128 129 this->info.errno = EINVAL; 130 return -1; 131 } 62 return 0; 63 } // end sys_thread_wakeup() -
trunk/kernel/syscalls/sys_thread_yield.c
r1 r23 1 1 /* 2 * kern/sys_thread_yield.c - calls the scheduler to yield current CPU2 * sys_thread_yield.c - calls the scheduler to yield 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016,2017) 6 * 5 7 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 6 8 * 7 * This file is part of ALMOS- kernel.9 * This file is part of ALMOS-MKH. 8 10 * 9 * ALMOS- kernelis free software; you can redistribute it and/or modify it11 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 12 * under the terms of the GNU General Public License as published by 11 13 * the Free Software Foundation; version 2.0 of the License. 12 14 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but15 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 19 * 18 20 * 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,21 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 22 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 23 */ 22 24 23 #include <thread.h>24 25 #include <scheduler.h> 25 26 26 27 int sys_thread_yield() 27 28 { 28 return sched_yield(current_thread); 29 sched_yield(); 30 return 0; 29 31 } -
trunk/kernel/syscalls/sys_trace.c
r15 r23 1 1 /* 2 * kern/sys_ps.c - show kernel active processes and threads2 * sys_trace.c - show kernel active processes and threads 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012,2013,2014,2015 UPMC Sorbonne Universites 4 * Author Alain Greiner (c) (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include < types.h>24 #include < task.h>25 #include <p id.h>24 #include <hal_types.h> 25 #include <hal_special.h> 26 #include <printk.h> 26 27 #include <thread.h> 27 #include <vmm.h>28 28 #include <errno.h> 29 #include <utils.h> 30 #include <rpc.h> 31 #include <cluster.h> 29 #include <syscalls.h> 32 30 33 extern error_t ps_func(void *param); 31 ////////////////////////////////// 32 int sys_trace( uint32_t operation, 33 pid_t pid, 34 uint32_t trdid ) 35 { 36 // get extended pointer on target thread 37 xptr_t thread_xp = thread_get_xptr( pid , trdid ); 34 38 35 /* TODO: add remote support. */ 36 static error_t sys_ps_check_thread(pid_t pid, uint_t tid, struct thread_s **th_ptr) 37 { 38 struct task_s *task; 39 struct thread_s *thread; 40 cid_t location; 39 if( thread_xp == XPTR_NULL ) 40 { 41 printk("\n[ERROR] in %s : undefined thread for PID = %x / TRDID = %x\n", 42 __FUNCTION__ , pid , trdid ); 43 CURRENT_THREAD->errno = EINVAL; 44 return -1; 45 } 41 46 42 if(pid == PID_MIN_LOCAL) 43 return EINVAL; 47 if( operation == TRACE_OFF ) 48 { 49 // desactivate thread trace TODO 44 50 45 location = task_whereis(pid); 51 printk("\n[INFO] %s : trace OFF for thread %x in process %x\n", 52 __FUNCTION__ , trdid , pid ); 53 } 54 else if( operation == TRACE_ON ) 55 { 56 // activate thread trace TODO 57 58 printk("\n[INFO] %s : trace ON for thread %x in process %x\n", 59 __FUNCTION__ , trdid , pid ); 60 } 61 else 62 { 63 printk("\n[ERROR] in %s : undefined operation\n", __FUNCTION__ ); 64 CURRENT_THREAD->errno = EINVAL; 65 return -1; 66 } 46 67 47 tasks_manager_lock(); 48 if ( location == current_cid ) 49 { 50 task = task_lookup(pid)->task; 68 hal_wbflush(); 51 69 52 if((task == NULL) || (tid > task->max_order)) 53 return EINVAL; 70 return 0; 54 71 55 thread = task->th_tbl[tid]; 56 57 if((thread == NULL) || 58 (thread->signature != THREAD_ID) || 59 (thread->info.attr.key != tid)) 60 { 61 return ESRCH; 62 } 63 64 *th_ptr = thread; 65 return 0; 66 } 67 else 68 { 69 printk(WARNING, "%s: cluster %u can't execute this function on remote task (pid %u on cluster %u)\n", \ 70 __FUNCTION__, current_cid, pid, location); 71 return ENOSYS; 72 } 73 tasks_manager_unlock(); 74 } 75 76 /*TODO: use RPC_ARG_NULL instead of sending a useless variable. 77 * It's not urgent, it's a minor change. 78 */ 79 RPC_DECLARE(__ps_func, \ 80 RPC_RET( RPC_RET_PTR(error_t, err) ), \ 81 RPC_ARG( RPC_ARG_PTR(error_t, foo) ) \ 82 ) 83 { 84 *err = ps_func(NULL); 85 } 86 87 int sys_ps(uint_t cmd, pid_t pid, uint_t tid) 88 { 89 cid_t next; 90 error_t err; 91 struct thread_s *thread; 92 struct kernel_iter_s *kernel_iter; 93 94 err = 0; 95 96 switch(cmd) 97 { 98 case TASK_PS_TRACE_OFF: 99 err = sys_ps_check_thread(pid, tid, &thread); 100 if(err) goto fail_trace_off; 101 thread->info.isTraced = false; 102 cpu_wbflush(); 103 printk(INFO,"INFO: pid %d, tid %x, tracing is turned [OFF]\n", pid, tid); 104 break; 105 106 case TASK_PS_TRACE_ON: 107 err = sys_ps_check_thread(pid, tid, &thread); 108 if(err) goto fail_trace_on; 109 thread->info.isTraced = true; 110 cpu_wbflush(); 111 printk(INFO,"INFO: pid %d, tid %x, tracing is turned [ON]\n", pid, tid); 112 break; 113 114 case TASK_PS_SHOW: 115 kernel_foreach_backward(kernel_iter, next) 116 { 117 RCPC( next, RPC_PRIO_PS, __ps_func, 118 RPC_RECV( RPC_RECV_OBJ(err) ), 119 RPC_SEND( RPC_SEND_OBJ(err) ) 120 ); 121 } 122 break; 123 } 124 125 fail_trace_on: 126 fail_trace_off: 127 current_thread->info.errno = err; 128 return err; 129 } 72 } // end sys_trace() -
trunk/kernel/syscalls/sys_undefined.c
r15 r23 1 1 /* 2 * kern/sys_dma_memcpy.c - exported DMA access to user process2 * sys_undefined.c - function executed for an undefined syscall. 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 24 #include <errno.h> 24 #include <types.h>25 #include <event.h>26 #include <chdev.h>27 #include <driver.h>28 #include <kmem.h>29 #include <kdmsg.h>30 #include <dma.h>31 #include <kcm.h>32 25 #include <thread.h> 33 #include < cluster.h>34 #include < kcm.h>26 #include <process.h> 27 #include <printk.h> 35 28 29 /////////////////// 30 int sys_undefined() 31 { 32 thread_t * this = CURRENT_THREAD; 33 process_t * process = this->process; 36 34 37 KMEM_OBJATTR_INIT(dma_kmem_request_init) 38 { 39 attr->type = KMEM_DMA_REQUEST; 40 attr->name = "KCM Dev-Request"; 41 attr->size = sizeof(dev_request_t); 42 attr->aligne = 0; 43 attr->min = CONFIG_DMA_RQ_KCM_MIN; 44 attr->max = CONFIG_DMA_RQ_KCM_MAX; 45 attr->ctor = NULL; 46 attr->dtor = NULL; 47 48 return 0; 35 printk("\n[ERROR] in %s : undefined syscall calle by thread %x in process %x\n", 36 __FUNCTION__ , this->trdid , process->pid ); 37 this->errno = EINVAL; 38 return -1; 49 39 } 50 51 static EVENT_HANDLER(dma_async_request_event)52 {53 kmem_req_t req;54 error_t err;55 56 if((err=event_get_error(event)) != 0)57 printk(ERROR, "ERROR: dma_async_request_event: DMA transfare is not well completed, remaining %d\n", err);58 59 req.type = KMEM_DMA_REQUEST;60 req.ptr = event_get_argument(event);61 62 assert(req.ptr != NULL && "Corrupted argument, expected the address of request");63 64 kmem_free(&req);65 return 0;66 }67 68 static inline error_t dma_do_async_request(void *dst, void *src, size_t size)69 {70 kmem_req_t req;71 dev_request_t *rq;72 73 req.type = KMEM_DMA_REQUEST;74 req.size = sizeof(*rq);75 req.flags = AF_KERNEL;76 77 if((rq = kmem_alloc(&req)) == NULL)78 return ENOMEM;79 80 memset(rq, 0, sizeof(*rq));81 82 rq->src = src;83 rq->dst = dst;84 rq->count = size;85 rq->flags = DEV_RQ_NOBLOCK;86 87 event_set_priority(&rq->event, E_FUNC);88 event_set_handler(&rq->event, &dma_async_request_event);89 event_set_argument(&rq->event, rq);90 91 return __sys_dma->op.dev.write(__sys_dma, rq);92 }93 94 static inline error_t dma_do_sync_request(void *dst, void *src, size_t size)95 {96 dev_request_t rq;97 98 rq.src = src;99 rq.dst = dst;100 rq.count = size;101 rq.flags = 0;102 103 return __sys_dma->op.dev.write(__sys_dma, &rq);104 }105 106 107 error_t dma_memcpy(void *dst, void *src, size_t size, uint_t isAsync)108 {109 if(isAsync == DMA_ASYNC)110 return dma_do_async_request(dst, src, size);111 else112 return dma_do_sync_request(dst, src, size);113 }114 115 116 int sys_dma_memcpy(void *src, void *dst, size_t size)117 {118 return dma_do_sync_request(dst, src, size);119 } -
trunk/kernel/syscalls/sys_unlink.c
r1 r23 1 1 /* 2 * kern/sys_unlink.c - file unlink2 * sys_unlink.c - file unlink 3 3 * 4 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless … … 21 21 */ 22 22 23 #include <hal_types.h> 24 #include <hal_uspace.h> 23 25 #include <vfs.h> 24 #include <sys-vfs.h> 25 #include <task.h> 26 #include <process.h> 26 27 #include <thread.h> 28 #include <printk.h> 27 29 28 int sys_unlink (char *pathname) 30 ////////////////////////////////// 31 int sys_unlink ( char * pathname ) 29 32 { 30 error_t err = 0; 31 struct ku_obj ku_path; 33 error_t error; 34 uint32_t length; 35 char kbuf[CONFIG_VFS_MAX_PATH_LENGTH]; 32 36 33 KU_BUFF(ku_path, pathname); 34 if((err = vfs_unlink(¤t_task->vfs_cwd, &ku_path))) 37 thread_t * this = CURRENT_THREAD; 38 process_t * process = this->process; 39 40 // get pathname length 41 length = hal_strlen_from_uspace( pathname ); 42 43 if( length >= CONFIG_VFS_MAX_PATH_LENGTH ) 44 { 45 printk("\n[ERROR] in %s : pathname too long\n", __FUNCTION__ ); 46 this->errno = ENFILE; 47 return -1; 48 } 49 50 // get pathname copy in kernel space 51 hal_copy_from_uspace( kbuf, pathname, length ); 52 53 // get cluster and local pointer on reference process 54 xptr_t ref_xp = process->ref_xp; 55 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 56 cxy_t ref_cxy = GET_CXY( ref_xp ); 57 58 // get the cwd lock in read mode from reference process 59 remote_rwlock_rd_lock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 60 61 // get extended pointer on cwd inode 62 xptr_t cwd_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_cwd_xp ) ); 63 64 // call relevant VFS function 65 error = vfs_unlink( cwd_xp , kbuf ); 66 67 // release the cwd lock in reference process 68 remote_rwlock_rd_unlock( XPTR( ref_cxy , &ref_ptr->cwd_lock ) ); 69 70 if( error ) 35 71 { 36 current_thread->info.errno = (err < 0) ? -err : err; 37 return -1; 72 printk("\n[ERROR] in %s : cannot unlink file/dir %s\n", 73 __FUNCTION__ , pathname ); 74 this->errno = ENFILE; 75 return -1; 38 76 } 39 77 40 78 return 0; 41 } 79 80 } // end sys_unlink() -
trunk/kernel/syscalls/sys_utls.c
r1 r23 2 2 * kern/sys_utls.c - User Thread Local Storage 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites4 * Author Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016,2017) 6 6 * 7 * This file is part of ALMOS-kernel.7 * Copyright (c) UPMC Sorbonne Universites 8 8 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 9 * This file is part of ALMOS-MKH. 10 * 11 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 12 * under the terms of the GNU General Public License as published by 11 13 * the Free Software Foundation; version 2.0 of the License. 12 14 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but15 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 19 * 18 20 * 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,21 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 22 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 23 */ 22 24 23 #include < types.h>25 #include <hal_types.h> 24 26 #include <errno.h> 25 27 #include <thread.h> 26 #include <kmem.h> 27 #include <kmagics.h> 28 #include <semaphore.h> 28 #include <printk.h> 29 #include <syscalls.h> 29 30 30 #define UTLS_SET 1 31 #define UTLS_GET 2 32 #define UTLS_GET_ERRNO 3 33 34 int sys_utls(uint_t operation, uint_t value) 31 ///////////////////////////////// 32 int sys_utls( uint32_t operation, 33 uint32_t value ) 35 34 { 36 struct thread_s *this = current_thread;35 thread_t * this = CURRENT_THREAD; 37 36 38 37 switch(operation) 39 38 { 40 case UTLS_SET:41 this-> info.usr_tls = value;39 case UTLS_SET: 40 this->utls = value; 42 41 return 0; 43 42 44 case UTLS_GET:45 return this-> info.usr_tls;43 case UTLS_GET: 44 return this->utls; 46 45 47 case UTLS_GET_ERRNO:48 return this-> info.errno;46 case UTLS_GET_ERRNO: 47 return this->errno; 49 48 50 default: 51 this->info.errno = EINVAL; 49 default: 50 printk("\n[ERROR] in %s : illegal utls operation\n", __FUNCTION__ ); 51 this->errno = EINVAL; 52 52 return -1; 53 53 } 54 } 54 55 } // end sys_utls() -
trunk/kernel/syscalls/sys_write.c
r1 r23 1 1 /* 2 * kern/sys_write.c - write bytes to a file2 * sys_write.c - write bytes to a file 3 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 4 * Author Alain Greiner (2016,2017) 6 5 * 7 * This file is part of ALMOS-kernel.6 * Copyright (c) UPMC Sorbonne Universites 8 7 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * 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 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 24 #include <kernel_config.h> 25 #include <hal_types.h> 26 #include <hal_uspace.h> 27 #include <hal_special.h> 23 28 #include <errno.h> 24 #include <thread.h>25 29 #include <vfs.h> 26 30 #include <thread.h> 27 #include < sys-vfs.h>28 #include < task.h>31 #include <printk.h> 32 #include <process.h> 29 33 30 int sys_write (uint_t fd, void *buf, size_t count) 34 /* TODO: user page(s) need to be locked [AG] */ 35 36 ////////////////////////////////// 37 int sys_write( uint32_t file_id, 38 void * buf, 39 uint32_t count ) 31 40 { 32 ssize_t err = 0;33 struct thread_s *this;34 struct task_s *task;35 struct vfs_file_s *file;36 struct ku_obj kub; 41 error_t error; 42 paddr_t paddr; 43 char kbuf[CONFIG_VFS_KBUF_SIZE]; 44 xptr_t file_xp; // remote file extended pointer 45 uint32_t nbytes; // number of bytes in one iteration 37 46 38 file = NULL; 39 this = current_thread; 40 task = current_task; 47 thread_t * this = CURRENT_THREAD; 48 process_t * process = this->process; 41 49 42 if((fd >= CONFIG_TASK_FILE_MAX_NR) || (task_fd_lookup(task, fd, &file))) 50 // check file_id argument 51 if( file_id >= CONFIG_PROCESS_FILE_MAX_NR ) 43 52 { 44 this->info.errno = EBADFD; 53 printk("\n[ERROR] in %s : illegal file descriptor index\n", __FUNCTION__ ); 54 this->errno = EBADFD; 45 55 return -1; 46 56 } 47 57 48 KU_SLICE_BUFF(kub, buf, count); 49 if((err = vfs_write(file, &kub)) < 0) 58 // check user buffer in user space 59 error = vmm_v2p_translate( false , buf , &paddr ); 60 61 if ( error ) 62 { 63 printk("\n[ERROR] in %s : user buffer unmapped = %x\n", 64 __FUNCTION__ , (intptr_t)buf ); 65 this->errno = EINVAL; 66 return -1; 67 } 68 69 // get extended pointer on remote file descriptor 70 file_xp = process_fd_get_xptr( process , file_id ); 71 72 if( file_xp == XPTR_NULL ) 73 { 74 printk("\n[ERROR] in %s : undefined file descriptor index = %d\n", 75 __FUNCTION__ , file_id ); 76 this->errno = EBADFD; 77 return -1; 78 } 79 80 // get file descriptor cluster and local pointer 81 vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 82 cxy_t file_cxy = GET_CXY( file_xp ); 83 84 // check file writable 85 uint32_t attr = hal_remote_lw( XPTR( file_cxy , &file_ptr->attr ) ); 86 if( (attr & FD_ATTR_WRITE_ENABLE) == 0 ) 50 87 { 51 this->info.errno = (err < 0) ? -err : err; 88 printk("\n[ERROR] in %s : file %d not writable\n", 89 __FUNCTION__ , file_id ); 90 this->errno = EBADFD; 52 91 return -1; 53 92 } 54 93 55 return err; 56 } 94 // transfer at most CONFIG_VFS_KBUF_SIZE bytes per iteration 95 while( count ) 96 { 97 if( count <= CONFIG_VFS_KBUF_SIZE ) 98 { 99 nbytes = count; 100 count = 0; 101 } 102 else 103 { 104 nbytes = CONFIG_VFS_KBUF_SIZE; 105 count = count - CONFIG_VFS_KBUF_SIZE; 106 } 107 108 // copy user buffer to kernel buffer 109 hal_copy_to_uspace( buf , kbuf , nbytes ); 110 111 // transfer nbytes from kernel buffer 112 error = vfs_move( false, // write => (to_buffer = false) 113 file_xp, 114 kbuf , 115 nbytes ); 116 117 if( error ) 118 { 119 printk("\n[ERROR] in %s cannot read data from file %d\n", 120 __FUNCTION__ , file_id ); 121 this->errno = error; 122 return -1; 123 } 124 } 125 126 hal_wbflush(); 127 128 return 0; 129 130 } // end sys_write() -
trunk/kernel/syscalls/syscalls.h
r16 r23 2 2 * syscalls.h - kernel services definition 3 3 * 4 * Author Ghassan Almaless (2007,2008,2009,2010,2011,2012) 5 * Alain Greiner (2016) 4 * Author Alain Greiner (2016,2017) 6 5 * 7 6 * Copyright (c) UPMC Sorbonne Universites … … 26 25 #define _SYSCALLS_H_ 27 26 27 #include <hal_types.h> 28 #include <time.h> 29 30 /***** Forward declarations *****/ 31 32 struct thread_s; // defined in thread.h 33 struct pthread_attr_s; // defined in thread.h 34 struct vfs_stat_s; // defined in vfs.h 35 struct vfs_dirent_s; // defined in vfs.h 36 struct mmap_attr_s; // defined in vmm.h 37 28 38 /****************************************************************************************** 29 39 * This enum defines the mnemonics for the syscall indexes. … … 32 42 enum 33 43 { 34 SYS_EXIT, /* 0 */ 35 SYS_MMAP, /* 1 */ 36 SYS_CREATE, /* 2 */ 37 SYS_JOIN, /* 3 */ 38 SYS_DETACH, /* 4 */ 39 SYS_YIELD, /* 5 */ 40 SYS_SEMAPHORE, /* 6 */ 41 SYS_COND_VAR, /* 7 */ 42 SYS_BARRIER, /* 8 */ 43 SYS_RWLOCK, /* 9 */ 44 SYS_SLEEP, /* 10 */ 45 SYS_WAKEUP, /* 11 */ 46 SYS_OPEN, /* 12 */ 47 SYS_CREAT, /* 13 */ 48 SYS_READ, /* 14 */ 49 SYS_WRITE, /* 15 */ 50 SYS_LSEEK, /* 16 */ 51 SYS_CLOSE, /* 17 */ 52 SYS_UNLINK, /* 18 */ 53 SYS_PIPE, /* 19 */ 54 SYS_CHDIR, /* 20 */ 55 SYS_MKDIR, /* 21 */ 56 SYS_MKFIFO, /* 22 */ 57 SYS_OPENDIR, /* 23 */ 58 SYS_READDIR, /* 24 */ 59 SYS_CLOSEDIR, /* 25 */ 60 SYS_GETCWD, /* 26 */ 61 SYS_CLOCK, /* 27 */ 62 SYS_ALARM, /* 28 */ 63 SYS_DMA_MEMCPY, /* 29 */ 64 SYS_UTLS, /* 30 */ 65 SYS_SIGRETURN, /* 31 */ 66 SYS_SIGNAL, /* 32 */ 67 SYS_SET_SIGRETURN, /* 33 */ 68 SYS_KILL, /* 34 */ 69 SYS_GETPID, /* 35 */ 70 SYS_FORK, /* 36 */ 71 SYS_EXEC, /* 37 */ 72 SYS_GETATTR, /* 38 */ 73 SYS_PS, /* 39 */ 74 SYS_MADVISE, /* 40 */ 75 SYS_PAGEINFO, /* 41 */ 76 SYS_STAT, /* 42 */ 77 SYS_MIGRATE, /* 43 */ 78 SYS_SBRK, /* 44 */ 79 SYS_RMDIR, /* 45 */ 80 SYS_FTIME, /* 46 */ 81 SYS_CHMOD, /* 47 */ 82 SYS_FSYNC, /* 48 */ 83 SYS_GET_TOD, /* 49 */ 84 SYS_TIMES, /* 50 */ 85 SYSCALLS_NR, 44 SYS_THREAD_EXIT = 0, 45 SYS_MMAP = 1, 46 SYS_THREAD_CREATE = 2, 47 SYS_THREAD_JOIN = 3, 48 SYS_THREAD_DETACH = 4, 49 SYS_THREAD_YIELD = 5, 50 SYS_SEM = 6, 51 SYS_CONDVAR = 7, 52 SYS_BARRIER = 8, 53 SYS_MUTEX = 9, 54 55 SYS_SLEEP = 10, 56 SYS_WAKEUP = 11, 57 SYS_OPEN = 12, 58 SYS_CREAT = 13, 59 SYS_READ = 14, 60 SYS_WRITE = 15, 61 SYS_LSEEK = 16, 62 SYS_CLOSE = 17, 63 SYS_UNLINK = 18, 64 SYS_PIPE = 19, 65 66 SYS_CHDIR = 20, 67 SYS_MKDIR = 21, 68 SYS_MKFIFO = 22, 69 SYS_OPENDIR = 23, 70 SYS_READDIR = 24, 71 SYS_CLOSEDIR = 25, 72 SYS_GETCWD = 26, 73 SYS_CLOCK = 27, 74 SYS_ALARM = 28, 75 SYS_RMDIR = 29, 76 77 SYS_UTLS = 30, 78 SYS_CHMOD = 31, 79 SYS_SIGNAL = 32, 80 SYS_TIMEOFDAY = 33, 81 SYS_KILL = 34, 82 SYS_GETPID = 35, 83 SYS_FORK = 36, 84 SYS_EXEC = 37, 85 SYS_STAT = 38, 86 SYS_TRACE = 39, 87 88 SYSCALLS_NR = 40, 86 89 }; 87 90 91 88 92 /********************************************************************************************/ 89 /******************** Process related system calls***************************************/93 /******************** system calls ****************************************************/ 90 94 /********************************************************************************************/ 91 95 92 93 /********************************************************************************************* 94 * [0] This function TODO 95 ********************************************************************************************/ 96 int sys_thread_exit( void * ); 97 98 /********************************************************************************************* 99 * [1] This function TODO 100 ********************************************************************************************/ 101 int sys_mmap(); 102 103 /********************************************************************************************* 104 * [2] This function TODO 105 ********************************************************************************************/ 106 int sys_thread_create(); 107 108 /********************************************************************************************* 109 * [3] This function TODO 110 ********************************************************************************************/ 111 int sys_thread_join(); 112 113 /********************************************************************************************* 114 * [4] This function TODO 115 ********************************************************************************************/ 116 int sys_thread_detach(); 117 118 /********************************************************************************************* 119 * [5] This function TODO 96 /********************************************************************************************* 97 * [0] This function terminates the execution of the calling user thread value, 98 * and makes the exit_value pointer available to any successful pthread_join() with the 99 * terminating thread. 100 ********************************************************************************************* 101 * @ exit_vallue : [out] pointer to to the parrent thread if attached. 102 * @ return 0 if success / return -1 if failure. 103 ********************************************************************************************/ 104 int sys_thread_exit( void * exit_value ); 105 106 /********************************************************************************************* 107 * [1] This function map physical memory (or a file) in the calling thread virtual space. 108 * The <attr> argument is a pointer on a structure containing arguments, defined in vmm.h. 109 * TODO not implemented yet... 110 ********************************************************************************************* 111 * @ attr : pointer on attributes structure. 112 * @ return 0 if success / return -1 if failure. 113 ********************************************************************************************/ 114 int sys_mmap( struct mmap_attr_s * attr ); 115 116 /********************************************************************************************* 117 * [2] This function creates a new user thread. The <user_attr> argument is a pointer 118 * on astructure containing the thread attributes, defined in thread.h file. 119 ********************************************************************************************* 120 * @ new_thread : [out] local pointer on created thread descriptor. 121 * @ user_attr : [in] pointer on thread attributes structure. 122 * @ start_func : [in] pointer on start function. 123 * @ start_args : [in] pointer on start function arguments. 124 * @ return 0 if success / return -1 if failure. 125 ********************************************************************************************/ 126 int sys_thread_create( struct thread_s * new_thread, 127 struct pthread_attr_s * user_attr, 128 void * start_func, 129 void * start_args ); 130 131 /********************************************************************************************* 132 * [3] This blocking function suspend execution of the calling thread until completion 133 * of another target thread identified by the <trdid> argument. 134 * If the <exit_value> argument is not NULL, the value passed to pthread_exit() by the 135 * target thread is stored in the location referenced by exit_value. 136 ********************************************************************************************* 137 * @ trdid : [in] target thread identifier. 138 * @ thread : [out] buffer for exit_value returned by target thread. 139 * @ return 0 if success / return -1 if failure. 140 ********************************************************************************************/ 141 int sys_thread_join( trdid_t trdid, 142 void ** exit_value ); 143 144 /********************************************************************************************* 145 * [4] This function detach a joinable thread. 146 ********************************************************************************************* 147 * @ trdid : thread identifier. 148 * @ return 0 if success / return -1 if failure. 149 ********************************************************************************************/ 150 int sys_thread_detach( trdid_t trdid ); 151 152 /********************************************************************************************* 153 * [5] This function calls the scheduler for the core running the calling thread. 154 ********************************************************************************************* 155 * @ return always 0. 120 156 ********************************************************************************************/ 121 157 int sys_thread_yield(); 122 158 123 159 /********************************************************************************************* 124 * [6] This function TODO 125 ********************************************************************************************/ 126 int sys_sem(); 127 128 /********************************************************************************************* 129 * [7] This function TODO 130 ********************************************************************************************/ 131 int sys_cond_var(); 132 133 /********************************************************************************************* 134 * [8] This function TODO 135 ********************************************************************************************/ 136 int sys_barrier(); 137 138 /********************************************************************************************* 139 * [9] This function TODO 140 ********************************************************************************************/ 141 int sys_rwlock(); 142 143 /********************************************************************************************* 144 * [10] This function TODO 160 * [6] This function implement all operations on a POSIX unnamed semaphore, 161 * that can be shared by threads running in different clusters. 162 * The kernel structure representing a remote semaphore is in the remote_sem.h file, 163 * and the code implementing the operations is in the remore_sem.c file. 164 ********************************************************************************************* 165 * @ vaddr : semaphore virtual address in user space == identifier. 166 * @ operation : SEM_INIT / SEM_DESTROY / SEM_GETVALUE / SEM_POST / SEM_WAIT. 167 * @ value : pointer on in/out argument in user space. 168 * @ return 0 if success / return -1 if failure. 169 ********************************************************************************************/ 170 int sys_sem( void * vaddr, 171 uint32_t operation, 172 uint32_t * value ); 173 174 typedef enum 175 { 176 SEM_INIT, 177 SEM_DESTROY, 178 SEM_GETVALUE, 179 SEM_WAIT, 180 SEM_POST, 181 } 182 sem_operation_t; 183 184 /********************************************************************************************* 185 * [7] This function implement all operations on a POSIX condition variable. 186 * The kernel structure representing a cond_var is defined in the remote_cv.h file, 187 * The code implementing the operations is defined in the remote_cv.c file. 188 ********************************************************************************************* 189 * @ vaddr : condvar virtual address in user space == identifier. 190 * @ operation : operation type (see below). 191 * @ attr : mutex virtual address in user space == identifier. 192 * @ return 0 if success / return -1 if failure. 193 ********************************************************************************************/ 194 int sys_condvar( void * condvar, 195 uint32_t operation, 196 void * mutex ); 197 198 typedef enum 199 { 200 CONDVAR_INIT, 201 CONDVAR_DESTROY, 202 CONDVAR_WAIT, 203 CONDVAR_SIGNAL, 204 CONDVAR_BROADCAST, 205 } 206 condvar_operation_t; 207 208 /********************************************************************************************* 209 * [8] This function implement all operations on a POSIX barrier. 210 * The kernel structure representing a barrier is defined in the remote_barrier.h file. 211 * The code implementting the operations is defined in the remote_barrier.c file. 212 ********************************************************************************************* 213 * @ vaddr : barrier virtual address in user space == identifier. 214 * @ operation : BARRIER_INIT / BARRIER_DESTROY / BARRIER_WAIT. 215 * @ count : number of expected threads (only used by BARRIER_INIT operation). 216 * @ return 0 if success / return -1 if failure. 217 ********************************************************************************************/ 218 int sys_barrier( void * vaddr, 219 uint32_t operation, 220 uint32_t count ); 221 222 typedef enum 223 { 224 BARRIER_INIT, 225 BARRIER_DESTROY, 226 BARRIER_WAIT, 227 } 228 barrier_operation_t; 229 230 /********************************************************************************************* 231 * [9] This function implement all operations on a POSIX mutex. 232 * The kernel structure representing a barrier is defined in the remote_barrier.h file. 233 * The code implementting the operations is defined in the remote_barrier.c file. 234 ********************************************************************************************* 235 * @ vaddr : mutex virtual address in user space == identifier. 236 * @ operation : MUTEX_INIT / MUTEX_DESTROY / MUTEX_LOCK / MUTEX_UNLOCK 237 * @ attr : mutex attributes (non supported yet => must be 0). 238 * @ return 0 if success / return -1 if failure. 239 ********************************************************************************************/ 240 int sys_mutex( void * vaddr, 241 uint32_t operation, 242 uint32_t count ); 243 244 typedef enum 245 { 246 MUTEX_INIT, 247 MUTEX_DESTROY, 248 MUTEX_LOCK, 249 MUTEX_UNLOCK, 250 } 251 mutex_operation_t; 252 253 /********************************************************************************************* 254 * [10] This function block the calling thread on the THREAD_BLOCKED_GLOBAL condition, 255 * and deschedule. 256 ********************************************************************************************* 257 * @ return 0 if success / returns -1 if failure. 145 258 ********************************************************************************************/ 146 259 int sys_thread_sleep(); 147 260 148 261 /********************************************************************************************* 149 * [11] This function TODO 262 * [11] This function unblock the thread identified by its <trdid> from the 263 * THREAD_BLOCKED_GLOBAL condition. 264 ********************************************************************************************* 265 * @ trdid : target thread identifier. 266 * @ return 0 if success / return -1 if failure. 150 267 ********************************************************************************************/ 151 268 int sys_thread_wakeup(); 152 269 153 270 /********************************************************************************************* 154 * [12] This function TODO 155 ********************************************************************************************/ 156 int sys_open(); 157 158 /********************************************************************************************* 159 * [13] This function TODO 160 ********************************************************************************************/ 161 int sys_creat(); 162 163 /********************************************************************************************* 164 * [14] This function TODO 165 ********************************************************************************************/ 166 int sys_read(); 167 168 /********************************************************************************************* 169 * [15] This function TODO 170 ********************************************************************************************/ 171 int sys_write(); 172 173 /********************************************************************************************* 174 * [16] This function TODO 175 ********************************************************************************************/ 176 int sys_lseek(); 177 178 /********************************************************************************************* 179 * [17] This function TODO 180 ********************************************************************************************/ 181 int sys_close(); 182 183 /********************************************************************************************* 184 * [18] This function TODO 185 ********************************************************************************************/ 186 int sys_unlink(); 187 188 /********************************************************************************************* 189 * [19] This function TODO 190 ********************************************************************************************/ 191 int sys_pipe(); 192 193 /********************************************************************************************* 194 * [20] This function TODO 195 ********************************************************************************************/ 196 int sys_chdir(); 197 198 /********************************************************************************************* 199 * [21] This function TODO 200 ********************************************************************************************/ 201 int sys_mkdir(); 202 203 /********************************************************************************************* 204 * [22] This function TODO 205 ********************************************************************************************/ 206 int sys_mkfifo(); 207 208 /********************************************************************************************* 209 * [23] This function TODO 210 ********************************************************************************************/ 211 int sys_opendir(); 212 213 /********************************************************************************************* 214 * [24] This function TODO 215 ********************************************************************************************/ 216 int sys_readdir(); 217 218 /********************************************************************************************* 219 * [25] This function TODO 220 ********************************************************************************************/ 221 int sys_closedir(); 222 223 /********************************************************************************************* 224 * [26] This function TODO 225 ********************************************************************************************/ 226 int sys_getcwd(); 227 228 /********************************************************************************************* 229 * [27] This function TODO 230 ********************************************************************************************/ 231 int sys_clock(); 232 233 /********************************************************************************************* 234 * [28] This function TODO 235 ********************************************************************************************/ 236 int sys_alarm(); 237 238 /********************************************************************************************* 239 * [29] This function TODO 240 ********************************************************************************************/ 241 int sys_dma_memcpy(); 242 243 /********************************************************************************************* 244 * [30] This function TODO 245 ********************************************************************************************/ 246 int sys_utls(); 247 248 /********************************************************************************************* 249 * [31] This function TODO 250 ********************************************************************************************/ 251 int sys_notAvailable(); 252 253 /********************************************************************************************* 254 * [32] This function TODO 255 ********************************************************************************************/ 256 int sys_signal(); 257 258 /********************************************************************************************* 259 * [33] This function TODO 260 ********************************************************************************************/ 261 int sys_sigreturn_setup(); 271 * [12] This function open or create a file. 272 ********************************************************************************************* 273 * @ pathname : pathname (can be relative or absolute). 274 * @ flags : bit vector attributes (see below). 275 * @ mode : access rights. 276 * @ return file descriptor index in fd_array if success / return -1 if failure. 277 ********************************************************************************************/ 278 int sys_open( char * pathname, 279 uint32_t flags, 280 uint32_t mode ); 281 282 typedef enum 283 { 284 O_RDONLY = 0x0010000, /*! open file in read-only mode */ 285 O_WRONLY = 0x0020000, /*! open file in write-only mode */ 286 O_RDWR = 0x0030000, /*! open file in read/write mode */ 287 O_NONBLOCK = 0x0040000, /*! do not block if data non available */ 288 O_APPEND = 0x0080000, /*! append on each write */ 289 O_CREAT = 0x0100000, /*! create file if it does not exist */ 290 O_TRUNC = 0x0200000, /*! file length is forced to 0 */ 291 O_EXCL = 0x0400000, /*! error if VFS_O_CREAT and file exist */ 292 O_SYNC = 0x0800000, /*! synchronize File System on each write */ 293 O_CLOEXEC = 0x1000000, /*! set the close-on-exec flag in file descriptor */ 294 O_DIR = 0x2000000, /*! new file descriptor is for a directory */ 295 } 296 open_attributes_t; 297 298 /********************************************************************************************* 299 * [13] This function creates a new file as specified by the arguments. 300 * This function is obsolete, you should use open() with 0_CREATE. 301 ********************************************************************************************* 302 * @ pathname : pathname (can be relative or absolute). 303 * @ mode : access rights. 304 ********************************************************************************************/ 305 int sys_creat( char * pathname, 306 uint32_t mode ); 307 308 /********************************************************************************************* 309 * [14] This function read bytes from an open file identified by its file descriptor. 310 * This file can be a regular file or character oriented device. 311 ********************************************************************************************* 312 * @ file_id : open file index in fd_array. 313 * @ buf : buffer virtual address in user space. 314 * @ count : number of bytes. 315 * @ return number of bytes actually read if success / returns -1 if failure. 316 ********************************************************************************************/ 317 int sys_read( uint32_t file_id, 318 void * buf, 319 uint32_t count ); 320 321 /********************************************************************************************* 322 * [15] This function writes bytes to an open file identified by its file descriptor. 323 * This file can be a regular file or character oriented device. 324 ********************************************************************************************* 325 * @ file_id : open file index in fd_array. 326 * @ buf : buffer virtual address in user space. 327 * @ count : number of bytes. 328 * @ return number of bytes actually written if success / returns -1 if failure. 329 ********************************************************************************************/ 330 int sys_write( uint32_t file_id, 331 void * buf, 332 uint32_t count ); 333 334 /********************************************************************************************* 335 * [16] This function epositions the offset of the file descriptor identified by <file_id>, 336 * according to the operation type defined by the <whence> and <offset> arguments. 337 ********************************************************************************************* 338 * @ file_id : open file index in fd_array. 339 * @ offset : buffer virtual address in user space. 340 * @ whence : operation type (see below). 341 * @ return 0 if success / returns -1 if failure. 342 ********************************************************************************************/ 343 int sys_lseek( xptr_t file_id, 344 uint32_t offset, 345 uint32_t whence ); 346 347 typedef enum 348 { 349 SEEK_SET = 0, /*! new_offset <= offset */ 350 SEEK_CUR = 1, /*! new_offset <= current_offset + offset */ 351 SEEK_END = 2, /*! new_iffset <= current_size + offset */ 352 } 353 lseek_operation_t; 354 355 /********************************************************************************************* 356 * [17] This function release the memory allocated for the file descriptor identified by 357 * the <file_id> argument, and remove the fd array_entry in all copies of the process 358 * descriptor. 359 ********************************************************************************************* 360 file_id : file descriptor index in fd_array. 361 * @ return 0 if success / returns -1 if failure. 362 ********************************************************************************************/ 363 int sys_close( uint32_t file_id ); 364 365 /********************************************************************************************* 366 * [18] This function removes a directory entry identified by the <pathname> from its 367 * directory, and decrement the link count of the file referenced by the link. 368 * If the link count reduces to zero, and no process has the file open, then all resources 369 * associated with the file are reclaimed. If one or more process have the file open when 370 * the last link is removed, the link is removed, but the removal of the file is delayed 371 * until all references to it have been closed. 372 ********************************************************************************************* 373 * @ pathname : pathname (can be relative or absolute). 374 * @ return 0 if success / returns -1 if failure. 375 ********************************************************************************************/ 376 int sys_unlink( char * pathname ); 377 378 /********************************************************************************************* 379 * [19] This function creates in the calling thread cluster an unnamed pipe, and two 380 * (read and write) file descriptors. 381 ********************************************************************************************* 382 * @ file_id[0] : [out] read only file descriptor index. 383 * @ file_id[1] : [out] write only file descriptor index. 384 * @ return 0 if success / return -1 if failure. 385 ********************************************************************************************/ 386 int sys_pipe( uint32_t file_id[2] ); 387 388 /********************************************************************************************* 389 * [20] This function change the current working directory in reference process descriptor. 390 ********************************************************************************************* 391 * @ pathname : pathname (can be relative or absolute). 392 * @ return 0 if success / returns -1 if failure. 393 ********************************************************************************************/ 394 int sys_chdir( char * pathname ); 395 396 /********************************************************************************************* 397 * [21] This function creates a new directory in file system. 398 ********************************************************************************************* 399 * @ pathname : pathname (can be relative or absolute). 400 * @ mode : access rights (as defined in chmod). 401 * @ return 0 if success / returns -1 if failure. 402 ********************************************************************************************/ 403 int sys_mkdir( char pathname, 404 uint32_t mode ); 405 406 /********************************************************************************************* 407 * [22] This function creates a named FIFO file in the calling thread cluster. 408 * The associated read and write file descriptors mut be be explicitely created 409 * using the sy_open() function. 410 ********************************************************************************************* 411 * @ pathname : pathname (can be relative or absolute). 412 * @ mode : access rights (as defined in chmod). 413 * @ return 0 if success / returns -1 if failure. 414 ********************************************************************************************/ 415 int sys_mkfifo( char * pathname, 416 uint32_t mode ); 417 418 /********************************************************************************************* 419 * [23] This function open a directory, that must exist in the file system. 420 ********************************************************************************************* 421 * @ pathname : pathname (can be relative or absolute). 422 * @ return file descriptor index in fd_array if success / return -1 if failure. 423 ********************************************************************************************/ 424 int sys_opendir( char * pathname ); 425 426 /********************************************************************************************* 427 * [24] This function returns in the structure pointed by the <dirent> argument various 428 * information about an entry of the directory identified by the <file_id> argument. 429 ********************************************************************************************* 430 * @ file_id : file descriptor index of the searched directory. 431 * @ dirent : pointer on a dirent structure in user space. 432 * @ return 0 if success / returns -1 if failure. 433 ********************************************************************************************/ 434 int sys_readdir( uint32_t file_id, 435 struct vfs_dirent_s * dirent ); 436 437 /********************************************************************************************* 438 * [25] This function close the file descriptor previouly open by the opendir() function. 439 ********************************************************************************************* 440 * @ file_id : file descriptor index of the searched directory. 441 * @ return 0 if success / returns -1 if failure. 442 ********************************************************************************************/ 443 int sys_closedir( uint32_t file_id ); 444 445 /********************************************************************************************* 446 * [26] This function returns the pathname of the current working directory. 447 ********************************************************************************************* 448 * buf : buffer addres in user space. 449 * nbytes : user buffer size in bytes. 450 * @ return 0 if success / returns -1 if failure. 451 ********************************************************************************************/ 452 int sys_getcwd( char * buf, 453 uint32_t nbytes ); 454 455 /********************************************************************************************* 456 * [27] This function returns in a 64 bits user buffer the calling core cycles count. 457 * It uses both the hardware register and the core descriptor cycles count tos take 458 * into account a possible harware register overflow in 32 bits architectures. 459 ********************************************************************************************* 460 * cyles : [out] address of buffer in user space. 461 ********************************************************************************************/ 462 int sys_clock( uint64_t * cycles ); 463 464 /********************************************************************************************* 465 * [28] This function forces the calling thread to sleep, for a fixed number of cycles. 466 ********************************************************************************************* 467 * cycles : number of cycles. 468 ********************************************************************************************/ 469 int sys_alarm( uint32_t cycles ); 470 471 /********************************************************************************************* 472 * [29] This undefined function does nothing. 473 ********************************************************************************************* 474 * @ pathname : pathname (can be relative or absolute). 475 * @ return 0 if success / returns -1 if failure. 476 ********************************************************************************************/ 477 int sys_rmdir( char * pathname ); 478 479 /********************************************************************************************* 480 * [30] This function implement the operations related to User Thread Local Storage. 481 * It is actually implemented as an uint32_t variable in the thread descriptor. 482 ********************************************************************************************* 483 * @ operation : UTLS operation type as defined below. 484 * @ value : argument value for the UTLS_SET operation. 485 * @ return value for the UTLS_GET and UTLS_GET_ERRNO / return -1 if failure. 486 ********************************************************************************************/ 487 int sys_utls( uint32_t operation, 488 uint32_t value ); 489 490 typedef enum 491 { 492 UTLS_SET = 1, 493 UTLS_GET = 2, 494 UTLS_GET_ERRNO = 3, 495 } 496 utls_operation_t; 497 498 /********************************************************************************************* 499 * [31] This function change the acces rights for the file/dir identified by the 500 * pathname argument. 501 ********************************************************************************************* 502 * @ pathname : pathname (can be relative or absolute). 503 * @ rights : acces rights. 504 * @ return 0 if success / returns -1 if failure. 505 ********************************************************************************************/ 506 int sys_chmod( char * pathname, 507 uint32_t rights ); 508 509 /********************************************************************************************* 510 * [32] This function associate a specific signal handler to a given signal type. 511 * Tee handlers for the SIGKILL and SIGSTOP signals cannot be redefined. 512 ********************************************************************************************* 513 * @ sig_id : index defining signal type (from 1 to 31). 514 * @ handler : pointer on fonction implementing the specific handler. 515 * @ return 0 if success / returns -1 if failure. 516 ********************************************************************************************/ 517 int sys_signal( uint32_t sig_id, 518 void * handler ); 519 520 /********************************************************************************************* 521 * [33] This function returns in the structure <tv>, defined in the time.h file, 522 * the current time (in seconds & micro-seconds). 523 * It is computed from the calling core descriptor. 524 * The timezone is not supported. 525 ********************************************************************************************* 526 * @ tv : pointer on the timeval structure. 527 * @ tz : pointer on the timezone structure : must be NULL. 528 * @ return 0 if success / returns -1 if failure. 529 ********************************************************************************************/ 530 int sys_gettimeofday( struct timeval * tv, 531 struct timezone * tz ); 262 532 263 533 /********************************************************************************************* 264 534 * [34] This function implements the "kill" system call. 265 * It register the signal identified by the <sig> argument in all thread descriptors 266 * of process identified by the <pid> argument. 535 * It register the signal defined by the <sig_id> argument in all thread descriptors 536 * of a target process identified by the <pid> argument. This is done in all clusters 537 * containing threads for the target process. 538 * It can be executed by any thread running in any cluster, as this function uses 539 * remote access to traverse the list of process copies in the owner cluster, 540 * and the RPC_SIGNAL_RISE to signal the remote threads. 267 541 ********************************************************************************************* 268 542 * @ pid : target process identifier. 269 * @ sig : signal index. 543 * @ sig_id : index defining the signal type (from 1 to 31). 544 * @ return 0 if success / returns -1 if failure. 270 545 ********************************************************************************************/ 271 546 int sys_kill( pid_t pid, 272 uint32_t sig ); 273 274 /********************************************************************************************* 275 * [35] This function TODO 547 uint32_t sig_id ); 548 549 /********************************************************************************************* 550 * [35] This function implements the "getpid" system call. 551 ********************************************************************************************* 552 * @ returns the PID for the calling thread. 276 553 ********************************************************************************************/ 277 554 int sys_getpid(); … … 281 558 * The calling process descriptor (parent process), and the associated thread descriptor are 282 559 * replicated in the same cluster as the calling thread, but the new process (child process) 283 * is registered in another target cluster, that will become theprocess owner.560 * is registered in another target cluster, that is the new process owner. 284 561 * The child process and the associated main thread will be migrated to the target cluster 285 562 * later, when the child process makes an "exec" or any other system call. … … 295 572 * [37] This function implement the "exec" system call. 296 573 * It is executed in the client cluster, but the new process descriptor and main thread 297 * must be created in a server cluster, that is generally another cluster, using a RPC. 298 * - If the server_cluster is the client cluster, call directly make_exec() in local 299 * mode, to change the process image and launch a new thread in local cluster. 300 * finally, the old thread is deleted. 301 * - If the target_cluster is remote, call rpc_process_exec_client() to execute the 302 * make_exec() in remote mode on the remote cluster, to create a new process 303 * descriptor and a new thread on remote cluster. Finally, both the local 304 * process descriptor and the local thread descriptor are deleted. 574 * must be created in a server cluster, that is generally another cluster. 575 * - if the server_cluster is the client cluster, call directly the process_make_exec() 576 * function to create a new process, and launch a new thread in local cluster. 577 * - if the target_cluster is remote, call rpc_process_exec_client() to execute the 578 * process_make_exec() on the remote cluster. 305 579 * In both case this function build an exec_info_t structure containing all informations 306 * required to build the new process descriptor and the associated thread , including307 * the mode (local/remote).580 * required to build the new process descriptor and the associated thread. 581 * Finally, the calling process and thread are deleted. 308 582 ********************************************************************************************* 309 583 * @ filename : string pointer on .elf filename (virtual pointer in user space) 310 584 * @ argv : array of strings on process arguments (virtual pointers in user space) 311 585 * @ envp : array of strings on Renvironment variables (virtual pointers in user space) 312 * @ returns O if success / returns non-zero if error.586 * @ returns O if success / returns -1 if failure. 313 587 ********************************************************************************************/ 314 588 int sys_exec( char * filename, … … 317 591 318 592 /********************************************************************************************* 319 * [38] This function TODO 320 ********************************************************************************************/ 321 int sys_thread_getattr(); 322 323 /********************************************************************************************* 324 * [39] This function implements the ps system call. 325 ********************************************************************************************/ 326 int sys_ps( uint32_t cmd, 327 pid_t pid, 328 uint32_t tid ); 329 330 /********************************************************************************************* 331 * [40] This function TODO 332 ********************************************************************************************/ 333 int sys_madvise(); 334 335 /********************************************************************************************* 336 * [41] This function TODO 337 ********************************************************************************************/ 338 int sys_mcntl(); 339 340 /********************************************************************************************* 341 * [42] This function TODO 342 ********************************************************************************************/ 343 int sys_stat(); 344 345 /********************************************************************************************* 346 * [43] This function TODO 347 ********************************************************************************************/ 348 int sys_thread_migrate(); 349 350 /********************************************************************************************* 351 * [44] This function TODO 352 ********************************************************************************************/ 353 int sys_sbrk(); 354 355 /********************************************************************************************* 356 * [45] This function TODO 357 ********************************************************************************************/ 358 int sys_rmdir(); 359 360 /********************************************************************************************* 361 * [46] This function TODO 362 ********************************************************************************************/ 363 int sys_ftime(); 364 365 /********************************************************************************************* 366 * [47] This function TODO 367 ********************************************************************************************/ 368 int sys_chmod(); 369 370 /********************************************************************************************* 371 * [48] This function TODO 372 ********************************************************************************************/ 373 int sys_fsync(); 374 375 /********************************************************************************************* 376 * [49] This function TODO 377 ********************************************************************************************/ 378 int sys_gettimeofday(); 379 380 /********************************************************************************************* 381 * [50] This function TODO 382 ********************************************************************************************/ 383 int sys_times(); 593 * [38] This function returns in the <stat> structure, defined in the vfs.h file, 594 * various informations on the file/directory identified by the <file_id> argument. 595 ********************************************************************************************* 596 * @ file_id : file descriptor index in fd_array. 597 * @ stat : pointer on the stat structure. 598 * @ returns O if success / returns -1 if failure. 599 ********************************************************************************************/ 600 int sys_stat( uint32_t file_id, 601 struct vfs_stat_s * stat ); 602 603 /********************************************************************************************* 604 * [39] This function is used to activate / desactivate Rthe trace for a thread 605 * identified by the <trdid> and <pid> arguments. 606 * It can be called by any other thread. 607 ********************************************************************************************* 608 * @ operation : operation type as defined below. 609 * @ pid : process identifier. 610 * @ trdid : thread identifier. 611 * @ returns O if success / returns -1 if failure. 612 ********************************************************************************************/ 613 int sys_trace( uint32_t operation, 614 pid_t pid, 615 uint32_t trdid ); 616 617 typedef enum 618 { 619 TRACE_ON = 0, 620 TRACE_OFF = 1, 621 } 622 trace_operation_t; 384 623 385 624 -
trunk/kernel/vfs/fatfs.c
r15 r23 2 2 * fatfs.c - FATFS file system API implementation. 3 3 * 4 * Author Mohamed Lamine Karaoui (201 5)5 * Alain Greiner (2016 )4 * Author Mohamed Lamine Karaoui (2014,2015) 5 * Alain Greiner (2016,2017) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 32 32 #include <rpc.h> 33 33 #include <mapper.h> 34 #include <cluster.h> 34 35 #include <dev_ioc.h> 35 36 #include <fatfs.h> 36 37 37 38 38 ////////////////////////////////////////////////////////////////////////////////////////// 39 // Extern variables 40 ////////////////////////////////////////////////////////////////////////////////////////// 41 42 extern vfs_ctx_t fs_context[FS_TYPES_NR]; // allocated in vfs.c file 43 44 extern remote_barrier_t global_barrier; // allocated dans kernel_init.c 45 39 46 ////////////////////////////////////////////////////////////////////////////////////////// 40 47 // FATFS specific functions : these functions cannot be called by the VFS 41 48 ////////////////////////////////////////////////////////////////////////////////////////// 42 //////////////////////////////////////////////////////////////////////////////////////////43 49 44 50 ////////////////////////////////////////////////////////// … … 46 52 uint32_t cluster ) 47 53 { 48 return (ctx->cluster_begin_lba + ((cluster - 2) * ctx->sectors_per_cluster));54 return (ctx->cluster_begin_lba + ((cluster - 2) << 3)); 49 55 } 50 56 … … 95 101 96 102 } // end fatfs_get_cluster() 103 104 /////////////////////////////////////////////////////////////////////////////////////// 105 // This static function return an integer record value (one, two, or four bytes) 106 // from a memory buffer, taking into account endianness. 107 /////////////////////////////////////////////////////////////////////////////////////// 108 // @ offset : first byte of record in buffer. 109 // @ size : record length in bytes (1/2/4). 110 // @ buffer : pointer on buffer base. 111 // @ little endian : the most significant byte has the highest address when true. 112 // @ return the integer value in a 32 bits word. 113 /////////////////////////////////////////////////////////////////////////////////////// 114 static uint32_t get_record_from_buffer( uint32_t offset, 115 uint32_t size, 116 uint8_t * buffer, 117 uint32_t little_endian ) 118 { 119 uint32_t n; 120 uint32_t res = 0; 121 122 if ( little_endian) 123 { 124 for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1]; 125 } 126 else 127 { 128 for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n]; 129 } 130 return res; 131 132 } // end get_record_from_buffer() 133 97 134 98 135 … … 162 199 163 200 /////////////////////////////////////////////////////////////////////////////////////// 201 // The following functions are called by the VFS. 164 202 /////////////////////////////////////////////////////////////////////////////////////// 165 // Generic API : the following functions are called by the VFS, 166 // and must be defined by all isupported file systems. 167 /////////////////////////////////////////////////////////////////////////////////////// 168 /////////////////////////////////////////////////////////////////////////////////////// 169 170 //////////////////////////////////////////////////////////// 171 error_t fatfs_inode_create( struct vfs_inode_s * vfs_inode ) 172 { 173 printk("\n[PANIC] %s not fully implemented yet\n", __FUNCTION__ ); 174 hal_core_sleep(); 175 203 204 205 /////////////////// 206 xptr_t fatfs_init() 207 { 208 kmem_req_t req; 209 fatfs_ctx_t * fatfs_ctx; // local pointer on FATFS context 210 vfs_ctx_t * vfs_ctx; // local pointer on VFS context 211 xptr_t root_inode_xp; // extended pointer on root inode 212 error_t error; 213 214 // get local pointer on VFS context for FATFS 215 vfs_ctx = &fs_context[FS_TYPE_FATFS]; 216 217 // get number of kernel instances and extended pointer on global barrier 218 cluster_t * cluster = LOCAL_CLUSTER; 219 uint32_t nb_clusters = cluster->x_size * cluster->y_size; 220 xptr_t barrier_xp = XPTR( cluster->io_cxy , &global_barrier ); 221 222 ///// step 1 : all clusters allocate memory for FATFS context 223 224 // allocate memory for FATFS context extension 225 req.type = KMEM_FATFS_CTX; 226 req.size = sizeof(fatfs_ctx_t); 227 req.flags = AF_KERNEL | AF_ZERO; 228 fatfs_ctx = (fatfs_ctx_t *)kmem_alloc( &req ); 229 230 if( fatfs_ctx == NULL ) 231 { 232 printk("\n[PANIC] in %s : no memory for FATFS context\n", __FUNCTION__ ); 233 hal_core_sleep(); 234 } 235 236 ///// step 2 : only cluster_0 access device and creates root inode 237 238 if( local_cxy == 0 ) 239 { 240 // create VFS root inode 241 error = vfs_inode_create( XPTR_NULL, // no parent dentry 242 FS_TYPE_FATFS, 243 INODE_TYPE_DIR, 244 0, // attr 245 0, // rights 246 0, // uid 247 0, // gid 248 &root_inode_xp ); 249 250 assert( (error == 0 ) , __FUNCTION__ , "cannot create VFS root inode" ); 251 252 // initialize VFS context / access device to initialize FATFS context 253 error = fatfs_ctx_init( vfs_ctx, 254 fatfs_ctx, 255 root_inode_xp ); 256 257 // create FATFS root inode 258 error = fatfs_inode_create( GET_PTR( root_inode_xp ) , 259 fatfs_ctx->root_dir_cluster ); 260 261 if( error ) 262 { 263 printk("\n[PANIC] in %s : cannot create FATFS root inode\n", __FUNCTION__ ); 264 hal_core_sleep(); 265 } 266 267 } 268 269 //////////////// synchronize all clusters 270 remote_barrier( barrier_xp , nb_clusters ); 271 272 ///// step 3 : all others clusters initialize both context and extension 273 274 if( local_cxy != 0 ) 275 { 276 // copy VFS context from remote cluster_0 to local cluster 277 hal_remote_memcpy( XPTR( local_cxy , vfs_ctx ), 278 XPTR( 0 , vfs_ctx ), 279 sizeof(vfs_ctx_t) ); 280 281 // copy FATFS context from remote cluster_0 to local cluster 282 hal_remote_memcpy( XPTR( local_cxy , fatfs_ctx ), 283 XPTR( 0 , vfs_ctx->extend ) , 284 sizeof(fatfs_ctx_t) ); 285 286 // update extend field in local copy of VFS context 287 vfs_ctx->extend = fatfs_ctx; 288 } 289 290 return root_inode_xp; 291 292 } // end fatfs_init() 293 294 ////////////////////////////////////////////// 295 error_t fatfs_ctx_init( vfs_ctx_t * vfs_ctx, 296 fatfs_ctx_t * fatfs_ctx, 297 xptr_t root_inode_xp ) 298 { 299 error_t error; 300 uint8_t buffer[512]; // buffer for boot record 301 302 // make a synchronous access to IOC device to read the boot record from device 303 error = dev_ioc_sync_read( buffer , 0 , 1 ); 304 assert( (error == 0) , __FUNCTION__ , "cannot access FAT boot record" ); 305 306 // check sector size from boot record 307 uint32_t sector_size = get_record_from_buffer( BPB_BYTSPERSEC , buffer , 1 ); 308 assert( (sector_size == 512) , __FUNCTION__ , "sector size must be 512 bytes" ); 309 310 // check cluster size from boot record 311 uint32_t nb_sectors = get_record_from_buffer( BPB_SECPERCLUS , buffer , 1 ); 312 assert( (nb_sectors == 8) , __FUNCTION__ , "cluster size must be 8 sectors" ); 313 314 // check number of FAT copies from boot record 315 uint32_t nb_fats = get_record_from_buffer( BPB_NUMFATS , buffer , 1 ); 316 assert( (nb_fats == 1) , __FUNCTION__ , "number of FAT copies must be 1" ); 317 318 // get & check number of sectors in FAT from boot record 319 uint32_t fat_sectors = get_record_from_buffer( BPB_FAT32_FATSZ32 , buffer , 1 ); 320 assert( ((fat_sectors & 0xF) == 0) , __FUNCTION__ , "FAT not multiple of 16 sectors"); 321 322 // get and check root cluster from boot record 323 uint32_t root_cluster = get_record_from_buffer( BPB_FAT32_ROOTCLUS , buffer , 1 ); 324 assert( (root_cluster == 2) , __FUNCTION__ , "Root cluster index must be 2"); 325 326 // get FAT lba from boot record 327 uint32_t fat_lba = get_record_from_buffer( BPB_RSVDSECCNT , buffer , 1 ); 328 329 // allocate a mapper for the FAT itself 330 mapper_t * fat_mapper = mapper_create(); 331 assert( (fat_mapper != NULL) , __FUNCTION__ , "no memory for FAT mapper" ); 332 333 // initialize the FATFS context 334 fatfs_ctx->fat_begin_lba = fat_lba; 335 fatfs_ctx->fat_sectors_count = fat_sectors; 336 fatfs_ctx->bytes_per_sector = sector_size; 337 fatfs_ctx->bytes_per_cluster = sector_size * nb_sectors; 338 fatfs_ctx->cluster_begin_lba = fat_lba + fat_sectors; 339 fatfs_ctx->root_dir_cluster = 2; 340 fatfs_ctx->last_allocated_sector = 0; // TODO ??? 341 fatfs_ctx->last_allocated_index = 0; // TODO ??? 342 fatfs_ctx->fat_mapper_xp = XPTR( local_cxy , fat_mapper ); 343 344 // initialize the VFS context 345 vfs_ctx->type = FS_TYPE_FATFS; 346 vfs_ctx->attr = 0; // not READ_ONLY / not SYNC 347 vfs_ctx->count = fat_sectors << 10; // total number of sectors in data region 348 vfs_ctx->blksize = 512; // number of bytes per sector 349 vfs_ctx->root_xp = root_inode_xp; 350 vfs_ctx->extend = fatfs_ctx; 351 352 spinlock_init( &vfs_ctx->lock ); 353 354 bitmap_init( vfs_ctx->bitmap , CONFIG_VFS_MAX_INODES ); 355 356 return 0; 357 358 } // end fatfs_ctx_init() 359 360 361 362 //////////////////////////////////////////////////// 363 void fatfs_ctx_destroy( struct vfs_ctx_s * vfs_ctx ) 364 { 365 kmem_req_t req; 366 fatfs_ctx_t * fatfs_ctx; 367 368 // get pointer on FATFS context extension 369 fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend; 370 371 req.type = KMEM_FATFS_INODE; 372 req.ptr = fatfs_ctx; 373 kmem_free( &req ); 374 } 375 376 377 //////////////////////////////////////////////////// 378 error_t fatfs_inode_create( vfs_inode_t * vfs_inode, 379 uint32_t first_cluster ) 380 { 176 381 kmem_req_t req; 177 382 fatfs_inode_t * fatfs_inode; 178 383 179 // allocate memory for fatfs inode384 // allocate memory for FATFS inode extension 180 385 req.type = KMEM_FATFS_INODE; 181 386 req.size = sizeof(fatfs_inode_t); … … 185 390 if( fatfs_inode == NULL ) return ENOMEM; 186 391 187 // initialise ramfs_inode 188 fatfs_inode->first_cluster = 0; // TODO ??? 189 fatfs_inode->ctx = (fatfs_ctx_t *)vfs_inode->ctx->extend; 392 // link FATFS inode to VFS inode 393 vfs_inode->extend = fatfs_inode; 394 395 // initialise FATFS inode 396 fatfs_inode->first_cluster = first_cluster; 190 397 191 // link fatfs_inode to vfs_inode192 vfs_inode->extend = fatfs_inode;193 194 398 return 0; 195 196 } 197 198 ////////////////////////////////////////////////////// 199 void fatfs_inode_destroy( struct vfs_inode_s * inode ) 200 { 201 printk("\n[PANIC] %s not fully implemented yet\n", __FUNCTION__ ); 202 hal_core_sleep(); 203 } 204 205 ////////////////////////////////////////////////// 206 error_t fatfs_ctx_create( struct vfs_ctx_s * ctx ) 207 { 208 printk("\n[PANIC] %s not fully implemented yet\n", __FUNCTION__ ); 209 hal_core_sleep(); 210 211 return 0; 212 } 213 214 //////////////////////////////////////////////// 215 void fatfs_ctx_destroy( struct vfs_ctx_s * ctx ) 216 { 217 printk("\n[PANIC] %s not fully implemented yet\n", __FUNCTION__ ); 218 hal_core_sleep(); 219 } 399 } 400 401 /////////////////////////////////////////////////// 402 void fatfs_inode_destroy( vfs_inode_t * vfs_inode ) 403 { 404 kmem_req_t req; 405 fatfs_inode_t * fatfs_inode; 406 407 // get pointer on FATFS inode 408 fatfs_inode = (fatfs_inode_t *)vfs_inode->extend; 409 410 req.type = KMEM_FATFS_INODE; 411 req.ptr = fatfs_inode; 412 kmem_free( &req ); 413 414 vfs_inode->extend = NULL; 415 } 416 220 417 221 418 //////////////////////////////////////////////// … … 223 420 bool_t is_read ) 224 421 { 225 // get sourcebuffer base address226 char * buffer = (char*)ppm_page2base( page );422 // get memory buffer base address 423 uint8_t * buffer = (uint8_t *)ppm_page2base( page ); 227 424 228 425 // get pointer on source mapper and page index from page descriptor 229 mapper_t * src_mapper= page->mapper;426 mapper_t * mapper = page->mapper; 230 427 uint32_t page_index = page->index; 231 428 232 if( src_mapper == NULL)233 {234 printk("\n[PANIC] in %s : no mapper for this page\n", __FUNCTION__ );235 hal_core_sleep();236 }237 238 429 // get VFS inode pointer from mapper 239 vfs_inode_t * vfs_inode = src_mapper->inode;430 vfs_inode_t * vfs_inode = mapper->inode; 240 431 241 432 // get FATFS inode pointer for VFS inode … … 246 437 247 438 // get FATFS context pointer from FATFS inode 248 fatfs_ctx_t * fatfs_ctx = fatfs_inode->ctx;439 fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_inode->ctx->extend; 249 440 250 441 // get number of sectors -
trunk/kernel/vfs/fatfs.h
r15 r23 2 2 * fatfs.h - FATFS file system API definition. 3 3 * 4 * Author Mohamed Lamine Karaoui (201 5)5 * Alain Greiner (2016 )4 * Author Mohamed Lamine Karaoui (2014,2015) 5 * Alain Greiner (2016,2017) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 28 28 #include <hal_types.h> 29 29 #include <rwlock.h> 30 #include <vfs.h> 31 32 33 /////////////////////////////////////////////////////////////////////////////////////////// 34 // The FATFS File System implements a FAT32 read/write file system. 35 /////////////////////////////////////////////////////////////////////////////////////////// 36 37 /*************** Partition Boot Sector Format **********************************/ 38 // offset | length 39 #define BS_JMPBOOT 0 , 3 40 #define BS_OEMNAME 3 , 8 41 #define BPB_BYTSPERSEC 11 , 2 42 #define BPB_SECPERCLUS 13 , 1 43 #define BPB_RSVDSECCNT 14 , 2 44 #define BPB_NUMFATS 16 , 1 45 #define BPB_ROOTENTCNT 17 , 2 46 #define BPB_TOTSEC16 19 , 2 47 #define BPB_MEDIA 21 , 1 48 #define BPB_FATSZ16 22 , 2 49 #define BPB_SECPERTRK 24 , 2 50 #define BPB_NUMHEADS 26 , 2 51 #define BPB_HIDDSEC 28 , 4 52 #define BPB_TOTSEC32 32 , 4 53 #define BPB_PARTITION_TABLE 446 , 64 54 55 // FAT 32 56 #define BPB_FAT32_FATSZ32 36 , 4 57 #define BPB_FAT32_EXTFLAGS 40 , 2 58 #define BPB_FAT32_FSVER 42 , 2 59 #define BPB_FAT32_ROOTCLUS 44 , 4 60 #define BPB_FAT32_FSINFO 48 , 2 61 #define BPB_FAT32_BKBOOTSEC 50 , 2 62 #define BS_FAT32_DRVNUM 64 , 1 63 #define BS_FAT32_BOOTSIG 66 , 1 64 #define BS_FAT32_VOLID 67 , 4 65 #define BS_FAT32_VOLLAB 71 , 11 66 #define BS_FAT32_FILSYSTYPE 82 , 8 67 68 // Partitions 69 #define FIRST_PARTITION_ACTIVE 446 , 8 70 #define FIRST_PARTITION_BEGIN_LBA 454 , 4 71 #define FIRST_PARTITION_SIZE 458 , 4 72 #define SECOND_PARTITION_ACTIVE 462 , 8 73 #define SECOND_PARTITION_BEGIN_LBA 470 , 4 74 #define SECOND_PARTITION_SIZE 474 , 4 75 #define THIRD_PARTITION_ACTIVE 478 , 8 76 #define THIRD_PARTITION_BEGIN_LBA 486 , 4 77 #define THIRD_PARTITION_SIZE 490 , 4 78 #define FOURTH_PARTITION_ACTIVE 494 , 8 79 #define FOURTH_PARTITION_BEGIN_LBA 502 , 4 80 #define FOURTH_PARTITION_SIZE 506 , 4 81 /*******************************************************************************/ 82 83 #define MBR_SIGNATURE_POSITION 510 , 2 84 #define MBR_SIGNATURE_VALUE 0xAA55 85 86 /************** FAT_FS_INFO SECTOR ********************************************/ 87 #define FS_SIGNATURE_VALUE_1 0x52526141 88 #define FS_SIGNATURE_VALUE_2 0x72724161 89 #define FS_SIGNATURE_VALUE_3 0x000055AA 90 #define FS_SIGNATURE_POSITION_1 0 , 4 91 #define FS_SIGNATURE_POSITION_2 484 , 4 92 #define FS_SIGNATURE_POSITION_3 508 , 4 93 #define FS_FREE_CLUSTERS 488 , 4 94 #define FS_FREE_CLUSTER_HINT 492 , 4 95 /*******************************************************************************/ 96 97 #define DIR_ENTRY_SIZE 32 98 99 #define NAME_MAX_SIZE 31 100 101 /******* Directory Entry Structure (32 bytes) **********************************/ 102 // offset | length 103 #define DIR_NAME 0 , 11 // dir_entry name 104 #define DIR_ATTR 11 , 1 // attributes 105 #define DIR_NTRES 12 , 1 // reserved for the OS 106 #define DIR_CRT_TIMES_TENTH 13 , 1 107 #define DIR_FST_CLUS_HI 20 , 2 // cluster index 16 MSB bits 108 #define DIR_WRT_TIME 22 , 2 // time of last write 109 #define DIR_WRT_DATE 24 , 2 // date of last write 110 #define DIR_FST_CLUS_LO 26 , 2 // cluster index 16 LSB bit 111 #define DIR_FILE_SIZE 28 , 4 // dir_entry size (up to 4 Gbytes) 112 /*******************************************************************************/ 113 114 /******* LFN Directory Entry Structure (32 bytes) *****************************/ 115 // offset | length 116 #define LDIR_ORD 0 , 1 // Sequence number (from 0x01 to 0x0f) 117 #define LDIR_NAME_1 1 , 10 // name broken into 3 parts 118 #define LDIR_ATTR 11 , 1 // attributes (must be 0x0F) 119 #define LDIR_TYPE 12 , 1 // directory type (must be 0x00) 120 #define LDIR_CHKSUM 13 , 1 // checksum of name in short dir 121 #define LDIR_NAME_2 14 , 12 122 #define LDIR_RSVD 26 , 2 // artifact of previous fat (must be 0) 123 #define LDIR_NAME_3 28 , 4 124 /*******************************************************************************/ 125 126 /*********************** DIR_ATTR values (attributes) ************************/ 127 #define ATTR_READ_ONLY 0x01 128 #define ATTR_HIDDEN 0x02 129 #define ATTR_SYSTEM 0x04 130 #define ATTR_VOLUME_ID 0x08 131 #define ATTR_DIRECTORY 0x10 132 #define ATTR_ARCHIVE 0x20 133 #define ATTR_LONG_NAME_MASK 0x0f // READ_ONLY|HIDDEN|SYSTEM|VOLUME_ID 134 /*******************************************************************************/ 135 136 /********************* DIR_ORD special values **********************************/ 137 #define FREE_ENTRY 0xE5 // this entry is free in the directory 138 #define NO_MORE_ENTRY 0x00 // no more entry in the directory 139 /*******************************************************************************/ 140 141 /******************** CLuster Index Special Values *****************************/ 142 #define FREE_CLUSTER 0x00000000 143 #define RESERVED_CLUSTER 0x00000001 144 #define BAD_CLUSTER 0x0FFFFFF7 145 #define END_OF_CHAIN_CLUSTER_MIN 0x0ffffff8 146 #define END_OF_CHAIN_CLUSTER_MAX 0x0fffffff 147 /*******************************************************************************/ 30 148 31 149 /**** Forward declarations ****/ 32 150 33 151 struct mapper_s; 34 struct device_s; 152 struct page_s; 153 struct vfs_ctx_s; 35 154 struct vfs_inode_s; 36 struct vfs_ctx_s; 37 struct page_s; 38 39 /***************************************************************************************** 40 * This structure defines a FATFS specific context extension. 155 156 /***************************************************************************************** 157 * This structure defines a FATFS specific context (extension to VFS context). 41 158 ****************************************************************************************/ 42 159 43 160 typedef struct fatfs_ctx_s 44 161 { 45 rwlock_t lock; /*! TODO protect what ??? */ 46 uint32_t fat_begin_lba; /*! first lba of FAT region */ 162 uint32_t fat_begin_lba; /*! lba of FAT region */ 47 163 uint32_t fat_sectors_count; /*! number of sectors in FAT region */ 48 164 uint32_t bytes_per_sector; /*! */ 49 165 uint32_t bytes_per_cluster; /*! */ 50 uint32_t cluster_begin_lba; /*! first lba of data region on device*/51 uint32_t sectors_per_cluster; /*! 52 uint32_t root dir_first_cluster; /**/53 uint32_t last_allocated_sector; /*! 54 uint32_t last_allocated_index; /*! TODO last allocated cluster ???*/55 xptr_t fat_mapper_xp; /*! FAT mapper (in IO cluster) */ 166 uint32_t cluster_begin_lba; /*! lba of data region */ 167 uint32_t sectors_per_cluster; /*! cluster index for root directory */ 168 uint32_t root_dir_cluster; /*! */ 169 uint32_t last_allocated_sector; /*! TODO ??? */ 170 uint32_t last_allocated_index; /*! TODO ??? */ 171 xptr_t fat_mapper_xp; /*! FAT mapper (in IO cluster) */ 56 172 } 57 173 fatfs_ctx_t; 58 174 59 175 /***************************************************************************************** 60 * This structure defines the FAT specific inode extension (versus theVFS inode).176 * This structure defines the FATFS specific inode (extension to VFS inode). 61 177 ****************************************************************************************/ 62 178 63 179 typedef struct fatfs_inode_s 64 180 { 65 struct fatfs_ctx_s * ctx; /*! local pointer on the FATFS context */ 66 uint32_t first_cluster; /*! first cluster for this file/dir */ 181 uint32_t first_cluster; /*! first cluster for this file/dir */ 67 182 } 68 183 fatfs_inode_t; … … 70 185 71 186 187 188 ////////////////////////////////////////////////////////////////////////////////////////// 189 // These functions are specific to the FATFS, and cannot be called by the VFS. 190 ////////////////////////////////////////////////////////////////////////////////////////// 191 72 192 /***************************************************************************************** 73 193 * This function returns the LBA of the first sector of a FAT cluster. … … 76 196 * @ ctx : pointer on FATFS context. 77 197 * @ cluster : cluster index in FATFS. 78 * #return the lba value.198 * @ return the lba value. 79 199 ****************************************************************************************/ 80 200 inline uint32_t fatfs_lba_from_cluster( fatfs_ctx_t * ctx, … … 105 225 uint32_t * cluster ); 106 226 227 228 229 230 ////////////////////////////////////////////////////////////////////////////////////////// 231 // These functions are called by the VFS, and must be implemented by all File Systems. 232 ////////////////////////////////////////////////////////////////////////////////////////// 233 234 /****************************************************************************************** 235 * This function initializes the FATFS file system as the root FS. 236 * It is executed cooperatively during kernel init by all CP0s in all clusters. 237 * The initilisation is made in three phases, separated by synchronisation barrier: 238 * - phase 1 : all CP0s in all clusters allocate memory for the local copy of 239 * the FATFS context. 240 * - phase 2 : cluster_0 only creates the root inode descriptor, access the external 241 * device to get information stored on the boot record, and initialises both 242 * the VFS context, and the FATFS context. 243 * - phase 3 : all other clusters initialize their local VFS context and FATFS context 244 * from values contained in cluster_0, using hal_remote_memcpy(). 245 ****************************************************************************************** 246 * @ return an extended pointer on the created root inode / return XPTR_NULL if failure. 247 *****************************************************************************************/ 248 xptr_t fatfs_init(); 249 250 /****************************************************************************************** 251 * This function mount the FATFS on the root FS. 252 * TODO not implemented [AG] 253 ****************************************************************************************** 254 * @ parent_inode_xp : extended pointer on the parent inode. 255 *****************************************************************************************/ 256 error_t fatfs_mount( xptr_t parent_inode_xp ); 257 258 259 /***************************************************************************************** 260 * This function initializes both the VFS context and the FATFS context. 261 * Both the VFS context and the FATFS context must have been previously allocated. 262 * It access the device to read the boot record, and is supposed to be called only 263 * in cluster_0 (in other clusters these contexts are replicated from values 264 * contained in cluster_0). 265 ***************************************************************************************** 266 * @ vfs_ctx : local pointer on VFS context for FATFS. 267 * @ fatfs_ctx : local pointer on specific FATFS context. 268 * @ root_inode_xp : extended pointer on VFS root inode. 269 ****************************************************************************************/ 270 error_t fatfs_ctx_init( struct vfs_ctx_s * vfs_ctx, 271 struct fatfs_ctx_s * fatfs_ctx, 272 xptr_t root_inode_xp ); 273 274 /***************************************************************************************** 275 * This function releases memory dynamically allocated for the FATFS context extension. 276 ***************************************************************************************** 277 * @ vfs_ctx : local pointer on VFS context. 278 ****************************************************************************************/ 279 void fatfs_ctx_destroy( struct vfs_ctx_s * vfs_ctx ); 280 281 282 107 283 /***************************************************************************************** 108 284 * This function allocates memory for a FATFS inode, initializes it, 109 285 * and link it to the VFS inode. 110 286 ***************************************************************************************** 287 * @ inode : local pointer on the VFS inode. 288 * @ first_cluster : first cluster index in the FAT32. 289 * @ return 0 if success / return ENOMEM if error. 290 ****************************************************************************************/ 291 error_t fatfs_inode_create( struct vfs_inode_s * inode, 292 uint32_t first_cluster); 293 294 /***************************************************************************************** 295 * This function releases memory allocated for a FATFS inode. 296 ***************************************************************************************** 111 297 * @ inode : local pointer on vfs_inode. 112 * @ return 0 if success / return ENOMEM if error.113 ****************************************************************************************/114 error_t fatfs_inode_create( struct vfs_inode_s * inode );115 116 /*****************************************************************************************117 * This function releases memory allocated for a FATFS inode.118 *****************************************************************************************119 * @ inode : local pointer on vfs_inode.120 298 ****************************************************************************************/ 121 299 void fatfs_inode_destroy( struct vfs_inode_s * inode ); 122 300 123 /***************************************************************************************** 124 * This function allocates memory for a FATFS context, initialises it, 125 * and link it to the local VFS context. 126 ***************************************************************************************** 127 * @ inode : local pointer on VFS context. 128 * @ return 0 if success / return ENOMEM if error. 129 ****************************************************************************************/ 130 error_t fatfs_ctx_create( struct vfs_ctx_s * ctx ); 131 132 /***************************************************************************************** 133 * This function releases memory allocated for a FATFS context. 134 ***************************************************************************************** 135 * @ ctx : local pointer on VFS context. 136 ****************************************************************************************/ 137 void fatfs_ctx_destroy( struct vfs_ctx_s * ctx ); 138 139 /***************************************************************************************** 140 * This function moves a page from the mapper to the FATFS file system. 301 302 303 /***************************************************************************************** 304 * This function moves a page from the mapper to the FATFS file system on device. 141 305 * It must be called by a thread running in cluster containing the mapper. 142 * The pointer on the mapper and the page index in file are supposed to beregistered306 * The pointer on the mapper and the page index in file are registered 143 307 * in the page descriptor. 144 308 ***************************************************************************************** … … 151 315 * This function moves a page from the FATFS file system on device to the mapper. 152 316 * It must be called by a thread running in cluster containing the mapper. 153 * The pointer on the mapper and the page index in file are supposed to beregistered317 * The pointer on the mapper and the page index in file are registered 154 318 * in the page descriptor. 155 319 ***************************************************************************************** … … 160 324 161 325 326 327 162 328 #endif /* _FATFS_H_ */ -
trunk/kernel/vfs/ramfs.c
r15 r23 2 2 * ramfs.c RAMFS file system API implementation. 3 3 * 4 * Authors Mohamed Lamine Karaoui (201 5)5 * Alain Greiner (2016 )4 * Authors Mohamed Lamine Karaoui (2014,2015) 5 * Alain Greiner (2016,2017) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 32 32 33 33 34 ///////////////////////////////////////////////////////////////////////////////////////35 // RAMFS specific functions : these static functions cannot be called by the VFS36 ///////////////////////////////////////////////////////////////////////////////////////37 34 38 35 39 36 40 37 /////////////////////////////////////////////////////////////////////////////////////// 41 // Generic API : the following functions are called by the VFS, 42 // and must be defined by all supported file systems. 38 // The following functions are called by the VFS. 43 39 /////////////////////////////////////////////////////////////////////////////////////// 44 40 45 //////////////////////////////////////////////////////////// 46 error_t ramfs_inode_create( struct vfs_inode_s * vfs_inode ) 41 ////////////////////////////////////////////// 42 error_t ramfs_mount( xptr_t parent_inode_xp, 43 char * ramfs_root_name ) 47 44 { 48 printk("\n[PANIC] %s not fully implemented yet\n", __FUNCTION__ ); 49 hal_core_sleep(); 45 xptr_t root_inode_xp; // unused 46 47 // create VFS dentry and VFS inode for RAMFS root directory 48 return vfs_add_child_in_parent( INODE_TYPE_DIR, 49 FS_TYPE_RAMFS, 50 parent_inode_xp, 51 ramfs_root_name, 52 &root_inode_xp ); 53 } 50 54 51 kmem_req_t req;52 ramfs_inode_t * ramfs_inode;53 55 54 // allocate memory for ramfs inode 55 req.type = KMEM_RAMFS_INODE; 56 req.size = sizeof(ramfs_inode_t); 57 req.flags = AF_KERNEL | AF_ZERO; 58 ramfs_inode = (ramfs_inode_t *)kmem_alloc( &req ); 56 //////////////////////////////////////////// 57 error_t ramfs_ctx_init( vfs_ctx_t * vfs_ctx, 58 xptr_t root_inode_xp ) 59 59 60 if( ramfs_inode == NULL ) return ENOMEM; 60 { 61 vfs_ctx->type = FS_TYPE_RAMFS; 62 vfs_ctx->attr = 0; // not READ_ONLY / not SYNC 63 vfs_ctx->count = 0; // unused for RAMFS 64 vfs_ctx->blksize = 512; // unused for RAMFS 65 vfs_ctx->root_xp = root_inode_xp; 66 vfs_ctx->extend = NULL; // unused for DEVFS 61 67 62 // initialise ramfs_inode TODO68 spinlock_init( &vfs_ctx->lock ); 63 69 64 // link vfs_inode to ramfs_inode 65 vfs_inode->extend = ramfs_inode; 70 bitmap_init( vfs_ctx->bitmap , CONFIG_VFS_MAX_INODES ); 66 71 67 72 return 0; 68 73 } 69 74 70 //////////////////////////////////////////////////////71 void ramfs_inode_destroy( struct vfs_inode_s * inode )72 {73 assert( false , __FUNCTION__ , "not fully implemented yet" );74 }75 76 /////////////////////////////////////////////////77 error_t ramfs_write_page( struct page_s * page )78 {79 printk("\n[PANIC] %s not fully implemented yet\n", __FUNCTION__ );80 hal_core_sleep();81 82 return 0;83 }84 85 ////////////////////////////////////////////////86 error_t ramfs_read_page( struct page_s * page )87 {88 printk("\n[PANIC] %s not fully implemented yet\n", __FUNCTION__ );89 hal_core_sleep();90 91 return 0;92 }93 -
trunk/kernel/vfs/ramfs.h
r15 r23 2 2 * ramfs.h RAMFS file system API definition. 3 3 * 4 * Authors Mohamed Lamine Karaoui (201 5)5 * Alain Greiner (2016 )4 * Authors Mohamed Lamine Karaoui (2014,2015) 5 * Alain Greiner (2016,2017) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 26 26 #define _RAMFS_H_ 27 27 28 /////////////////////////////////////////////////////////////////////////////////////////// 29 // The RAMFS File System Rdoes not uses any external device to store data. 30 // It stores the dynamically created files and directories in the VFS mappers. 31 // The ramfs_read_page() and ramfs_write_page() functions should never be used. 32 // The RAMFS cannot be used as the root FS. 33 // There is no RAMFS context extension, and no RAMFS inode extension. 34 /////////////////////////////////////////////////////////////////////////////////////////// 35 36 28 37 /**** Forward declarations ****/ 29 38 30 struct vfs_inode_s; 31 struct page_s; 39 40 ////////////////////////////////////////////////////////////////////////////////////////// 41 // These functions are called by the VFS, and must be implemented by all FS. 42 ////////////////////////////////////////////////////////////////////////////////////////// 43 44 /****************************************************************************************** 45 * This function does not exist, as the RAMFS cannot be the root FS. 46 *****************************************************************************************/ 47 xptr_t ramfs_init(); 48 49 /****************************************************************************************** 50 * This function mount a RAMFS on a given inode of the root FS. 51 * It actually creates a new VFS dentry in the cluster containing the parent inode, 52 * and create a new VFS inode in another cluster. 53 ****************************************************************************************** 54 * @ parent_inode_xp : extended pointer on the parent inode. 55 * @ ramfs_root_name : RAMFS root directory name. 56 *****************************************************************************************/ 57 error_t ramfs_mount( xptr_t parent_inode_xp, 58 char * ramfs_root_name ); 32 59 33 60 /***************************************************************************************** 34 * This structure defines a RAMFS specific context extension. 61 * This function initializes all fields of the VFS context. 62 * No extra memory is allocated for a RAMFS context. 35 63 ****************************************************************************************/ 36 37 typedef struct ramfs_ctx_s 38 { 39 intptr_t base; 40 rwlock_t size; 41 } 42 ramfs_ctx_t; 64 error_t ramfs_ctx_init( struct vfs_ctx_s * vfs_ctx, 65 xptr_t root_inode_xp ); 43 66 44 67 /***************************************************************************************** 45 * This structure defines the RAMFS inode specific extension (versus the VFS inode).68 * This function does not exist for a RAMFS context, as there is no RAMFS context. 46 69 ****************************************************************************************/ 47 48 typedef struct ramfs_inode_s 49 { 50 struct vfs_inode_s * vfs_inode; /*! local pointer on VFS inode */ 51 } 52 ramfs_inode_t; 53 54 55 70 error_t ramfs_ctx_destroy(); 56 71 57 72 /***************************************************************************************** 58 * This function allocates memory for a RAMFS inode, and link it to the VFS inode. 59 ***************************************************************************************** 60 * @ inode : local pointer on vfs_inode. 61 * @ return 0 if success / return ENOMEM if error. 73 * This function does not exist, as the RAMFS does not use a RAMFS inode extension. 62 74 ****************************************************************************************/ 63 75 error_t ramfs_inode_create( struct vfs_inode_s * inode ); 64 76 65 77 /***************************************************************************************** 66 * This function releases memory allocated for a RAMFS inode. 67 ***************************************************************************************** 68 * @ inode : local pointer on vfs_inode. 78 * This function does not exist, as the RAMFS does not use a RAMFS inode extension. 69 79 ****************************************************************************************/ 70 80 void ramfs_inode_destroy( struct vfs_inode_s * inode ); 71 81 72 82 /***************************************************************************************** 73 * This function moves a page from the mapper to the RAMFS file system. 74 * It must be called by a thread running in cluster containing the mapper. 75 * The pointer on the mapper and the page index in file are supposed to be registered 76 * in the page descriptor. 77 ****************************************************************************************** 78 * @ page : local pointer on source page descriptor. 79 * @ return 0 if success / return EIO if error. 83 * This function does nothing for the RAMFS File System. 80 84 ****************************************************************************************/ 81 error_t ramfs_write_page( struct page_s 85 error_t ramfs_write_page( struct page_s * page ); 82 86 83 87 /***************************************************************************************** 84 * This function moves a page from the RAMFS file system to the mapper. 85 * It must be called by a thread running in cluster containing the mapper. 86 * The pointer on the mapper and the page index in file are supposed to be registered 87 * in the page descriptor. 88 ***************************************************************************************** 89 * @ page : local pointer on destination page descriptor. 90 * @ return 0 if success / return EIO if error. 88 * This function does not exist for the RAMFS File System. 91 89 ****************************************************************************************/ 92 error_t ramfs_read_page( struct page_s 90 error_t ramfs_read_page( struct page_s * page ); 93 91 94 92 95 96 93 #endif /* _RAMFS_H_ */ -
trunk/kernel/vfs/vfs.c
r14 r23 35 35 #include <slist.h> 36 36 #include <xhtab.h> 37 #include <rpc.h> 37 38 #include <errno.h> 38 39 #include <kmem.h> … … 40 41 #include <thread.h> 41 42 #include <process.h> 43 #include <vfs.h> 42 44 #include <fatfs.h> 43 45 #include <ramfs.h> 44 #include <vfs.h> 46 #include <devfs.h> 47 #include <syscalls.h> 45 48 46 49 … … 49 52 ////////////////////////////////////////////////////////////////////////////////////////// 50 53 51 // array of supported FS contexts (indexed by the FS type)54 // array of supported FS contexts 52 55 vfs_ctx_t fs_context[FS_TYPES_NR]; 53 56 … … 56 59 ////////////////////////////////////////////////////////////////////////////////////////// 57 60 58 //////////////////////////////////////////// /////61 //////////////////////////////////////////// 59 62 error_t vfs_ctx_inum_alloc( vfs_ctx_t * ctx, 60 63 uint32_t * inum ) … … 64 67 65 68 // get lid from local inum allocator 66 uint32_t lid = bitmap_ffc( ctx-> inum, CONFIG_VFS_MAX_INODES );69 uint32_t lid = bitmap_ffc( ctx->bitmap , CONFIG_VFS_MAX_INODES ); 67 70 68 71 if( lid == -1 ) // no more free slot => error … … 77 80 { 78 81 // set slot allocated 79 bitmap_set( ctx-> inum, lid );82 bitmap_set( ctx->bitmap , lid ); 80 83 81 84 // release lock … … 92 95 uint32_t inum ) 93 96 { 94 bitmap_clear( ctx-> inum, inum & 0xFFFF );97 bitmap_clear( ctx->bitmap , inum & 0xFFFF ); 95 98 } 96 99 … … 99 102 ////////////////////////////////////////////////////////////////////////////////////////// 100 103 101 //////////////////////////////////////////////// 102 error_t vfs_inode_create( xptr_t dentry_xp, 103 uint32_t type, 104 uint32_t attr, 105 uint32_t mode, 106 uid_t uid, 107 gid_t gid, 108 xptr_t * inode_xp ) 104 ////////////////////////////////////////////////////// 105 106 error_t vfs_inode_create( xptr_t dentry_xp, 107 vfs_fs_type_t fs_type, 108 vfs_inode_type_t inode_type, 109 uint32_t attr, 110 uint32_t rights, 111 uid_t uid, 112 gid_t gid, 113 xptr_t * inode_xp ) 109 114 { 110 115 mapper_t * mapper; // associated mapper( to be allocated) … … 115 120 error_t error; 116 121 117 // check type and get pointer on context 118 if ( type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS]; 119 else if( type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS]; 122 // check fs type and get pointer on context 123 if ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS]; 124 else if( fs_type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS]; 125 else if( fs_type == FS_TYPE_DEVFS ) ctx = &fs_context[FS_TYPE_DEVFS]; 120 126 else 121 127 { … … 144 150 } 145 151 146 // allocate memory for inode descriptor152 // allocate memory for VFS inode descriptor 147 153 req.type = KMEM_VFS_INODE; 148 154 req.size = sizeof(vfs_inode_t); … … 160 166 // initialize inode descriptor 161 167 inode->gc = 0; 168 inode->type = inode_type; 162 169 inode->inum = inum; 163 170 inode->attr = attr; 164 inode-> mode = mode;171 inode->rights = rights; 165 172 inode->uid = uid; 166 173 inode->gid = gid; … … 174 181 175 182 // initialize dentries hash table, if new inode is a directory 176 if( attr & INODE_ATTR_DIR )xhtab_init( &inode->children , XHTAB_DENTRY_TYPE );183 if( inode_type == INODE_TYPE_DIR ) xhtab_init( &inode->children , XHTAB_DENTRY_TYPE ); 177 184 178 185 // initialize inode locks 179 186 remote_rwlock_init( XPTR( local_cxy , &inode->data_lock ) ); 180 187 remote_spinlock_init( XPTR( local_cxy , &inode->main_lock ) ); 181 182 // create FS specific inode183 if ( ctx->type == FS_TYPE_FATFS ) fatfs_inode_create( inode );184 else if( ctx->type == FS_TYPE_RAMFS ) ramfs_inode_create( inode );185 188 186 189 // return extended pointer on inode … … 284 287 ////////////////////////////////////////////////////////////////////////////////////////// 285 288 286 ////////////////////////////////////////////// 287 error_t vfs_dentry_create( uint32_ttype,288 char * name,289 vfs_inode_t * parent,290 xptr_t * dentry_xp )289 /////////////////////////////////////////////////// 290 error_t vfs_dentry_create( vfs_fs_type_t fs_type, 291 char * name, 292 vfs_inode_t * parent, 293 xptr_t * dentry_xp ) 291 294 { 292 295 vfs_ctx_t * ctx; // context descriptor 293 296 vfs_dentry_t * dentry; // dentry descriptor (to be allocated) 294 297 kmem_req_t req; // request to kernel memory allocator 295 xptr_t xhtab_xp; // extended pointer on xhtab_t embedded in inode 296 xptr_t xlist_xp; // extended pointer on xlist_entry_t in dentry 298 299 printk("\n @@@ dentry_create : 0 / name = %s\n", name ); 297 300 298 301 // check type and get pointer on context 299 if ( type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS]; 300 else if( type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS]; 302 if ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS]; 303 else if( fs_type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS]; 304 else if( fs_type == FS_TYPE_DEVFS ) ctx = &fs_context[FS_TYPE_DEVFS]; 301 305 else 302 306 { … … 309 313 uint32_t length = strlen( name ); 310 314 311 if( length > (CONFIG_VFS_MAX_NAME_LENGTH - 1))315 if( length >= CONFIG_VFS_MAX_NAME_LENGTH ) 312 316 { 313 317 printk("\n[ERROR] in %s : name too long\n", __FUNCTION__ ); 314 318 return EINVAL; 315 319 } 320 321 printk("\n @@@ dentry_create : 1 / name = %s\n", name ); 316 322 317 323 // allocate memory for dentry descriptor … … 328 334 329 335 // initialize dentry descriptor 336 330 337 dentry->ctx = ctx; 331 338 dentry->length = length; … … 333 340 strcpy( dentry->name , name ); 334 341 335 // return extended pointer on dentry to caller 342 printk("\n @@@ dentry_create : 2 / name = %s\n", name ); 343 344 // register dentry in hash table rooted in parent inode 345 xhtab_insert( XPTR( local_cxy , &parent->children ), 346 name, 347 XPTR( local_cxy , &dentry->xlist ) ); 348 349 printk("\n @@@ dentry_create : 3 / name = %s\n", name ); 350 351 // return extended pointer on dentry 336 352 *dentry_xp = XPTR( local_cxy , dentry ); 337 353 338 // register dentry in hash table rooted in parent inode339 xhtab_xp = XPTR( local_cxy , &parent->children );340 xlist_xp = XPTR( local_cxy , &dentry->xlist );341 xhtab_register( xhtab_xp , name , xlist_xp );342 343 354 return 0; 344 355 … … 365 376 ////////////////////////////////////////////////////////////////////////////////////////// 366 377 367 //////////////////////////////////////// 368 void vfs_file_count_up( xptr_t file_xp ) 369 { 370 // get file cluster and local pointer 371 cxy_t file_cxy = GET_CXY( file_xp ); 372 vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 373 374 // atomically increment count 375 hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , 1 ); 376 } 377 378 ////////////////////////////////////////// 379 void vfs_file_count_down( xptr_t file_xp ) 380 { 381 // get file cluster and local pointer 382 cxy_t file_cxy = GET_CXY( file_xp ); 383 vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 384 385 // atomically decrement count 386 hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , -1 ); 387 } 388 389 //////////////////////////////////////////////// 390 error_t vfs_file_create( xptr_t inode_xp, 391 uint32_t type, 378 ///////////////////////////////////////////// 379 error_t vfs_file_create( vfs_inode_t * inode, 392 380 uint32_t attr, 393 xptr_t * file_xp ) 394 { 395 vfs_file_t * file _ptr;381 xptr_t * file_xp ) 382 { 383 vfs_file_t * file; 396 384 kmem_req_t req; 397 398 // get inode cluster and local pointer399 cxy_t inode_cxy = GET_CXY( inode_xp );400 vfs_inode_t * inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );401 402 // check cluster identifier403 if( inode_cxy != local_cxy )404 {405 printk("\n[PANIC] in %s : local cluster is not the inode owner\n", __FUNCTION__ );406 hal_core_sleep();407 }408 385 409 386 // allocate memory for new file descriptor … … 411 388 req.size = sizeof(vfs_file_t); 412 389 req.flags = AF_KERNEL | AF_ZERO; 413 file_ptr = (vfs_file_t *)kmem_alloc( &req ); 414 415 if( file_ptr == NULL ) return ENOMEM; 416 417 // get inode local pointer 390 file = (vfs_file_t *)kmem_alloc( &req ); 391 392 if( file == NULL ) return ENOMEM; 393 418 394 // initializes new file descriptor 419 file_ptr->gc = 0; 420 file_ptr->type = type; 421 file_ptr->attr = attr; 422 file_ptr->offset = 0; 423 file_ptr->refcount = 0; 424 file_ptr->inode = inode_ptr; 425 file_ptr->ctx = inode_ptr->ctx; 426 file_ptr->mapper = inode_ptr->mapper; 427 428 remote_rwlock_init( XPTR( local_cxy , &file_ptr->lock ) ); 429 430 *file_xp = XPTR( local_cxy , file_ptr ); 431 return 0; 432 } 433 434 //////////////////////////////////////// 435 void vfs_file_destroy( xptr_t file_xp ) 436 { 437 // get file cluster and local pointer 438 cxy_t file_cxy = GET_CXY( file_xp ); 439 vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 440 441 if( file_cxy != local_cxy ) 442 { 443 printk("\n[PANIC] in %s : file descriptor not in local cluster\n", __FUNCTION__ ); 444 hal_core_sleep(); 445 } 446 447 if( file_ptr->refcount ) 395 file->gc = 0; 396 file->type = inode->type; 397 file->attr = attr; 398 file->offset = 0; 399 file->refcount = 0; 400 file->inode = inode; 401 file->ctx = inode->ctx; 402 file->mapper = inode->mapper; 403 404 remote_rwlock_init( XPTR( local_cxy , &file->lock ) ); 405 406 *file_xp = XPTR( local_cxy , file ); 407 return 0; 408 409 } // end vfs_file_create() 410 411 /////////////////////////////////////////// 412 void vfs_file_destroy( vfs_file_t * file ) 413 { 414 if( file->refcount ) 448 415 { 449 416 printk("\n[PANIC] in %s : file refcount non zero\n", __FUNCTION__ ); … … 452 419 453 420 kmem_req_t req; 454 req.ptr = file _ptr;421 req.ptr = file; 455 422 req.type = KMEM_VFS_FILE; 456 423 kmem_free( &req ); 457 } 458 459 ////////////////////////////////////////////////////////////////////////////////////////// 460 // File related functions 424 425 } // end vfs_file_destroy() 426 427 428 //////////////////////////////////////// 429 void vfs_file_count_up( xptr_t file_xp ) 430 { 431 // get file cluster and local pointer 432 cxy_t file_cxy = GET_CXY( file_xp ); 433 vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 434 435 // atomically increment count 436 hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , 1 ); 437 } 438 439 ////////////////////////////////////////// 440 void vfs_file_count_down( xptr_t file_xp ) 441 { 442 // get file cluster and local pointer 443 cxy_t file_cxy = GET_CXY( file_xp ); 444 vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 445 446 // atomically decrement count 447 hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , -1 ); 448 } 449 450 ////////////////////////////////////////////////////////////////////////////////////////// 451 // File access related functions 461 452 ////////////////////////////////////////////////////////////////////////////////////////// 462 453 … … 465 456 char * path, 466 457 uint32_t flags, 467 xptr_t * file_xp ) 468 { 469 return 0; 470 } 471 472 /////////////////////////////////// 473 uint32_t vfs_read( xptr_t file_xp, 474 void * buffer, 475 uint32_t size ) 476 { 477 return 0; 478 } 479 480 //////////////////////////////////// 481 uint32_t vfs_write( xptr_t file_xp, 482 void * buffer, 483 uint32_t size ) 484 { 485 return 0; 486 } 458 uint32_t mode, 459 xptr_t * new_file_xp, 460 uint32_t * new_file_id ) 461 { 462 error_t error; 463 xptr_t inode_xp; // extended pointer on target inode 464 cxy_t inode_cxy; // inode cluster identifier 465 vfs_inode_t * inode_ptr; // inode local pointer 466 uint32_t file_attr; // file descriptor attributes 467 uint32_t lookup_mode; // lookup working mode 468 xptr_t file_xp; // extended pointer on created file descriptor 469 uint32_t file_id; // created file descriptor index in reference fd_array 470 471 // compute lookup working mode 472 lookup_mode = VFS_LOOKUP_OPEN; 473 if( (flags & O_DIR ) ) lookup_mode |= VFS_LOOKUP_DIR; 474 if( (flags & O_CREAT ) ) lookup_mode |= VFS_LOOKUP_CREATE; 475 if( (flags & O_EXCL ) ) lookup_mode |= VFS_LOOKUP_EXCL; 476 477 // compute attributes for the created file 478 file_attr = 0; 479 if( (flags & O_RDONLY ) == 0 ) file_attr |= FD_ATTR_READ_ENABLE; 480 if( (flags & O_WRONLY ) == 0 ) file_attr |= FD_ATTR_WRITE_ENABLE; 481 if( (flags & O_SYNC ) ) file_attr |= FD_ATTR_SYNC; 482 if( (flags & O_APPEND ) ) file_attr |= FD_ATTR_APPEND; 483 if( (flags & O_CLOEXEC) ) file_attr |= FD_ATTR_CLOSE_EXEC; 484 485 // get extended pointer on target inode 486 error = vfs_lookup( cwd_xp , path , lookup_mode , &inode_xp ); 487 488 if( error ) return error; 489 490 // get target inode cluster and local pointer 491 inode_cxy = GET_CXY( inode_xp ); 492 inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp ); 493 494 // create a new file descriptor in cluster containing inode 495 if( inode_cxy == local_cxy ) // target cluster is local 496 { 497 error = vfs_file_create( inode_ptr , file_attr , &file_xp ); 498 } 499 else // target cluster is remote 500 { 501 rpc_vfs_file_create_client( inode_cxy , inode_ptr , file_attr , &file_xp , &error ); 502 } 503 504 if( error ) return error; 505 506 // allocate and register a new file descriptor index in reference cluster fd_array 507 error = process_fd_register( file_xp , &file_id ); 508 509 if( error ) return error; 510 511 // success 512 *new_file_xp = file_xp; 513 *new_file_id = file_id; 514 return 0; 515 516 } // end vfs_open() 517 518 ///////////////////////////////////// 519 error_t vfs_move( bool_t to_buffer, 520 xptr_t file_xp, 521 void * buffer, 522 uint32_t size ) 523 { 524 assert( ( file_xp != XPTR_NULL ) , __FUNCTION__ , "file_xp == XPTR_NULL" ); 525 526 cxy_t file_cxy; // remote file descriptor cluster 527 vfs_file_t * file_ptr; // remote file descriptor local pointer 528 vfs_inode_type_t inode_type; 529 uint32_t file_offset; // current offset in file 530 mapper_t * mapper; 531 error_t error; 532 533 // get cluster and local pointer on remote file descriptor 534 file_cxy = GET_CXY( file_xp ); 535 file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 536 537 // get inode type from remote file descriptor 538 inode_type = hal_remote_lw( XPTR( file_cxy , &file_ptr->type ) ); 539 540 // action depends on inode type 541 if( inode_type == INODE_TYPE_FILE ) 542 { 543 // get mapper pointer and file offset from file descriptor 544 file_offset = hal_remote_lw( XPTR( file_cxy , &file_ptr->offset ) ); 545 mapper = (mapper_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) ); 546 547 // move data between mapper and buffer 548 if( file_cxy == local_cxy ) 549 { 550 error = mapper_move( mapper, 551 to_buffer, 552 file_offset, 553 buffer, 554 size ); 555 } 556 else 557 { 558 rpc_mapper_move_client( file_cxy, 559 mapper, 560 to_buffer, 561 file_offset, 562 buffer, 563 size, 564 &error ); 565 } 566 567 return error; 568 } 569 else if (inode_type == INODE_TYPE_DIR ) 570 { 571 printk("\n[ERROR] in %s : inode is a directory", __FUNCTION__ ); 572 return EINVAL; 573 } 574 else if (inode_type == INODE_TYPE_DEV ) 575 { 576 // TODO 577 return 0; 578 } 579 else 580 { 581 printk("\n[PANIC] in %s : illegal inode type\n", __FUNCTION__ ); 582 hal_core_sleep(); 583 return -1; 584 } 585 } // end vfs_access() 487 586 488 587 ////////////////////////////////////// … … 492 591 uint32_t * new_offset ) 493 592 { 494 return 0; 495 } 496 497 ////////////////////////////////////// 498 error_t vfs_close( xptr_t file_xp, 499 uint32_t * refcount ) 500 { 501 return 0; 502 } 593 printk("\n[PANIC] %s non implemented\n", __FUNCTION__ ); 594 hal_core_sleep(); 595 return 0; 596 597 assert( ( file_xp != XPTR_NULL ) , __FUNCTION__ , "file_xp == XPTR_NULL" ); 598 599 } // vfs_lseek() 600 601 /////////////////////////////////// 602 error_t vfs_close( xptr_t file_xp, 603 uint32_t file_id ) 604 { 605 assert( (file_xp != XPTR_NULL) , __FUNCTION__ , "file_xp == XPTR_NULL" ); 606 607 assert( (file_id < CONFIG_PROCESS_FILE_MAX_NR) , __FUNCTION__ , "illegal file_id" ); 608 609 thread_t * this = CURRENT_THREAD; 610 process_t * process = this->process; 611 612 // get cluster and local pointer on remote file descriptor 613 cxy_t file_cxy = GET_CXY( file_xp ); 614 vfs_file_t * file_ptr = (vfs_file_t *)GET_PTR( file_xp ); 615 616 // get local pointer on local cluster manager 617 cluster_t * cluster = LOCAL_CLUSTER; 618 619 // get owner process cluster and lpid 620 cxy_t owner_cxy = CXY_FROM_PID( process->pid ); 621 lpid_t lpid = LPID_FROM_PID( process->pid ); 622 623 // get extended pointers on copies root and lock 624 xptr_t root_xp = XPTR( owner_cxy , &cluster->pmgr.copies_root[lpid] ); 625 xptr_t lock_xp = XPTR( owner_cxy , &cluster->pmgr.copies_lock[lpid] ); 626 627 // take the lock protecting the copies 628 remote_spinlock_lock( lock_xp ); 629 630 // 1) loop on the process descriptor copies to cancel all fd_array[file_id] entries 631 xptr_t iter_xp; 632 XLIST_FOREACH( root_xp , iter_xp ) 633 { 634 xptr_t process_xp = XLIST_ELEMENT( iter_xp , process_t , copies_list ); 635 cxy_t process_cxy = GET_CXY( process_xp ); 636 process_t * process_ptr = (process_t *)GET_PTR( process_xp ); 637 638 xptr_t lock_xp = XPTR( process_cxy , &process_ptr->fd_array.lock ); 639 xptr_t entry_xp = XPTR( process_cxy , &process_ptr->fd_array.array[file_id] ); 640 641 // lock is required for atomic write of a 64 bits word 642 remote_rwlock_wr_lock( lock_xp ); 643 hal_remote_swd( entry_xp , XPTR_NULL ); 644 remote_rwlock_wr_unlock( lock_xp ); 645 646 hal_wbflush(); 647 } 648 649 // 2) release memory allocated to file descriptor in remote cluster 650 if( file_cxy == local_cxy ) // file cluster is local 651 { 652 vfs_file_destroy( file_ptr ); 653 } 654 else // file cluster is local 655 { 656 rpc_vfs_file_destroy_client( file_cxy , file_ptr ); 657 } 658 659 return 0; 660 661 } // end vfs_close() 503 662 504 663 //////////////////////////////////// … … 506 665 char * path ) 507 666 { 667 printk("\n[PANIC] %s non implemented\n", __FUNCTION__ ); 668 hal_core_sleep(); 669 return 0; 670 } // vfs_unlink() 671 672 /////////////////////////////////////// 673 error_t vfs_stat( xptr_t file_xp, 674 vfs_stat_t * k_stat ) 675 { 676 printk("\n[PANIC] %s non implemented\n", __FUNCTION__ ); 677 hal_core_sleep(); 678 return 0; 679 } 680 681 //////////////////////////////////////////// 682 error_t vfs_readdir( xptr_t file_xp, 683 vfs_dirent_t * k_dirent ) 684 { 685 printk("\n[PANIC] %s non implemented\n", __FUNCTION__ ); 686 hal_core_sleep(); 508 687 return 0; 509 688 } 510 689 511 690 ////////////////////////////////////// 512 error_t vfs_stat( xptr_t file_xp, 513 vfs_stat_t * stat ) 514 { 515 return 0; 516 } 517 518 ////////////////////////////////////////////////////////////////////////////////////////// 519 // Directory related functions 520 ////////////////////////////////////////////////////////////////////////////////////////// 521 522 523 524 525 526 ////////////////////////////////////////////////////////////////////////////////////////// 691 error_t vfs_mkdir( xptr_t file_xp, 692 char * path, 693 uint32_t mode ) 694 { 695 printk("\n[PANIC] %s non implemented\n", __FUNCTION__ ); 696 hal_core_sleep(); 697 return 0; 698 } 699 700 //////////////////////////////////// 701 error_t vfs_rmdir( xptr_t file_xp, 702 char * path ) 703 { 704 printk("\n[PANIC] %s non implemented\n", __FUNCTION__ ); 705 hal_core_sleep(); 706 return 0; 707 } 708 709 /////////////////////////////////// 710 error_t vfs_chdir( xptr_t cwd_xp, 711 char * path ) 712 { 713 error_t error; 714 xptr_t inode_xp; // extended pointer on target inode 715 cxy_t inode_cxy; // target inode cluster identifier 716 vfs_inode_t * inode_ptr; // target inode local pointer 717 uint32_t mode; // lookup working mode 718 vfs_inode_type_t inode_type; // target inode type 719 720 // set lookup working mode 721 mode = 0; 722 723 // get extended pointer on target inode 724 error = vfs_lookup( cwd_xp , path , mode , &inode_xp ); 725 726 if( error ) return error; 727 728 // get inode cluster and local pointer 729 inode_cxy = GET_CXY( inode_xp ); 730 inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp ); 731 732 // get inode type from remote file 733 inode_type = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->type ) ); 734 735 if( inode_type != INODE_TYPE_DIR ) 736 { 737 CURRENT_THREAD->errno = ENOTDIR; 738 return -1; 739 } 740 741 printk("\n[PANIC] %s non fully implemented\n", __FUNCTION__ ); 742 hal_core_sleep(); 743 return 0; 744 } 745 746 /////////////////////////////////// 747 error_t vfs_chmod( xptr_t cwd_xp, 748 char * path, 749 uint32_t rights ) 750 { 751 error_t error; 752 xptr_t inode_xp; // extended pointer on target inode 753 cxy_t inode_cxy; // inode cluster identifier 754 vfs_inode_t * inode_ptr; // inode local pointer 755 uint32_t mode; // lookup working mode 756 vfs_inode_type_t inode_type; // target inode type 757 758 // set lookup working mode 759 mode = 0; 760 761 // get extended pointer on target inode 762 error = vfs_lookup( cwd_xp , path , mode , &inode_xp ); 763 764 if( error ) return error; 765 766 // get inode cluster and local pointer 767 inode_cxy = GET_CXY( inode_xp ); 768 inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp ); 769 770 // get inode type from remote inode 771 inode_type = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->type ) ); 772 773 774 printk("\n[PANIC] %s non fully implemented\n", __FUNCTION__ ); 775 hal_core_sleep(); 776 return 0; 777 } 778 779 /////////////////////////////////// 780 error_t vfs_mkfifo( xptr_t cwd_xp, 781 char * path, 782 uint32_t rights ) 783 { 784 printk("\n[PANIC] in %s : not implemented yet\n", __FUNCTION__ ); 785 hal_core_sleep(); 786 return 0; 787 } 788 789 790 791 /////////////////////////////////////////////////////////////////////////////////////////r 527 792 // Inode Tree functions 528 793 ////////////////////////////////////////////////////////////////////////////////////////// 529 794 530 795 ////////////////////////////////////////////////////////////////////////////////////////// 531 // This staticfunction is used by the vfs_lookup() function.796 // This function is used by the vfs_lookup() function. 532 797 // It takes an extended pointer on a remote inode (parent directory inode), 533 798 // and check access_rights violation for the calling thread. … … 641 906 } 642 907 643 //////////////////////////////////////// 644 error_t vfs_lookup( xptr_t cwd_xp, 645 char * pathname, 646 uint32_t client_uid, 647 uint32_t client_gid, 648 xptr_t * inode_xp, 649 xptr_t * ctx_xp ) 908 ////////////////////////////////////////////// 909 error_t vfs_lookup( xptr_t cwd_xp, 910 char * pathname, 911 uint32_t mode, 912 xptr_t * inode_xp ) 650 913 { 651 914 char name[CONFIG_VFS_MAX_NAME_LENGTH]; // one name in path 652 915 653 xptr_t parent_xp; // extended pointer on parent inode 654 cxy_t parent_cxy; // cluster for parentc inode 655 vfs_inode_t * parent_ptr; // local pointer on parent inode 656 xptr_t child_xp; // extended pointer on child inode 657 cxy_t child_cxy; // cluster for child inode 658 vfs_inode_t * child_ptr; // local pointer on child inode 659 char * current; // current pointer on path 660 char * next; // next value for current pointer 661 bool_t last; // true when the name is the last in path 662 bool_t found; // true when a child has been found 663 thread_t * this; // pointer on calling thread descriptor 664 process_t * process; // pointer on calling process descriptor 665 vfs_ctx_t * ctx; // parent inode context 666 uint32_t type; // file system type of parent inode 667 error_t error; 916 xptr_t parent_xp; // extended pointer on parent inode 917 cxy_t parent_cxy; // cluster for parent inode 918 vfs_inode_t * parent_ptr; // local pointer on parent inode 919 xptr_t child_xp; // extended pointer on child inode 920 cxy_t child_cxy; // cluster for child inode 921 vfs_inode_t * child_ptr; // local pointer on child inode 922 vfs_inode_type_t inode_type; // child inode type 923 vfs_fs_type_t fs_type; // File system type 924 vfs_ctx_t * ctx_ptr; // local pointer on FS context 925 char * current; // current pointer on path 926 char * next; // next value for current pointer 927 bool_t last; // true when the name is the last in path 928 bool_t found; // true when a child has been found 929 thread_t * this; // pointer on calling thread descriptor 930 process_t * process; // pointer on calling process descriptor 931 error_t error; 668 932 669 933 this = CURRENT_THREAD; … … 687 951 do 688 952 { 689 // get cluster and local pointer for parent inode 690 parent_cxy = GET_CXY( parent_xp ); 691 parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp ); 692 693 // get parent inode FS type 694 ctx = (vfs_ctx_t *)(intptr_t)hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) ); 695 type = ctx->type; 696 697 // get one name from path 953 // get one name from path and the last flag 698 954 vfs_get_name_from_path( current , name , &next , &last ); 699 955 … … 708 964 vfs_inode_remote_unlock( parent_xp ); 709 965 710 // insert a new dentry/inode in parent inode 711 error = vfs_add_child_in_parent( type , parent_xp , name , &child_xp ); 966 // get cluster and local pointer on parent inode 967 parent_cxy = GET_CXY( parent_xp ); 968 parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp ); 969 970 // get parent inode FS type 971 ctx_ptr = (vfs_ctx_t *)hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) ); 972 fs_type = ctx_ptr->type; 973 974 // get child inode type 975 if( (last == false) || (mode & VFS_LOOKUP_DIR) ) inode_type = INODE_TYPE_DIR; 976 else inode_type = INODE_TYPE_FILE; 977 978 // insert a child dentry/inode in parent inode 979 error = vfs_add_child_in_parent( inode_type, 980 fs_type, 981 parent_xp, 982 name, 983 &child_xp ); 712 984 713 985 if( error ) … … 723 995 724 996 // check access rights 725 error = vfs_access_denied( child_xp,726 client_uid,727 client_gid );728 if( error )729 {730 printk("\n[ERROR] in %s : permission denied for %s\n", __FUNCTION__ , name );731 return EACCES;732 }997 // error = vfs_access_denied( child_xp, 998 // client_uid, 999 // client_gid ); 1000 // if( error ) 1001 // { 1002 // printk("\n[ERROR] in %s : permission denied for %s\n", __FUNCTION__ , name ); 1003 // return EACCES; 1004 // } 733 1005 734 1006 // take lock on child inode if not last … … 753 1025 // return searched pointers 754 1026 *inode_xp = child_xp; 755 *ctx_xp = (xptr_t)hal_remote_lwd( XPTR( child_cxy , &child_ptr->ctx ) );756 1027 757 1028 return 0; … … 770 1041 uint32_t count; // number of characters written in buffer 771 1042 uint32_t index; // slot index in buffer 772 xptr_t inode_xp; // extended pointer on1043 xptr_t inode_xp; // extended pointer on 773 1044 774 1045 // implementation note: … … 829 1100 } // end vfs_get_path() 830 1101 831 /////////////////////////////////////////////// 832 error_t vfs_add_child_in_parent( uint32_t type, 833 xptr_t parent_xp, 834 char * name, 835 xptr_t * child_xp ) 836 { 837 xptr_t dentry_xp; // extended pointer on created dentry 838 xptr_t inode_xp; // extended pointer on created inode 839 error_t error; 1102 /////////////////////////////////////////////////////////////// 1103 error_t vfs_add_child_in_parent( vfs_inode_type_t inode_type, 1104 vfs_fs_type_t fs_type, 1105 xptr_t parent_xp, 1106 char * name, 1107 xptr_t * child_xp ) 1108 { 1109 error_t error; 1110 xptr_t dentry_xp; // extended pointer on created dentry 1111 xptr_t inode_xp; // extended pointer on created inode 1112 cxy_t parent_cxy; // parent inode cluster identifier 1113 vfs_inode_t * parent_ptr; // parent inode local pointer 1114 vfs_ctx_t * parent_ctx; // parent inode context local pointer 840 1115 841 1116 // get parent inode cluster and local pointer 842 cxy_t parent_cxy = GET_CXY( parent_xp ); 843 vfs_inode_t * parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp ); 1117 parent_cxy = GET_CXY( parent_xp ); 1118 parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp ); 1119 1120 // get parent inode context local pointer 1121 parent_ctx = (vfs_ctx_t *)hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) ); 844 1122 845 1123 // create dentry 846 1124 if( parent_cxy == local_cxy ) // parent cluster is the local cluster 847 1125 { 848 error = vfs_dentry_create( type,1126 error = vfs_dentry_create( fs_type, 849 1127 name, 850 1128 parent_ptr, … … 854 1132 { 855 1133 rpc_vfs_dentry_create_client( parent_cxy, 856 type,1134 fs_type, 857 1135 name, 858 1136 parent_ptr, … … 887 1165 { 888 1166 error = vfs_inode_create( dentry_xp, 889 type, 1167 fs_type, 1168 inode_type, 890 1169 attr, 891 1170 mode, … … 898 1177 rpc_vfs_inode_create_client( child_cxy, 899 1178 dentry_xp, 900 type, 1179 fs_type, 1180 inode_type, 901 1181 attr, 902 1182 mode, … … 925 1205 926 1206 1207 1208 1209 ////////////////////////////////////////////////////////////////////////////////////////// 1210 // Mapper related functions 1211 ////////////////////////////////////////////////////////////////////////////////////////// 1212 1213 //////////////////////////////////////////////// 1214 error_t vfs_move_page_to_mapper( page_t * page ) 1215 { 1216 error_t error = 0; 1217 1218 assert( (page != NULL) , __FUNCTION__ , "page pointer is NULL\n" ); 1219 1220 mapper_t * mapper = page->mapper; 1221 1222 assert( (mapper != NULL) , __FUNCTION__ , "no mapper for page\n" ); 1223 1224 // get FS type 1225 vfs_fs_type_t fs_type = mapper->inode->ctx->type; 1226 1227 // update mapper if permitted by file system type 1228 if( fs_type == FS_TYPE_FATFS ) 1229 { 1230 // get mapper lock in WRITE_MODE 1231 rwlock_wr_lock( &mapper->lock ); 1232 1233 error = fatfs_read_page( page ); 1234 1235 // release mapper lock 1236 rwlock_wr_unlock( &mapper->lock ); 1237 } 1238 else if( fs_type == FS_TYPE_RAMFS ) 1239 { 1240 assert( false , __FUNCTION__ , "should not be called for RAMFS\n" ); 1241 } 1242 else if( fs_type == FS_TYPE_DEVFS ) 1243 { 1244 assert( false , __FUNCTION__ , "should not be called for DEVFS\n" ); 1245 } 1246 else 1247 { 1248 assert( false , __FUNCTION__ , "undefined file system type\n" ); 1249 } 1250 1251 return error; 1252 1253 } // end vfs_move_page_to_mapper() 1254 1255 ////////////////////////////////////////////////// 1256 error_t vfs_move_page_from_mapper( page_t * page ) 1257 { 1258 error_t error = 0; 1259 1260 assert( (page != NULL) , __FUNCTION__ , "page pointer is NULL\n" ); 1261 1262 mapper_t * mapper = page->mapper; 1263 1264 assert( (mapper != NULL) , __FUNCTION__ , "no mapper for page\n" ); 1265 1266 // get FS type 1267 vfs_fs_type_t fs_type = mapper->inode->ctx->type; 1268 1269 // update file system if permitted by file system type 1270 if( fs_type == FS_TYPE_FATFS ) 1271 { 1272 if( page_is_flag( page , PG_DIRTY ) ) 1273 { 1274 // get mapper lock in READ_MODE 1275 rwlock_rd_lock( &mapper->lock ); 1276 1277 error = fatfs_write_page( page ); 1278 1279 // release mapper lock from READ_MODE 1280 rwlock_rd_unlock( &mapper->lock ); 1281 1282 // clear dirty bit if success 1283 if( error == 0 ) page_undo_dirty( page ); 1284 } 1285 } 1286 else if( fs_type == FS_TYPE_RAMFS ) 1287 { 1288 assert( false , __FUNCTION__ , "should not be called for RAMFS\n" ); 1289 } 1290 else if( fs_type == FS_TYPE_DEVFS ) 1291 { 1292 assert( false , __FUNCTION__ , "should not be called for DEVFS\n" ); 1293 } 1294 else 1295 { 1296 assert( false , __FUNCTION__ , "undefined file system type\n" ); 1297 } 1298 1299 return error; 1300 1301 } // end vfs_move_page_from_mapper() 1302 1303 -
trunk/kernel/vfs/vfs.h
r14 r23 2 2 * vfs.h - Virtual File System definition. 3 3 * 4 * Author Mohamed Lamine Karaoui (201 5)5 * Alain Greiner (2016 )4 * Author Mohamed Lamine Karaoui (2014,2015) 5 * Alain Greiner (2016,2017) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 42 42 #include <fatfs.h> 43 43 #include <ramfs.h> 44 #include <devfs.h> 44 45 45 46 /**** Forward declarations ***/ … … 63 64 struct device_s; 64 65 struct vseg_s; 65 66 /********************************************************************************************* 67 * This defines the various Flags arguments for an open() or opendir() system call. 68 ********************************************************************************************/ 69 70 #define VFS_O_APPEND 0x00080000 71 #define VFS_O_RDONLY 0x00100000 72 #define VFS_O_WRONLY 0x00200000 73 #define VFS_O_RDWR 0x00300000 74 #define VFS_O_CREATE 0x00400000 75 #define VFS_O_EXCL 0x00800000 76 #define VFS_O_TRUNC 0x01000000 77 #define VFS_O_SYNC 0x08000000 78 79 /********************************************************************************************* 80 * This defines the various types of command for an lseek() system call. 81 ********************************************************************************************/ 82 83 #define VFS_SEEK_SET 0 84 #define VFS_SEEK_CUR 1 85 #define VFS_SEEK_END 2 86 87 /********************************************************************************************* 88 * TODO : the following flags were defined in the vfs-params.h file... 89 * ... and must be documented. [AG] 90 ********************************************************************************************/ 91 92 93 ////////////////////////////////////// 94 /// keep these flags compact /// 95 ////////////////////////////////////// 96 #define VFS_REGFILE 0x0000000 97 #define VFS_DIR 0x0000001 98 #define VFS_FIFO 0x0000002 99 #define VFS_DEV_CHR 0x0000004 100 #define VFS_DEV_BLK 0x0000008 101 #define VFS_DEV 0x000000C 102 #define VFS_SOCK 0x0000010 103 #define VFS_SYMLNK 0x0000020 104 ////////////////////////////////////// 105 106 #define VFS_RD_ONLY 0x0000040 107 #define VFS_SYS 0x0000080 108 #define VFS_ARCHIVE 0x0000100 109 #define VFS_PIPE 0x0000200 110 111 #define VFS_IFMT 0x0170000 112 #define VFS_IFSOCK 0x0140000 113 #define VFS_IFLNK 0x0120000 114 #define VFS_IFREG 0x0100000 115 #define VFS_IFBLK 0x0060000 116 #define VFS_IFDIR 0x0040000 117 #define VFS_IFCHR 0x0020000 118 #define VFS_IFIFO 0x0010000 119 120 #define VFS_ISUID 0x0004000 121 #define VFS_ISGID 0x0002000 122 #define VFS_ISVTX 0x0001000 66 struct page_s; 67 68 69 /****************************************************************************************** 70 * These flags are used to define the working mode of the vfs_lookup() function. 71 *****************************************************************************************/ 72 73 #define VFS_LOOKUP_DIR 0x01 /* the searched inode is a directory */ 74 #define VFS_LOOKUP_OPEN 0x02 /* the search is for an open/opendir */ 75 #define VFS_LOOKUP_PARENT 0x04 /* return the parent inode (not the inode itself) */ 76 #define VFS_LOOKUP_CREATE 0x10 /* file must be created if missing */ 77 #define VFS_LOOKUP_EXCL 0x20 /* file cannot previously exist */ 78 79 /****************************************************************************************** 80 * This define the masks for the POSIX access rights to inodes 81 *****************************************************************************************/ 82 83 #define VFS_ISUID 0x0004000 84 #define VFS_ISGID 0x0002000 85 #define VFS_ISVTX 0x0001000 123 86 124 87 #define VFS_IRWXU 0x0000700 … … 126 89 #define VFS_IWUSR 0x0000200 127 90 #define VFS_IXUSR 0x0000100 91 128 92 #define VFS_IRWXG 0x0000070 129 93 #define VFS_IRGRP 0x0000040 130 94 #define VFS_IWGRP 0x0000020 131 95 #define VFS_IXGRP 0x0000010 96 132 97 #define VFS_IRWXO 0x0000007 133 98 #define VFS_IROTH 0x0000004 … … 139 104 #define VFS_IEXEC VFS_IXUSR 140 105 141 #define VFS_SET(state,flag) (state) |= (flag) 142 #define VFS_IS(state,flag) (state) & (flag) 143 #define VFS_CLEAR(state,flag) (state) &= ~(flag) 144 145 146 /* Lookup flags */ 147 #define VFS_LOOKUP_FILE 0x1 148 #define VFS_LOOKUP_LAST 0x2 149 #define VFS_LOOKUP_OPEN 0x4 150 #define VFS_LOOKUP_RESTART 0x8 151 #define VFS_LOOKUP_RETRY 0x10 152 #define VFS_LOOKUP_PARENT 0x20 153 #define VFS_LOOKUP_HELD 0x40 154 155 /* Context flags*/ 156 #define VFS_FS_LOCAL 0x1 157 #define VFS_FS_USE_MAPPER 0x2 158 159 160 106 107 /****************************************************************************************** 108 * This structure defines informations common to all inodes and dentries 109 * of a given file system. As it is declared a global variable in the kdata segment, 110 * it is replicated in all clusters and handled as private by each OS intance. 111 *****************************************************************************************/ 112 113 typedef enum 114 { 115 FS_TYPE_DEVFS = 0, 116 FS_TYPE_FATFS = 1, 117 FS_TYPE_RAMFS = 2, 118 119 FS_TYPES_NR = 3, 120 } 121 vfs_fs_type_t; 122 123 typedef enum 124 { 125 CTX_ATTR_READ_ONLY = 0x01, /*! write access prohibited */ 126 CTX_ATTR_SYNC = 0x10, /*! synchronise FS on each write */ 127 } 128 vfs_ctx_attr_t; 129 130 typedef struct vfs_ctx_s 131 { 132 vfs_fs_type_t type; /*! File System type */ 133 uint32_t attr; /*! global attributes for all files in FS */ 134 uint32_t count; /*! total number of clusters on device */ 135 uint32_t blksize; /*! device cluster size (bytes) */ 136 xptr_t root_xp; /*! extended pointer on root inode */ 137 spinlock_t lock; /*! lock protecting inum allocator */ 138 uint32_t bitmap[BITMAP_SIZE(CONFIG_VFS_MAX_INODES)]; /* inum allocator */ 139 void * extend; /*! FS specific context extension */ 140 } 141 vfs_ctx_t; 161 142 162 143 /****************************************************************************************** … … 166 147 * The <parent> inode is unique for a directory (not hard links for directories). 167 148 * For a file, the parent field points to the first dentry who created this inode. 168 * Syncr onisation:149 * Syncrhonisation: 169 150 * - the main_lock (spinlock) is used during the inode tree traversal or for inode 170 151 * modification (add/remove children). … … 172 153 * in the mapper. 173 154 * - the mapper lock (rwlock) is only used during the radix tree traversal to return 174 * to return the relevant page for red/write. 175 *****************************************************************************************/ 155 * the relevant page for read/write. 156 *****************************************************************************************/ 157 158 /* this enum define the VFS inode types values */ 176 159 177 160 typedef enum 178 161 { 179 INODE_TYPE_NORMAL, /*! file or directory */ 180 INODE_TYPE_PIPE, /*! POSIX pipe */ 181 INODE_TYPE_SOCKET, /*! POSIX socket */ 182 INODE_TYPE_DEV, /*! peripheral channel */ 162 INODE_TYPE_FILE = 0x001, /*! file */ 163 INODE_TYPE_DIR = 0x002, /*! directory */ 164 INODE_TYPE_FIFO = 0x004, /*! POSIX named pipe */ 165 INODE_TYPE_PIPE = 0x008, /*! POSIX anonymous pipe */ 166 INODE_TYPE_SOCKET = 0x010, /*! POSIX socket */ 167 INODE_TYPE_DEV = 0x020, /*! character peripheral channel */ 168 INODE_TYPE_SYML = 0x080, /*! symbolic link */ 183 169 } 184 170 vfs_inode_type_t; 185 171 172 /* this enum define the VFS inode attributes values */ 173 186 174 typedef enum 187 175 { 188 INODE_ATTR_DIRTY = 0x01, 189 INODE_ATTR_DIR = 0x02, 190 INODE_ATTR_INLOAD = 0x04, 191 INODE_ATTR_NEW = 0x08, 176 INODE_ATTR_DIRTY = 0x01, /* modified versus the value on device */ 177 INODE_ATTR_INLOAD = 0x04, /* loading from device in progress */ 178 INODE_ATTR_NEW = 0x08, /* not saved on device yet */ 192 179 } 193 180 vfs_inode_attr_t; … … 195 182 typedef struct vfs_inode_s 196 183 { 197 struct vfs_ctx_s * ctx; /*! Rlocal pointer on FS context*/184 struct vfs_ctx_s * ctx; /*! local pointer on FS context */ 198 185 uint32_t gc; /*! generation counter */ 199 186 uint32_t inum; /*! inode identifier (unique in file system) */ 200 187 uint32_t attr; /*! inode attributes (see above) */ 201 uint32_ttype; /*! inode type (see above) */188 vfs_inode_type_t type; /*! inode type (see above) */ 202 189 uint32_t size; /*! number of bytes */ 203 190 uint32_t links; /*! number of alias dentry */ 204 191 uid_t uid; /*! user owner identifier */ 205 192 gid_t gid; /*! group owner identifier */ 206 uint32_t mode; /*! access mode*/193 uint32_t rights; /*! access rights */ 207 194 uint32_t refcount; /*! reference counter (all pointers) */ 208 195 xptr_t parent_xp; /*! extended pointer on parent dentry */ 209 xhtab_t children; /*! embedded htab of dir entries (for dir type)*/196 xhtab_t children; /*! embedded xhtab of vfs_dentry_t */ 210 197 remote_rwlock_t data_lock; /*! protect read/write to data and to size */ 211 198 remote_spinlock_t main_lock; /*! protect inode tree traversal and modifs */ 212 xlist_entry_t xlist;/*! member of set of inodes in same cluster */199 list_entry_t list; /*! member of set of inodes in same cluster */ 213 200 xlist_entry_t wait_root; /*! root of threads waiting on this inode */ 214 201 struct vfs_inode_op_s * op; /*! TODO ??? */ … … 240 227 241 228 /****************************************************************************************** 242 * This structure describes an open file/directory for a given process.229 * This file structure describes an open file/directory for a given process. 243 230 * It is not replicated, and is dynamically allocated in the cluster that contains 244 231 * the inode, when a thread makes an open() or opendir() system call. 245 *****************************************************************************************/ 246 232 * It cannot exist a file structure without an inode structure. 233 * Aa the fd_array (containing extended pointers on the open file descriptors) 234 * is replicated in all process descriptors, we need a references counter. 235 *****************************************************************************************/ 247 236 248 237 typedef enum 249 238 { 250 FD_ATTR_READ_ENABLE = 0x01,/*! read access possible */251 FD_ATTR_WRITE_ENABLE = 0x02,/*! write access possible */252 FD_ATTR_APPEND = 0x04,/*! append on each write */253 FD_ATTR_CLOSE_EXEC = 0x08,/*! close file on exec */254 FD_ATTR_SYNC = 0x10,/*! synchronise FS on each write */255 FD_ATTR_IS_DIR = 0x20,/*! this is a directory */256 } 257 vfs_f d_attr_t;239 FD_ATTR_READ_ENABLE = 0x01, /*! read access possible */ 240 FD_ATTR_WRITE_ENABLE = 0x02, /*! write access possible */ 241 FD_ATTR_APPEND = 0x04, /*! append on each write */ 242 FD_ATTR_CLOSE_EXEC = 0x08, /*! close file on exec */ 243 FD_ATTR_SYNC = 0x10, /*! synchronise FS on each write */ 244 FD_ATTR_IS_DIR = 0x20, /*! this is a directory */ 245 } 246 vfs_file_attr_t; 258 247 259 248 typedef struct vfs_file_s 260 249 { 250 struct vfs_ctx_s * ctx; /*! local pointer on FS context. */ 261 251 uint32_t gc; /*! generation counter */ 262 uint32_t type; /*! see above*/263 uint32_t attr; /*! see above*/252 vfs_file_attr_t attr; /*! file attributes bit vector (see above) */ 253 vfs_inode_type_t type; /*! same type as inode */ 264 254 uint32_t offset; /*! seek position in file */ 265 uint32_t refcount; /*! all pointers on this file 266 remote_rwlock_t lock; /*! protect offset modifications */255 uint32_t refcount; /*! all pointers on this file descriptor */ 256 remote_rwlock_t lock; /*! protect offset modifications */ 267 257 struct mapper_s * mapper; /*! associated file cache */ 268 258 struct vfs_inode_s * inode; /*! local pointer on associated inode */ 269 struct vfs_ctx_s * ctx; /*! file system features */ 270 struct vfs_file_op_s * op; /*! local set of function pointers */ 259 void * extend; /*! FS specific extension */ 271 260 } 272 261 vfs_file_t; 273 262 274 263 /****************************************************************************************** 275 * This structure defines informations common to all inodes and dentries 276 * of a given file system. As it is declared a global variable in the kdata segment, 277 * it is replicated in all clusters and handled as private by each OS intance. 278 *****************************************************************************************/ 279 280 typedef enum 281 { 282 FS_TYPE_SYSFS = 0, 283 FS_TYPE_DEVFS = 1, 284 FS_TYPE_FATFS = 2, 285 FS_TYPE_RAMFS = 3, 286 287 FS_TYPES_NR = 4, 288 } 289 vfs_types_t; 290 291 typedef enum 292 { 293 CTX_ATTR_READ_ONLY = 0x01, /*! read access possible */ 294 CTX_ATTR_SYNC = 0x10, /*! synchronise FS on each write */ 295 } 296 vfs_ctx_attr_t; 297 298 typedef struct vfs_ctx_s 299 { 300 uint32_t type; /*! File System type */ 301 uint32_t attr; /*! global attributes for all files in FS */ 302 uint32_t count; /*! number of clusters */ 303 uint32_t blksize; /*! cluster size */ 304 xptr_t ioc_xp; /*! extended pointer on IOC device */ 305 xptr_t root_xp; /*! extended pointer on root inode */ 306 307 spinlock_t lock; /*! lock protecting inum allocator */ 308 BITMAP( inum , CONFIG_VFS_MAX_INODES ); /*! inum allocator */ 309 310 void * extend; /*! FS specific context extension */ 311 } 312 vfs_ctx_t; 313 314 /****************************************************************************************** 315 * This structure define the informations associated to a given file descriptor, 316 * that are returned by the vfs_stat() function. 264 * This structure define the informations associated to a file descriptor, 265 * returned to user space by the stat() system call. 317 266 *****************************************************************************************/ 318 267 … … 335 284 vfs_stat_t; 336 285 337 338 339 340 341 342 /****************************************************************************************** 343 * This structure defines the set of operations that can be done on a VFS context. 344 * TODO A quoi cela sert-il ? [AG] 345 *****************************************************************************************/ 346 347 typedef error_t (vfs_create_context_t) ( vfs_ctx_t * context ); 348 typedef error_t (vfs_destroy_context_t) ( vfs_ctx_t * context ); 349 typedef error_t (vfs_read_root_t) ( vfs_ctx_t * context , vfs_inode_t * root ); 350 typedef error_t (vfs_reply_root_t) ( vfs_ctx_t * context , vfs_inode_t * root ); 351 typedef error_t (vfs_write_root_t) ( vfs_ctx_t * context , vfs_inode_t * root ); 352 353 struct vfs_ctx_op_s 354 { 355 vfs_create_context_t * create; /*! allocate memory and initialize a context */ 356 vfs_destroy_context_t * destroy; /*! release memory allocated to a context */ 357 vfs_read_root_t * read_root; /*! TODO */ 358 vfs_reply_root_t * repli_root; /*! TODO */ 359 vfs_write_root_t * write_root; /*! TODO */ 360 } 361 vfs_ctx_op_t; 362 363 /****************************************************************************************** 364 * This structure defines the set of operations that can be done on a VFS inode. 365 * TODO A quoi cela sert-il ? [AG] 366 *****************************************************************************************/ 367 368 typedef error_t (vfs_init_inode_t) ( vfs_inode_t * inode ); 369 typedef error_t (vfs_create_inode_t) ( vfs_inode_t * parent , vfs_dentry_t * dentry ); 370 typedef error_t (vfs_lookup_inode_t) ( vfs_inode_t * parent , vfs_dentry_t * dentry ); 371 typedef error_t (vfs_write_inode_t) ( vfs_inode_t * inode ); 372 typedef error_t (vfs_release_inode_t) ( vfs_inode_t * inode ); 373 typedef error_t (vfs_unlink_inode_t) ( vfs_inode_t * parent , vfs_dentry_t * dentry , uint32_t flags ); 374 typedef error_t (vfs_stat_inode_t) ( vfs_inode_t * inode ); 375 typedef error_t (vfs_trunc_inode_t) ( vfs_inode_t * inode ); 376 typedef error_t (vfs_delete_inode_t) ( vfs_inode_t * inode ); 377 378 typedef struct vfs_inode_op_s 379 { 380 vfs_init_inode_t * init; /*! initialise inode from scratch */ 381 vfs_create_inode_t * create; /*! allocate memory for one inode */ 382 vfs_lookup_inode_t * lookup; /*! get one directory entry by name */ 383 vfs_write_inode_t * write; /*! update the device from the inode */ 384 vfs_release_inode_t * release; /*! reset one inode and release associated objects */ 385 vfs_unlink_inode_t * unlink; /*! unlink a directory entry from parent inode */ 386 vfs_delete_inode_t * delete; /*! release memory allocated to inode when count = 0 */ 387 vfs_stat_inode_t * stat; /*! TODO */ 388 vfs_trunc_inode_t * trunc; /*! change the size of a file */ 389 } 390 vfs_inode_op_t; 391 392 /****************************************************************************************** 393 * This structure defines the set of operations that can be done on a VFS dentry. 394 * TODO A quoi cela sert-il ? [AG] 395 *****************************************************************************************/ 396 397 typedef error_t (vfs_compare_dentry_t) ( char * first , char * second ); 398 399 typedef struct vfs_dentry_op_s 400 { 401 vfs_compare_dentry_t * compare; 402 } 403 vfs_dentry_op_t; 404 405 /****************************************************************************************** 406 * This structure defines the set of operations that can be done on a VFS file. 407 * TODO A quoi cela sert-il ? [AG] 408 *****************************************************************************************/ 409 410 typedef error_t (vfs_open_file_t) ( vfs_file_t * file , void * priv ); 411 typedef error_t (vfs_read_file_t) ( vfs_file_t * file , char * buffer ); 412 typedef error_t (vfs_write_file_t) ( vfs_file_t * file , char * buffer ); 413 typedef error_t (vfs_lseek_file_t) ( vfs_file_t * file ); 414 typedef error_t (vfs_close_file_t) ( vfs_file_t * file ); 415 typedef error_t (vfs_release_file_t) ( vfs_file_t * file ); 416 typedef error_t (vfs_read_dir_t) ( vfs_file_t * file ); 417 typedef error_t (vfs_mmap_file_t) ( vfs_file_t * file , struct vseg_s * vseg ); 418 typedef error_t (vfs_munmap_file_t) ( vfs_file_t * file , struct vseg_s * vseg ); 419 420 typedef struct vfs_file_op_s 421 { 422 vfs_open_file_t * open; 423 vfs_read_file_t * read; 424 vfs_write_file_t * write; 425 vfs_lseek_file_t * lseek; 426 vfs_read_dir_t * readdir; 427 vfs_close_file_t * close; 428 vfs_release_file_t * release; 429 vfs_mmap_file_t * mmap; 430 vfs_munmap_file_t * munmap; 431 } 432 vfs_file_op_t; 433 434 435 286 /********************************************************************************************* 287 * This structure defines the information associated to a directory entry, 288 * returned to user space by the readdir() system call. 289 ********************************************************************************************/ 290 291 typedef struct vfs_dirent_s 292 { 293 uint32_t inum; /*! inode identifier */ 294 uint32_t type; /*! inode type */ 295 char name[CONFIG_VFS_MAX_NAME_LENGTH]; /*! dentry name */ 296 } 297 vfs_dirent_t; 436 298 437 299 … … 441 303 /*****************************************************************************************/ 442 304 443 /****************************************************************************************** 444 * This function initializes the Virtual File System. 445 *****************************************************************************************/ 446 void vfs_init(); 447 448 /****************************************************************************************** 449 * This function mount a given file system type for a given process. 305 306 /****************************************************************************************** 307 * This function mount a given file system type for a given process TODO. 450 308 *****************************************************************************************/ 451 309 error_t vfs_mount_fs_root( struct device_s * device, … … 482 340 483 341 484 /*****************************************************************************************/ 485 /************************ File Descriptor related functions ******************************/ 342 343 /*****************************************************************************************/ 344 /********************* Inode related functions *******************************************/ 345 /*****************************************************************************************/ 346 347 /****************************************************************************************** 348 * This function allocates memory from local cluster for an inode descriptor and the 349 * associated mapper. It initialise these descriptors from arguments values. 350 * The parent dentry must have been previously created. 351 * If the client thread is not running in the cluster containing this inode, 352 * it must use the rpc_vfs_inode_create_client() function. 353 ****************************************************************************************** 354 * @ dentry_xp : extended pointer on associated dentry (in parent inode cluster). 355 * @ fs_type : file system type. 356 * @ inode_type : inode type. 357 * @ attr : inode attributes. 358 * @ rights : inode access rights. 359 * @ uid : user owner ID. 360 * @ gid : group owner ID. 361 * @ inode_xp : [out] buffer for extended pointer on created inode. 362 * # return 0 if success / return ENOMEM or EINVAL if error. 363 *****************************************************************************************/ 364 error_t vfs_inode_create( xptr_t dentry_xp, 365 vfs_fs_type_t fs_type, 366 vfs_inode_type_t inode_type, 367 uint32_t attr, 368 uint32_t rights, 369 uid_t uid, 370 gid_t gid, 371 xptr_t * inode_xp ); 372 373 /****************************************************************************************** 374 * This function releases memory allocated to an inode descriptor. 375 * It must be executed by a thread running in the cluster containing the inode, 376 * and the inode refcount must be zero. 377 * If the client thread is not running in the owner cluster, it must use the 378 * rpc_vfs_inode_destroy_client() function. 379 ****************************************************************************************** 380 * @ inode : local pointer on inode descriptor. 381 *****************************************************************************************/ 382 void vfs_inode_destroy( vfs_inode_t * inode ); 383 384 /****************************************************************************************** 385 * This function atomically increment/decrement the inode refcount. 386 * It can be called by any thread running in any cluster. 387 *****************************************************************************************/ 388 void vfs_inode_remote_up( xptr_t inode_xp ); 389 void vfs_inode_remote_down( xptr_t inode_xp ); 390 391 /****************************************************************************************** 392 * This function returns the <size> of a file/dir from a remote inode, 393 * taking the remote_rwlock protecting <size> in READ_MODE. 394 ***************************************************************************************** 395 * @ inode_xp : extended pointer on the remote inode. 396 * @ return the current size. 397 *****************************************************************************************/ 398 uint32_t vfs_inode_get_size( xptr_t inode_xp ); 399 400 /****************************************************************************************** 401 * This function set the <size> of a file/dir to a remote inode, 402 * taking the remote_rwlock protecting <size> in WRITE_MODE. 403 ***************************************************************************************** 404 * @ inode_xp : extended pointer on the remote inode. 405 * @ size : value to be written. 406 *****************************************************************************************/ 407 void vfs_inode_set_size( xptr_t inode_xp, 408 uint32_t size ); 409 410 /****************************************************************************************** 411 * This function takes the main lock of a remote inode. 412 * This lock protect all inode fiels, including the children dentries. 413 ***************************************************************************************** 414 * @ inode_xp : extended pointer on the remote inode. 415 *****************************************************************************************/ 416 void vfs_inode_remote_lock( xptr_t inode_xp ); 417 418 /****************************************************************************************** 419 * This function releases the main lock of a remote inode. 420 * This lock protect all inode fiels, including the children dentries. 421 ***************************************************************************************** 422 * @ inode_xp : extended pointer on the remote inode. 423 *****************************************************************************************/ 424 void vfs_inode_remote_unlock( xptr_t inode_xp ); 425 426 427 428 429 /****************************************************************************************** 430 * This function TODO 431 *****************************************************************************************/ 432 error_t vfs_inode_hold( vfs_inode_t * inode, 433 uint32_t gc ); 434 435 /****************************************************************************************** 436 * This function TODO 437 *****************************************************************************************/ 438 error_t vfs_inode_trunc( vfs_inode_t * inode ); 439 440 /****************************************************************************************** 441 * This function TODO 442 *****************************************************************************************/ 443 error_t vfs_inode_link( vfs_inode_t * inode, 444 uint32_t igc ); 445 446 /****************************************************************************************** 447 * This function TODO 448 *****************************************************************************************/ 449 error_t vfs_inode_unlink( vfs_inode_t * inode ); 450 451 /****************************************************************************************** 452 * This function TODO 453 *****************************************************************************************/ 454 error_t vfs_inode_stat( vfs_inode_t * inode, 455 uint32_t inum ); 456 457 /****************************************************************************************** 458 * This function TODO 459 *****************************************************************************************/ 460 error_t vfs_icache_del( vfs_inode_t * inode ); 461 462 463 /****************************************************************************************** 464 * This function TODO Pourquoi 2 arguments ? 465 *****************************************************************************************/ 466 error_t vfs_stat_inode( vfs_inode_t * inode, 467 uint32_t inum ); 468 469 470 /*****************************************************************************************/ 471 /***************** Dentry related functions **********************************************/ 472 /*****************************************************************************************/ 473 474 /****************************************************************************************** 475 * This function allocates memory from local cluster for a dentry descriptor, 476 * initialises it from arguments values, and returns the extended pointer on dentry. 477 * The inode field is not initialized, because the inode does not exist yet. 478 * If the client thread is not running in the target cluster for this inode, 479 * it must use the rpc_dentry_create_client() function. 480 ****************************************************************************************** 481 * @ fs_type : file system type. 482 * @ name : directory entry file/dir name. 483 * @ parent : local pointer on parent inode. 484 * @ dentry_xp : [out] buffer for extended pointer on created dentry. 485 * @ return 0 if success / return ENOMEM or EINVAL if error. 486 *****************************************************************************************/ 487 error_t vfs_dentry_create( vfs_fs_type_t fs_type, 488 char * name, 489 vfs_inode_t * parent, 490 xptr_t * dentry_xp ); 491 492 /****************************************************************************************** 493 * This function releases memory allocated to a dentry descriptor. 494 * It must be executed by a thread running in the cluster containing the dentry, 495 * and the dentry refcount must be zero. 496 * If the client thread is not running in the owner cluster, it must use the 497 * rpc_dentry_destroy_client() function. 498 ****************************************************************************************** 499 * @ dentry : local pointer on dentry descriptor. 500 *****************************************************************************************/ 501 void vfs_dentry_destroy( vfs_dentry_t * dentry ); 502 503 /****************************************************************************************** 504 * These functions atomically increment/decrement the dentry refcount. 505 * It can be called by any thread running in any cluster. 506 *****************************************************************************************/ 507 void vfs_dentry_remote_up( xptr_t dentry_xp ); 508 void vfs_dentry_remote_down( xptr_t dentry_xp ); 509 510 511 /*****************************************************************************************/ 512 /************************ File descriptor related functions ******************************/ 486 513 /*****************************************************************************************/ 487 514 488 515 /****************************************************************************************** 489 516 * This function allocates memory and initializes a new local file descriptor. 490 * It must be executed in the ownercluster containing the inode.517 * It must be executed in the cluster containing the inode. 491 518 * If the client thread is not running in the owner cluster, it must use the 492 519 * rpc_vfs_file_create_client() function. 493 520 ****************************************************************************************** 494 * @ inode_xp : extended pointer on associated inode. 495 * @ type : file descriptor type. 521 * @ inode : local pointer on associated inode. 496 522 * @ attr : file descriptor attributes. 497 523 * @ file_xp : [out] buffer for extended pointer on created file descriptor. 498 524 * @ return 0 if success / return ENOMEM if error. 499 525 *****************************************************************************************/ 500 error_t vfs_file_create( xptr_t inode_xp, 501 uint32_t type, 502 uint32_t attr, 503 xptr_t * file_xp ); 526 error_t vfs_file_create( vfs_inode_t * inode, 527 uint32_t attr, 528 xptr_t * file_xp ); 504 529 505 530 /****************************************************************************************** … … 510 535 * rpc_vfs_file_destroy_client() function. 511 536 ****************************************************************************************** 512 * @ file_xp : extended pointer on file descriptor. 513 *****************************************************************************************/ 514 void vfs_file_destroy( xptr_t file_xp ); 515 537 * @ file : local pointer on file descriptor. 538 *****************************************************************************************/ 539 void vfs_file_destroy( vfs_file_t * file ); 516 540 517 541 /****************************************************************************************** … … 525 549 526 550 /*****************************************************************************************/ 527 /********************* Inode related functions *******************************************/ 528 /*****************************************************************************************/ 529 530 /****************************************************************************************** 531 * This function allocates memory from local cluster for an inode descriptor and the 532 * associated mapper. It initialise these descriptors from arguments values. 533 * The parent dentry must have been previously created. 534 * If the client thread is not running in the cluster containing this inode, 535 * it must use the rpc_vfs_inode_create_client() function. 536 ****************************************************************************************** 537 * @ dentry_xp : extended pointer on associated dentry (in parent inode cluster). 538 * @ type : file system type. 539 * @ attr : inode attributes. 540 * @ mode : inode access mode. 541 * @ uid : user owner ID. 542 * @ gid : group owner ID. 543 * @ inode_xp : [out] buffer for extended pointer on created inode. 544 * # return 0 if success / return ENOMEM or EINVAL if error. 545 *****************************************************************************************/ 546 error_t vfs_inode_create( xptr_t dentry_xp, 547 uint32_t type, 548 uint32_t attr, 549 uint32_t mode, 550 uid_t uid, 551 gid_t gid, 552 xptr_t * inode_xp ); 553 554 /****************************************************************************************** 555 * This function releases memory allocated to an inode descriptor. 556 * It must be executed by a thread running in the cluster containing the inode, 557 * and the inode refcount must be zero. 558 * If the client thread is not running in the owner cluster, it must use the 559 * rpc_vfs_inode_destroy_client() function. 560 ****************************************************************************************** 561 * @ inode : local pointer on inode descriptor. 562 *****************************************************************************************/ 563 void vfs_inode_destroy( vfs_inode_t * inode ); 564 565 /****************************************************************************************** 566 * This function atomically increment the inode refcount. 567 * It can be called by any thread running in any cluster. 568 *****************************************************************************************/ 569 void vfs_inode_remote_up( xptr_t inode_xp ); 570 571 /****************************************************************************************** 572 * This function atomically decrement the inode refcount. 573 * It can be called by any thread running in any cluster. 574 *****************************************************************************************/ 575 void vfs_inode_remote_down( xptr_t inode_xp ); 576 577 /****************************************************************************************** 578 * This function returns the <size> of a file/dir from a remote inode, 579 * taking the remote_rwlock protecting <size> in READ_MODE. 580 ***************************************************************************************** 581 * @ inode_xp : extended pointer on the remote inode. 582 * @ return the current size. 583 *****************************************************************************************/ 584 uint32_t vfs_inode_get_size( xptr_t inode_xp ); 585 586 /****************************************************************************************** 587 * This function set the <size> of a file/dir to a remote inode, 588 * taking the remote_rwlock protecting <size> in WRITE_MODE. 589 ***************************************************************************************** 590 * @ inode_xp : extended pointer on the remote inode. 591 * @ size : value to be written. 592 *****************************************************************************************/ 593 void vfs_inode_set_size( xptr_t inode_xp, 594 uint32_t size ); 595 596 /****************************************************************************************** 597 * This function takes the main lock of a remote inode. 598 * This lock protect all inode fiels, including the children dentries. 599 ***************************************************************************************** 600 * @ inode_xp : extended pointer on the remote inode. 601 *****************************************************************************************/ 602 void vfs_inode_remote_lock( xptr_t inode_xp ); 603 604 /****************************************************************************************** 605 * This function releases the main lock of a remote inode. 606 * This lock protect all inode fiels, including the children dentries. 607 ***************************************************************************************** 608 * @ inode_xp : extended pointer on the remote inode. 609 *****************************************************************************************/ 610 void vfs_inode_remote_unlock( xptr_t inode_xp ); 611 612 613 614 615 /****************************************************************************************** 616 * This function TODO 617 *****************************************************************************************/ 618 error_t vfs_inode_hold( vfs_inode_t * inode, 619 uint32_t gc ); 620 621 /****************************************************************************************** 622 * This function TODO 623 *****************************************************************************************/ 624 error_t vfs_inode_trunc( vfs_inode_t * inode ); 625 626 /****************************************************************************************** 627 * This function TODO 628 *****************************************************************************************/ 629 error_t vfs_inode_link( vfs_inode_t * inode, 630 uint32_t igc ); 631 632 /****************************************************************************************** 633 * This function TODO 634 *****************************************************************************************/ 635 error_t vfs_inode_unlink( vfs_inode_t * inode ); 636 637 /****************************************************************************************** 638 * This function TODO 639 *****************************************************************************************/ 640 error_t vfs_inode_stat( vfs_inode_t * inode, 641 uint32_t inum ); 642 643 /****************************************************************************************** 644 * This function TODO 645 *****************************************************************************************/ 646 error_t vfs_icache_del( vfs_inode_t * inode ); 647 648 649 /****************************************************************************************** 650 * This function TODO Pourquoi 2 arguments ? 651 *****************************************************************************************/ 652 error_t vfs_stat_inode( vfs_inode_t * inode, 653 uint32_t inum ); 654 655 656 /*****************************************************************************************/ 657 /***************** Dentry related functions **********************************************/ 658 /*****************************************************************************************/ 659 660 /****************************************************************************************** 661 * This function allocates memory from local cluster for a dentry descriptor, 662 * initialises it from arguments values, and returns the extended pointer on dentry. 663 * The inode field is not initialized, because the inode does not exist yet. 664 * If the client thread is not running in the target cluster for this inode, 665 * it must use the rpc_dentry_create_client() function. 666 ****************************************************************************************** 667 * @ type : file system type. 668 * @ name : directory entry file/dir name. 669 * @ parent : local pointer on parent inode. 670 * @ dentry_xp : [out] buffer for extended pointer on created inode. 671 * @ return 0 if success / return ENOMEM or EINVAL if error. 672 *****************************************************************************************/ 673 error_t vfs_dentry_create( uint32_t type, 674 char * name, 675 vfs_inode_t * parent, 676 xptr_t * dentry_xp ); 677 678 /****************************************************************************************** 679 * This function releases memory allocated to a dentry descriptor. 680 * It must be executed by a thread running in the cluster containing the dentry, 681 * and the dentry refcount must be zero. 682 * If the client thread is not running in the owner cluster, it must use the 683 * rpc_dentry_destroy_client() function. 684 ****************************************************************************************** 685 * @ dentry : local pointer on dentry descriptor. 686 *****************************************************************************************/ 687 void vfs_dentry_destroy( vfs_dentry_t * dentry ); 688 689 /****************************************************************************************** 690 * This function atomically increment the dentry refcount. 691 * It can be called by any thread running in any cluster. 692 *****************************************************************************************/ 693 void vfs_dentry_remote_up( xptr_t dentry_xp ); 694 695 /****************************************************************************************** 696 * This function atomically decrement the dentry refcount. 697 * It can be called by any thread running in any cluster. 698 *****************************************************************************************/ 699 void vfs_dentry_remote_down( xptr_t dentry_xp ); 700 701 702 /*****************************************************************************************/ 703 /* Inode-Tree related functions */ 551 /******************* Inode-Tree related functions ****************************************/ 704 552 /*****************************************************************************************/ 705 553 … … 721 569 /****************************************************************************************** 722 570 * This function takes a pathname (absolute or relative to cwd) and returns an extended 723 * pointer on the associated inode, and an extended pointer on the inode context. 724 * If a given name in the path is not found in the inode tree, it try to load the missing 725 * dentry/inode couple, from informations found in the parent directory. 726 * If this directory entry does not exist on device, it returns an error. 727 ****************************************************************************************** 728 * @ cwd_xp : extended pointer on current directory (for relative path). 729 * @ pathname : path in kernel space (can be relative or absolute). 730 * @ client_uid : client thread user ID (for checking). 731 * @ client_gid : client thread group ID (for checking). 732 * @ inode_xp : [out] buffer for extended pointer on inode. 733 * @ ctx_xp : [out] buffer for extended pointer on inode context. 734 * @ return 0 if success / ENOENT if inode not found / EACCES if permissopn denied 735 *****************************************************************************************/ 736 error_t vfs_lookup( xptr_t cwd_xp, 737 char * pathname, 738 uint32_t client_uid, 739 uint32_t client_gid, 740 xptr_t * inode_xp, 741 xptr_t * ctx_xp ); 571 * pointer on the associated inode. 572 * - If a given name in the path is not found in the inode tree, it try to load the missing 573 * dentry/inode couple, from informations found in the parent directory. 574 * - If this directory entry does not exist on device, it returns an error. 575 * - If the the file identified by the pathname does not exist on device but the 576 * flag CREATE is set, the inode is created. 577 * - If the the file identified by the pathname exist on device but both flags EXCL 578 * and CREATE are set, an error is returned. 579 ****************************************************************************************** 580 * @ cwd_xp : extended pointer on current directory (for relative path). 581 * @ pathname : path in kernel space (can be relative or absolute). 582 * @ lookup_mode : flags defining the working mode (defined above in this file). 583 * @ inode_xp : [out] buffer for extended pointer on inode. 584 * @ return 0 if success / ENOENT if inode not found , EACCES if permissopn denied, 585 * EAGAIN if a new complete lookup must be made 586 *****************************************************************************************/ 587 error_t vfs_lookup( xptr_t cwd_xp, 588 char * pathname, 589 uint32_t lookup_mode, 590 xptr_t * inode_xp ); 742 591 743 592 /****************************************************************************************** … … 747 596 * - The dentry is created in the cluster containing the existing <parent_xp> inode. 748 597 * - the child inode and its associated mapper are created in a randomly selected cluster. 749 * - The dentry name is defined by the <name> argument. 750 ****************************************************************************************** 751 * @ type : new inode type 598 * - The new dentry name is defined by the <name> argument. 599 * - The new inode and the parent inode can have different FS types. 600 ****************************************************************************************** 601 * @ inode_type : new inode type 602 * @ fs_type : new inode FS type. 752 603 * @ parent_xp : extended pointer on parent inode. 753 604 * @ name : new directory entry name. … … 755 606 * @ return 0 if success / ENOENT if entry not found in parent directory 756 607 *****************************************************************************************/ 757 error_t vfs_add_child_in_parent( uint32_t type, 758 xptr_t parent_xp, 759 char * name, 760 xptr_t * child_xp ); 761 762 /****************************************************************************************** 763 * TODO 608 error_t vfs_add_child_in_parent( vfs_inode_type_t inode_type, 609 vfs_fs_type_t fs_type, 610 xptr_t parent_xp, 611 char * name, 612 xptr_t * child_xp ); 613 614 /****************************************************************************************** 615 * This function removes a couple dentry/inode from the Inode-Tree, and remove it from 616 * the external device. 617 * TODO 764 618 ****************************************************************************************** 765 619 * @ child_xp : extended pointer on removed inode. … … 767 621 error_t vfs_remove_child_from_parent( xptr_t child_xp ); 768 622 769 /*****************************************************************************************/ 770 /************************ File related functions *****************************************/ 623 624 625 626 627 628 /*****************************************************************************************/ 629 /****************** File access API ******************************************************/ 771 630 /*****************************************************************************************/ 772 631 773 632 /****************************************************************************************** 774 633 * This function allocates a vfs_file_t structure in the cluster containing the inode 775 * associated to the requested file, initializes it, and returns an extended pointer 776 * on this remote open file descriptor. 634 * associated to the file identified by <cwd_xp> & <path>. 635 * It initializes it, register it in the reference process fd_array, and returns both 636 * the extended pointer on the remote file descriptor, and the index in the fd_array. 777 637 * The pathname can be relative to current directory or absolute. 778 * If the inode does not exist in the inode cache, it try to find file on the mounted638 * If the inode does not exist in the inode cache, it try to find the file on the mounted 779 639 * device, and creates an inode on a pseudo randomly selected cluster if found. 780 640 * It the requested file does not exist on device, it creates a new inode if the 781 641 * O_CREAT flag is set and return an error otherwise. 782 642 ****************************************************************************************** 783 * @ cwd_xp : extended pointer on current directory file descriptor (for relative path). 784 * @ path : file pathname (absolute or relative to current directory). 785 * @ flags : O_RDONLY, O_WRONLY, O_CREATE etc... 786 * @ file_xp : [out] buffer for extended pointer on created remote file descriptor. 643 * @ cwd_xp : extended pointer on current working directory file descriptor. 644 * @ path : file pathname (absolute or relative to current directory). 645 * @ flags : defined above 646 * @ mode : access rights (as defined by chmod) 647 * @ file_xp : [out] buffer for extended pointer on created remote file descriptor. 648 * @ file_id : [out] buffer for created file descriptor index in reference fd_array. 787 649 * @ return 0 if success / return non-zero if error. 788 650 *****************************************************************************************/ … … 790 652 char * path, 791 653 uint32_t flags, 792 xptr_t * file_xp ); 793 794 /****************************************************************************************** 795 * This function moves <size> bytes from the file identified by the open file descriptor 796 * <file_xp> to the local kernel <buffer> , taken into account the offset in <file_xp>. 797 ****************************************************************************************** 798 * @ file_xp : extended pointer on the remote open file descriptor. 799 * @ buffer : local pointer on destination kernel buffer. 654 uint32_t mode, 655 xptr_t * file_xp, 656 uint32_t * file_id ); 657 658 /****************************************************************************************** 659 * This function moves <size> bytes between the file identified by the open file descriptor 660 * <file_xp> and a local kernel <buffer> , taken into account the offset in <file_xp>. 661 * The transfer direction is defined by the <to_buffer> argument. 662 ****************************************************************************************** 663 * @ to_buffer : mapper -> buffer if true / buffer->mapper if false. 664 * @ file_xp : extended pointer on the remote file descriptor. 665 * @ buffer : local pointer on local kernel buffer. 800 666 * @ size : requested number of bytes from offset. 801 * @ returns number of bytes actually transfered / 0 if EOF / -1 if error.802 *****************************************************************************************/803 uint32_t vfs_read( xptr_t file_xp,804 void * buffer,805 uint32_t size );806 807 /******************************************************************************************808 * This function moves <size> bytes from the local kernel <buffer> to the open file809 * descriptor <file_xp>, taken into account the offset defined in <file_xp>.810 ******************************************************************************************811 * @ file_xp : extended pointer on the remote open file descriptor.812 * @ buffer : local pointer on source kernel buffer.813 * @ size : requested number of bytes to be written from offset.814 667 * @ returns number of bytes actually transfered / -1 if error. 815 668 *****************************************************************************************/ 816 uint32_t vfs_write( xptr_t file_xp, 817 void * buffer, 818 uint32_t size ); 669 error_t vfs_move( bool_t to_buffer, 670 xptr_t file_xp, 671 void * buffer, 672 uint32_t size ); 819 673 820 674 /****************************************************************************************** … … 837 691 838 692 /****************************************************************************************** 839 * This function close an open file descriptor. 693 * This function close an open file descriptor: 694 * 1) All entries in fd_array copies are directly cancelled by the calling thread, 695 * using remote accesses. 696 * 2) The memory allocated to file descriptor in cluster containing the inode is released. 697 * It requires a RPC if cluster containing the file descriptor is remote. 840 698 ****************************************************************************************** 841 699 * @ file_xp : extended pointer on the file descriptor. 842 * @ refcount : number of references after close.843 * @ return 0 if success / return -1 if error844 *****************************************************************************************/ 845 error_t vfs_close( xptr_t file_xp,846 uint32_t * refcount);847 848 /****************************************************************************************** 849 * This function remove from the file system a directory entry identified by its pathname.850 * The pathname can be relative to current directory or absolute.851 ****************************************************************************************** 852 * @ cwd_xp : extended pointer on the current directory file descriptor.700 * @ file_id : file descriptor index in fd_array. 701 * @ returns 0 if success / -1 if error. 702 *****************************************************************************************/ 703 error_t vfs_close( xptr_t file_xp, 704 uint32_t file_id ); 705 706 /****************************************************************************************** 707 * This function remove from the file system a directory entry identified by the 708 * <cwd_xp> & <path> arguments. 709 ****************************************************************************************** 710 * @ cwd_xp : extended pointer on the current working directory file descriptor. 853 711 * @ path : pathname (absolute or relative to current directory). 712 * @ returns 0 if success / -1 if error. 854 713 *****************************************************************************************/ 855 714 error_t vfs_unlink( xptr_t cwd_xp, … … 857 716 858 717 /****************************************************************************************** 859 * This function returns in the <ustat> structure various informations on the file TODO 718 * This function returns, in the structure pointed by the <k_stat> kernel pointer, 719 * various informations on the file descriptor identified by the <file_xp> argument. 720 * TODO not implemented yet... 721 ****************************************************************************************** 722 * @ file_xp : extended pointer on the file descriptor of the searched directory . 723 * @ k_dirent : local pointer on the dirent_t structure in kernel space. 724 * @ returns 0 if success / -1 if error. 860 725 *****************************************************************************************/ 861 726 error_t vfs_stat( xptr_t file_xp, 862 vfs_stat_t * ustat ); 863 864 865 866 867 /*****************************************************************************************/ 868 /************************ Directory related functions ************************************/ 869 /*****************************************************************************************/ 870 871 /****************************************************************************************** 872 * This function TODO 873 *****************************************************************************************/ 874 error_t vfs_opendir( xptr_t cwd_xp, 875 char * path, 876 uint32_t flags, 877 xptr_t file_xp ); 878 879 /****************************************************************************************** 880 * This function TODO 881 * fat32_readdir need cleaning 882 *****************************************************************************************/ 883 error_t vfs_readdir( xptr_t file_xp, 884 char * path ); 885 886 /****************************************************************************************** 887 * This function TODO 888 *****************************************************************************************/ 889 error_t vfs_mkdir( xptr_t file_xp, 890 char * path, 891 uint32_t mode ); 892 893 /****************************************************************************************** 894 * This function remove a directory from the file system. 895 *****************************************************************************************/ 896 error_t vfs_rmdir( xptr_t file_xp, 897 char * path ); 898 899 /****************************************************************************************** 900 * This function TODO 901 *****************************************************************************************/ 902 error_t vfs_chdir( char * pathname, 903 xptr_t cwd_xp ); 904 905 /****************************************************************************************** 906 * This function TODO 907 *****************************************************************************************/ 908 error_t vfs_chmod( char * pathname, 909 vfs_file_t * cwd, 910 uint32_t mode ); 911 912 /****************************************************************************************** 913 * This function TODO 914 *****************************************************************************************/ 915 error_t vfs_closedir( xptr_t file_xp, 916 uint32_t * refcount ); 917 918 919 920 921 /*****************************************************************************************/ 922 /******************* Pipe related functions *********************************************/ 923 /*****************************************************************************************/ 924 925 /****************************************************************************************** 926 * This function TODO ??? 927 *****************************************************************************************/ 928 error_t vfs_pipe( xptr_t pipefd[2] ); 929 930 /****************************************************************************************** 931 * This function TODO 932 *****************************************************************************************/ 933 error_t vfs_mkfifo( xptr_t cwd_xp, 934 char * path, 935 uint32_t mode ); 936 937 938 727 vfs_stat_t * k_stat ); 728 729 /****************************************************************************************** 730 * This function returns, in the structure pointed by the <k_dirent> kernel pointer, 731 * various infos on the directory entry currently pointed by the <file_xp> file descriptor. 732 * TODO not implemented yet... 733 ****************************************************************************************** 734 * @ file_xp : extended pointer on the file descriptor of the searched directory . 735 * @ k_dirent : local pointer on the dirent_t structure in kernel space. 736 * @ returns 0 if success / -1 if error. 737 *****************************************************************************************/ 738 error_t vfs_readdir( xptr_t file_xp, 739 vfs_dirent_t * k_dirent ); 740 741 /****************************************************************************************** 742 * This function creates a new inode and associated dentry for the directory defined 743 * by the <cwd_xp> & <path> arguments. 744 * TODO not implemented yet... 745 ****************************************************************************************** 746 * @ cwd_xp : extended pointer on the current working directory file descriptor. 747 * @ path : pathname (absolute or relative to current directory). 748 * @ mode : access rights (as defined by chmod) 749 * @ returns 0 if success / -1 if error. 750 *****************************************************************************************/ 751 error_t vfs_mkdir( xptr_t cwd_xp, 752 char * path, 753 uint32_t mode ); 754 755 /****************************************************************************************** 756 * This function remove a directory identified by the <cwd_xp / path> arguments 757 * from the file system. 758 * TODO not implemented yet... 759 ****************************************************************************************** 760 * @ cwd_xp : extended pointer on the current working directory file descriptor. 761 * @ path : pathname (absolute or relative to current directory). 762 * @ returns 0 if success / -1 if error. 763 *****************************************************************************************/ 764 error_t vfs_rmdir( xptr_t cwd_xp, 765 char * path ); 766 767 /****************************************************************************************** 768 * This function makes the directory identified by <cwd_xp / path> arguments to become 769 * the working directory for the calling process. 770 ****************************************************************************************** 771 * @ cwd_xp : extended pointer on current directory file descriptor (relative path). 772 * @ path : file pathname (absolute or relative to current directory). 773 * return 0 if success / -1 if error. 774 *****************************************************************************************/ 775 error_t vfs_chdir( xptr_t cwd_xp, 776 char * path ); 777 778 /****************************************************************************************** 779 * This function change the access rigths for the file identified by the <cwd_xp / path> 780 * arguments. The new access rights are defined by the <mode> argument value. 781 ****************************************************************************************** 782 * @ cwd_xp : extended pointer on current directory file descriptor (relative path). 783 * @ path : file pathname (absolute or relative to current directory). 784 * @ mode : access rights new value. 785 * return 0 if success / -1 if error. 786 *****************************************************************************************/ 787 error_t vfs_chmod( xptr_t cwd_xp, 788 char * path, 789 uint32_t mode ); 790 791 /****************************************************************************************** 792 * This function creates a named FIFO file. 793 * TODO not implemented yet 794 ****************************************************************************************** 795 * @ path : FIFO pathname (absolute or relative to current directory). 796 * @ cwd_xp : extended pointer on the current working directory file descriptor. 797 * @ mode : access rights new value. 798 *****************************************************************************************/ 799 error_t vfs_mkfifo( xptr_t cwd_xp, 800 char * path, 801 uint32_t mode ); 802 803 804 /*****************************************************************************************/ 805 /****************** Mapper access API ****************************************************/ 806 /*****************************************************************************************/ 807 808 /****************************************************************************************** 809 * This function makes an I/O operation to move one page from VFS to a given mapper, 810 * in case of MISS on the mapper cache. 811 * Depending on the file system type, it calls the proper, FS specific function. 812 * It must be executed by a thread running in the cluster containing the mapper. 813 * The mapper pointer is obtained from the page descriptor. 814 * It takes the mapper lock before launching the IO operation. 815 ****************************************************************************************** 816 * @ page : local pointer on the page descriptor. 817 * @ returns 0 if success / return EINVAL if it cannot access the external device. 818 *****************************************************************************************/ 819 error_t vfs_move_page_to_mapper( struct page_s * page ); 820 821 /****************************************************************************************** 822 * This function makes an I/0 operation to move one page from a given mapper to VFS, 823 * when a dirty page in the mapper cache must be updated in the File System. 824 * Depending on the file system type, it calls the proper, FS specific function. 825 * It must be executed by a thread running in the cluster containing the mapper. 826 * The mapper pointer is obtained from the page descriptor. 827 * It takes the mapper lock before launching the IO operation. 828 * It does nothing if the page is not dirty. If the page is dirty, it clear the page 829 * dirty bit, and remove the page from the PPM dirty list. 830 ****************************************************************************************** 831 * @ page : local pointer on the page descriptor. 832 * @ returns 0 if success / return EINVAL if it cannot access the external device. 833 *****************************************************************************************/ 834 error_t vfs_move_page_from_mapper( struct page_s * page ); 835 836 837 838 839 840 841 /////////////////////////////////////////////////////////////////////////////////////////// 842 // These typedef define the FS specific operations that must be implemented by any 843 // specific file system to be supported by the ALMOS_MKH VFS. 844 // These typedef are not actually used, and are only defined for documentation 845 /////////////////////////////////////////////////////////////////////////////////////////// 846 847 typedef error_t (fs_init_t) ( xptr_t vfs_root_xp ); 848 849 typedef error_t (fs_inode_extend_t) ( struct vfs_inode_s * inode, 850 void * extend ); 851 852 typedef void (fs_inode_release_t) ( struct vfs_inode_s * inode ); 853 854 typedef error_t (fs_write_page_t) ( struct page_s * page ); 855 856 typedef error_t (fs_read_page_t) ( struct page_s * page ); 857 858 859 860 861 862 863 864 865 /* deprecated [AG] 866 867 typedef error_t (lookup_inode_t) ( vfs_inode_t * parent , 868 vfs_dentry_t * dentry ); 869 870 typedef error_t (write_inode_t) ( vfs_inode_t * inode ); 871 872 typedef error_t (release_inode_t) ( vfs_inode_t * inode ); 873 874 typedef error_t (unlink_inode_t) ( vfs_inode_t * parent, 875 vfs_dentry_t * dentry, 876 uint32_t flags ); 877 878 typedef error_t (stat_inode_t) ( vfs_inode_t * inode ); 879 880 typedef error_t (trunc_inode_t) ( vfs_inode_t * inode ); 881 882 typedef error_t (delete_inode_t) ( vfs_inode_t * inode ); 883 884 typedef struct vfs_inode_op_s 885 { 886 init_inode_t * init; 887 create_inode_t * create; 888 lookup_inode_t * lookup; 889 write_inode_t * write; 890 release_inode_t * release; 891 unlink_inode_t * unlink; 892 delete_inode_t * delete; 893 stat_inode_t * stat; 894 trunc_inode_t * trunc; // change the size of a file 895 } 896 vfs_inode_op_t; 897 898 ****************************************************************************************** 899 * These typedef define the set of FS specific operations on a VFS DENTRY descriptor. 900 * They must be implemented by any specific file system to be supported by ALMOS_MKH. 901 * This code is not actually used, and is only defined for documentation 902 ****************************************************************************************** 903 904 905 typedef error_t (vfs_compare_dentry_t) ( char * first , char * second ); 906 907 typedef struct vfs_dentry_op_s 908 { 909 vfs_compare_dentry_t * compare; 910 } 911 vfs_dentry_op_t; 912 913 914 ****************************************************************************************** 915 * These typedef define the set of FS specific operations on FILE descriptors 916 * They must be implemented by any specific file system to be supported by ALMOS_MKH. 917 * This code is not actually used, and is only defined for documentation 918 ****************************************************************************************** 919 920 921 typedef error_t (open_file_t ) ( vfs_file_t * file, 922 void * extend ); 923 924 typedef error_t (read_file_t ) ( vfs_file_t * file, 925 char * buffer, 926 uint32_t count ); 927 928 typedef error_t (write_file_t ) ( vfs_file_t * file, 929 char * buffer, 930 uint32_t count ); 931 932 typedef error_t (lseek_file_t ) ( vfs_file_t * file ); 933 934 typedef error_t (close_file_t ) ( vfs_file_t * file ); 935 936 typedef error_t (release_file_t) ( vfs_file_t * file ); 937 938 typedef error_t (read_dir_t ) ( vfs_file_t * file ); 939 940 typedef error_t (mmap_file_t ) ( vfs_file_t * file , 941 struct vseg_s * vseg ); 942 943 typedef error_t (munmap_file_t ) ( vfs_file_t * file, 944 struct vseg_s * vseg ); 945 946 typedef struct vfs_file_op_s 947 { 948 open_file_t * open; 949 read_file_t * read; 950 write_file_t * write; 951 lseek_file_t * lseek; 952 read_dir_t * readdir; 953 close_file_t * close; 954 release_file_t * release; 955 mmap_file_t * mmap; 956 munmap_file_t * munmap; 957 } 958 vfs_file_op_t; 959 960 */ 939 961 940 962 #endif /* _VFS_H_ */
Note: See TracChangeset
for help on using the changeset viewer.