#include #include #include #include #include #include #include #include "simu.h" #include "basetask.h" #include "basesched.h" using namespace std; //#define DBG_THREAD #ifdef DBG_THREAD #define _D(X) X #else #define _D(X) #endif #define forn(i,n) for(int i = 0; i < (int)(n); ++i) #define DBG(X) _D(cerr << #X << " = " << X << endl;) typedef struct cpu_ctx { int pid; int remaining; } cpu_ctx_t; /* "Globales" */ // static int cur_pid; //Habria que modificar el nombre de cur_pid //lo mantuve para que sea mas facil modificar //codigo y mirar que hacia antes static vector contexts; static unsigned int cur_time; static pthread_mutex_t m_sched; enum status_t {ST_EXIT, ST_IO, ST_CPU}; //enum status_t {ST_CPU, ST_IO, ST_EXIT}; struct task_data { pthread_t tid; int pid, running; status_t blk; int blkms; TaskBase* tsk; vector* prms; pthread_mutex_t mutex; int lastcpu; }; static task_data* tsks; void* task_thread(task_data* tsk) { pthread_mutex_lock(&tsk->mutex); //fprintf(stderr, "Thread %d\n", tsk->pid); _D(cerr << "tsk->tsk( " << tsk->pid << ", *tsk->prms)" << endl;) tsk->tsk(tsk->pid, *tsk->prms); // Run! // tsk->blk = ST_EXIT; _D(cerr << "TSK unlock(sched) exit" << endl;) pthread_mutex_unlock(&m_sched); return NULL; } /* Funciones llamadas por el scheduler */ int current_pid(int cpu) { return contexts[cpu].pid; } int current_remaining(int cpu) { return contexts[cpu].remaining; } unsigned int current_time(void) { return cur_time; } /* Funciones llamadas por las tareas */ static void uso_X(task_data* tsk, enum status_t tp, unsigned int ms) { if (ms == 0) return; tsk->blk = tp; tsk->blkms = ms; _D(cerr << "TSK unlock(sched)" << endl;) pthread_mutex_unlock(&m_sched); pthread_mutex_lock(&tsk->mutex); _D(cerr << "TSK lock(mutex["<& lote, const Settings& settings) { int n = lote.size(); cout.flush(); if (settings.output_log != "-") { /* Oh yeah! */ freopen(settings.output_log.c_str(), "wt", stdout); } tsks = (task_data*)malloc(sizeof(task_data)*n); if (!tsks) { perror("malloc(task_data)"); return; } forn(i, n) { tsks[i].pid = i; pthread_mutex_init(&(tsks[i].mutex), NULL); pthread_mutex_lock(&(tsks[i].mutex)); tsks[i].tsk = lote[i].tsk; tsks[i].prms = &(lote[i].prms); tsks[i].running = 0; tsks[i].blk = ST_CPU; tsks[i].blkms = 0; tsks[i].lastcpu = -1; if (pthread_create(&(tsks[i].tid), NULL, (void*(*)(void*))task_thread, (void*)(&(tsks[i]))) < 0) { perror("Lanzando la tarea (no use muchas tareas, < 500)"); return; } } pthread_mutex_init(&m_sched, NULL); pthread_mutex_lock(&m_sched); int finished = 0; //Inicializa los cpus contexts = vector(settings.num_cores); for (uint i = 0; i > load; forn(i, n) load.push(make_pair(-lote[i].start, -i)); vector > dlote(0); forn(i, n){ if(lote[i].end > 0) dlote.push_back(make_pair(lote[i].end, i)); } priority_queue > unblock; int context_remain = 0; /* Remaining context_switch ticks */ while (finished < n || context_remain) { if (settings.verbose) { //cerr << "--- sched, tm=" << cur_time << " pid=" << cur_pid; cerr << "--- sched, tm=" << cur_time << endl; for(uint i = 0; i < settings.num_cores; i++) { int pid=contexts[i].pid; cerr << "cpu " << i << " pid = " << pid << " rem " << contexts[i].remaining; if (pid != IDLE_TASK) { cerr << " [" << pid << " ST:"<< tsks[pid].blk << " ms:" << tsks[pid].blkms << "]"; } cerr << endl; } cerr << "--------------" << cur_time << endl; } // Load de las tareas while (!load.empty() && load.top().first >= -(int)cur_time) { int pid = -load.top().second; int deadline = lote[-load.top().second].end; load.pop(); tsks[pid].running = 1; sch.load(pid,deadline); cout << "LOAD " << cur_time << " " << pid << endl; } vector to_unblock; while (!unblock.empty() && unblock.top().first >= -(int)cur_time) { int pid = -unblock.top().second; unblock.pop(); _D(cerr << "SCH unblock(" << pid << ")" << endl;) sch.unblock(pid); // pid to_unblock.push_back(pid); int unblocked = 0; for(uint i = 0; i < settings.num_cores && !unblocked; i++) { int it = contexts[i].pid; if (it == pid) { tsks[pid].blkms = -2; unblocked = true; } } if (!unblocked) { tsks[pid].blk = ST_CPU; tsks[pid].blkms = 0; } } //Itera por cada cpu for(uint cpu= 0; cpu < settings.num_cores; cpu++){ int cpu_pid= contexts[cpu].pid; int cpu_context_remain = contexts[cpu].remaining; if (!cpu_context_remain) { int npid; if (cpu_pid == IDLE_TASK) { npid = sch.tick(cpu, TICK); _D(cerr << "SCH tick( " << cpu << " ,TICK) -> " << npid << endl;) } else { if (tsks[cpu_pid].blk == ST_CPU && !tsks[cpu_pid].blkms){ _D(cerr << "SCH unlock(" << cpu_pid << ") tick" << endl;) pthread_mutex_unlock(&(tsks[cpu_pid].mutex)); pthread_mutex_lock(&m_sched); _D(cerr << "SCH lock(sched)" << endl;) } switch (tsks[cpu_pid].blk) { case ST_EXIT: finished++; npid = sch.tick(cpu, EXIT); cout << "EXIT " << cur_time << " " << cpu_pid << " " << cpu << endl; _D(cerr << "SCH tick( " << cpu << " ,EXIT) -> " << npid << endl;) tsks[cpu_pid].running = 0; break; case ST_IO: if (tsks[cpu_pid].blkms >= 0) { unblock.push(make_pair(-(cur_time+tsks[cpu_pid].blkms), -cpu_pid)); tsks[cpu_pid].blkms = -1; } if (tsks[cpu_pid].blkms == -2) { tsks[cpu_pid].blk = ST_CPU; tsks[cpu_pid].blkms = 0; } cout << "BLOCK " << cur_time << " " << cpu_pid << endl; npid = sch.tick(cpu, BLOCK); _D(cerr << "SCH tick( " << cpu << " ,BLOCK) -> " << npid << endl;) break; case ST_CPU: if (tsks[cpu_pid].blkms) { tsks[cpu_pid].blkms--; } else { cerr << "FATAL ERROR, this should not happend" << endl; } npid = sch.tick(cpu, TICK); _D(cerr << "SCH tick( " << cpu << " ,TICK) -> " << npid << endl;) break; } } if (npid == IDLE_TASK) { // cerr << "SCH unlock(sched)" << endl;pthread_mutex_unlock(&m_sched); } else { if (npid < 0 || npid >= n) { cerr << "Error!, scheduler sent an invalid pid="< 0) { contexts[cpu].remaining += settings.switch_cost; } if ((int) cpu != tsks[npid].lastcpu && tsks[npid].lastcpu != -1) { contexts[cpu].remaining += settings.migrate_cost; } tsks[npid].lastcpu = cpu; } } cpu_pid = npid; } else { contexts[cpu].remaining--; } contexts[cpu].pid = cpu_pid; } //Hasta aca el codigo para cada CPU /* Unblock tasks at the end of the tick */ for(int j=0; j<(int)to_unblock.size(); j++) cout << "UNBLOCK " << cur_time << " " << to_unblock[j] << endl; context_remain= 0; //Muestra que esta realizando cada cpu //y calcula si hay contexto total restante (ver while) for(uint i= 0; i < contexts.size(); i++){ context_remain += contexts[i].remaining; if (contexts[i].remaining /*context_remain*/) { cout << "# CONTEXT CPU " << i << " " << cur_time << endl; } else{ cout << "CPU "<< cur_time << " " << contexts[i].pid << " " << i <