Changeset 651 for trunk/kernel
- Timestamp:
- Nov 14, 2019, 11:50:09 AM (5 years ago)
- Location:
- trunk/kernel
- Files:
-
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/fs/vfs.c
r647 r651 937 937 uint32_t new; 938 938 939 // check argument 939 // check arguments 940 940 assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL" ); 941 assert( (new_offset != NULL ) , "new_offset == NULL" ); 941 942 942 943 // get cluster and local pointer on remote file descriptor … … 991 992 992 993 // success 993 if ( new_offset != NULL )*new_offset = new;994 *new_offset = new; 994 995 return 0; 995 996 -
trunk/kernel/kern/kernel_init.c
r647 r651 929 929 /////////////////////////////////////////////////////////////////////////////////////////// 930 930 // This function is the entry point for the kernel initialisation. 931 // It is executed by all cores in all clusters, but only core[ 0] initializes931 // It is executed by all cores in all clusters, but only core[cxy][0] initializes 932 932 // the shared resources such as the cluster manager, or the local peripherals. 933 933 // To comply with the multi-kernels paradigm, it accesses only local cluster memory, using … … 1017 1017 ///////////////////////////////////////////////////////////////////////////////// 1018 1018 1019 // core[0] initialises DQDT (only core[0] in cluster 0build the quad-tree)1019 // core[0] initialises DQDT (only core[0][0] build the quad-tree) 1020 1020 if( core_lid == 0 ) dqdt_init(); 1021 1021 -
trunk/kernel/kern/process.c
r637 r651 916 916 { 917 917 // mark target thread for delete and block it 918 thread_delete( target_xp , process->pid , false ); // notforced918 thread_delete( target_xp , true ); // forced 919 919 } 920 920 } … … 1802 1802 // allocates memory for process descriptor from local cluster 1803 1803 process = process_alloc(); 1804 1805 1806 1804 if( process == NULL ) 1807 1805 { -
trunk/kernel/kern/process.h
r635 r651 122 122 typedef struct process_s 123 123 { 124 125 126 127 128 129 130 124 vmm_t vmm; /*! embedded virtual memory manager */ 125 126 fd_array_t fd_array; /*! embedded open file descriptors array */ 127 128 xptr_t vfs_root_xp; /*! extended pointer on VFS root inode */ 129 xptr_t vfs_bin_xp; /*! extended pointer on .elf file descriptor */ 130 pid_t pid; /*! process identifier */ 131 131 xptr_t ref_xp; /*! extended pointer on reference process */ 132 132 xptr_t owner_xp; /*! extended pointer on owner process */ 133 133 xptr_t parent_xp; /*! extended pointer on parent process */ 134 134 135 136 137 138 135 xptr_t cwd_xp; /*! extended pointer on current working dir inode */ 136 remote_busylock_t cwd_lock; /*! lock protecting working directory changes */ 137 138 xlist_entry_t children_root; /*! root of the children process xlist */ 139 139 remote_queuelock_t children_lock; /*! lock protecting children process xlist */ 140 140 uint32_t children_nr; /*! number of children processes */ 141 141 142 142 xlist_entry_t children_list; /*! member of list of children of same parent */ 143 143 xlist_entry_t local_list; /*! member of list of process in same cluster */ 144 144 xlist_entry_t copies_list; /*! member of list of copies of same process */ 145 145 xlist_entry_t txt_list; /*! member of list of processes sharing same TXT */ 146 146 147 148 149 147 struct thread_s * th_tbl[CONFIG_THREADS_MAX_PER_CLUSTER]; /*! local threads */ 148 149 uint32_t th_nr; /*! number of threads in this cluster */ 150 150 rwlock_t th_lock; /*! lock protecting th_tbl[] i */ 151 151 -
trunk/kernel/kern/scheduler.c
r641 r651 493 493 #endif 494 494 495 // This assert should never be false, as this check has been495 // This assert should always be true, as this check has been 496 496 // done before, by any function that can possibly deschedule... 497 497 assert( (current->busylocks == 0), 498 " unexpected descheduling of thread holding %d busylocks = %d\n", current->busylocks );498 "current thread hold %d busylocks\n", current->busylocks ); 499 499 500 500 // activate or create an RPC thread if RPC_FIFO non empty … … 514 514 "kernel stack overflow for thread %x on core[%x,%d]", next, local_cxy, lid ); 515 515 516 // check next thread attached to same core as the c allingthread516 // check next thread attached to same core as the current thread 517 517 assert( (next->core == current->core), 518 "next core %x != current core %x", next->core, current->core);519 518 "next_core_lid %d / current_core_lid %d", current->core->lid, next->core->lid ); 519 520 520 // check next thread not blocked when type != IDLE 521 521 assert( ((next->blocked == 0) || (next->type == THREAD_IDLE)) , -
trunk/kernel/kern/thread.c
r647 r651 673 673 uint32_t cycle = (uint32_t)hal_get_cycles(); 674 674 if( DEBUG_THREAD_USER_EXEC < cycle ) 675 printk("\n[%s] thread[%x,%x] enter / cycle %d\n",676 __FUNCTION__, process->pid, thread->trdid, cycle );675 printk("\n[%s] thread[%x,%x] enter / entry %x / cycle %d\n", 676 __FUNCTION__, process->pid, thread->trdid, entry_func , cycle ); 677 677 #endif 678 678 … … 1105 1105 ////////////////////////////////////// 1106 1106 void thread_delete( xptr_t target_xp, 1107 pid_t pid,1108 1107 bool_t is_forced ) 1109 1108 { … … 1115 1114 cxy_t target_cxy; // target thread cluster 1116 1115 thread_t * target_ptr; // pointer on target thread 1117 process_t * target_process; // pointer on arget process1116 process_t * target_process; // pointer on target process 1118 1117 pid_t target_pid; // target process identifier 1119 1118 xptr_t target_flags_xp; // extended pointer on target thread <flags> … … 1122 1121 trdid_t target_trdid; // target thread identifier 1123 1122 ltid_t target_ltid; // target thread local index 1123 uint32_t target_flags; // target thread flags 1124 1124 xptr_t joining_xp; // extended pointer on joining thread 1125 thread_t * joining_ptr; // local pointer on joining thread 1126 cxy_t joining_cxy; // joining thread cluster 1125 1127 1126 1128 // get target thread cluster and local pointer … … 1128 1130 target_ptr = GET_PTR( target_xp ); 1129 1131 1130 // get target thread identifier, attached flag, and process PID1132 // get target thread trdid, ltid, flags, and process PID 1131 1133 target_trdid = hal_remote_l32( XPTR( target_cxy , &target_ptr->trdid ) ); 1132 1134 target_ltid = LTID_FROM_TRDID( target_trdid ); 1133 target_flags_xp = XPTR( target_cxy , &target_ptr->flags ); 1134 target_ attached = ( (hal_remote_l32( target_flags_xp ) & THREAD_FLAG_DETACHED) == 0);1135 target_flags_xp = XPTR( target_cxy , &target_ptr->flags ); 1136 target_flags = hal_remote_l32( target_flags_xp ); 1135 1137 target_process = hal_remote_lpt( XPTR( target_cxy , &target_ptr->process ) ); 1136 1138 target_pid = hal_remote_l32( XPTR( target_cxy , &target_process->pid ) ); 1137 1138 // check target PID 1139 assert( (pid == target_pid), 1140 "unconsistent pid and target_xp arguments" ); 1139 target_attached = ((target_flags & THREAD_FLAG_DETACHED) == 0); 1141 1140 1142 1141 // get killer thread pointers … … 1147 1146 uint32_t cycle = (uint32_t)hal_get_cycles(); 1148 1147 if( DEBUG_THREAD_DELETE < cycle ) 1149 printk("\n[%s] killer[%x,%x] enters / target[%x,%x] / cycle %d\n",1148 printk("\n[%s] killer[%x,%x] enters / target[%x,%x] / forced %d / flags %x / cycle %d\n", 1150 1149 __FUNCTION__, killer_ptr->process->pid, killer_ptr->trdid, 1151 target_p tr->process->pid, target_ptr->trdid, cycle );1150 target_pid, target_trdid, is_forced, target_flags, cycle ); 1152 1151 #endif 1153 1152 1154 1153 // check target thread is not the main thread, because the main thread 1155 1154 // must be deleted by the parent process sys_wait() function 1156 assert( ((CXY_FROM_PID( pid ) != target_cxy) || (target_ltid != 0)),1155 assert( ((CXY_FROM_PID( target_pid ) != target_cxy) || (target_ltid != 0)), 1157 1156 "target thread cannot be the main thread" ); 1158 1157 … … 1182 1181 // get extended pointer on joining thread 1183 1182 joining_xp = (xptr_t)hal_remote_l64( target_join_xp_xp ); 1183 1184 // get cluster and local pointer on joining thread 1185 joining_ptr = GET_PTR( joining_xp ); 1186 joining_cxy = GET_CXY( joining_xp ); 1187 1188 // copy exit_status from target thread to joining thread, because 1189 // target thread may be deleted before joining thread resume 1190 void * status = hal_remote_lpt( XPTR( target_cxy , &target_ptr->exit_status ) ); 1191 hal_remote_spt( XPTR( joining_cxy , &joining_ptr->exit_status ) , status ); 1184 1192 1185 1193 // reset the join_done flag in target thread … … 1202 1210 1203 1211 #if DEBUG_THREAD_DELETE 1204 cycle = (uint32_t)hal_get_cycles ;1212 cycle = (uint32_t)hal_get_cycles(); 1205 1213 if( DEBUG_THREAD_DELETE < cycle ) 1206 1214 printk("\n[%s] killer[%x,%x] exit / target[%x,%x] marked after join / cycle %d\n", 1207 1215 __FUNCTION__, killer_ptr->process->pid, killer_ptr->trdid, 1208 target_p tr->process->pid, target_ptr->trdid, cycle );1216 target_pid, target_trdid, cycle ); 1209 1217 #endif 1210 1218 … … 1215 1223 hal_remote_atomic_or( target_flags_xp , THREAD_FLAG_KILL_DONE ); 1216 1224 1217 // block t histhread on BLOCKED_JOIN1225 // block target thread on BLOCKED_JOIN 1218 1226 thread_block( killer_xp , THREAD_BLOCKED_JOIN ); 1219 1227 … … 1225 1233 1226 1234 #if DEBUG_THREAD_DELETE 1227 cycle = (uint32_t)hal_get_cycles ;1235 cycle = (uint32_t)hal_get_cycles(); 1228 1236 if( DEBUG_THREAD_DELETE < cycle ) 1229 1237 printk("\n[%s] killer[%x,%x] deschedules / target[%x,%x] not completed / cycle %d\n", 1230 1238 __FUNCTION__, killer_ptr->process->pid, killer_ptr->trdid, 1231 target_p tr->process->pid, target_ptr->trdid, cycle );1239 target_pid, target_trdid, cycle ); 1232 1240 #endif 1233 1241 // deschedule … … 1244 1252 1245 1253 #if DEBUG_THREAD_DELETE 1246 cycle = (uint32_t)hal_get_cycles ;1254 cycle = (uint32_t)hal_get_cycles(); 1247 1255 if( DEBUG_THREAD_DELETE < cycle ) 1248 1256 printk("\n[%s] killer[%x,%x] exit / target[%x,%x] marked after join / cycle %d\n", 1249 1257 __FUNCTION__, killer_ptr->process->pid, killer_ptr->trdid, 1250 target_p tr->process->pid, target_ptr->trdid, cycle );1258 target_pid, target_trdid, cycle ); 1251 1259 #endif 1252 1260 … … 1262 1270 1263 1271 #if DEBUG_THREAD_DELETE 1264 cycle = (uint32_t)hal_get_cycles ;1272 cycle = (uint32_t)hal_get_cycles(); 1265 1273 if( DEBUG_THREAD_DELETE < cycle ) 1266 1274 printk("\n[%s] killer[%x,%x] exit / target [%x,%x] marked / no join / cycle %d\n", 1267 1275 __FUNCTION__, killer_ptr->process->pid, killer_ptr->trdid, 1268 target_p tr->process->pid, target_ptr->trdid, cycle );1276 target_pid, target_trdid, cycle ); 1269 1277 #endif 1270 1278 -
trunk/kernel/kern/thread.h
r647 r651 153 153 remote_busylock_t join_lock; /*! lock protecting the join/exit */ 154 154 xptr_t join_xp; /*! joining/killer thread extended pointer */ 155 void * exit_status; /*! status returned to joiniy thread */ 155 156 156 157 uint32_t * ack_rsp_count; /*! pointer on acknowledge response counter */ … … 392 393 *************************************************************************************** 393 394 * @ thread_xp : extended pointer on the target thread. 394 * @ pid : process identifier (to get the owner cluster identifier).395 395 * @ is_forced : the deletion does not depends on the attached mode. 396 396 **************************************************************************************/ 397 397 void thread_delete( xptr_t thread_xp, 398 pid_t pid,399 398 bool_t is_forced ); 400 399 -
trunk/kernel/kernel_config.h
r647 r651 56 56 #define DEBUG_DEV_NIC_RX 0 57 57 #define DEBUG_DEV_NIC_RX 0 58 #define DEBUG_DEV_FBF 158 #define DEBUG_DEV_FBF 0 59 59 #define DEBUG_DEV_DMA 0 60 60 #define DEBUG_DEV_MMC 0 … … 90 90 #define DEBUG_FATFS_UPDATE_IOC 0 91 91 92 #define DEBUG_HAL_CONTEXT 0 92 #define DEBUG_HAL_CONTEXT_FORK 0 93 #define DEBUG_HAL_CONTEXT_INIT 0 93 94 #define DEBUG_HAL_EXCEPTIONS 0 94 95 #define DEBUG_HAL_GPT_COPY 0 … … 104 105 #define DEBUG_HAL_TXT_RX 0 105 106 #define DEBUG_HAL_TXT_TX 0 106 #define DEBUG_HAL_FBF 1107 #define DEBUG_HAL_FBF 0 107 108 #define DEBUG_HAL_USPACE 0 108 109 #define DEBUG_HAL_VMM 0 … … 134 135 #define DEBUG_PROCESS_GET_LOCAL_COPY 0 135 136 #define DEBUG_PROCESS_INIT_CREATE 0 136 #define DEBUG_PROCESS_MAKE_EXEC 1137 #define DEBUG_PROCESS_MAKE_FORK 1137 #define DEBUG_PROCESS_MAKE_EXEC 0 138 #define DEBUG_PROCESS_MAKE_FORK 0 138 139 #define DEBUG_PROCESS_REFERENCE_INIT 0 139 140 #define DEBUG_PROCESS_SIGACTION 0 … … 177 178 #define DEBUG_SEM 0 178 179 179 #define DEBUG_SYSCALLS_ERROR 180 #define DEBUG_SYSCALLS_ERROR 2 180 181 181 182 #define DEBUG_SYS_BARRIER 0 … … 184 185 #define DEBUG_SYS_CONDVAR 0 185 186 #define DEBUG_SYS_DISPLAY 0 186 #define DEBUG_SYS_EXEC 2187 #define DEBUG_SYS_EXEC 0 187 188 #define DEBUG_SYS_EXIT 0 188 189 #define DEBUG_SYS_FBF 0 189 190 #define DEBUG_SYS_FG 0 190 #define DEBUG_SYS_FORK 2191 #define DEBUG_SYS_FORK 0 191 192 #define DEBUG_SYS_GET_CONFIG 0 192 193 #define DEBUG_SYS_GETCWD 0 … … 199 200 #define DEBUG_SYS_IS_FG 0 200 201 #define DEBUG_SYS_KILL 0 202 #define DEBUG_SYS_LSEEK 0 201 203 #define DEBUG_SYS_MKDIR 0 202 204 #define DEBUG_SYS_MMAP 0 … … 264 266 #define DEBUG_VMM_HANDLE_PAGE_FAULT 0 265 267 #define DEBUG_VMM_HANDLE_COW 0 266 #define DEBUG_VMM_MMAP _ALLOC0268 #define DEBUG_VMM_MMAP 0 267 269 #define DEBUG_VMM_PAGE_ALLOCATE 0 268 270 #define DEBUG_VMM_REMOVE_VSEG 0 … … 326 328 //////////////////////////////////////////////////////////////////////////////////////////// 327 329 328 #define CONFIG_VERSION "Version 2. 2 / June2019"330 #define CONFIG_VERSION "Version 2.3 / November 2019" 329 331 330 332 //////////////////////////////////////////////////////////////////////////////////////////// … … 431 433 432 434 //////////////////////////////////////////////////////////////////////////////////////////// 433 // 32 bits USER SPACE SEGMENTATION / all values are numbers of pages435 // 32 bits USER SPACE SEGMENTATION / all bases and sizes are numbers of pages 434 436 //////////////////////////////////////////////////////////////////////////////////////////// 435 437 … … 438 440 #define CONFIG_VMM_UTILS_BASE 0x000200 // UTILS zone base : 2 Mbytes 439 441 #define CONFIG_VMM_ELF_BASE 0x000400 // ELF zone base : 4 Mbytes 440 #define CONFIG_VMM_HEAP_BASE 0x0 02000 // HEAP zone base : 32 Mbytes442 #define CONFIG_VMM_HEAP_BASE 0x040000 // HEAP zone base : 32 Mbytes 441 443 #define CONFIG_VMM_STACK_BASE 0x0C0000 // STACK zone base : 3 Gbytes 442 444 … … 445 447 #define CONFIG_VMM_STACK_SIZE 0x001000 // single stack vseg size : 16 Mbytes 446 448 449 #define CONFIG_VMM_HEAP_MAX_ORDER 18 // max size of MMAP vseg : 1 Gbytes 447 450 //////////////////////////////////////////////////////////////////////////////////////////// 448 451 // PHYSICAL MEMORY MANAGEMENT … … 463 466 464 467 #define CONFIG_INSTRUMENTATION_SYSCALLS 0 465 #define CONFIG_INSTRUMENTATION_PGFAULTS 1468 #define CONFIG_INSTRUMENTATION_PGFAULTS 0 466 469 #define CONFIG_INSTRUMENTATION_FOOTPRINT 0 467 #define CONFIG_INSTRUMENTATION_GPT 1470 #define CONFIG_INSTRUMENTATION_GPT 0 468 471 469 472 -
trunk/kernel/libk/elf.c
r635 r651 216 216 process_t * process ) 217 217 { 218 uint32_t new_offset; // unused, required by vfs_lseek() 218 219 kmem_req_t req; // kmem request for program header 219 220 Elf_Ehdr header; // local buffer for .elf header … … 274 275 275 276 // set seek pointer in file descriptor to access segment descriptors array 276 error = vfs_lseek( file_xp , header.e_phoff, SEEK_SET , NULL);277 error = vfs_lseek( file_xp , header.e_phoff, SEEK_SET , &new_offset ); 277 278 278 279 if( error ) -
trunk/kernel/libk/list.h
r636 r651 61 61 62 62 /*************************************************************************** 63 * This macro return an uint32_t that is the offset (number of bytes)63 * This macro return an intptr_t that is the offset (number of bytes) 64 64 * of a field in a structure. 65 *************************************************************************** 65 66 * @ type : structure type 66 67 * @ member : name of the field -
trunk/kernel/libk/user_dir.h
r635 r651 37 37 * - An user process open a directory by calling the "opendir()" syscall. 38 38 * The user_dir_create() function allocates physical memory to create in the cluster 39 * containing the targetinode one or several physical pages to implement an array40 * of "dirent" , mapped in the user process space as an ANON vseg. It allocates also41 * an "user_dir_t" descriptor structure defined below, registered in the xlist rooted42 * in the reference user process descriptor.39 * containing the directory inode one or several physical pages to implement an array 40 * of "dirent". This array is mapped in the user process space as an ANON vseg. 41 * It allocates also an "user_dir_t" descriptor structure defined below, registered 42 * in the xlist rooted in the reference user process descriptor. 43 43 * - This "user_dir_t" structure contains the total number of "entries", the "current" 44 44 * pointer used by the readdir() syscall, and an "ident" field, that is actually … … 104 104 * structures rooted in the reference process descriptor, release all memory 105 105 * allocated for the user_dir_t struct in the directory inode cluster, including 106 * the dirent array, and delete allANON vseg copies in all process VMM copies,106 * the dirent array, and delete the ANON vseg copies in all process VMM copies, 107 107 * using parallel RPCs. 108 108 * It must be executed by a thread running in the cluster containing the target inode. -
trunk/kernel/mm/mapper.c
r637 r651 442 442 if ( page_xp == XPTR_NULL ) return -1; 443 443 444 // compute extended pointer in kernel mapper444 // compute extended pointer on kernel mapper 445 445 xptr_t map_xp = ppm_page2base( page_xp ) + page_offset; 446 446 … … 448 448 if( DEBUG_MAPPER_MOVE_USER < cycle ) 449 449 printk("\n[%s] thread[%x,%x] : get buffer(%x,%x) in mapper\n", 450 __FUNCTION__, this->process->pid, this->trdid, map_cxy, map_ptr);450 __FUNCTION__, this->process->pid, this->trdid, GET_CXY(map_xp), GET_PTR(map_xp) ); 451 451 #endif 452 452 // compute pointer in user buffer -
trunk/kernel/mm/ppm.c
r637 r651 296 296 current_size >>= 1; 297 297 298 // update order fiel s in new free block298 // update order fields in new free block 299 299 current_block = found_block + current_size; 300 300 current_block->order = current_order; -
trunk/kernel/mm/vmm.c
r641 r651 55 55 56 56 //////////////////////////////////////////////////////////////////////////////////////////// 57 // This static function is called by the vmm_user_init() function. 58 // It initialises the free lists of vsegs used by the VMM MMAP allocator. 59 // It makes the assumption that HEAP_BASE == 1 Gbytes and HEAP_SIZE == 2 Gbytes. 60 //////////////////////////////////////////////////////////////////////////////////////////// 61 static void vmm_stack_init( vmm_t * vmm ) 62 { 63 64 // check STACK zone 65 assert( ((CONFIG_VMM_STACK_SIZE * CONFIG_THREADS_MAX_PER_CLUSTER) <= 66 (CONFIG_VMM_VSPACE_SIZE - CONFIG_VMM_STACK_BASE)) , "STACK zone too small\n"); 67 68 // get pointer on STACK allocator 69 stack_mgr_t * mgr = &vmm->stack_mgr; 70 71 mgr->bitmap = 0; 72 mgr->vpn_base = CONFIG_VMM_STACK_BASE; 73 busylock_init( &mgr->lock , LOCK_VMM_STACK ); 74 75 } 76 77 //////////////////////////////////////////////////////////////////////////////////////////// 57 78 // This static function is called by the vmm_create_vseg() function, and implements 58 // the VMM STACK specific allocator. 79 // the VMM STACK specific allocator. Depending on the local thread index <ltid>, 80 // it ckeks availability of the corresponding slot in the process STACKS region, 81 // allocates a vseg descriptor, and initializes the "vpn_base" and "vpn_size" fields. 59 82 //////////////////////////////////////////////////////////////////////////////////////////// 60 83 // @ vmm : [in] pointer on VMM. 61 84 // @ ltid : [in] requested slot == local user thread identifier. 62 // @ vpn_base : [out] first allocated page63 // @ vpn_size : [out] number of allocated pages64 85 //////////////////////////////////////////////////////////////////////////////////////////// 65 static void vmm_stack_alloc( vmm_t * vmm, 66 ltid_t ltid, 67 vpn_t * vpn_base, 68 vpn_t * vpn_size ) 86 static vseg_t * vmm_stack_alloc( vmm_t * vmm, 87 ltid_t ltid ) 69 88 { 70 89 … … 76 95 stack_mgr_t * mgr = &vmm->stack_mgr; 77 96 78 // get lock onstack allocator97 // get lock protecting stack allocator 79 98 busylock_acquire( &mgr->lock ); 80 99 … … 83 102 "slot index %d already allocated", ltid ); 84 103 104 // allocate a vseg descriptor 105 vseg_t * vseg = vseg_alloc(); 106 107 if( vseg == NULL ) 108 { 109 // release lock protecting free lists 110 busylock_release( &mgr->lock ); 111 112 printk("\n[ERROR] %s cannot allocate memory for vseg in cluster %x\n", 113 __FUNCTION__ , local_cxy ); 114 115 return NULL; 116 } 117 85 118 // update bitmap 86 119 bitmap_set( &mgr->bitmap , ltid ); … … 89 122 busylock_release( &mgr->lock ); 90 123 91 // returns vpn_base, vpn_size (first page non allocated) 92 *vpn_base = mgr->vpn_base + ltid * CONFIG_VMM_STACK_SIZE + 1; 93 *vpn_size = CONFIG_VMM_STACK_SIZE - 1; 124 // set "vpn_base" & "vpn_size" fields (first page non allocated) 125 vseg->vpn_base = mgr->vpn_base + (ltid * CONFIG_VMM_STACK_SIZE) + 1; 126 vseg->vpn_size = CONFIG_VMM_STACK_SIZE - 1; 127 128 return vseg; 94 129 95 130 } // end vmm_stack_alloc() … … 98 133 // This static function is called by the vmm_remove_vseg() function, and implements 99 134 // the VMM STACK specific desallocator. 135 // It updates the bitmap to release the corresponding slot in the process STACKS region, 136 // and releases memory allocated to vseg descriptor. 100 137 //////////////////////////////////////////////////////////////////////////////////////////// 101 138 // @ vmm : [in] pointer on VMM. … … 128 165 busylock_release( &mgr->lock ); 129 166 167 // release memory allocated to vseg descriptor 168 vseg_free( vseg ); 169 130 170 } // end vmm_stack_free() 171 172 173 174 //////////////////////////////////////////////////////////////////////////////////////////// 175 // This function display the current state of the VMM MMAP allocator of a process VMM 176 // identified by the <vmm> argument. 177 //////////////////////////////////////////////////////////////////////////////////////////// 178 void vmm_mmap_display( vmm_t * vmm ) 179 { 180 uint32_t order; 181 xptr_t root_xp; 182 xptr_t iter_xp; 183 184 // get pointer on process 185 process_t * process = (process_t *)(((char*)vmm) - OFFSETOF( process_t , vmm )); 186 187 // get process PID 188 pid_t pid = process->pid; 189 190 // get pointer on VMM MMAP allocator 191 mmap_mgr_t * mgr = &vmm->mmap_mgr; 192 193 // display header 194 printk("***** VMM MMAP allocator / process %x *****\n", pid ); 195 196 // scan the array of free lists of vsegs 197 for( order = 0 ; order <= CONFIG_VMM_HEAP_MAX_ORDER ; order++ ) 198 { 199 root_xp = XPTR( local_cxy , &mgr->free_list_root[order] ); 200 201 if( !xlist_is_empty( root_xp ) ) 202 { 203 printk(" - %d (%x pages) : ", order , 1<<order ); 204 205 XLIST_FOREACH( root_xp , iter_xp ) 206 { 207 xptr_t vseg_xp = XLIST_ELEMENT( iter_xp , vseg_t , xlist ); 208 vseg_t * vseg = GET_PTR( vseg_xp ); 209 210 printk("%x | ", vseg->vpn_base ); 211 } 212 213 printk("\n"); 214 } 215 } 216 } // end vmm_mmap_display() 217 218 //////////////////////////////////////////////////////////////////////////////////////////// 219 // This static function is called by the vmm_user_init() function. 220 // It initialises the free lists of vsegs used by the VMM MMAP allocator. 221 // TODO this function is only valid for 32 bits cores, and makes three assumptions: 222 // HEAP_BASE == 1 Gbytes / HEAP_SIZE == 2 Gbytes / MMAP_MAX_SIZE == 1 Gbytes 223 //////////////////////////////////////////////////////////////////////////////////////////// 224 void vmm_mmap_init( vmm_t * vmm ) 225 { 226 227 // check HEAP base and size 228 assert( (CONFIG_VMM_HEAP_BASE == 0x40000) & (CONFIG_VMM_STACK_BASE == 0xc0000), 229 "CONFIG_VMM_HEAP_BASE != 0x40000 or CONFIG_VMM_STACK_BASE != 0xc0000" ); 230 231 // check MMAP vseg max order 232 assert( (CONFIG_VMM_HEAP_MAX_ORDER == 18), "max mmap vseg size is 256K pages" ); 233 234 // get pointer on MMAP allocator 235 mmap_mgr_t * mgr = &vmm->mmap_mgr; 236 237 // initialize HEAP base and size 238 mgr->vpn_base = CONFIG_VMM_HEAP_BASE; 239 mgr->vpn_size = CONFIG_VMM_STACK_BASE - CONFIG_VMM_HEAP_BASE; 240 241 // initialize lock 242 busylock_init( &mgr->lock , LOCK_VMM_MMAP ); 243 244 // initialize free lists 245 uint32_t i; 246 for( i = 0 ; i <= CONFIG_VMM_HEAP_MAX_ORDER ; i++ ) 247 { 248 xlist_root_init( XPTR( local_cxy , &mgr->free_list_root[i] ) ); 249 } 250 251 // allocate and register first 1 Gbytes vseg 252 vseg_t * vseg0 = vseg_alloc(); 253 254 assert( (vseg0 != NULL) , "cannot allocate vseg" ); 255 256 vseg0->vpn_base = CONFIG_VMM_HEAP_BASE; 257 vseg0->vpn_size = CONFIG_VMM_HEAP_BASE; 258 259 xlist_add_first( XPTR( local_cxy , &mgr->free_list_root[CONFIG_VMM_HEAP_MAX_ORDER] ), 260 XPTR( local_cxy , &vseg0->xlist ) ); 261 262 // allocate and register second 1 Gbytes vseg 263 vseg_t * vseg1 = vseg_alloc(); 264 265 assert( (vseg1 != NULL) , "cannot allocate vseg" ); 266 267 vseg1->vpn_base = CONFIG_VMM_HEAP_BASE << 1; 268 vseg1->vpn_size = CONFIG_VMM_HEAP_BASE; 269 270 xlist_add_first( XPTR( local_cxy , &mgr->free_list_root[CONFIG_VMM_HEAP_MAX_ORDER] ), 271 XPTR( local_cxy , &vseg1->xlist ) ); 272 273 #if DEBUG_VMM_MMAP 274 thread_t * this = CURRENT_THREAD; 275 uint32_t cycle = (uint32_t)hal_get_cycles(); 276 printk("\n[%s] thread[%x,%x] / cycle %d\n", 277 __FUNCTION__, this->process->pid, this->trdid, cycle ); 278 vmm_mmap_display( vmm ); 279 #endif 280 281 } // end vmm_mmap_init() 131 282 132 283 //////////////////////////////////////////////////////////////////////////////////////////// 133 284 // This static function is called by the vmm_create_vseg() function, and implements 134 // the VMM MMAP specific allocator. 285 // the VMM MMAP specific allocator. Depending on the requested number of pages <npages>, 286 // it get a free vseg from the relevant free_list, and initializes the "vpn_base" and 287 // "vpn_size" fields. 135 288 //////////////////////////////////////////////////////////////////////////////////////////// 136 289 // @ vmm : [in] pointer on VMM. 137 290 // @ npages : [in] requested number of pages. 138 // @ vpn_base : [out] first allocated page. 139 // @ vpn_size : [out] actual number of allocated pages. 291 // @ returns local pointer on vseg if success / returns NULL if failure. 140 292 //////////////////////////////////////////////////////////////////////////////////////////// 141 static error_t vmm_mmap_alloc( vmm_t * vmm, 142 vpn_t npages, 143 vpn_t * vpn_base, 144 vpn_t * vpn_size ) 293 static vseg_t * vmm_mmap_alloc( vmm_t * vmm, 294 vpn_t npages ) 145 295 { 146 uint32_t order; 147 xptr_t vseg_xp; 148 vseg_t * vseg; 149 vpn_t base; 150 vpn_t size; 151 vpn_t free; 152 153 #if DEBUG_VMM_MMAP_ALLOC 296 297 #if DEBUG_VMM_MMAP 154 298 thread_t * this = CURRENT_THREAD; 155 299 uint32_t cycle = (uint32_t)hal_get_cycles(); 156 if( DEBUG_VMM_MMAP _ALLOC< cycle )157 printk("\n[%s] thread[%x,%x] enter/ cycle %d\n",158 __FUNCTION__, this->process->pid, this->trdid, cycle );300 if( DEBUG_VMM_MMAP < cycle ) 301 printk("\n[%s] thread[%x,%x] for %x pages / cycle %d\n", 302 __FUNCTION__, this->process->pid, this->trdid, npages, cycle ); 159 303 #endif 160 304 161 305 // number of allocated pages must be power of 2 162 306 // compute actual size and order 163 size= POW2_ROUNDUP( npages );164 order = bits_log2(size );307 vpn_t required_vpn_size = POW2_ROUNDUP( npages ); 308 uint32_t required_order = bits_log2( required_vpn_size ); 165 309 166 310 // get mmap allocator pointer 167 311 mmap_mgr_t * mgr = &vmm->mmap_mgr; 168 312 169 // build extended pointer on root of zombi_list[order] 170 xptr_t root_xp = XPTR( local_cxy , &mgr->zombi_list[order] ); 171 172 // take lock protecting zombi_lists 313 // take lock protecting free lists in MMAP allocator 173 314 busylock_acquire( &mgr->lock ); 174 315 175 // get vseg from zombi_list or from mmap zone 176 if( xlist_is_empty( root_xp ) ) // from mmap zone 177 { 178 // check overflow 179 free = mgr->first_free_vpn; 180 if( (free + size) > mgr->vpn_size ) return -1; 181 182 // update MMAP allocator 183 mgr->first_free_vpn += size; 184 185 // compute base 186 base = free; 187 } 188 else // from zombi_list 189 { 190 // get pointer on zombi vseg from zombi_list 191 vseg_xp = XLIST_FIRST( root_xp , vseg_t , xlist ); 192 vseg = GET_PTR( vseg_xp ); 193 194 // remove vseg from free-list 195 xlist_unlink( XPTR( local_cxy , &vseg->xlist ) ); 196 197 // compute base 198 base = vseg->vpn_base; 199 } 200 201 // release lock 202 busylock_release( &mgr->lock ); 203 204 #if DEBUG_VMM_MMAP_ALLOC 205 cycle = (uint32_t)hal_get_cycles(); 206 if( DEBUG_VMM_DESTROY < cycle ) 207 printk("\n[%s] thread[%x,%x] exit / vpn_base %x / vpn_size %x / cycle %d\n", 208 __FUNCTION__, this->process->pid, this->trdid, base, size, cycle ); 209 #endif 210 211 // returns vpn_base, vpn_size 212 *vpn_base = base; 213 *vpn_size = size; 214 return 0; 316 // initialises the while loop variables 317 uint32_t current_order = required_order; 318 vseg_t * current_vseg = NULL; 319 320 // search a free vseg equal or larger than requested size 321 while( current_order <= CONFIG_VMM_HEAP_MAX_ORDER ) 322 { 323 // build extended pointer on free_pages_root[current_order] 324 xptr_t root_xp = XPTR( local_cxy , &mgr->free_list_root[current_order] ); 325 326 if( !xlist_is_empty( root_xp ) ) 327 { 328 // get extended pointer on first vseg in this free_list 329 xptr_t current_vseg_xp = XLIST_FIRST( root_xp , vseg_t , xlist ); 330 current_vseg = GET_PTR( current_vseg_xp ); 331 332 // build extended pointer on xlist field in vseg descriptor 333 xptr_t list_entry_xp = XPTR( local_cxy , ¤t_vseg->xlist ); 334 335 // remove this vseg from the free_list 336 xlist_unlink( list_entry_xp ); 337 338 break; 339 } 340 341 // increment loop index 342 current_order++; 343 344 } // end while loop 345 346 if( current_vseg == NULL ) // return failure 347 { 348 // release lock protecting free lists 349 busylock_release( &mgr->lock ); 350 351 printk("\n[ERROR] %s cannot allocate ) %d page(s) in cluster %x\n", 352 __FUNCTION__, npages , local_cxy ); 353 354 return NULL; 355 } 356 357 // split recursively the found vseg in smaller vsegs 358 // if required, and update the free-lists accordingly 359 while( current_order > required_order ) 360 { 361 // get found vseg base and size 362 vpn_t vpn_base = current_vseg->vpn_base; 363 vpn_t vpn_size = current_vseg->vpn_size; 364 365 // allocate a new vseg for the upper half of current vseg 366 vseg_t * new_vseg = vseg_alloc(); 367 368 if( new_vseg == NULL ) 369 { 370 // release lock protecting free lists 371 busylock_release( &mgr->lock ); 372 373 printk("\n[ERROR] %s cannot allocate memory for vseg in cluster %x\n", 374 __FUNCTION__ , local_cxy ); 375 376 return NULL; 377 } 378 379 // initialise new vseg (upper half of found vseg) 380 new_vseg->vmm = vmm; 381 new_vseg->vpn_base = vpn_base + (vpn_size >> 1); 382 new_vseg->vpn_size = vpn_size >> 1; 383 384 // insert new vseg in relevant free_list 385 xlist_add_first( XPTR( local_cxy , &mgr->free_list_root[current_order-1] ), 386 XPTR( local_cxy , &new_vseg->xlist ) ); 387 388 // update found vseg 389 current_vseg->vpn_size = vpn_size>>1; 390 391 // update order 392 current_order --; 393 } 394 395 // release lock protecting free lists 396 busylock_release( &mgr->lock ); 397 398 #if DEBUG_VMM_MMAP 399 vmm_mmap_display( vmm ); 400 #endif 401 402 return current_vseg; 215 403 216 404 } // end vmm_mmap_alloc() … … 219 407 // This static function implements the VMM MMAP specific desallocator. 220 408 // It is called by the vmm_remove_vseg() function. 409 // It releases the vseg to the relevant free_list, after trying (recursively) to 410 // merge it to the buddy vseg. 221 411 //////////////////////////////////////////////////////////////////////////////////////////// 222 412 // @ vmm : [in] pointer on VMM. … … 226 416 vseg_t * vseg ) 227 417 { 228 // get pointer on mmap allocator 418 419 #if DEBUG_VMM_MMAP 420 thread_t * this = CURRENT_THREAD; 421 uint32_t cycle = (uint32_t)hal_get_cycles(); 422 if( DEBUG_VMM_MMAP < cycle ) 423 printk("\n[%s] thread[%x,%x] for vpn_base %x / vpn_size %x / cycle %d\n", 424 __FUNCTION__, this->process->pid, this->trdid, vseg->vpn_base, vseg->vpn_size, cycle ); 425 #endif 426 427 vseg_t * buddy_vseg; 428 429 // get mmap allocator pointer 229 430 mmap_mgr_t * mgr = &vmm->mmap_mgr; 230 431 231 // compute zombi_list order 232 uint32_t order = bits_log2( vseg->vpn_size ); 233 234 // take lock protecting zombi lists 432 // take lock protecting free lists 235 433 busylock_acquire( &mgr->lock ); 236 434 237 // update relevant zombi_list 238 xlist_add_first( XPTR( local_cxy , &mgr->zombi_list[order] ), 239 XPTR( local_cxy , &vseg->xlist ) ); 435 // initialise loop variables 436 // released_vseg is the currently released vseg 437 vseg_t * released_vseg = vseg; 438 uint32_t released_order = bits_log2( vseg->vpn_size ); 439 440 // iteratively merge the released vseg to the buddy vseg 441 // release the current page and exit when buddy not found 442 while( released_order <= CONFIG_VMM_HEAP_MAX_ORDER ) 443 { 444 // compute buddy_vseg vpn_base 445 vpn_t buddy_vpn_base = released_vseg->vpn_base ^ (1 << released_order); 446 447 // build extended pointer on free_pages_root[current_order] 448 xptr_t root_xp = XPTR( local_cxy , &mgr->free_list_root[released_order] ); 449 450 // scan this free list to find the buddy vseg 451 xptr_t iter_xp; 452 buddy_vseg = NULL; 453 XLIST_FOREACH( root_xp , iter_xp ) 454 { 455 xptr_t current_vseg_xp = XLIST_ELEMENT( iter_xp , vseg_t , xlist ); 456 vseg_t * current_vseg = GET_PTR( current_vseg_xp ); 457 458 if( current_vseg->vpn_base == buddy_vpn_base ) 459 { 460 buddy_vseg = current_vseg; 461 break; 462 } 463 } 464 465 if( buddy_vseg != NULL ) // buddy found => merge released & buddy 466 { 467 // update released vseg fields 468 released_vseg->vpn_size = buddy_vseg->vpn_size<<1; 469 if( released_vseg->vpn_base > buddy_vseg->vpn_base) 470 released_vseg->vpn_base = buddy_vseg->vpn_base; 471 472 // remove buddy vseg from free_list 473 xlist_unlink( XPTR( local_cxy , &buddy_vseg->xlist ) ); 474 475 // release memory allocated to buddy descriptor 476 vseg_free( buddy_vseg ); 477 } 478 else // buddy not found => register & exit 479 { 480 // register released vseg in free list 481 xlist_add_first( root_xp , XPTR( local_cxy , &released_vseg->xlist ) ); 482 483 // exit while loop 484 break; 485 } 486 487 // increment released_order 488 released_order++; 489 } 240 490 241 491 // release lock 242 492 busylock_release( &mgr->lock ); 243 493 244 } // end of vmm_mmap_free() 494 #if DEBUG_VMM_MMAP 495 vmm_mmap_display( vmm ); 496 #endif 497 498 } // end vmm_mmap_free() 245 499 246 500 //////////////////////////////////////////////////////////////////////////////////////////// … … 288 542 error_t vmm_user_init( process_t * process ) 289 543 { 290 uint32_t i;291 544 292 545 #if DEBUG_VMM_USER_INIT … … 306 559 "UTILS zone too small\n" ); 307 560 308 // check STACK zone 309 assert( ((CONFIG_VMM_STACK_SIZE * CONFIG_THREADS_MAX_PER_CLUSTER) <= 310 (CONFIG_VMM_VSPACE_SIZE - CONFIG_VMM_STACK_BASE)) , 311 "STACK zone too small\n"); 312 313 // initialize the lock protecting the VSL 561 // initialize lock protecting the VSL 314 562 remote_queuelock_init( XPTR( local_cxy , &vmm->vsl_lock ) , LOCK_VMM_VSL ); 315 563 564 565 // initialize STACK allocator 566 vmm_stack_init( vmm ); 567 568 // initialize MMAP allocator 569 vmm_mmap_init( vmm ); 570 571 // initialize instrumentation counters 572 vmm->false_pgfault_nr = 0; 573 vmm->local_pgfault_nr = 0; 574 vmm->global_pgfault_nr = 0; 575 vmm->false_pgfault_cost = 0; 576 vmm->local_pgfault_cost = 0; 577 vmm->global_pgfault_cost = 0; 316 578 317 579 /* … … 356 618 vmm->envs_vpn_base = base; 357 619 */ 358 // initialize STACK allocator359 vmm->stack_mgr.bitmap = 0;360 vmm->stack_mgr.vpn_base = CONFIG_VMM_STACK_BASE;361 busylock_init( &vmm->stack_mgr.lock , LOCK_VMM_STACK );362 363 // initialize MMAP allocator364 vmm->mmap_mgr.vpn_base = CONFIG_VMM_HEAP_BASE;365 vmm->mmap_mgr.vpn_size = CONFIG_VMM_STACK_BASE - CONFIG_VMM_HEAP_BASE;366 vmm->mmap_mgr.first_free_vpn = CONFIG_VMM_HEAP_BASE;367 busylock_init( &vmm->mmap_mgr.lock , LOCK_VMM_MMAP );368 for( i = 0 ; i < 32 ; i++ )369 {370 xlist_root_init( XPTR( local_cxy , &vmm->mmap_mgr.zombi_list[i] ) );371 }372 373 // initialize instrumentation counters374 vmm->false_pgfault_nr = 0;375 vmm->local_pgfault_nr = 0;376 vmm->global_pgfault_nr = 0;377 vmm->false_pgfault_cost = 0;378 vmm->local_pgfault_cost = 0;379 vmm->global_pgfault_cost = 0;380 381 620 hal_fence(); 382 621 … … 1158 1397 remote_queuelock_release( parent_lock_xp ); 1159 1398 1399 /* deprecated [AG] : this is already done by the vmm_user_init() funcfion 1400 1160 1401 // initialize the child VMM STACK allocator 1161 child_vmm->stack_mgr.bitmap = 0; 1162 child_vmm->stack_mgr.vpn_base = CONFIG_VMM_STACK_BASE; 1402 vmm_stack_init( child_vmm ); 1163 1403 1164 1404 // initialize the child VMM MMAP allocator 1165 uint32_t i; 1166 child_vmm->mmap_mgr.vpn_base = CONFIG_VMM_HEAP_BASE; 1167 child_vmm->mmap_mgr.vpn_size = CONFIG_VMM_STACK_BASE - CONFIG_VMM_HEAP_BASE; 1168 child_vmm->mmap_mgr.first_free_vpn = CONFIG_VMM_HEAP_BASE; 1169 for( i = 0 ; i < 32 ; i++ ) 1170 { 1171 xlist_root_init( XPTR( local_cxy , &child_vmm->mmap_mgr.zombi_list[i] ) ); 1172 } 1405 vmm_mmap_init( child_vmm ); 1173 1406 1174 1407 // initialize instrumentation counters … … 1179 1412 child_vmm->local_pgfault_cost = 0; 1180 1413 child_vmm->global_pgfault_cost = 0; 1181 1414 */ 1182 1415 // copy base addresses from parent VMM to child VMM 1183 1416 child_vmm->args_vpn_base = (vpn_t)hal_remote_lpt(XPTR(parent_cxy, &parent_vmm->args_vpn_base)); … … 1260 1493 remote_queuelock_release( vsl_lock_xp ); 1261 1494 1262 // remove all registered MMAP vsegs 1263 // from zombi_lists in MMAP allocator 1495 // remove all registered MMAP vsegs from free_lists in MMAP allocator 1264 1496 uint32_t i; 1265 for( i = 0 ; i <32; i++ )1266 { 1267 // build extended pointer on zombi_list[i]1268 xptr_t root_xp = XPTR( local_cxy , &vmm->mmap_mgr. zombi_list[i] );1497 for( i = 0 ; i <= CONFIG_VMM_HEAP_MAX_ORDER ; i++ ) 1498 { 1499 // build extended pointer on free list root 1500 xptr_t root_xp = XPTR( local_cxy , &vmm->mmap_mgr.free_list_root[i] ); 1269 1501 1270 1502 // scan zombi_list[i] … … 1343 1575 cxy_t cxy ) 1344 1576 { 1345 vseg_t * vseg; // created vseg pointer 1346 vpn_t vpn_base; // first page index 1347 vpn_t vpn_size; // number of pages covered by vseg 1348 error_t error; 1577 vseg_t * vseg; // pointer on allocated vseg descriptor 1349 1578 1350 1579 #if DEBUG_VMM_CREATE_VSEG … … 1364 1593 vmm_t * vmm = &process->vmm; 1365 1594 1366 // compute base, size, vpn_base, vpn_size, depending on vseg type 1367 // we use the VMM specific allocators for "stack", "file", "anon", & "remote" vsegs 1368 1595 // allocate a vseg descriptor and initialize it, depending on type 1596 // we use specific allocators for "stack" and "mmap" types 1597 1598 ///////////////////////////// 1369 1599 if( type == VSEG_TYPE_STACK ) 1370 1600 { 1371 // get vpn_base and vpn_size from STACK allocator 1372 vmm_stack_alloc( vmm , base , &vpn_base , &vpn_size ); 1373 1374 // compute vseg base and size from vpn_base and vpn_size 1375 base = vpn_base << CONFIG_PPM_PAGE_SHIFT; 1376 size = vpn_size << CONFIG_PPM_PAGE_SHIFT; 1377 } 1378 else if( type == VSEG_TYPE_FILE ) 1379 { 1380 // compute page index (in mapper) for first byte 1381 vpn_t vpn_min = file_offset >> CONFIG_PPM_PAGE_SHIFT; 1382 1383 // compute page index (in mapper) for last byte 1384 vpn_t vpn_max = (file_offset + size - 1) >> CONFIG_PPM_PAGE_SHIFT; 1385 1386 // compute offset in first page 1387 uint32_t offset = file_offset & CONFIG_PPM_PAGE_MASK; 1388 1389 // compute number of pages required in virtual space 1390 vpn_t npages = vpn_max - vpn_min + 1; 1391 1392 // get vpn_base and vpn_size from MMAP allocator 1393 error = vmm_mmap_alloc( vmm , npages , &vpn_base , &vpn_size ); 1394 if( error ) 1601 // get vseg from STACK allocator 1602 vseg = vmm_stack_alloc( vmm , base ); // base == ltid 1603 1604 if( vseg == NULL ) 1395 1605 { 1396 printk("\n[ERROR] in %s : no vspace for mmap vseg /process %x in cluster %x\n",1397 __FUNCTION__, process->pid , local_cxy );1606 printk("\n[ERROR] %s cannot create %s vseg for process %x in cluster %x\n", 1607 __FUNCTION__ , vseg_type_str( type ) , process->pid , local_cxy ); 1398 1608 return NULL; 1399 1609 } 1400 1610 1401 // set the vseg base (not always aligned for FILE) 1402 base = (vpn_base << CONFIG_PPM_PAGE_SHIFT) + offset; 1403 } 1404 else if( (type == VSEG_TYPE_ANON) || 1405 (type == VSEG_TYPE_REMOTE) ) 1611 // initialize vseg 1612 vseg->type = type; 1613 vseg->vmm = vmm; 1614 vseg->min = vseg->vpn_base << CONFIG_PPM_PAGE_SHIFT; 1615 vseg->max = vseg->min + (vseg->vpn_size << CONFIG_PPM_PAGE_SHIFT); 1616 vseg->cxy = cxy; 1617 1618 vseg_init_flags( vseg , type ); 1619 } 1620 ///////////////////////////////// 1621 else if( type == VSEG_TYPE_FILE ) 1622 { 1623 // compute page index (in mapper) for first and last byte 1624 vpn_t vpn_min = file_offset >> CONFIG_PPM_PAGE_SHIFT; 1625 vpn_t vpn_max = (file_offset + size - 1) >> CONFIG_PPM_PAGE_SHIFT; 1626 1627 // compute offset in first page and number of pages 1628 uint32_t offset = file_offset & CONFIG_PPM_PAGE_MASK; 1629 vpn_t npages = vpn_max - vpn_min + 1; 1630 1631 // get vseg from MMAP allocator 1632 vseg = vmm_mmap_alloc( vmm , npages ); 1633 1634 if( vseg == NULL ) 1635 { 1636 printk("\n[ERROR] %s cannot create %s vseg for process %x in cluster %x\n", 1637 __FUNCTION__ , vseg_type_str( type ) , process->pid , local_cxy ); 1638 return NULL; 1639 } 1640 1641 // initialize vseg 1642 vseg->type = type; 1643 vseg->vmm = vmm; 1644 vseg->min = (vseg->vpn_base << CONFIG_PPM_PAGE_SHIFT) + offset; 1645 vseg->max = vseg->min + size; 1646 vseg->file_offset = file_offset; 1647 vseg->file_size = file_size; 1648 vseg->mapper_xp = mapper_xp; 1649 vseg->cxy = cxy; 1650 1651 vseg_init_flags( vseg , type ); 1652 } 1653 ///////////////////////////////////////////////////////////////// 1654 else if( (type == VSEG_TYPE_ANON) || (type == VSEG_TYPE_REMOTE) ) 1406 1655 { 1407 1656 // compute number of required pages in virtual space … … 1409 1658 if( size & CONFIG_PPM_PAGE_MASK) npages++; 1410 1659 1411 // get vpn_base and vpn_size from MMAP allocator 1412 error = vmm_mmap_alloc( vmm , npages , &vpn_base , &vpn_size ); 1413 if( error ) 1660 // allocate vseg from MMAP allocator 1661 vseg = vmm_mmap_alloc( vmm , npages ); 1662 1663 if( vseg == NULL ) 1414 1664 { 1415 printk("\n[ERROR] in %s : no vspace for mmap vseg /process %x in cluster %x\n",1416 __FUNCTION__, process->pid , local_cxy );1665 printk("\n[ERROR] %s cannot create %s vseg for process %x in cluster %x\n", 1666 __FUNCTION__ , vseg_type_str( type ) , process->pid , local_cxy ); 1417 1667 return NULL; 1418 1668 } 1419 1669 1420 // set vseg base (always aligned for ANON or REMOTE) 1421 base = vpn_base << CONFIG_PPM_PAGE_SHIFT; 1422 } 1670 // initialize vseg 1671 vseg->type = type; 1672 vseg->vmm = vmm; 1673 vseg->min = vseg->vpn_base << CONFIG_PPM_PAGE_SHIFT; 1674 vseg->max = vseg->min + (vseg->vpn_size << CONFIG_PPM_PAGE_SHIFT); 1675 vseg->cxy = cxy; 1676 1677 vseg_init_flags( vseg , type ); 1678 } 1679 ///////////////////////////////////////////////////////////////// 1423 1680 else // VSEG_TYPE_DATA, VSEG_TYPE_CODE or KERNEL vseg 1424 1681 { … … 1426 1683 uint32_t vpn_max = (base + size - 1) >> CONFIG_PPM_PAGE_SHIFT; 1427 1684 1428 vpn_base = vpn_min; 1429 vpn_size = vpn_max - vpn_min + 1; 1685 // allocate vseg descriptor 1686 vseg = vseg_alloc(); 1687 1688 if( vseg == NULL ) 1689 { 1690 printk("\n[ERROR] %s cannot create %s vseg for process %x in cluster %x\n", 1691 __FUNCTION__ , vseg_type_str( type ) , process->pid , local_cxy ); 1692 return NULL; 1693 } 1694 // initialize vseg 1695 vseg->type = type; 1696 vseg->vmm = vmm; 1697 vseg->min = base; 1698 vseg->max = base + size; 1699 vseg->vpn_base = base >> CONFIG_PPM_PAGE_SHIFT; 1700 vseg->vpn_size = vpn_max - vpn_min + 1; 1701 vseg->file_offset = file_offset; 1702 vseg->file_size = file_size; 1703 vseg->mapper_xp = mapper_xp; 1704 vseg->cxy = cxy; 1705 1706 vseg_init_flags( vseg , type ); 1430 1707 } 1431 1708 1432 1709 // check collisions 1433 vseg = vmm_check_conflict( process , vpn_base , vpn_size ); 1434 1435 if( vseg != NULL ) 1436 { 1437 printk("\n[ERROR] in %s for process %x : new vseg [vpn_base %x / vpn_size %x]\n" 1438 " overlap existing vseg [vpn_base %x / vpn_size %x]\n", 1439 __FUNCTION__ , process->pid, vpn_base, vpn_size, vseg->vpn_base, vseg->vpn_size ); 1710 vseg_t * existing_vseg = vmm_check_conflict( process , vseg->vpn_base , vseg->vpn_size ); 1711 1712 if( existing_vseg != NULL ) 1713 { 1714 printk("\n[ERROR] in %s for process %x : new vseg %s [vpn_base %x / vpn_size %x]\n" 1715 " overlap existing vseg %s [vpn_base %x / vpn_size %x]\n", 1716 __FUNCTION__ , process->pid, vseg_type_str(vseg->type), vseg->vpn_base, vseg->vpn_size, 1717 vseg_type_str(existing_vseg->type), existing_vseg->vpn_base, existing_vseg->vpn_size ); 1718 vseg_free( vseg ); 1440 1719 return NULL; 1441 1720 } 1442 1443 // allocate physical memory for vseg descriptor1444 vseg = vseg_alloc();1445 if( vseg == NULL )1446 {1447 printk("\n[ERROR] in %s for process %x : cannot allocate memory for vseg\n",1448 __FUNCTION__ , process->pid );1449 return NULL;1450 }1451 1452 #if (DEBUG_VMM_CREATE_VSEG & 1)1453 if( DEBUG_VMM_CREATE_VSEG < cycle )1454 printk("\n[%s] thread[%x,%x] : base %x / size %x / vpn_base %x / vpn_size %x\n",1455 __FUNCTION__, this->process->pid, this->trdid, base, size, vpn_base, vpn_size );1456 #endif1457 1458 // initialize vseg descriptor1459 vseg_init( vseg,1460 type,1461 base,1462 size,1463 vpn_base,1464 vpn_size,1465 file_offset,1466 file_size,1467 mapper_xp,1468 cxy );1469 1721 1470 1722 // build extended pointer on VSL lock … … 1480 1732 remote_queuelock_release( lock_xp ); 1481 1733 1482 #if DEBUG_VMM_CREATE_VSEG 1734 #if DEBUG_VMM_CREATE_VSEG 1483 1735 cycle = (uint32_t)hal_get_cycles(); 1484 // if( DEBUG_VMM_CREATE_VSEG < cycle ) 1485 if( type == VSEG_TYPE_REMOTE ) 1486 printk("\n[%s] thread[%x,%x] exit / process %x / %s / base %x / cxy %x / cycle %d\n", 1487 __FUNCTION__, this->process->pid, this->trdid, 1488 process->pid, vseg_type_str(type), base, cxy, cycle ); 1736 if( DEBUG_VMM_CREATE_VSEG < cycle ) 1737 printk("\n[%s] thread[%x,%x] exit / %s / vpn_base %x / vpn_size %x / cycle %d\n", 1738 __FUNCTION__, this->process->pid, this->trdid, 1739 vseg_type_str(type), vseg->vpn_base, vseg->vpn_size, cycle ); 1489 1740 #endif 1490 1741 … … 1654 1905 // release slot to local stack allocator 1655 1906 vmm_stack_free( vmm , vseg ); 1656 1657 // release vseg descriptor to local kmem1658 vseg_free( vseg );1659 1907 } 1660 1908 else if( (vseg_type == VSEG_TYPE_ANON) || -
trunk/kernel/mm/vmm.h
r640 r651 64 64 65 65 /********************************************************************************************* 66 * This structure defines the MMAP allocator used by the VMM to dynamically handle 67 * MMAP vsegs requested or released by an user process. 68 * This allocator should be only used in the reference cluster. 69 * - allocation policy : all allocated vsegs occupy an integer number of pages that is 70 * power of 2, and are aligned on a page boundary. The requested number of pages is 71 * rounded if required. The first_free_vpn variable defines completely the MMAP zone state. 72 * It is never decremented, as the released vsegs are simply registered in a zombi_list. 73 * The relevant zombi_list is checked first for each allocation request. 74 * - release policy : a released MMAP vseg is registered in an array of zombi_lists. 75 * This array is indexed by ln(number of pages), and each entry contains the root of 76 * a local list of zombi vsegs that have the same size. The physical memory allocated 77 * for a zombi vseg descriptor is not released, to use the "list" field. 78 * This physical memory allocated for MMAP vseg descriptors is actually released 79 * when the VMM is destroyed. 66 * This structure defines the MMAP allocator used by the VMM to dynamically handle MMAP vsegs 67 * requested or released by an user process. It must be called in the reference cluster. 68 * - allocation policy : 69 * This allocator implements the buddy algorithm. All allocated vsegs occupy an integer 70 * number of pages, that is power of 2, and are aligned (vpn_base is multiple of vpn_size). 71 * The requested number of pages is rounded if required. The global allocator state is 72 * completely defined by the free_pages_root[] array indexed by the vseg order. 73 * These free lists are local, but are implemented as xlist because we use the existing 74 * vseg.xlist to register a free vseg in its free list. 75 * - release policy : 76 * A released vseg is recursively merged with the "buddy" vseg when it is free, in 77 * order to build the largest possible aligned free vsegs. The resulting vseg.vpn_size 78 * field is updated. 79 * Implementation note: 80 * The only significant (and documented) fiels in the vsegs registered in the MMAP allocator 81 * free lists are "xlist", "vpn_base", and "vpn_size". 80 82 ********************************************************************************************/ 81 83 … … 85 87 vpn_t vpn_base; /*! first page of MMAP zone */ 86 88 vpn_t vpn_size; /*! number of pages in MMAP zone */ 87 vpn_t first_free_vpn; /*! first free page in MMAP zone */ 88 xlist_entry_t zombi_list[32]; /*! array of roots of released vsegs lists */ 89 xlist_entry_t free_list_root[CONFIG_VMM_HEAP_MAX_ORDER + 1]; /* roots of free lists */ 89 90 } 90 91 mmap_mgr_t; … … 103 104 * 2. The VSL contains only local vsegs, but it is implemented as an xlist, and protected by 104 105 * a remote_rwlock, because it can be accessed by a thread running in a remote cluster. 105 * An ex emple is the vmm_fork_copy() function.106 * An example is the vmm_fork_copy() function. 106 107 * 3. The GPT in the reference cluster can be directly accessed by remote threads to handle 107 108 * false page-fault (page is mapped in the reference GPT, but the PTE copy is missing … … 119 120 120 121 stack_mgr_t stack_mgr; /*! embedded STACK vsegs allocator */ 122 121 123 mmap_mgr_t mmap_mgr; /*! embedded MMAP vsegs allocator */ 122 124 … … 156 158 * call to the vmm_user_init() function after an exec() syscall. 157 159 * It removes from the VMM of the process identified by the <process> argument all 158 * non kernel vsegs (i.e. all user vsegs), by calling the vmm_remove_vseg() function.160 * all user vsegs, by calling the vmm_remove_vseg() function. 159 161 * - the vsegs are removed from the VSL. 160 162 * - the corresponding GPT entries are removed from the GPT. … … 279 281 /********************************************************************************************* 280 282 * This function allocates memory for a vseg descriptor, initialises it, and register it 281 * in the VSL of the local process descriptor , that must be the reference process.282 * - For the FILE, ANON, & REMOTE types, it does not use the <base> a nd <size> arguments,283 * but uses the specific MMAP virtual memoryallocator.283 * in the VSL of the local process descriptor. 284 * - For the FILE, ANON, & REMOTE types, it does not use the <base> argument, but uses 285 * the specific VMM MMAP allocator. 284 286 * - For the STACK type, it does not use the <base> and <size> arguments, but uses the 285 * and the <base> argument the specific STACK virtual memoryallocator.287 * the specific VMM STACK allocator. 286 288 * It checks collision with pre-existing vsegs. 287 289 * To comply with the "on-demand" paging policy, this function does NOT modify the GPT, -
trunk/kernel/mm/vseg.c
r635 r651 81 81 } 82 82 83 /////////////////////////////////// 84 void vseg_init( vseg_t * vseg, 85 vseg_type_t type, 86 intptr_t base, 87 uint32_t size, 88 vpn_t vpn_base, 89 vpn_t vpn_size, 90 uint32_t file_offset, 91 uint32_t file_size, 92 xptr_t mapper_xp, 93 cxy_t cxy ) 83 ///////////////////////////////////////// 84 void vseg_init_flags( vseg_t * vseg, 85 vseg_type_t type ) 94 86 { 95 vseg->type = type;96 vseg->min = base;97 vseg->max = base + size;98 vseg->vpn_base = vpn_base;99 vseg->vpn_size = vpn_size;100 vseg->file_offset = file_offset;101 vseg->file_size = file_size;102 vseg->mapper_xp = mapper_xp;103 vseg->cxy = cxy;104 105 87 // set vseg flags depending on type 106 if 88 if( type == VSEG_TYPE_CODE ) 107 89 { 108 90 vseg->flags = VSEG_USER | -
trunk/kernel/mm/vseg.h
r640 r651 41 41 typedef enum 42 42 { 43 VSEG_TYPE_CODE = 0, /*! executable user code / private / localized */44 VSEG_TYPE_DATA = 1, /*! initialized user data / public / distributed */45 VSEG_TYPE_STACK = 2, /*! execution user stack / private / localized */46 VSEG_TYPE_ANON = 3, /*! anonymous mmap / public / localized */47 VSEG_TYPE_FILE = 4, /*! file mmap / public / localized */48 VSEG_TYPE_REMOTE = 5, /*! remote mmap / public / localized */43 VSEG_TYPE_CODE = 1, /*! executable user code / private / localized */ 44 VSEG_TYPE_DATA = 2, /*! initialized user data / public / distributed */ 45 VSEG_TYPE_STACK = 3, /*! execution user stack / private / localized */ 46 VSEG_TYPE_ANON = 4, /*! anonymous mmap / public / localized */ 47 VSEG_TYPE_FILE = 5, /*! file mmap / public / localized */ 48 VSEG_TYPE_REMOTE = 6, /*! remote mmap / public / localized */ 49 49 50 VSEG_TYPE_KCODE = 6, /*! executable kernel code / private / localized */51 VSEG_TYPE_KDATA = 7, /*! initialized kernel data / private / localized */52 VSEG_TYPE_KDEV = 8, /*! kernel peripheral device / public / localized */50 VSEG_TYPE_KCODE = 7, /*! executable kernel code / private / localized */ 51 VSEG_TYPE_KDATA = 8, /*! initialized kernel data / private / localized */ 52 VSEG_TYPE_KDEV = 9, /*! kernel peripheral device / public / localized */ 53 53 } 54 54 vseg_type_t; … … 115 115 116 116 /******************************************************************************************* 117 * This function initializes a local vseg descriptor, from the arguments values.118 * It does NOT register the vseg in the local VMM.117 * This function initializes the "flags" field for a local <vseg> descriptor, 118 * depending on the vseg <type>. 119 119 ******************************************************************************************* 120 120 * @ vseg : pointer on the vseg descriptor. 121 * @ base : vseg base address.122 * @ size : vseg size (bytes).123 * @ vpn_base : first page index.124 * @ vpn_size : number of pages.125 121 * @ type : vseg type. 126 * @ cxy : target cluster for physical mapping.127 122 ******************************************************************************************/ 128 void vseg_init( vseg_t * vseg, 129 vseg_type_t type, 130 intptr_t base, 131 uint32_t size, 132 vpn_t vpn_base, 133 vpn_t vpn_size, 134 uint32_t file_offset, 135 uint32_t file_size, 136 xptr_t mapper_xp, 137 cxy_t cxy ); 123 void vseg_init_flags( vseg_t * vseg, 124 vseg_type_t type ); 138 125 139 126 /******************************************************************************************* -
trunk/kernel/syscalls/sys_exit.c
r625 r651 108 108 __FUNCTION__, pid, this->trdid ); 109 109 #endif 110 thread_delete( XPTR( local_cxy , this ) , pid , true );110 thread_delete( XPTR( local_cxy , this ) , true ); // forced 111 111 } 112 112 -
trunk/kernel/syscalls/sys_get_nb_cores.c
r639 r651 35 35 #include <syscalls.h> 36 36 37 //////////////////////////////////// 37 ///////////////////////////////////// 38 38 int sys_get_nb_cores( uint32_t cxy, 39 39 uint32_t * ncores ) … … 51 51 #if DEBUG_SYS_GET_NB_CORES 52 52 if( DEBUG_SYS_GET_NB_CORES < tm_start ) 53 printk("\n[%s] thread[%x,%x] enter / cycle %d\n",54 __FUNCTION__, process->pid, this->trdid, (uint32_t)tm_start );53 printk("\n[%s] thread[%x,%x] enter for cluster %x / cycle %d\n", 54 __FUNCTION__, process->pid, this->trdid, cxy, (uint32_t)tm_start ); 55 55 #endif 56 56 … … 88 88 #if DEBUG_SYS_GET_NB_CORES 89 89 if( DEBUG_SYS_GET_NB_CORES < tm_end ) 90 printk("\n[%s] thread[%x,%x] exit / cycle %d\n",91 __FUNCTION__ , process->pid, this->trdid, (uint32_t)tm_end );90 printk("\n[%s] thread[%x,%x] exit / ncores %d / cycle %d\n", 91 __FUNCTION__ , process->pid, this->trdid, k_ncores, (uint32_t)tm_end ); 92 92 #endif 93 93 -
trunk/kernel/syscalls/sys_lseek.c
r457 r651 1 1 /* 2 * kern/sys_lseek.c - set the read/write offset of an opened file2 * kern/sys_lseek.c - Kernel function implementing the lseek system call. 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,2018,2019) 5 s 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 */ … … 31 32 #include <process.h> 32 33 33 //////////////////////////////// 34 int sys_lseek ( uint32_t file_id,35 uint32_t offset,36 uint32_t whence )34 ///////////////////////////////// 35 int sys_lseek ( uint32_t file_id, 36 uint32_t offset, 37 uint32_t whence ) 37 38 { 38 39 error_t error; … … 43 44 process_t * process = this->process; 44 45 46 #if (DEBUG_SYS_LSEEK || CONFIG_INSTRUMENTATION_SYSCALLS) 47 uint64_t tm_start = hal_get_cycles(); 48 #endif 49 50 #if DEBUG_SYS_LSEEK 51 if( DEBUG_SYS_LSEEK < tm_start ) 52 printk("\n[%s] thread[%x,%x] enter / file_id %d / offset %d / cycle %d\n", 53 __FUNCTION__, process->pid, this->trdid, file_id, offset, (uint32_t)tm_start ); 54 #endif 55 45 56 // check file_id argument 46 57 if( file_id >= CONFIG_PROCESS_FILE_MAX_NR ) 47 58 { 48 printk("\n[ERROR] in %s : illegal file descriptor index = %d\n", 49 __FUNCTION__ , file_id ); 59 60 #if DEBUG_SYSCALLS_ERROR 61 printk("\n[ERROR] in %s : thread[%x,%x] illegal file descriptor index %d\n", 62 __FUNCTION__ , process->pid, this->trdid, file_id ); 63 #endif 50 64 this->errno = EBADFD; 51 65 return -1; … … 57 71 if( file_xp == XPTR_NULL ) 58 72 { 59 printk("\n[ERROR] in %s : undefined file descriptor index = %d\n", 60 __FUNCTION__ , file_id ); 73 74 #if DEBUG_SYSCALLS_ERROR 75 printk("\n[ERROR] in %s : thread[%x,%x] undefined fd_id %d\n", 76 __FUNCTION__, process->pid, this->trdid, file_id ); 77 #endif 61 78 this->errno = EBADFD; 62 79 return -1; 63 80 } 64 81 65 /* FIXME: file may be closed in parallel 66 * of seek/read/write/mmap ..etc 67 * so file may be NULL or invalid */ 82 // FIXME: file may be closed in parallel of seek/read/write/mmap ..etc 68 83 69 84 // call relevant VFS function … … 72 87 if( error ) 73 88 { 74 printk("\n[ERROR] in %s : cannot seek file = %d\n", 75 __FUNCTION__ , file_id ); 89 90 #if DEBUG_SYSCALLS_ERROR 91 printk("\n[ERROR] in %s : thread[%x,%x] cannot seek file_id %d\n", 92 __FUNCTION__, process->pid, this->trdid, file_id ); 93 #endif 76 94 this->errno = error; 77 95 return -1; 78 96 } 97 98 #if (DEBUG_SYS_LSEEK || CONFIG_INSTRUMENTATION_SYSCALLS) 99 uint64_t tm_end = hal_get_cycles(); 100 #endif 101 102 #if DEBUG_SYS_LSEEK 103 if( DEBUG_SYS_LSEEK < tm_end ) 104 printk("\n[%s] thread[%x,%x] exit / cycle %d\n", 105 __FUNCTION__ , process->pid, this->trdid, (uint32_t)tm_end ); 106 #endif 107 108 #if CONFIG_INSTRUMENTATION_SYSCALLS 109 hal_atomic_add( &syscalls_cumul_cost[SYS_LSEEK] , tm_end - tm_start ); 110 hal_atomic_add( &syscalls_occurences[SYS_LSEEK] , 1 ); 111 #endif 79 112 80 113 return new_offset; -
trunk/kernel/syscalls/sys_mmap.c
r637 r651 112 112 } 113 113 114 114 // FIXME handle Copy_On_Write for MAP_PRIVATE... 115 115 116 116 // test mmap type : can be FILE / ANON / REMOTE … … 127 127 #endif 128 128 129 129 // FIXME: handle concurent delete of file by another thread 130 130 131 131 if( fdid >= CONFIG_PROCESS_FILE_MAX_NR ) … … 164 164 #endif 165 165 166 // get inode pointer & mapper pointer 167 vfs_inode_t * inode_ptr = hal_remote_lpt(XPTR(file_cxy , &file_ptr->inode )); 166 // get mapper pointer 168 167 mapper_t * mapper_ptr = hal_remote_lpt(XPTR(file_cxy , &file_ptr->mapper)); 169 168 170 // get file size 171 uint32_t size = hal_remote_l32( XPTR( file_cxy , &inode_ptr->size ) ); 172 173 #if (DEBUG_SYS_MMAP & 1) 174 if ( DEBUG_SYS_MMAP < tm_start ) 175 printk("\n[%s] thread[%x,%x] get file size : %d bytes\n", 176 __FUNCTION__, process->pid, this->trdid, size ); 177 #endif 178 179 // chek offset and length arguments 180 if( (offset + length) > size) 181 { 182 183 #if DEBUG_SYSCALLS_ERROR 184 printk("\n[ERROR] in %s: thread[%x,%x] / offset(%d) + len(%d) >= file's size(%d)\n", 185 __FUNCTION__, process->pid, this->trdid, k_attr.offset, k_attr.length, size ); 186 #endif 187 this->errno = ERANGE; 188 return -1; 189 } 169 #if (DEBUG_SYS_MMAP & 1) 170 if ( DEBUG_SYS_MMAP < tm_start ) 171 printk("\n[%s] thread[%x,%x] get file mapper %x\n", 172 __FUNCTION__, process->pid, this->trdid, mapper_ptr ); 173 #endif 190 174 191 175 /* TODO -
trunk/kernel/syscalls/sys_thread_cancel.c
r506 r651 101 101 { 102 102 // block target thread and mark it for delete 103 thread_delete( target_xp , pid , false );103 thread_delete( target_xp , false ); // not forced 104 104 } 105 105 -
trunk/kernel/syscalls/sys_thread_create.c
r637 r651 154 154 else // set default attributes 155 155 { 156 kern_attr.attributes = PT_ATTR_ DETACH | PT_ATTR_CLUSTER_DEFINED;156 kern_attr.attributes = PT_ATTR_CLUSTER_DEFINED; 157 157 child_cxy = dqdt_get_cluster_for_thread( LOCAL_CLUSTER->dqdt_root_xp ); 158 158 } -
trunk/kernel/syscalls/sys_thread_exit.c
r635 r651 33 33 #include <syscalls.h> 34 34 35 //////////////////////////////////////// 36 int sys_thread_exit( void * exit_ value)35 ///////////////////////////////////////// 36 int sys_thread_exit( void * exit_status ) 37 37 { 38 error_t error; 39 vseg_t * vseg; 40 38 41 thread_t * this = CURRENT_THREAD; 39 42 trdid_t trdid = this->trdid; 40 43 process_t * process = this->process; 41 44 pid_t pid = process->pid; 45 46 // check exit_value pointer in user space if required 47 if( exit_status != NULL ) 48 { 49 error = vmm_get_vseg( process , (intptr_t)exit_status , &vseg ); 42 50 43 // check exit_value argument 44 if( exit_value != NULL ) 45 { 51 if( error ) 52 { 46 53 47 54 #if DEBUG_SYSCALLS_ERROR 48 printk("\n[ERROR] in %s : thread[%x,%x] / exit_value argument %x must be NULL\n",49 __FUNCTION__ , pid, trdid , exit_value);55 printk("\n[ERROR] in %s : exit_status buffer %x unmapped / thread[%x,%x]\n", 56 __FUNCTION__, (intptr_t)exit_status, process->pid, this->trdid ); 50 57 #endif 51 this->errno = EINVAL; 52 return -1; 58 this->errno = EINVAL; 59 return -1; 60 } 61 } 62 63 // check busylocks 64 uint32_t count = this->busylocks; 65 if( count ) 66 { 67 68 #if DEBUG_SYSCALLS_ERROR 69 printk("\n[ERROR] in %s : busylocks count = %d / thread[%x,%x]\n", 70 __FUNCTION__ , count, process->pid, this->trdid ); 71 #endif 72 this->errno = EINVAL; 73 return -1; 53 74 } 54 75 55 76 // If calling thread is the main thread, the process must be deleted. 56 // => delete all process threads and synchronise with parent process. 57 // If calling thread is not the main thread, it must be deleted. 58 // => block the thread and mark it for delete. 59 if( (CXY_FROM_PID( pid ) == local_cxy) && (LTID_FROM_TRDID(trdid) == 0) ) 77 // => delete all process threads and synchronize with parent process. 78 // If calling thread is not the main thread, only this thread must be deleted. 79 // => register exit_status in thread descriptor, block the thread, 80 // mark it for delete, and synchronize with joining thread. 81 82 if( (CXY_FROM_PID( pid ) == local_cxy) && (LTID_FROM_TRDID(trdid) == 0) ) // main 60 83 { 61 84 … … 69 92 sys_exit( 0 ); 70 93 } 71 else 94 else // not the main 72 95 { 73 96 … … 78 101 __FUNCTION__ , pid , trdid , (uint32_t)tm_start ); 79 102 #endif 103 // register exit_status in thread descriptor 104 this->exit_status = exit_status; 105 80 106 // block calling thread and mark it for delete, 81 thread_delete( XPTR( local_cxy , this ) , pid , false );107 thread_delete( XPTR( local_cxy , this ) , false ); // not forced 82 108 83 109 // deschedule -
trunk/kernel/syscalls/sys_thread_join.c
r637 r651 1 1 /* 2 * sys_thread_join.c - passive wait on the end of a giventhread.2 * sys_thread_join.c - wait termination of of an attached thread. 3 3 * 4 4 * Authors Alain Greiner (2016,2017,2018,2019) … … 26 26 #include <hal_special.h> 27 27 #include <hal_irqmask.h> 28 #include <hal_uspace.h> 28 29 #include <thread.h> 29 30 #include <vmm.h> … … 37 38 /////////////////////////////////////// 38 39 int sys_thread_join ( trdid_t trdid, 39 void ** exit_ value)40 void ** exit_status ) 40 41 { 42 error_t error; 41 43 reg_t save_sr; 42 44 xptr_t target_xp; … … 47 49 xptr_t target_flags_xp; 48 50 xptr_t target_join_xp_xp; 51 xptr_t target_exit_status_xp; 49 52 xptr_t killer_xp; 50 53 xptr_t joining_xp; 51 54 thread_t * joining_ptr; 52 55 process_t * process; 56 vseg_t * vseg; 57 void * status; 53 58 54 59 // get joining thread pointers … … 62 67 63 68 #if DEBUG_SYS_THREAD_JOIN 64 uint64_t tm_start; 65 uint64_t tm_end; 66 tm_start = hal_get_cycles(); 69 uint64_t tm_start = hal_get_cycles(); 67 70 if( DEBUG_SYS_THREAD_JOIN < tm_start ) 68 printk("\n[ DBG] %s :joining thread[%x,%x] enter / target thread[%x,%x] / cycle %d\n",71 printk("\n[%s] joining thread[%x,%x] enter / target thread[%x,%x] / cycle %d\n", 69 72 __FUNCTION__ , process->pid, joining_ptr->trdid, 70 73 process->pid, trdid, (uint32_t)tm_start ); … … 77 80 78 81 #if DEBUG_SYSCALLS_ERROR 79 printk("\n[ERROR] in %s : illegal trdid argument %x \n",80 __FUNCTION__, trdid );82 printk("\n[ERROR] in %s : illegal trdid argument %x / joining thread[%x,%x]\n", 83 __FUNCTION__, trdid, joining_ptr->process->pid, joining_ptr-trdid ); 81 84 #endif 82 85 joining_ptr->errno = EINVAL; … … 84 87 } 85 88 86 // check exit_value argument 87 if( exit_value != NULL ) 89 // check exit_value argument in user space 90 error = vmm_get_vseg( process , (intptr_t)exit_status , &vseg ); 91 if( error ) 88 92 { 89 93 90 94 #if DEBUG_SYSCALLS_ERROR 91 printk("\n[ERROR] in %s : exit_ value argument must be NULL\n",92 __FUNCTION__ );95 printk("\n[ERROR] in %s : exit_status argument %x not mapped / joining thread[%x,%x]\n", 96 __FUNCTION__, exit_status, joining_ptr->process->pid, joining_ptr-trdid ); 93 97 #endif 94 98 joining_ptr->errno = EINVAL; … … 101 105 102 106 #if DEBUG_SYSCALLS_ERROR 103 printk("\n[ERROR] in %s : this thread (%x) == target thread(%x)\n",104 __FUNCTION__, joining_ptr-> trdid,trdid );107 printk("\n[ERROR] in %s : joinig thread[%x,%x] == target thread\n", 108 __FUNCTION__, joining_ptr->process->pid, joining_ptr->trdid ); 105 109 #endif 106 110 joining_ptr->errno = EDEADLK; … … 116 120 117 121 #if DEBUG_SYSCALLS_ERROR 118 printk("\n[ERROR] in %s : target thread %x not found\n",119 __FUNCTION__, trdid );122 printk("\n[ERROR] in %s : target thread[%x,%x] not found / joining_thread[%x,%x]\n", 123 __FUNCTION__, process->pid, trdid, joining_ptr->process->pid, joining_ptr-trdid ); 120 124 #endif 121 125 joining_ptr->errno = ESRCH; … … 124 128 125 129 // get extended pointers on various fields in target thread 126 target_join_lock_xp = XPTR( target_cxy , &target_ptr->join_lock ); 127 target_flags_xp = XPTR( target_cxy , &target_ptr->flags ); 128 target_join_xp_xp = XPTR( target_cxy , &target_ptr->join_xp ); 130 target_join_lock_xp = XPTR( target_cxy , &target_ptr->join_lock ); 131 target_flags_xp = XPTR( target_cxy , &target_ptr->flags ); 132 target_join_xp_xp = XPTR( target_cxy , &target_ptr->join_xp ); 133 target_exit_status_xp = XPTR( target_cxy , &target_ptr->exit_status ); 129 134 130 135 // check target thread joinable … … 133 138 134 139 #if DEBUG_SYSCALLS_ERROR 135 printk("\n[ERROR] in %s : target thread %x not joinable\n", __FUNCTION__, trdid ); 140 printk("\n[ERROR] in %s : target thread[%x,‰x] not attached / joining thread[%x,%x]\n", 141 __FUNCTION__, process->pid, trdid, joining_ptr->process->pid, joining_ptr-trdid ); 136 142 #endif 137 143 joining_ptr->errno = EINVAL; … … 146 152 147 153 // test the kill_done flag from the target thread 148 if( hal_remote_l32( target_flags_xp ) & THREAD_FLAG_KILL_DONE ) // killer thread is first 149 { 154 if( hal_remote_l32( target_flags_xp ) & THREAD_FLAG_KILL_DONE ) // killer is first 155 { 156 // get exit_status from target thread 157 status = (void*)hal_remote_lpt( target_exit_status_xp ); 158 150 159 // get pointers on killer thread 151 160 killer_xp = (xptr_t)hal_remote_l64( target_join_xp_xp ); … … 159 168 // release the lock protecting join 160 169 remote_busylock_release( target_join_lock_xp ); 161 162 #if DEBUG_SYS_THREAD_JOIN 163 tm_end = hal_get_cycles(); 164 if( DEBUG_SYS_THREAD_JOIN < tm_end ) 165 printk("\n[DBG] %s : joining thread[%x,%x] exit / target thread[%x,%x] completed / cycle %d\n", 166 __FUNCTION__, process->pid, joining_ptr->trdid, process->pid, trdid, (uint32_t)tm_end ); 167 #endif 168 169 } 170 else // joining thread is first 170 } 171 else // joining is first 171 172 { 172 173 // set the join_done flag in target thread … … 184 185 #if DEBUG_SYS_THREAD_JOIN 185 186 if( DEBUG_SYS_THREAD_JOIN < tm_start ) 186 printk("\n[ DBG] %s :joining thread[%x,%x] deschedules / target thread[%x,%x] not completed\n",187 printk("\n[%s] joining thread[%x,%x] deschedules / target thread[%x,%x] not completed\n", 187 188 __FUNCTION__ , process->pid, joining_ptr->trdid, process->pid, trdid ); 188 189 #endif 189 190 // deschedule 190 191 sched_yield( "joining thread waiting killer thread" ); 192 193 // returns exit_status from joining thread 194 status = joining_ptr->exit_status; 195 } 191 196 197 // returns exit_status to user space 198 hal_copy_to_uspace( exit_status, 199 XPTR( local_cxy , &status ), 200 sizeof( void* ) ); 201 202 // restore IRQs 203 hal_restore_irq( save_sr ); 204 205 hal_fence(); 206 207 #if (DEBUG_SYS_THREAD_JOIN || CONFIG_INSTRUMENTATION_SYSCALLS) 208 uint64_t tm_end = hal_get_cycles(); 209 #endif 210 211 #if CONFIG_INSTRUMENTATION_SYSCALLS 212 hal_atomic_add( &syscalls_cumul_cost[SYS_THREAD_JOIN] , tm_end - tm_start ); 213 hal_atomic_add( &syscalls_occurences[SYS_THREAD_JOIN] , 1 ); 214 #endif 215 192 216 #if DEBUG_SYS_THREAD_JOIN 193 217 tm_end = hal_get_cycles(); 194 218 if( DEBUG_SYS_THREAD_JOIN < tm_end ) 195 printk("\n[ DBG] %s :joining thread[%x,%x] exit / target thread[%x,%x] completed / cycle %d\n",219 printk("\n[%s] joining thread[%x,%x] exit / target thread[%x,%x] completed / cycle %d\n", 196 220 __FUNCTION__ , process->pid, joining_ptr->trdid, process->pid, trdid, (uint32_t)tm_end ); 197 221 #endif 198 222 199 }200 201 // restore IRQs202 hal_restore_irq( save_sr );203 204 223 return 0; 205 224 -
trunk/kernel/syscalls/syscalls.h
r642 r651 37 37 38 38 /****************************************************************************************** 39 * [0] This function terminates the execution of the calling user thread, 40 * and makes the exit_valuepointer available to any successful pthread_join() with the39 * [0] This function terminates the execution of the calling user thread, and makes 40 * the <exit_status> pointer available to any successful pthread_join() with the 41 41 * terminating thread. 42 * It actually set the THREAD_SIG_EXIT signal, set the THREAD_BLOCKED_GLOBAL bit in the 43 * thread descriptor and deschedule. 44 * The thread will be detached from its process, and the memory allocated to the thread 45 * descriptor will be released later by the scheduler. 46 ****************************************************************************************** 47 * @ exit_vallue : pointer to be returned to joining thread if thread is attached. 42 * - If the calling thread is the main thread, it calls the sys_exit() function to delete 43 * completely the user process. 44 * - if the calling thread is not the main thread, it registers the <exit_status> pointer 45 * in the thread descriptor, and calls the thread_delete() function, that will set the 46 * THREAD_SIG_EXIT signal, set the THREAD_BLOCKED_GLOBAL bit in thread descriptor, and 47 * deschedules. All memory allocated to the thread is released later by the scheduler. 48 * If the thread is in "detached" mode, the thread_delete() function implements 49 * the synchonisation with the joining thread. 50 ****************************************************************************************** 51 * @ exit_status : pointer to be returned to joining thread if thread is attached. 48 52 * @ return 0 if success / return -1 if all locks not released or illegal argument. 49 53 *****************************************************************************************/ 50 int sys_thread_exit( void * exit_ value);54 int sys_thread_exit( void * exit_status ); 51 55 52 56 /****************************************************************************************** … … 222 226 ****************************************************************************************** 223 227 * @ attr : pointer on attributes structure. 224 * @ return 0 if success / return-1 if failure.228 * @ returns 0 if success / returns -1 if failure. 225 229 *****************************************************************************************/ 226 230 int sys_mmap( mmap_attr_t * attr ); … … 234 238 * @ buf : buffer virtual address in user space. 235 239 * @ count : number of bytes. 236 * @ return number of bytes actually read if success / returns -1 if failure.240 * @ returns number of bytes actually read if success / returns -1 if failure. 237 241 *****************************************************************************************/ 238 242 int sys_read( uint32_t file_id, … … 251 255 * @ buf : buffer virtual address in user space. 252 256 * @ count : number of bytes. 253 * @ return number of bytes actually written if success / returns -1 if failure.257 * @ returns number of bytes actually written if success / returns -1 if failure. 254 258 *****************************************************************************************/ 255 259 int sys_write( uint32_t file_id, … … 258 262 259 263 /****************************************************************************************** 260 * [16] This function repositions the offset of the file descriptor identified by <file_id>,261 * according to the operation type defined by the <whence> argument.264 * [16] This function repositions the offset of the file descriptor identified by the 265 * <file_id> argument, according to the operation type defined by the <whence> argument. 262 266 ****************************************************************************************** 263 267 * @ file_id : open file index in fd_array. 264 268 * @ offset : used to compute new offset value. 265 269 * @ whence : operation type (see below). 266 * @ return 0if success / returns -1 if failure.270 * @ returns new offset value if success / returns -1 if failure. 267 271 *****************************************************************************************/ 268 272 int sys_lseek( xptr_t file_id, … … 276 280 ****************************************************************************************** 277 281 file_id : file descriptor index in fd_array. 278 * @ return 0 if success / returns -1 if failure.282 * @ returns 0 if success / returns -1 if failure. 279 283 *****************************************************************************************/ 280 284 int sys_close( uint32_t file_id ); … … 289 293 ****************************************************************************************** 290 294 * @ pathname : pathname (can be relative or absolute). 291 * @ return 0 if success / returns -1 if failure.295 * @ returns 0 if success / returns -1 if failure. 292 296 *****************************************************************************************/ 293 297 int sys_unlink( char * pathname );
Note: See TracChangeset
for help on using the changeset viewer.