Changeset 625 for trunk/hal/tsar_mips32/core/hal_context.c
- Timestamp:
- Apr 10, 2019, 10:09:39 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/hal/tsar_mips32/core/hal_context.c
r570 r625 152 152 { 153 153 context->a0_04 = (uint32_t)thread->entry_args; 154 context->sp_29 = (uint32_t)thread->u _stack_base + (uint32_t)thread->u_stack_size- 8;154 context->sp_29 = (uint32_t)thread->user_stack_vseg->max - 8; 155 155 context->ra_31 = (uint32_t)&hal_kentry_eret; 156 156 context->c0_epc = (uint32_t)thread->entry_func; … … 175 175 void hal_cpu_context_fork( xptr_t child_xp ) 176 176 { 177 // allocate a local CPU context in kernel stack178 // It is initialized from local parent context179 // and from child specific values, and is copied in 180 // in the remote child context using a remote_memcpy()177 // get pointer on calling thread 178 thread_t * this = CURRENT_THREAD; 179 180 // allocate a local CPU context in parent kernel stack 181 181 hal_cpu_context_t context; 182 182 183 // get local parent thread local pointer 183 // get local parent thread cluster and local pointer 184 cxy_t parent_cxy = local_cxy; 184 185 thread_t * parent_ptr = CURRENT_THREAD; 185 186 … … 188 189 thread_t * child_ptr = GET_PTR( child_xp ); 189 190 190 // get remote child cpu_context local pointer191 // get local pointer on remote child cpu context 191 192 char * child_context_ptr = hal_remote_lpt( XPTR(child_cxy , &child_ptr->cpu_context) ); 192 193 193 194 // get local pointer on remote child process 194 process_t * process = (process_t *)hal_remote_lpt( XPTR(child_cxy , &child_ptr->process) );195 process_t * process = hal_remote_lpt( XPTR(child_cxy , &child_ptr->process) ); 195 196 196 197 // get ppn of remote child process page table 197 uint32_t pt_ppn = hal_remote_l32( XPTR(child_cxy , &process->vmm.gpt.ppn) ); 198 199 // save CPU registers in local CPU context 198 uint32_t pt_ppn = hal_remote_l32( XPTR(child_cxy , &process->vmm.gpt.ppn) ); 199 200 // get local pointer on parent uzone from parent thread descriptor 201 uint32_t * parent_uzone = parent_ptr->uzone_current; 202 203 // compute local pointer on child uzone 204 uint32_t * child_uzone = (uint32_t *)( (intptr_t)parent_uzone + 205 (intptr_t)child_ptr - 206 (intptr_t)parent_ptr ); 207 208 // update the uzone pointer in child thread descriptor 209 hal_remote_spt( XPTR( child_cxy , &child_ptr->uzone_current ) , child_uzone ); 210 211 #if DEBUG_HAL_CONTEXT 212 uint32_t cycle = (uint32_t)hal_get_cycles(); 213 if( DEBUG_HAL_CONTEXT < cycle ) 214 printk("\n[%s] thread[%x,%x] parent_uzone %x / child_uzone %x / cycle %d\n", 215 __FUNCTION__, this->process->pid, this->trdid, parent_uzone, child_uzone, cycle ); 216 #endif 217 218 // copy parent kernel stack to child thread descriptor 219 // (this includes the uzone, that is allocated in the kernel stack) 220 char * parent_ksp = (char *)hal_get_sp(); 221 char * child_ksp = (char *)((intptr_t)parent_ksp + 222 (intptr_t)child_ptr - 223 (intptr_t)parent_ptr ); 224 225 uint32_t size = (uint32_t)parent_ptr + CONFIG_THREAD_DESC_SIZE - (uint32_t)parent_ksp; 226 227 hal_remote_memcpy( XPTR( child_cxy , child_ksp ), 228 XPTR( local_cxy , parent_ksp ), 229 size ); 230 231 #if DEBUG_HAL_CONTEXT 232 cycle = (uint32_t)hal_get_cycles(); 233 printk("\n[%s] thread[%x,%x] copied kstack from parent %x to child %x / cycle %d\n", 234 __FUNCTION__, this->process->pid, this->trdid, parent_ptr, child_ptr, cycle ); 235 #endif 236 237 // patch the user stack pointer slot in the child uzone[UZ_SP] 238 // because parent and child use the same offset to access the user stack, 239 // but parent and child do not have the same user stack base address. 240 uint32_t parent_us_base = parent_ptr->user_stack_vseg->min; 241 vseg_t * child_us_vseg = hal_remote_lpt( XPTR( child_cxy , &child_ptr->user_stack_vseg ) ); 242 uint32_t child_us_base = hal_remote_l32( XPTR( child_cxy , &child_us_vseg->min ) ); 243 uint32_t parent_usp = parent_uzone[UZ_SP]; 244 uint32_t child_usp = parent_usp + child_us_base - parent_us_base; 245 246 hal_remote_s32( XPTR( child_cxy , &child_uzone[UZ_SP] ) , child_usp ); 247 248 #if DEBUG_HAL_CONTEXT 249 cycle = (uint32_t)hal_get_cycles(); 250 printk("\n[%s] thread[%x,%x] parent_usp %x / child_usp %x / cycle %d\n", 251 __FUNCTION__, this->process->pid, this->trdid, parent_usp, child_usp, cycle ); 252 #endif 253 254 // save current values of CPU registers to local CPU context 200 255 hal_do_cpu_save( &context ); 201 256 202 // From this point, both parent and child threads execute the following code. 203 // They can be distinguished by the CURRENT_THREAD value, and child will only 204 // execute it when it is unblocked by parent, after return to sys_fork(). 205 // - parent thread copies user stack, and patch sp_29 / c0_th / C0_sr / c2_ptpr 206 // - child thread does nothing 207 208 thread_t * current = CURRENT_THREAD; 209 210 if( current == parent_ptr ) // current == parent thread 257 // From this point, both parent and child can execute the following code, 258 // but child thread will only execute it after being unblocked by parent thread. 259 // They can be distinguished by the (CURRENT_THREAD,local_cxy) values, 260 // and we must re-initialise the calling thread pointer from c0_th register 261 262 this = CURRENT_THREAD; 263 264 if( (this == parent_ptr) && (local_cxy == parent_cxy) ) // parent thread 211 265 { 212 // get parent and child stack pointers 213 char * parent_sp = (char *)context.sp_29; 214 char * child_sp = (char *)((intptr_t)parent_sp + 215 (intptr_t)child_ptr - 216 (intptr_t)parent_ptr ); 217 218 // patch kernel_stack pointer, current thread, and status slots 219 context.sp_29 = (uint32_t)child_sp; 266 // patch 4 slots in the local CPU context: the sp_29 / c0_th / C0_sr / c2_ptpr 267 // slots are not identical in parent and child 268 context.sp_29 = context.sp_29 + (intptr_t)child_ptr - (intptr_t)parent_ptr; 220 269 context.c0_th = (uint32_t)child_ptr; 221 270 context.c0_sr = SR_SYS_MODE; 222 271 context.c2_ptpr = pt_ppn >> 1; 223 272 224 // copy local context to remote child context)273 // copy this patched context to remote child context 225 274 hal_remote_memcpy( XPTR( child_cxy , child_context_ptr ), 226 275 XPTR( local_cxy , &context ) , 227 276 sizeof( hal_cpu_context_t ) ); 228 229 // copy kernel stack content from local parent thread to remote child thread 230 uint32_t size = (uint32_t)parent_ptr + CONFIG_THREAD_DESC_SIZE - (uint32_t)parent_sp; 231 hal_remote_memcpy( XPTR( child_cxy , child_sp ), 232 XPTR( local_cxy , parent_sp ), 233 size ); 277 #if DEBUG_HAL_CONTEXT 278 cycle = (uint32_t)hal_get_cycles(); 279 printk("\n[%s] thread[%x,%x] copied CPU context to child / cycle %d\n", 280 __FUNCTION__, this->process->pid, this->trdid, cycle ); 281 #endif 282 283 // parent thread unblock child thread 284 thread_unblock( XPTR( child_cxy , child_ptr ) , THREAD_BLOCKED_GLOBAL ); 285 286 #if DEBUG_HAL_CONTEXT 287 cycle = (uint32_t)hal_get_cycles(); 288 printk("\n[%s] thread[%x,%x] unblocked child thread / cycle %d\n", 289 __FUNCTION__, this->process->pid, this->trdid, cycle ); 290 #endif 291 234 292 } 235 else // current == child thread 236 { 237 assert( (current == child_ptr) , "current = %x / child = %x\n"); 238 } 293 239 294 } // end hal_cpu_context_fork() 240 295 … … 285 340 void hal_cpu_context_destroy( thread_t * thread ) 286 341 { 287 kmem_req_t req; 288 289 req.type = KMEM_CPU_CTX; 290 req.ptr = thread->cpu_context; 291 kmem_free( &req ); 342 kmem_req_t req; 343 344 hal_cpu_context_t * ctx = thread->cpu_context; 345 346 // release CPU context if required 347 if( ctx != NULL ) 348 { 349 req.type = KMEM_CPU_CTX; 350 req.ptr = ctx; 351 kmem_free( &req ); 352 } 292 353 293 354 } // end hal_cpu_context_destroy() … … 348 409 kmem_req_t req; 349 410 350 req.type = KMEM_FPU_CTX; 351 req.ptr = thread->fpu_context; 352 kmem_free( &req ); 411 hal_fpu_context_t * context = thread->fpu_context; 412 413 // release FPU context if required 414 if( context != NULL ) 415 { 416 req.type = KMEM_FPU_CTX; 417 req.ptr = context; 418 kmem_free( &req ); 419 } 353 420 354 421 } // end hal_fpu_context_destroy()
Note: See TracChangeset
for help on using the changeset viewer.