#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>

// Función para medir tiempo en microsegundos
long long tiempo_actual_us() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000000LL + tv.tv_usec;
}

int main() {
    long long inicio, fin;
    long long tiempo_pow, tiempo_open, tiempo_variable;
    double resultado;
    int fd;
    int variable = 0;
    
    printf("=== DEMOSTRACIÓN: Costo del TRAP ===\n\n");
    printf("Medición de 100,000 operaciones de cada tipo:\n\n");
    
    // ========================================
    // 1. POW() - Biblioteca matemática (SIN trap)
    // ========================================
    inicio = tiempo_actual_us();
    
    for (int i = 0; i < 100000; i++) {
        resultado = pow(2.0, 10.0);  // 2^10 = 1024
    }
    
    fin = tiempo_actual_us();
    tiempo_pow = fin - inicio;
    
    printf("1. POW() (biblioteca matemática):\n");
    printf("   Resultado: %.0f\n", resultado);
    printf("   Tiempo total: %lld μs\n", tiempo_pow);
    printf("   Tiempo por operación: %.3f μs\n", tiempo_pow / 100000.0);
    printf("   → Sin trap: solo cálculo en CPU\n\n");
    
    // ========================================
    // 2. VARIABLE LOCAL (SIN trap)
    // ========================================
    inicio = tiempo_actual_us();
    
    for (int i = 0; i < 100000; i++) {
        variable = i * 2;  // Operación simple
    }
    
    fin = tiempo_actual_us();
    tiempo_variable = fin - inicio;
    
    printf("2. VARIABLE LOCAL (operación simple):\n");
    printf("   Resultado final: %d\n", variable);
    printf("   Tiempo total: %lld μs\n", tiempo_variable);
    printf("   Tiempo por operación: %.3f μs\n", tiempo_variable / 100000.0);
    printf("   → Sin trap: solo acceso a registro/CPU\n\n");
    
    // ========================================
    // 3. OPEN() - System call (CON trap)
    // ========================================
    // Crear archivo de prueba primero
    int fd_temp = open("test_temp.txt", O_CREAT | O_WRONLY, 0644);
    close(fd_temp);
    
    inicio = tiempo_actual_us();
    
    for (int i = 0; i < 100000; i++) {
        fd = open("test_temp.txt", O_RDONLY);  // SYSCALL con TRAP
        close(fd);                              // Otra syscall
    }
    
    fin = tiempo_actual_us();
    tiempo_open = fin - inicio;
    
    printf("3. OPEN() + CLOSE() (system calls):\n");
    printf("   Operaciones: 100,000 open + 100,000 close\n");
    printf("   Tiempo total: %lld μs\n", tiempo_open);
    printf("   Tiempo por open(): %.3f μs\n", tiempo_open / 100000.0);
    printf("   → CON trap: cambio Usuario→Kernel→Usuario\n\n");
    
    // ========================================
    // COMPARACIÓN
    // ========================================
    printf("=== COMPARACIÓN DE RENDIMIENTO ===\n");
    printf("Variable local:  %lld μs\n", tiempo_variable);
    printf("pow():           %lld μs\n", tiempo_pow);
    printf("open()+close():  %lld μs\n", tiempo_open);
    printf("\n");
    printf("open() es %.0fx más lento que pow()\n", 
           (double)tiempo_open / tiempo_pow);
    printf("open() es %.0fx más lento que variable local\n",
           (double)tiempo_open / tiempo_variable);
    printf("\n");
    
    // ========================================
    // ¿POR QUÉ?
    // ========================================
    printf("=== ¿POR QUÉ ES TAN LENTO OPEN()? ===\n\n");
    
    printf("POW() y variable local:\n");
    printf("  [CPU] Ejecuta instrucciones ←── Todo en User Space\n");
    printf("        ↓\n");
    printf("  [CPU] Resultado listo\n\n");
    
    printf("OPEN() (con TRAP):\n");
    printf("  [User] Prepara parámetros\n");
    printf("         ↓\n");
    printf("  [TRAP] SYSCALL instruction ──► Cambio a Kernel Mode\n");
    printf("         ↓\n");
    printf("  [Kernel] Guarda registros del usuario\n");
    printf("  [Kernel] Valida permisos del proceso\n");
    printf("  [Kernel] Busca archivo en VFS → ext4 → driver\n");
    printf("  [Kernel] Asigna file descriptor\n");
    printf("  [Kernel] Restaura registros\n");
    printf("         ↓\n");
    printf("  [TRAP] SYSRET ──► Vuelve a User Mode\n");
    printf("         ↓\n");
    printf("  [User] Recibe fd (o error)\n\n");
    
    printf("El trap añade: cambio de modo + validaciones +\n");
    printf("                saltos de contexto + trabajo del kernel\n\n");
    
    // Limpieza
    unlink("test_temp.txt");
    
    return 0;
}