// cfs.c — la idea central de CFS: correr siempre al de menor vruntime.
//
// Uso: ./cfs <ms> <nice1> <nice2> ...
// Ejemplo: ./cfs 30 0 5
//
// Cada trabajo acumula vruntime = tiempo real * 1024 / peso. El peso sale de
// la tabla de Linux (sched_prio_to_weight en kernel/sched/core.c). Un trabajo
// con más peso acumula vruntime más despacio y por eso corre más.
// Simplificación: quantum fijo de 1 ms y búsqueda lineal (Linux usa un árbol
// rojo-negro y slices variables).
#include <stdio.h>
#include <stdlib.h>

#define MAX_JOBS 8

// Pesos de Linux para nice -20 .. 19 (nice 0 = 1024).
static const int prio_to_weight[40] = {
    88761, 71755, 56483, 46273, 36291, 29154, 23254, 18705, 14949, 11916,
    9548,  7620,  6100,  4904,  3906,  3121,  2501,  1991,  1586,  1277,
    1024,  820,   655,   526,   423,   335,   272,   215,   172,   137,
    110,   87,    70,    56,    45,    36,    29,    23,    18,    15,
};

struct job {
    char name;
    int nice;
    int weight;
    double vruntime;  // en ms "virtuales"
    int ran;          // ms reales de CPU
};

int main(int argc, char *argv[]) {
    if (argc < 3 || argc - 2 > MAX_JOBS) {
        fprintf(stderr, "uso: %s <ms> <nice>...\n", argv[0]);
        return 1;
    }
    int ms = atoi(argv[1]);
    int n = argc - 2;
    struct job jobs[MAX_JOBS];
    long total_weight = 0;
    for (int i = 0; i < n; i++) {
        int nice = atoi(argv[2 + i]);
        if (nice < -20 || nice > 19) {
            fprintf(stderr, "nice debe estar entre -20 y 19\n");
            return 1;
        }
        jobs[i] = (struct job){'A' + i, nice, prio_to_weight[nice + 20], 0.0, 0};
        total_weight += jobs[i].weight;
    }

    for (int t = 0; t < ms; t++) {
        int best = 0;
        for (int i = 1; i < n; i++)
            if (jobs[i].vruntime < jobs[best].vruntime)
                best = i;
        jobs[best].ran++;
        jobs[best].vruntime += 1.0 * 1024 / jobs[best].weight;
        if (t < 12) {
            printf("ms %2d: corre %c   vruntime:", t + 1, jobs[best].name);
            for (int i = 0; i < n; i++)
                printf("  %c=%.2f", jobs[i].name, jobs[i].vruntime);
            printf("\n");
        }
    }

    printf("\ntrabajo  nice   peso  esperado  obtenido\n");
    for (int i = 0; i < n; i++)
        printf("   %c     %3d  %5d    %5.1f%%    %5.1f%%\n", jobs[i].name, jobs[i].nice,
               jobs[i].weight, 100.0 * jobs[i].weight / total_weight,
               100.0 * jobs[i].ran / ms);
    return 0;
}
