myth_thread_t myth_default_steal_func(int rank) { myth_running_env_t env,busy_env; myth_thread_t next_run=NULL; #ifdef MYTH_WS_PROF_DETAIL uint64_t t0,t1; t0=myth_get_rdtsc(); #endif //Choose a worker thread that seems to be busy env=&g_envs[rank]; busy_env=myth_env_get_first_busy(env); if (busy_env){ //int ws_victim; #if 0 #ifdef MYTH_SCHED_LOOP_DEBUG myth_dprintf("env %p is trying to steal thread from %p...\n",env,busy_env); #endif #endif //ws_victim=busy_env->rank; //Try to steal thread next_run=myth_queue_take(&busy_env->runnable_q); if (next_run){ #ifdef MYTH_SCHED_LOOP_DEBUG myth_dprintf("env %p is stealing thread %p from %p...\n",env,steal_th,busy_env); #endif myth_assert(next_run->status==MYTH_STATUS_READY); //Change worker thread descriptor } } #ifdef MYTH_WS_PROF_DETAIL t1=myth_get_rdtsc(); if (g_sched_prof){ env->prof_data.ws_attempt_count[busy_env->rank]++; if (next_run){ env->prof_data.ws_hit_cycles+=t1-t0; env->prof_data.ws_hit_cnt++; }else{ env->prof_data.ws_miss_cycles+=t1-t0; env->prof_data.ws_miss_cnt++; } } #endif return next_run; }
static void myth_eco_sched_loop(myth_running_env_t env) { // printf("%d\n",FINISH); while (1) { //sched_yield(); myth_thread_t next_run; //Get runnable thread next_run=myth_queue_pop(&env->runnable_q); #ifdef MYTH_WRAP_SOCKIO //If there is no runnable thread, check I/O if (!next_run){ next_run=myth_io_polling(env); } #endif //If there is no runnable thread after I/O checking, try work-stealing if (!next_run){ //next_run=myth_steal_from_others(env); //next_run=g_myth_steal_func(env->rank); next_run=myth_eco_steal(env->rank); } if ((worker_cond_t)next_run == FINISH) { //next_run == FINISH if(env->rank != 0) { env->this_thread=NULL; return; } else { while(1) { int temp = 0; int j; for(j = 1; j < g_worker_thread_num; j++) { if(g_envs[j].c != EXITED) { temp = 1; } } if(temp == 0) return; } } } if (next_run) { //sanity check myth_assert(next_run->status==MYTH_STATUS_READY); env->this_thread=next_run; next_run->env=env; //Switch to runnable thread #ifdef MYTH_SCHED_LOOP_DEBUG myth_dprintf("myth_sched_loop:switching to thread:%p\n",next_run); #endif myth_assert(next_run->status==MYTH_STATUS_READY); myth_swap_context(&env->sched.context, &next_run->context); #ifdef MYTH_SCHED_LOOP_DEBUG myth_dprintf("myth_sched_loop:returned from thread:%p\n",(void*)next_run); #endif env->this_thread=NULL; } //Check exit flag if (env->exit_flag==1){ if(env->rank == 0) while(1) { int temp = 0; int j; for(j = 1; j < g_worker_thread_num; j++) { if(g_envs[j].c != EXITED) { temp = 1; } } if(temp == 0) return; } env->this_thread=NULL; #ifdef MYTH_SCHED_LOOP_DEBUG myth_dprintf("env %p received exit signal,exiting\n",env); #endif return; } } }
myth_thread_t myth_eco_steal(int rank) { myth_running_env_t env,busy_env; myth_thread_t next_run=NULL; #ifdef MYTH_WS_PROF_DETAIL uint64_t t0,t1; t0=myth_get_rdtsc(); #endif //Choose a worker thread that seems to be busy env=&g_envs[rank]; if(env->isSleepy == 1) { env->isSleepy = 0; busy_env = &g_envs[env->ws_target]; } else { busy_env=myth_env_get_first_busy(env); } if (busy_env){ myth_assert(busy_env!=env); //int ws_victim; //ws_victim=busy_env->rank; //Try to steal thread next_run=myth_queue_take(&busy_env->runnable_q); if (next_run){ #ifdef MYTH_SCHED_LOOP_DEBUG myth_dprintf("env %p is stealing thread %p from %p...\n",env,steal_th,busy_env); #endif myth_assert(next_run->status==MYTH_STATUS_READY); //Change worker thread descriptor next_run->env=env; } } if(!next_run) { if(busy_env->c == STEALING) { #ifdef MYTH_ECO_TEST if(env->thief_count < 3) { env->thief_count++; return 0; } #endif myth_sleep(); // This line seems not correct, it may occur infinite recursion //return myth_eco_steal(env->rank); return NULL; } else if(busy_env->c == SLEEPING) { MAY_BE_UNUSED int tmp = task_num; next_run = myth_eco_all_task_check(env); if(!next_run){ myth_sleep(); } else { return next_run; } } else if(busy_env->c == RUNNING) { // victim has one task and executing int tmp = task_num; next_run = myth_eco_all_task_check(env); if(!next_run){ myth_sleep_2(tmp); } else { return next_run; } } else if(busy_env->c == FINISH) { return (myth_thread_t)FINISH; } } #ifdef MYTH_WS_PROF_DETAIL t1=myth_get_rdtsc(); if (g_sched_prof){ env->prof_data.ws_attempt_count[busy_env->rank]++; if (next_run){ env->prof_data.ws_hit_cycles+=t1-t0; env->prof_data.ws_hit_cnt++; }else{ env->prof_data.ws_miss_cycles+=t1-t0; env->prof_data.ws_miss_cnt++; } } #endif #ifdef MYTH_ECO_TEST env->thief_count = 0; #endif return next_run; }