Changeset 296 for trunk/kernel/kern/scheduler.c
- Timestamp:
- Jul 31, 2017, 1:59:52 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/kern/scheduler.c
r279 r296 30 30 #include <core.h> 31 31 #include <thread.h> 32 #include <chdev.h> 32 33 #include <scheduler.h> 34 35 /////////////////////////////////////////////////////////////////////////////////////////// 36 // Extern global variables 37 /////////////////////////////////////////////////////////////////////////////////////////// 38 39 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c file 33 40 34 41 … … 144 151 thread_t * sched_select( core_t * core ) 145 152 { 146 thread_t * thread;153 thread_t * thread; 147 154 148 155 scheduler_t * sched = &core->scheduler; 156 157 sched_dmsg("\n[INFO] %s : enter core[%x,%d] / cycle %d\n", 158 __FUNCTION__ , local_cxy , core->lid , hal_time_stamp() ); 149 159 150 160 // take lock protecting sheduler lists … … 154 164 list_entry_t * last; 155 165 156 // first : scan the kernel threads list, 157 // only if this list is not empty 166 // first : scan the kernel threads list if not empty 158 167 if( list_is_empty( &sched->k_root ) == false ) 159 168 { … … 171 180 thread = LIST_ELEMENT( current , thread_t , sched_list ); 172 181 173 // return thread if runnable174 if( thread->blocked == 0)182 // return thread if not idle_thread and runnable 183 if( (thread->type != THREAD_IDLE) && (thread->blocked == 0) ) 175 184 { 176 185 // release lock 177 186 spinlock_unlock( &sched->lock ); 187 188 sched_dmsg("\n[INFO] %s : exit core[%x,%d] / k_thread = %x / cycle %d\n", 189 __FUNCTION__ , local_cxy , core->lid , thread->trdid , hal_time_stamp() ); 190 178 191 return thread; 179 192 } … … 182 195 } 183 196 184 // second : scan the user threads list, 185 // only if this list is not empty 197 // second : scan the user threads list if not empty 186 198 if( list_is_empty( &sched->u_root ) == false ) 187 199 { … … 204 216 // release lock 205 217 spinlock_unlock( &sched->lock ); 218 219 sched_dmsg("\n[INFO] %s : exit core[%x,%d] / u_thread = %x / cycle %d\n", 220 __FUNCTION__ , local_cxy , core->lid , thread->trdid , hal_time_stamp() ); 206 221 return thread; 207 222 } … … 213 228 spinlock_unlock( &sched->lock ); 214 229 230 sched_dmsg("\n[INFO] %s : exit core[%x,%d] / idle = %x / cycle %d\n", 231 __FUNCTION__ , local_cxy , core->lid , sched->idle->trdid , hal_time_stamp() ); 232 215 233 // third : return idle thread if no runnable thread 216 234 return sched->idle; 217 235 218 } // end sched_ elect()236 } // end sched_select() 219 237 220 238 ////////////////////////////////////////// … … 223 241 list_entry_t * iter; 224 242 thread_t * thread; 225 226 243 scheduler_t * sched = &core->scheduler; 244 245 sched_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d]\n", 246 __FUNCTION__, CURRENT_THREAD->trdid , local_cxy , core->lid ); 227 247 228 248 // take lock protecting threads lists … … 246 266 spinlock_unlock( &sched->lock ); 247 267 268 sched_dmsg("\n[INFO] %s : exit / thread %x on core[%x,%d]\n", 269 __FUNCTION__, CURRENT_THREAD->trdid , local_cxy , core->lid ); 270 248 271 } // end sched_handle_signals() 249 272 250 ////////////////// 251 void sched_yield( )273 /////////////////////////////////// 274 void sched_yield( thread_t * next ) 252 275 { 253 276 reg_t sr_save; 254 thread_t * next;255 277 256 278 thread_t * current = CURRENT_THREAD; … … 258 280 scheduler_t * sched = &core->scheduler; 259 281 260 if( thread_can_yield() == false ) 261 { 262 printk("\n[PANIC] in %s : thread %x for process %x on core_gid %x" 263 " has not released all locks at cycle %d\n", 264 __FUNCTION__, current->trdid, current->process->pid, 265 local_cxy , core->lid , hal_get_cycles() ); 266 hal_core_sleep(); 267 } 268 269 // desactivate IRQs 270 hal_disable_irq( &sr_save ); 282 sched_dmsg("\n[INFO] %s : thread %x on core[%x,%d] enter / cycle %d\n", 283 __FUNCTION__, current->trdid, local_cxy, core->lid, hal_time_stamp() ); 284 285 // check calling thread released all locks 286 assert( (thread_can_yield() == true), __FUNCTION__, "locks not released\n"); 271 287 272 288 // first loop on all threads to handle pending signals 273 289 sched_handle_signals( core ); 274 290 275 // second loop on threads to select next thread 276 next = sched_select( core ); 277 278 // check stack overflow for selected thread 279 if( next->signature != THREAD_SIGNATURE ) 280 { 281 printk("\n[PANIC] in %s : detected stack overflow for thread %x of process %x" 282 " on core [%x][%d]\n", 283 __FUNCTION__, next->trdid, next->process->pid, local_cxy , core->lid ); 284 hal_core_sleep(); 285 } 286 287 sched_dmsg("\n[INFO] %s on core %d in cluster %x / old thread = %x / new thread = %x\n", 288 __FUNCTION__, core->lid, local_cxy, current->trdid, next->trdid ); 289 290 // switch contexts and update scheduler state if new thread 291 if( next != current ) 292 { 293 hal_cpu_context_save( current ); 294 hal_cpu_context_restore( next ); 295 291 // second loop on threads to select next thread if required 292 if( next == NULL ) next = sched_select( core ); 293 294 // check next thread attached to same core as the calling thread 295 assert( (next->core == current->core), __FUNCTION__ , "next core != current core\n"); 296 297 // check next thread not blocked 298 assert( (next->blocked == 0), __FUNCTION__ , "next thread is blocked\n"); 299 300 // switch contexts and update scheduler state if next != current 301 if( next != current ) 302 { 303 sched_dmsg("\n[INFO] %s : trd %x (%s) on core[%x,%d] => trd %x (%s) / cycle %d\n", 304 __FUNCTION__, current->trdid, thread_type_str(current->type), local_cxy, core->lid, 305 next->trdid, thread_type_str(next->type), hal_time_stamp() ); 306 307 // calling thread desactivate IRQs 308 hal_disable_irq( &sr_save ); 309 310 // update scheduler 296 311 if( current->type == THREAD_USER ) sched->u_last = ¤t->sched_list; 297 312 else sched->k_last = ¤t->sched_list; 298 299 313 sched->current = next; 300 } 301 302 // restore IRQs 303 hal_restore_irq( sr_save ); 304 305 if( current->type != THREAD_USER ) return; 306 307 if( next == core->fpu_owner ) hal_fpu_enable(); 308 else hal_fpu_disable(); 309 314 315 // handle FPU 316 if( next->type == THREAD_USER ) return; 317 { 318 if( next == core->fpu_owner ) hal_fpu_enable(); 319 else hal_fpu_disable(); 320 } 321 322 // switch contexts 323 hal_cpu_context_save( current->cpu_context ); 324 hal_cpu_context_restore( next->cpu_context ); 325 326 // restore IRQs when calling thread resume 327 hal_restore_irq( sr_save ); 328 329 sched_dmsg("\n[INFO] %s : thread %x on core[%x,%d] / cycle %d\n", 330 __FUNCTION__, current->trdid, local_cxy, core->lid, hal_time_stamp() ); 331 } 332 else 333 { 334 sched_dmsg("\n[INFO] %s : thread %x on core[%x,%d] continue / cycle %d\n", 335 __FUNCTION__, current->trdid, local_cxy, core->lid, hal_time_stamp() ); 336 } 310 337 } // end sched_yield() 311 338 312 ////////////////////////////////////// 313 void sched_switch_to( thread_t * new ) 314 { 315 reg_t sr_save; 316 317 thread_t * current = CURRENT_THREAD; 318 core_t * core = current->core; 319 process_t * process = current->process; 320 321 // check calling thread released all locks 322 if( thread_can_yield() == false ) 323 { 324 printk("\n[PANIC] in %s : thread %x for process %x on core %d in cluster %x" 325 " has not released all locks\n", 326 __FUNCTION__, current->trdid, process->pid, core->lid, local_cxy ); 327 hal_core_sleep(); 328 } 329 330 // check new thread attached to same core as the calling thread 331 if( new->core != current->core ) 332 { 333 printk("\n[PANIC] in %s : new thread %x is attached to core %d" 334 " different from core %d of current thread\n", 335 __FUNCTION__, new->trdid, new->core->lid, core->lid , current->trdid ); 336 hal_core_sleep(); 337 } 338 339 // check new thread not blocked 340 if( new->blocked == 0 ) 341 { 342 printk("\n[PANIC] in %s for thread %x of process %x on core %d in cluster %x" 343 " : new thread %x is blocked\n", 344 __FUNCTION__, current->trdid, process->pid , core->lid, local_cxy , new->trdid ); 345 hal_core_sleep(); 346 } 347 348 // check stack overflow for new thread 349 if( new->signature != THREAD_SIGNATURE ) 350 { 351 printk("\n[PANIC] in %s : stack overflow for new thread %x of process %x" 352 " on core %d in cluster %x\n", 353 __FUNCTION__, new->trdid, process->pid , core->lid , local_cxy ); 354 hal_core_sleep(); 355 } 356 357 // desactivate IRQs 358 hal_disable_irq( &sr_save ); 359 360 // loop on all threads to handle pending signals 361 sched_handle_signals( core ); 362 363 // check stack overflow for new thread 364 if( new->signature != THREAD_SIGNATURE ) 365 { 366 printk("PANIC %s detected stack overflow for thread %x of process %x" 367 " on core %d in cluster %x\n", 368 __FUNCTION__, new->trdid, new->process->pid, core->lid, local_cxy); 369 hal_core_sleep(); 370 } 371 372 sched_dmsg("INFO : %s on core %d in cluster %x / old thread = %x / new thread = %x\n", 373 __FUNCTION__, core->lid, local_cxy, current->trdid, new->trdid ); 374 375 // switch contexts if new thread 376 hal_cpu_context_save( current ); 377 hal_cpu_context_restore( new ); 378 379 // restore IRQs 380 hal_restore_irq( sr_save ); 381 382 if( current->type != THREAD_USER ) return; 383 384 if( current == core->fpu_owner ) hal_fpu_enable(); 385 else hal_fpu_disable(); 386 387 } // end sched_switch_to() 388 339 //////////////////// 340 void sched_display() 341 { 342 list_entry_t * iter; 343 thread_t * thread; 344 uint32_t save_sr; 345 346 thread_t * current = CURRENT_THREAD; 347 core_t * core = current->core; 348 scheduler_t * sched = &core->scheduler; 349 350 // get pointers on TXT0 chdev 351 xptr_t txt0_xp = chdev_dir.txt[0]; 352 cxy_t txt0_cxy = GET_CXY( txt0_xp ); 353 chdev_t * txt0_ptr = GET_PTR( txt0_xp ); 354 355 // get extended pointer on remote TXT0 chdev lock 356 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 357 358 // get TXT0 lock in busy waiting mode 359 remote_spinlock_lock_busy( lock_xp , &save_sr ); 360 361 nolock_printk("\n********** scheduler state for core[%x,%d] **********************\n" 362 "kernel_threads = %d / user_threads = %d / current = %x\n", 363 local_cxy , core->lid, 364 sched->k_threads_nr, sched->u_threads_nr, sched->current->trdid ); 365 366 // display kernel threads 367 LIST_FOREACH( &sched->k_root , iter ) 368 { 369 thread = LIST_ELEMENT( iter , thread_t , sched_list ); 370 nolock_printk(" - type = %s / trdid = %x / pid = %x / func = %x / blocked_vect = %x\n", 371 thread_type_str( thread->type ), thread->trdid, thread->process->pid, 372 thread->entry_func, thread->blocked ); 373 } 374 375 // display user threads 376 LIST_FOREACH( &sched->u_root , iter ) 377 { 378 thread = LIST_ELEMENT( iter , thread_t , sched_list ); 379 nolock_printk(" - type = %s / trdid = %x / pid = %x / func = %x / blocked_vect = %x\n", 380 thread_type_str( thread->type ), thread->trdid, thread->process->pid, 381 thread->entry_func, thread->blocked ); 382 } 383 384 // release TXT0 lock 385 remote_spinlock_unlock_busy( lock_xp , save_sr ); 386 387 } // end sched_display() 388
Note: See TracChangeset
for help on using the changeset viewer.