diff --git a/src/scheduler.c b/src/scheduler.c index 7c125fe..2459c6c 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -26,44 +26,155 @@ // - La función devuelve un PID diferente al curr_pid: Simula un cambio de // contexto y se ejecuta el proceso indicado. // -int fifo_scheduler(proc_info_t *procs_info, int procs_count, int curr_time, - int curr_pid) { +int fifo_scheduler(proc_info_t *procs_info, int procs_count, int curr_time, int curr_pid) { // Se devuelve el PID del primer proceso de todos los disponibles (los // procesos están ordenados por orden de llegada). return procs_info[0].pid; } -int my_own_scheduler(proc_info_t *procs_info, int procs_count, int curr_time, - int curr_pid) { - // Implementa tu scheduler aqui ... (el nombre de la función lo puedes - // cambiar) +// Shortest Job First (SJF) +int sjf_scheduler(proc_info_t *procs_info, int procs_count, int curr_time, int curr_pid) { + // Se devuelve el PID del proceso con menor duración de todos los disponibles - // Información que puedes obtener de un proceso - int pid = procs_info[0].pid; // PID del proceso - int on_io = procs_info[0].on_io; // Indica si el proceso se encuentra - // realizando una opreación IO - int exec_time = procs_info[0].executed_time; // Tiempo que el proceso se ha - // ejecutado (en CPU o en I/O) + int shortest_job_pid=procs_info[0].pid; + int shortest_job_duration = process_total_time(shortest_job_pid); + for(int i = 1; i < procs_count; i++){ + int pid = procs_info[i].pid; + int duration = process_total_time(pid); + if(shortest_job_duration > duration){ + shortest_job_duration = duration; + shortest_job_pid = pid; + } + } - // También puedes usar funciones definidas en `simulation.h` para extraer - // información extra: - int duration = process_total_time(pid); + return shortest_job_pid; +} + +// Shortest Time-to-Completion First (STCF) +int stcf_scheduler(proc_info_t *procs_info, int procs_count, int curr_time, int curr_pid) { + // Se devuelve el PID del proceso con menor duración de todos los disponibles + + int stc_pid=procs_info[0].pid; + int stc_rem_time = process_total_time(stc_pid) - procs_info[0].executed_time; + for(int i = 1; i < procs_count; i++){ + int pid = procs_info[i].pid; + int duration = process_total_time(pid); + int exec_time = procs_info[i].executed_time; + int rem_time = duration - exec_time; + if(stc_rem_time > rem_time){ + stc_rem_time = rem_time; + stc_pid = pid; + } + } + + return stc_pid; +} + +// Round Robin (RR) +int rr_scheduler(proc_info_t *procs_info, int procs_count, int curr_time, int curr_pid){ + // Cambia de proceso cada cierto tiempo (time slice) + + static int time_slice_counter = 0; // para simular el time_slice = timer_interrupt * 2 + static int proc_index = 0; + if (curr_pid != -1 && time_slice_counter < 2){ + time_slice_counter++; + return curr_pid; + } + time_slice_counter = 0; + proc_index = (proc_index + 1) % procs_count; + return procs_info[proc_index].pid; +} + +#define MAX_PROCS 100005 +#define NUM_QUEUES 3 +#define TIME_SLICES {5, 10, 20} // Time slice para cada cola +#define BOOST_INTERVAL 10 // Intervalo de tiempo después del cual se "boostean" las prioridades + +int queues[NUM_QUEUES][MAX_PROCS]; +int time_slice_counters[MAX_PROCS]; +int queue_heads[NUM_QUEUES] = {0}; +int queue_tails[NUM_QUEUES] = {0}; +int seen[MAX_PROCS]; +int mlfq_init = 0; - return -1; +// Inicializacion del MLFQ +void init_mlfq(proc_info_t *procs_info, int procs_count) { + for (int i = 0; i < procs_count; i++) { + queues[0][queue_tails[0]++] = procs_info[i].pid; + seen[procs_info[i].pid] = 1; + } +} + +// Multi-level Feedback Queue (MLFQ) +int mlfq_scheduler(proc_info_t *procs_info, int procs_count, int curr_time, int curr_pid) { + if(mlfq_init == 0){ + // inicializar + init_mlfq(procs_info,procs_count); + mlfq_init = 1; + } + + // insertar nuevos procesos en la cola de mayor prioridad + for(int i = procs_count - 1; i >= 0; i--){ + if(seen[procs_info[i].pid] == 0){ + queues[0][queue_tails[0]++] = procs_info[i].pid; + seen[procs_info[i].pid] = 1; + } + else{ + break; + } + } + + // Priority Boost + if (curr_time % BOOST_INTERVAL == 0) { + for (int q = 1; q < NUM_QUEUES; q++) { + for(int j = queue_heads[q]; j < queue_tails[q]; j++){ + queues[0][queue_tails[0]++] = queues[q][j]; + } + queue_heads[q] = queue_tails[q] = 0; + } + } + + int chosen_pid = -1; + int chosen_queue = -1; + + // buscar proceso de mayor prioridad + for (int q = 0; q < NUM_QUEUES; q++) { + if (queue_heads[q] != queue_tails[q]) { + chosen_pid = queues[q][queue_heads[q]]; + int ok = 0; + for(int j = 0; j < procs_count; j++){ + if(procs_info[j].pid == chosen_pid){ + ok = 1; + break; + } + } + queue_heads[q]++; + if(ok == 0){ + q--; + continue; + } + chosen_queue = q; + break; + } + } + + if (chosen_pid != -1) { + if (chosen_queue < NUM_QUEUES - 1) { + queues[chosen_queue][queue_tails[chosen_queue]++] = chosen_pid; + } + } + + return chosen_pid; } // Esta función devuelve la función que se ejecutará en cada timer-interrupt // según el nombre del scheduler. schedule_action_t get_scheduler(const char *name) { - // Si necesitas inicializar alguna estructura antes de comenzar la simulación - // puedes hacerlo aquí. - if (strcmp(name, "fifo") == 0) return *fifo_scheduler; - - // Añade aquí los schedulers que implementes. Por ejemplo: - // - // if (strcmp(name, "sjf") == 0) return *sjf_scheduler; - // + if (strcmp(name, "sjf") == 0) return *sjf_scheduler; + if (strcmp(name, "stcf") == 0) return *stcf_scheduler; + if (strcmp(name, "rr") == 0) return *rr_scheduler; + if (strcmp(name, "mlfq") == 0) return *mlfq_scheduler; fprintf(stderr, "Invalid scheduler name: '%s'\n", name); exit(1); diff --git a/src/simulation.c b/src/simulation.c index bca3ea1..035acfd 100644 --- a/src/simulation.c +++ b/src/simulation.c @@ -171,8 +171,6 @@ void start_new_simulation(process_t *processes, int process_count, } } - if (show_graph) show_sim_state(); - // Se recalculan los procesos activos (y los que se encuentra haciendo // operaciones IO) active_processes = 0; @@ -224,6 +222,8 @@ void start_new_simulation(process_t *processes, int process_count, g_sim->curr_proc_pid = next_active_pid; } } + } else { + g_sim->curr_proc_pid = -1; } } @@ -239,6 +239,8 @@ void start_new_simulation(process_t *processes, int process_count, } } + if (show_graph) show_sim_state(); + // Actualiza el tiempo de la simulación g_sim->curr_time = next_sim_time; @@ -248,6 +250,7 @@ void start_new_simulation(process_t *processes, int process_count, // Comprueba si todos los procesos terminaron ended_sim = ended_processes == process_count; + } int64_t final_sim_time = ms_time();