Interseccion (Vida y Penurias)

Son muchos los que me han preguntado en que consistia la practica de Laboratorio de Sistemas Operativos que me ha mantenido alejado de la biblioteca y las chanzas oportunas estas semanas. Y unos cuantos los que me han pedido que se la enseñara una vez terminada.

El pasado sábado por fin terminé la versión de Windows, que es la que podréis ejecutar la mayoria. No se realmente que esperan ver aquellos que tan intrigados me preguntaban, pero estoy seguro que será decepcionante para la gran mayoria. Porque asi de putas son estas practicas, que te tienen entretenido semanas con lineas y lineas de codigo para luego, ver esto:

Y aqui teneis los archivos: Interseccion

[EDITO] Aqui esta el codigo

El funcionamiento es sencillo, solo hay que descomprimir el archivo y hacer doble click en el archivo “ejecutar.bat”. Si hacéis “click derecho” sobre ese archivo y le dais a “editar” podéis cambiar las opciones de ejecución. El primer numero es la cantidad de coches / peatones (min 3, max 48) y el segundo la velocidad (0 máxima).

VERSION 2.0

El pasado jueves, se confirmo esa maxima de la informatica que dice “Si algo puede fallar, fallara”. Cuando llevaba desde las 8 de la mañana en la biblioteca, preparando el siguiente examen, me dio por hacer una prueba final. La habia probado cientos de veces con todas las combinaciones. Nada habia fallado nunca, o si…

Dada la velocidad de los procesadores actuales, cuando ejecutaba la practica a maxima velocidad era imposible ver bien lo que ocurria, simplemente podia ver que jamas se paraba ni habia choques / infracciones. A la hora de probarlo a una velocidad  mas lenta, podia comprobar que efectivamente todo era correcto. Así pues, habia dado por concluida la practica el sabado, pero al probarlo en un procesador menos potente, todo cambio.

Me encontré con que, sin saber por que, la practica se quedaba bloqueada a maxima velocidad. Quedaban poco mas de 24h y llevaba 18 horas despierto, mal momento y mala leche.

Al final, despues de muchas vueltas al codigo, varias horas de MSN de madrugada con el incansable Robertiño y 28 horas despues de haber amanecido parecía que todo iba encaminado de nuevo,  el error estaba encontrado y  con unas cuantas modificaciones en el codigo, la solucion planteada. Antes de pasar a la pizarra preferí dormir un poco.

Cuatro horas mas tarde, con una fria taza de cafe en la mano (caliente es lo peor que me puede pasar) retome la labor de pizarra. No habia tiempo para reescribir o replantear el codigo, asi que hubo que adaptar lo que tenia como buenamente pudiera. Faltaban pocas horas. Y ya sabemos que parchear un error suele hacer aflorar otro. En lugar de dos semaforos, que fallaban inicialmente hubo que modificar los cuatro. Los coches fueron pan comido y los peatones verticales tampoco supusieron ningun problema, sin embargo los horizontales dieron bastante guerra por un error de coordenadas.

Cincuenta horas despues de mi ultimo “amanecer feliz” parecia que todo funcionaba. Otro par de horas de pruebas en todos los ordenadores que pillé y di por buena la solución. Tampoco quedaba tiempo para mas.

No fue un error en el planteamiento de mi solución, ni tampoco que la biblioteca fallara. Fue un error de conjunto.

La biblioteca hacía lo que supongo su autor quería que hiciera, sin embargo a maxima velocidad, las pausas que ofrecía no eran tales y todo transcurria con tal velocidad que los coches no siempre tenían la oportunidad de avanzar. Es por eso que aumentando la velocidad, al funcionar las pausas como se esperaba, todo iba bien.

Un simple error de documentación. Un error imposible de preveer y, sobre todo, de comprobar si no hubiera tenido un PC viejo por casa, pues hacia falta que el procesador se sobrecargara para poder ver el error. La diferencia entre un 10 y un 4 en la defensa hubiera dependido, unicamente, de la capacidad de proceso del ordenador donde hubiera tenido que hacer la demostracion.

6 pensamientos sobre “Interseccion (Vida y Penurias)”

    1. Bueno, la solución es bastante sencilla, una vez encuentras el error.

      El problema es el siguiente:

      La biblioteca de Gyermo, en la función pausa() llama internamente a un sleep() proporcional a la velocidad que le pases como pararmetro al programa. Pero al hacer velocidad 0, omite el sleep, para no demorar la ejecución, con lo que no llega a ceder la CPU a otro hilo para que comience el avance (al menos no siempre). Esto lo solucionas con algo tan sencillo como poniendo un sleep(0) detras de la llamada a pausa si la velocidad es 0. Aun siendo el parametro 0, ese sleep lo que hará sera forzar a ceder el procesador al siguiente hilo (recuerda que NT usa Round Robin en la planificacion de HIlos).

      Lamentablemente esa solución Gyermo no nos la daba por valida. Pero el problema ya estaba acotado. ¿La solucion? Semaforos de turno.

      Aqui tienes el esquema de sincronizacion

      Lo que hago es sencillo. Cuando los hijos llegan al semaforo, toman primero el semaforo de turno y luego el de acceso. Mientras el semaforo esta en rojo, los semaforos de turno estan abiertos, luego aun esperando en le paso, ya los tendria en su poder. Una vez que el semaforo se pone en verde libera el de acceso e intenta coger los de turno, pero hasta que los peatones que haya esperando no entren y lo liberen, no podrá cambiar de color el semaforo. Por supuesto, si no hay ningun peaton, el semaforo seguirá su ciclo normalmente.

      En el esquema solo figura un semaforo, el “Semaforo de Turno”, porque el “Semaforo de Acceso” yo no lo he implementado, en su lugar, cuando se pone en rojo, el gestor ocupa la posicion del mapa de memoria, impidiendo el avance, y asi simplifico el codigo.

      EDITO: Añado un nuevo paquete al articulo. Ahi están tanto esquema de sincronizacion como fuentes, por si alguien quiere consultarlo, aunque no es ninguna maravilla.

  1. muchas gracias. ¿gyermo te dijo claramente que poner un sleep(0) no es una solucion valida? porque en el correo que le envie yo, explicandole que el gestor no cedia la cpu al resto de hilos para que pudieran comprobar y pasar, dijo que pusiera un sleep(0) donde pensara que tenia que ceder la cpu, como bien dices, y dejo entrever que si asi funcionaba, la sincronizacion estaria bien, pero que el sleep(0) lo deberia de quitar. con todo esto entiendo que una solucion valida, es dejarlo sin sleep(0) pero habiendo comprobado lo anterior, dado que el “error” esta en la biblioteca. aunque esto no lo sabre hasta el dia 1 en la defensa
    gracias

    1. PodEis usar el Sleep(0) para tratar de diagnosticar el problema, pero en
      la versiOn final tenEis que quitarlo para que no produzca efectos
      secundarios no deseados de sincronizaciOn.

      Exactamente eso digo Gyermo. Puede que quisiera decir lo que tu comentas, que lo usaramos solo para asegurarnos de que el error estaba ahi pero que luego lo quitaramos. El caso es que como a velocidad 0 si la maquina era lo suficientemente “estupida” se quedaba practicamente bloqueado, asi que busque la solución para evitar eso, porque siendo como son los examenes de Gyermo, preferia asegurarme el punto. Además, era cuestión de amor propio. Después de tantas horas, queria que funcionara perfecto.

      Yo tambien tengo la defensa el dia 1, asi que ahi nos veremos. Defendiendo el honor de nuestro código a capa y espada 😉

  2. Buenas compañero. Pues al final hubo un pequeño problema y nos quedamos en el 5, con mas puteo que otra cosa, me explico.

    El no ver este fallo fue culpa mia, aunque deribado de los problemas con la biblioteca ya comentados. Resulta que en la peticion de avance, como podrás ver en el codigo, incluimos un bucle while y dentro una seccion critica. Al salir de esta, tanto si hay exito como fracaso se llama a “pausa()”, porque asi lo pide el enunciado y porque asi evitamos que un proceso se adueñe siempre de la seccion, produciendo espera ocupada.

    Sin embargo… dado que, como ya hemos dicho, a velocidad 0 realmente esa pausa no se hace, aparece ese problema.

    No me di cuenta cuando descubri lo de la pausa, y durante las ejecuciones, pasaba algo similar a lo de los semaforos y quedaba camuflado, porqeu las evidencias eran:

    1.- Alto consumo de CPU. Pero como todos sabemos, en velocidad 0, se supone que el consumo va a ser alto y al aumentar de velocidad y existir ya las pausas, este problema deja de existir.

    2.- Lentitud en la ejecucion. Aunque solo en los procesadores mononucleo, pues al repartirse la carga de trabajo los multinucleo, esto pasa desapercibido y van a toda velocidad (o por lo menos realmente rapido). Claro, como mis mononucleo son realmente viejos y lentos, supuse que la lentitud venia causada por la poca potencia de proceso.

    En fin… que estaba condenada a fracasar. De haber visto antes lo de la “pausa()”, podia haber plantado toda la practica de otro modo, pero al ser asi no hubiera tenido tiempo material para cambiarla entera, luego hubiera quedado igual solo que mas triste XD.

    En fin… al menos el resultado final ha sido gratificante y la asignatura esta aprobada. Espero que tu también hayas tenido suerte.

    Un saludo y si necesitas cualquier cosa, aqui estoy.

Anímate a comentar...