El plazo para la tarea vence el lunes el 15 de abril a 11:30. Tu compañero de trabajo y tú deben mandarme un email con sus nombres antes de la clase del 10 de abril.
Tu compañero y tú recibirán la misma nota para la tarea.
Nachos está en /usr/local/nachos. Copia el código (aproximadamente 551K) a tu cuenta con
cp -pr /usr/local/nachos/code .Para probar si todo está funcionando con tu cuenta, paths, etc., haz lo siguiente:
cd code/threads make depend make ./nachosEl make generará algunos avisos. Si Nachos corre correctamente, tendrás el siguiente output:
*** thread 0 looped 0 times *** thread 1 looped 0 times *** thread 0 looped 1 times *** thread 1 looped 1 times *** thread 0 looped 2 times *** thread 1 looped 2 times *** thread 0 looped 3 times *** thread 1 looped 3 times *** thread 0 looped 4 times *** thread 1 looped 4 times No threads ready or runnable, and no pending interrupts. Assuming the program completed. Machine halting! Ticks: total 130, idle 0, system 130, user 0 Disk I/O: reads 0, writes 0 Console I/O: reads 0, writes 0 Paging: faults 0 Network I/O: packets received 0, sent 0 Cleaning up...Debieras imprimir los archivos en el directorio de threads y usarlos para seguir la ejecución del sistema. Empieza con main en main.cc, la llamada a Initialize en system.cc, y la llamada a ThreadTest en threadtest.cc.
Hay un archivo de TAGS en el directorio code. Si usas Emacs, es muy fácil encontrar una función o una clase con M-. (find-tag). Debieras leer también la Sección 3, 6.1, y 6.2 de A Roadmap Through Nachos, que explica la estructura del sistema de threads usado por Nachos.
Si no entiendes una parte del sistema, ¡pregunta! Usa el newsgroup del curso (puc.cursos.iic2332). Puedes discutir la tarea con otros alumnos, pero tu código debe ser el tuyo propio. Por supuesto, puedes mandarme correo electrónico con preguntas, pero el newsgroup sería mejor. Y puedes visitarme cuando quieras.
#ifdef CHANGED ...codigo modificado o nuevo... #endif // CHANGEDLos comentarios son críticos para revisar tu trabajo. ¡No los olvides!
Crearás también algunos archivos nuevos en el directorio threads. Para compilarlos tendrás que modificar las definiciones de THREAD_H, THREAD_C, y THREAD_O en code/Makefile.common. Tienes que ejecutar un "make depend" en threads después de cada cambio a Makefile.common.
acquire(lock)
if lock.value = 1 then lock.value = 0
else begin
poner el proceso en lock.queue
bloquear
end
release(lock)
if lock.queue es vacio then lock.value = 1
else begin
sacar un proceso P de lock.queue
despertar P
end
Un thread despertado continua del punto inmediatamente siguiente a la
llamada a la función para bloquear.
Implementa locks. Añade declaraciones para variables privadas en
synch.h. En synch.cc, implementa Lock,
~Lock, Acquire, Release, y isHeldByCurrentThread.
La última vuelve TRUE si el lock pertenece al thread
corriente y es útil en Acquire, Release, y la segunda parte
de la tarea. ¿Debiera ser atómica? Ten cuidado.
Acquire debiera chequear a través de un ASSERT si el thread que llama ya lo ha adquirido. Release debiera chequear con ASSERT si el thread que llama tiene el lock.
No uses los semáforos (clase Semaphore) para la implementación de locks. Empero, puedes usar el código para semáforos como una guía.
Para probar tu solución debieras modificar threadtest.cc. Puedes encontrar mis archivos de prueba en
/usr/local/nachos/iic2332/tarea1/threadtestN.ccUse Nachos sin argumentos (threads ceden el control solamente a través de llamadas a Yield) y con el argumento "-rs " (Nachos produzca llamadas adicionales de Yield en puntos aleatorios), donde es un entero que sirve como una semilla aleatoria. El argumento "-d t" produzca información sobre los cambios de control.
Cuando sabe que la condición es verdadera, un thread que tiene el lock puede desear señalar a cualesquier threads que esperan la condición. En este caso el thread llama a Signal (para despertar un thread) o Broadcast (para despertar todos los threads que esperan la condición). Entonces el thread libera el lock.
Un thread despertado tiene que readquirir el lock. Existe la posibilidad cuando el thread empieza a correr que la condición no sea verdadera. La razón es que algún otro thread puede accesar el recurso y cambiarlo antes de que el thread despertado sea planificado (i.e., entre el señal y el tiempo cuando el thread despertado empiezas a correr). El thread despertado puede tener que esperar otra vez.
Las operaciones para variables de condición tienen que ser atómicas. Por ejemplo, en Wait, un thread no puede liberar el lock antes de bloquearse si la acción no es atómica. En este caso otro thread podría adquirir el lock y señalar la condición antes de que el primer thread se bloquee y empiece a esperar la condición.
Implementa la clase Condition en synch.cc. Algunos de mis archivos de threadtestN.cc prueban variables de condición, pero debieras implementar tus propias pruebas también.
La ventaja de SynchBuffer es que sus usuarios no tienen que saber nada sobre la sincronización. Toda la sincronización es dentro de la implementación de la clase.
En el directorio tarea1 están synchbuffer.h, con un esqueleto de la definición de la clase, y prodcon.cc, con código para productores y consumidores. Tienes que modificar synchbuffer.h y crear synchbuffer.cc. Para probar tu solución, reemplaza la llamada a ThreadTest en main con una llamada a ProdCon. Empieza con pruebas de solamente un productor y un consumidor (tendrás que comentar algunas líneas en ProdCon) y continua con pruebas con más de uno de ambos. Puedes ver más de tres mensajes seguidos de Get o Put. ¿Por qué?
Necesitarás también los archivos buffer.h y buffer.cc. No olvides modificar Makefile.common.
Tu solución debiera usar variables de condición y locks. No uses los semáforos. Incluye en synchbuffer.cc un comentario que describa tu diseño.
Mi solución para synchbuffer.cc tiene 46 líneas, incluyendo líneas vacías (pero no comentarios).