Implementación de monitores POSIX



Documentos relacionados
Concurrencia. Primitivas IPC con bloqueo

CDI Exclusión mutua a nivel alto. conceptos

Concurrencia entre Procesos.

Concurrencia: deberes. Concurrencia: Exclusión Mutua y Sincronización. Concurrencia. Dificultades con la Concurrencia

Concurrencia: Exclusión mutua y Sincronización

Tema 4. Gestión de entrada/salida

PROGRAMACIÓN CONCURRENTE. Tema 5 Monitores

Modulo 1 El lenguaje Java

un programa concurrente

Sistemas Operativos Temas 4, 5 y 6. Jorge García Duque Despacho: B-202 Tutorías: Lunes 16:00-18:00 y Martes 16:00-20:00

1 (2 5 puntos) Responda con brevedad y precisión a las siguientes preguntas:

SISTEMAS OPERATIVOS AVANZADOS

4. Programación Paralela

Parámetros con la ventana de selección de usuario, reglas, texto y descomposición (IVE)

SIMM: TEORÍA DE LOS S.O. I.E.S. JUAN DE LA CIERVA CURSO 2007/2008

Capítulo 1 Introducción a la Computación

Mensajes. Interbloqueo

PROGRAMACION CONCURRENTE

SOLUCION EXAMEN junio 2006

Sistemas Operativos Práctica 4

Receta general para resolver problemas de sincronización con semáforos

Elementos requeridos para crearlos (ejemplo: el compilador)

7. Manejo de Archivos en C.

Ejemplos de conversión de reales a enteros

Control Digital en PC con MS-DOS

Introducción a la programación orientada a objetos

Tema 3. Monitores Programación Concurrente

DISCOS RAID. Se considera que todos los discos físicos tienen la misma capacidad, y de no ser así, en el que sea mayor se desperdicia la diferencia.

Hilos, comunicación y competencia entre procesos. Dr. Alonso Ramírez Manzanares 2-Sep-2010

MONITORES EN JAVA. Antonio Tomeu Control de la Concurrencia en Java: API Estándar

Trey-SAT Pag. 1. Manual de usuario

Práctica 2: El problema de la sección crítica

PROGRAMACION CONCURRENTE Y DISTRIBUIDA. II.5 Sincronización basada en memoria compartida: Monitores

Sistemas Operativos. Características de la Multiprogramación. Interacción entre Procesos. Características de la Multiprogramación

Estructuras de Sistemas Operativos

PROGRAMACION CONCURRENTE

LiLa Portal Guía para profesores

En cualquier caso, tampoco es demasiado importante el significado de la "B", si es que lo tiene, lo interesante realmente es el algoritmo.

Introducción a la Firma Electrónica en MIDAS

Visual Basic 1. Empleo de módulos y Procedimientos. Procedimientos definidos por el usuario

Capítulo 9. Archivos de sintaxis

Unidad 1. Fundamentos en Gestión de Riesgos

ESTRUCTURA DE DATOS: ARREGLOS

Práctica 5. Curso

Unidad II: Administración de Procesos y del procesador

INTERRUPCIONES. La comunicación asíncrona de los sistemas periféricos con la CPU, en ambos sentidos, se puede establecer de dos maneras fundamentales:

SERVIDOR WEB PARA ACCESO EN TIEMPO REAL A INFORMACIÓN METEOROLÓGICA DISTRIBUIDA

Capítulo 4. Requisitos del modelo para la mejora de la calidad de código fuente

TABLA DE DECISION. Consideremos la siguiente tabla, expresada en forma genérica, como ejemplo y establezcamos la manera en que debe leerse.

Benemérita Universidad Autónoma del Estado de Puebla

SEGURIDAD Y PROTECCION DE FICHEROS

15 CORREO WEB CORREO WEB

Unidad 1: Conceptos generales de Sistemas Operativos.

Anexo B. Comunicaciones entre mc y PC

- Bases de Datos - - Diseño Físico - Luis D. García

2) Tenemos un sistema informático con una sola CPU que está gestionada mediante una cola multinivel con realimentación.

Instalar protocolo, cliente o servicio nuevo. Seleccionar ubicación de red. Práctica - Compartir y conectar una carpeta

INTRODUCCION A LA PROGRAMACION DE PLC

UNIVERSIDAD DE SALAMANCA

Introduccion al Lenguaje C. Omar Andrés Zapata Mesa Grupo de Fenomenología de Interacciones Fundamentales, (Gfif) Universidad de Antioquia

MANUAL COPIAS DE SEGURIDAD

Propuesta de Portal de la Red de Laboratorios Virtuales y Remotos de CEA

Benemérita Universidad Autónoma del Estado de Puebla

Edición de Ofertas Excel Manual de Usuario

Capítulo IV. INTERBLOQUEO E INANICIÓN

INTRODUCCIÓN A LOS SISTEMAS GESTORES DE BASE DE DATOS

Utilidades de la base de datos

Tema 3: Concurrencia de procesos

Estas visiones de la información, denominadas vistas, se pueden identificar de varias formas.

GENERACIÓN DE CÓDIGO

El soporte del sistema operativo. Hace que un computador sea más fácil de usar. Permite que los recursos del computador se aprovechen mejor.

Guía paso a paso para la cumplimentación del formulario de candidatura

Arquitectura de Aplicaciones

McAfee Security-as-a-Service

Una variable de clase escalar tiene un nivel de indirección igual a 1. Por ejemplo, las variables i, b y x definidas como se muestra a continuación.

Gestión de Permisos. Bizagi Suite. Copyright 2014 Bizagi

TEMA 3. EL PROCESO DE COMPILACIÓN, DEL CÓDIGO FUENTE AL CÓDIGO MÁQUINA

App para realizar consultas al Sistema de Información Estadística de Castilla y León

Consultas con combinaciones

INSTALACIÓ N A3ERP. Informática para empresas INTRODUCCIÓN CONSIDERACIONES GENERALES DE LA INSTALACIÓN PAQUETES DE INSTALACIÓN PREDEFINIDOS

Java Inicial (20 horas)

Procesos. Planificación del Procesador.

GENERACIÓN DE ANTICIPOS DE CRÉDITO

Algorítmica y Lenguajes de Programación. Ordenación (i)

Acronis License Server. Guía del usuario

WINDOWS : SERVIDOR DHCP

Curso Completo de Electrónica Digital

Caravel Modernization Tool: Tipos de Proyectos. Caravel Modernization Tool: Tipos de Proyectos

OPERACIONES EN RÉGIMEN DE COMPUESTA

Curso de Java POO: Programación orientada a objetos

Tema 11. Soporte del Sistema Operativo REQUERIMIENTOS DE LOS SISTEMAS OPERATIVOS MULTIPROGRAMACIÓN.

Centro de Capacitación en Informática

Sistemas de archivos distribuidos. Alvaro Ospina Sanjuan

MICQ. Trabajo Práctico Final Seminario de Ingeniería en Informática I Facultad de Ingeniería, UBA. Junio Cátedra: Pablo Cosso

Tema 3. Medidas de tendencia central Introducción. Contenido

UNIDADES FUNCIONALES DEL ORDENADOR TEMA 3

15. Arquitectura de los multiprocesadores. 16. Multiprocesadores de memoria compartida. 17. Multicomputadores.

Sistema de Facturación de Ventas WhitePaper Enero de 2007

Universidad de Colima Facultad de Ingeniería Mecánica y Eléctrica. Base de Datos I. Maestra: Martha E. Evangelista Salazar

Transcripción:

Implementación de monitores POSIX Ampliación de Sistemas Operativos (prácticas) E.U. Informática en Segovia Universidad de Valladolid Programación concurrente: Problemática Presencia de condiciones de carrera Una condición de carrera se produce cuando la ejecución de un conjunto de operaciones concurrentes sobre una variable compartida deja la variable en un estado inconsistente con las especificaciones de corrección Además, el resultado final depende de la velocidad relativa en que se ejecutan las operaciones Solución a las condiciones de carrera En general, no se puede controlar cuándo se producen cambios de contexto entre los hilos involucrados Por lo tanto, se tiene que lograr que los programas concurrentes sean correctos a pesar de que se produzcan cambios de contexto en cualquier lugar del código Para ello, una posible solución para garantizar la corrección de un programa concurrente es sincronizar el acceso a variables compartidas Sincronización En este contexto, sincronizar significa imponer un orden en la ejecución de zonas de código (pertenecientes a diferentes hilos) que acceden a variables compartidas Estas zonas de código se denominarán secciones críticas EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 2 1

El problema de la sección crítica (1) El problema de la sección crítica se caracteriza por: Tener N procesos/hilos que se ejecutan concurrentemente, compitiendo por acceder a un conjunto de datos compartidos Cada proceso o hilo Tiene, al menos, una zona de código en la que se accede a datos compartidos y que se denomina sección crítica Puede tener además otras zonas de código en que no se acceden a dichos datos. Estas zonas se consideran secciones de código genéricas y se referirá a ellas como sección restante El problema de la sección crítica trata de encontrar un protocolo que defina la entrada y la salida de una sección crítica, que impida la ocurrencia de condiciones de carrera protocolo de entrada sección CRÍTICA protocolo de salida sección RESTANTE EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 3 El problema de la sección crítica (2) Requisitos de cualquier solución al problema de la sección crítica: El protocolo diseñado debe satisfacer las tres condiciones siguientes: Exclusión mutua: si un proceso está ejecutando su sección crítica, ningún otro proceso puede estar ejecutando la suya Progreso: si ningún proceso está ejecutando su sección crítica y hay otros que desean entrar a las suyas, entonces la decisión de qué proceso entrará en la sección crítica se toma en un tiempo finito y sólo depende de los procesos que desean entrar Espera limitada: Después de que un proceso haya solicitado entrar en su sección crítica, existe un límite en el número de veces que se permite que otros procesos entren a sus secciones críticas Y todo ello, suponiendo que... Los procesos se ejecutan a velocidad no nula La corrección no ha de depender de hacer suposiciones sobre la velocidad relativa de ejecución de los procesos EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 4 2

El problema de la sección crítica: clasificación de soluciones (1) Existen varias alternativas a la hora de implementar el protocolo de entrada (y salida) de la sección crítica Soluciones de tipo software El protocolo se implementa con código a nivel de usuario, sin mecanismos añadidos. Por ejemplo, los algoritmos de Dekker. Soluciones de tipo hardware Se aprovechan de instrucciones máquina especiales (inhabilitación interrupciones, instrucciones test and set) para implementar el protocolo Soluciones con soporte del sistema operativo El protocolo se implementa mediante mecanismos proporcionados por el sistema operativo, a través de llamadas al sistema (semáforos, cerrojos de exclusión mutua, variables de condición, etc.) Soluciones con soporte del lenguaje de programación (construcciones lingüísticas) Algunos lenguajes de programación poseen tipos de datos especiales que garantizan su acceso en exclusión mutua de forma automática, como por ejemplo, Ada95, Java EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 5 El problema de la sección crítica: clasificación de soluciones (2) Java, Ada Aplicaciones Construcciones Lingüísticas Sistema Operativo Hardware Monitores Regiones críticas Tipos protegidos... Semáforos Mutex Eventos Variables de condición... Inhabilitación de interrupciones Instrucciones test_and_set C, C++ Programación de sistemas Aplicaciones C Drivers EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 6 3

Soluciones a nivel del lenguaje de programación Algunos lenguajes de programación incorporan tipos de datos específicos, y/o construcciones lingüísticas que permiten al programador, solucionar el problema de la sección crítica de forma más cómoda, ya que: Garantizan la exclusión mutua de forma automática Aportan una solución a la suspensión voluntaria de los procesos/hilos dentro de secciones de código en exclusión mutua Fuerzan el uso de un determinado estilo de programación Generalmente, el compilador del lenguaje de programación utiliza soluciones a nivel del sistema operativo para implementar esas características especiales Existen numerosas soluciones a este nivel (1) Soluciones definidas teóricamente Monitores Regiones críticas (2) Soluciones reales de lenguajes de programación existentes: Objetos protegidos de Ada95 Objetos de sincronización de Java EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 7 Monitor Concepto de monitor (1) Es un tipo abstracto de datos que encapsula: Tanto un conjunto de variables (internas) Como una serie de operaciones de acceso de forma que: Los procesos/hilos pueden únicamente invocar a las operaciones de acceso Las variables internas sólo pueden ser accedidas desde el código de las operaciones de acceso (concepto de encapsulamiento, propio de los tipos abstractos de datos) El código de las operaciones se ejecuta en exclusión mutua de forma automática No es necesario protegerlo con ningún mecanismo añadido Se proporciona además un mecanismo general de suspensión, basado en variables denominadas condición Los procesos/hilos pueden suspenderse en una variable condición Otro proceso/hilo puede despertar a un proceso/hilo suspendido anteriormente EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 8 4

Concepto de monitor (2) Monitor Variables privadas variables variables condición de datos Operaciones de acceso (Zona mutex) Entrada Colas de hilos Suspendidos en variables condición Salida La zona mutex se abandona si el hilo se suspende en una variable condición Cola de entrada al monitor (mutex) Hilos EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 9 Sintaxis Concepto de monitor (3) type nombre_monitor = monitor... Declaración de variables procedure entry P1 (...);... Código de P1 end; function entry F2 (...);... Código de F2 end...... Código de inicialización end; Variables internas al monitor: variables compartidas variables de condición Métodos de acceso: única vía de acceso a las variables compartidas Exclusión mutua automática Inicialización: Se invoca automáticamente al instanciar el monitor y antes de ser accedido por ningún proceso Se utiliza para la inicialización de las variables del monitor EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 10 5

Concepto de monitor (4) Variables de tipo condición: En ocasiones es necesario definir esquemas complejos de sincronización, en los que un proceso/hilo debe suspenderse dentro del código del monitor Para ello el programador del monitor puede declarar, como variables internas del monitor, variables de tipo condición ( condition ) var x: condition; Sobre estas variables condition se pueden realizar las siguientes operaciones: x.wait; Causa la suspensión (en una cola asociada a x) del proceso que invocó la operación x.signal; Se reanuda (si existe) un proceso suspendido en la cola asociada a x. Si no existe ninguno, no tiene efecto x.awaited; Retorna el número de procesos suspendido en la cola de la variable de condición x EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 11 Concepto de monitor (5) Ejemplo: Productor/consumidor (pseudo-pascal) type buffer_acotado = monitor const N = 100; contador, entrada, salida: integer; lleno, vacio: condition; buffer: array[0..n-1] of integer; procedure entry insertar (item: interger); if (contador = N) then lleno.wait; contador:= contador +1; buffer[entrada] := item; entrada:= (entrada+1)mod N; vacio.signal; end; (...) (...) procedure entry extraer (var item: integer); if (contador = 0) then vacio.wait; contador:= contador 1; item:= buffer[salida]; salida:= (salida+1) mod n; lleno.signal; end; entrada:= 0; salida:= 0; contador:= 0; end; EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 12 6

Variantes de monitor Qué ocurre cuando un hilo despierta a otro en un signal? El hilo que ejecuta la operación signal (P) se encuentra en estado en ejecución El hilo que se despierta del wait (Q) pasa a estado preparado Existe entonces un problema Dos hilos (P y Q) pueden resultar ser elegidos por el sistema operativo para continuar su ejecución y, ambos están dentro del código del monitor Esto viola la definición de monitor, que garantiza automáticamente la exclusión mutua dentro del código del monitor Existen tres alternativas para solucionar el problema Cada alternativa fue aportada por un autor diferente, resultando tres variantes: (1) Modelo de Hoare Cuando P despierta a Q, P se espera (se suspende) hasta que Q sale del monitor, o vuelve a suspenderse en otra variable de condición (2) Modelo de Lampson y Redell Cuando P despierta a Q, Q se espera (se suspende hasta que P sale del monitor, o se suspende en una variable de condición (3) Modelo de Brinch-Hansen Si algún procedure entry de un monitor tiene una operación signal, esta tiene que ser la última instrucción del procedimiento, de modo que se soluciona el problema por construcción EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 13 POSIX Implementación de monitores en POSIX Proporciona primitivas muy simples (mutex y variables de condición) para conseguir la sincronización de hilos de ejecución, en comparación con los monitores Sin embargo, su metodología de programación resulta en un modelo muy parecido al concepto de monitor, en concreto al modelo de Lampson y Redell A continuación, se muestra una implementación genérica de monitores de tipo Lampson y Redell utilizando primitivas POSIX Ello permitiría traducir directamente un monitor concreto en términos de primitivas POSIX, teniendo una forma de convertir un código teórico en una aplicación real Se hará manualmente, lo que haría un compilador de un hipotético lenguaje de programación que soportara monitores, al compilar un programa con monitores en un sistema operativo compatible con el estándar POSIX EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 14 7

Implementación de monitores en POSIX Implementación: exclusión mutua Cada procedure entry del monitor se convierte en una función en C que debe ser protegida en exclusión mutua Como todos los procedure entry tienen que excluirse mutuamente entre ellos, se necesita un único cerrojo de exclusión mutua (mutex) para proteger todo el código Debe definirse una única variable global mutex que se denominará mutex_monitor Cada procedure entry se traducira de la siguiente forma: procedure entry p1 (param);... end; void p1 (param); {... ptrhead_mutex_unlock(&mutex_monitor); EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 15 Implementación de monitores en POSIX Implementación: gestión de la suspensión en variables de condición Dentro de cada procedure entry, puede haber instrucciones wait y signal sobre ciertas variables de tipo condition Por cada variable condition x se necesita una variable de condición POSIX, que se denominará cond_x Cada instrucción x.wait se traduce por una llamada pthread_cond_wait Cada instrucción x.signal se convierte en una llamada pthread_cond_signal Hay que prestar especial atención a las condiciones lógicas en que los procesos se suspenden en las operaciones x.wait y se despiertan en las operaciones x.signal, puesto que probablemente habrá que ajustar las condiciones ligeramente en el código POSIX Adicionalmente, en POSIX, se puede despertar a todos los procesos suspendidos en una variable de condición por medio de la llamada pthread_cond_broadcast EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 16 8

Implementación de monitores en POSIX Implementación: gestión de la suspensión en variables de condición Opción 1: (utilizando if) if (condicion1) then x.wait; if (_condicion1_) pthread_cond_wait(&cond_x, &mutex_monitor); if (condicion2) then x.signal; if (_condicion2_) pthread_cond_signal(&cond_x); Opción 2: (utilizando while) while (condicion1) x.wait; if (condicion2) while (x.awaited > 0) x.signal; while (_condicion1_) pthread_cond_wait(&cond_x, &mutex_monitor); if (_condicion2_) pthread_cond_broadcast(&cond_x); EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 17 Implementación de monitores en POSIX Implementación: gestión de la suspensión en variables de condición Opción 1: (utilizando if) Ventajas: Cuando condicion2 es verdadero, sólo se despierta un hilo, y este, sin volver a comprobar su condicion1, pasa a ejecutar su sección crítica. Esto hace que la sobrecarga computacional sea pequeña Inconvenientes: Cuando el hilo que estaba suspendido en una variable condición se activa (la variable condición ha recibido un signal), no vuelve a comprobar el valor de la condicion1, por lo que no está seguro de estar ejecutando la sección crítica bajo las condiciones establecidas en condicion1. Esto debe asegurarse como parte de condicion2, de forma que sólo se despierten hilos cuando se cumplan sus condiciones de ejecución. Usando este modelo de programación es fácil cometer errores Opción 2: (utilizando while) Ventajas: Como cada hilo que estaba suspendido en una variable condición, comprueba la condicion1 cada vez que se despierta, el programador puede despreocuparse de las condiciones bajo las cuales ejecuta operaciones signal. Típicamente, se ejecuta pthread_cond_broadcast cada vez que condicion1 puede haber cambiado. Esto da lugar a un modelo de programación sencillo Inconvenientes: Mayor sobrecarga computacional EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 18 9

Implementación de monitores en POSIX Ejemplo: Lectores y Escritores Problema de sincronización entre procesos/hilos que se da cuando éstos quieren compartir concurrentemente un recurso representado por un objeto de datos (por ejemplo, un fichero, una base de datos, un registro de una base de datos,...) y, además, determinados procesos/hilos únicamente desean leer el contenido del objeto compartido, mientras que otros desean actualizarlo (es decir, leer y escribir) A los primeros se les denomina procesos/hilos lectores y a los segundos escritores Diferentes versiones según se dé prioridad a unos u otros en el acceso: Prioridad en la lectura: ningún lector debe esperar salvo que un escritor haya obtenido ya permiso para usar el objeto compartido. Es decir, ningún lector debe esperar a que otros lectores acaben por el simple hecho de que un escritor esté esperando. Puede originar inanición en los escritores Prioridad en la escritura: una vez que un escritor está esperando, debe realizar su escritura tan pronto como sea posible. Es decir, si un escritor está esperando, ningún lector nuevo debe iniciar su lectura. Puede generar inanición en los lectores EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 19 Implementación de monitores en POSIX Ejemplo: Lectores y Escritores Variables globales y programa principal int nlec= 0, nesc= 0; w_lec= 0; w_esc= 0; pthread_mutex_t mutex_monitor; pthread_cond_t cond_lec, cond_esc; int main(int argc, char *argv[]) { pthread_t pid_lec[n_lec], pid_esc[n_esc]; int i; int escritores= N_ESC, lectores= N_LEC; pthread_mutex_init(&mutex_monitor, NULL); pthread_cond_init(&cond_lec, NULL); pthread_cond_init(&cond_esc, NULL); for (i=0; i<escritores; i++) pthread_create(&(pid_esc[i]), NULL, func_esc, NULL); for (i=0; i<lectores; i++) pthread_create(&(pid_lec[i]), NULL, func_lec, NULL); for (i=0; i<lectores; i++) pthread_join(pid_lec[i], NULL); for (i=0; i<escritores; i++) pthread_join(pid_esc[i], NULL); EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 20 10

Implementación de monitores en POSIX Ejemplo: Lectores y Escritores Definición de los hilos Monitor void *func_esc(void * p) { int i; for (i=0; i<escriturasxhilo; i++) { pre_escribir(); escribir(); post_escribir(); void *func_lec(void * p) { int i; for (i=0; i<lecturasxhilo; i++) { pre_leer(); leer(); post_leer(); EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 21 Implementación de monitores en POSIX Ejemplo: Lectores y Escritores (versión prioridad lectores) void pre_leer() { while (nesc > 0) { w_lec++; pthread_cond_wait(&cond_lec, &mutex_monitor); w_lec -; nlec++; pthread_cond_signal(&cond_lec); void post_leer() { nlec -; if (nlec == 0) pthread_cond_signal(&cond_esc); void pre_escribir() { while ( (nesc > 0) (nlec > 0) ) { w_esc++; pthread_cond_wait(&cond_esc, &mutex_monitor); w_esc -; nesc++; void post_escribir() { nesc -; if (w_lec > 0) pthread_cond_signal(&cond_lec); else pthread_cond_signal(&cond_esc); EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 22 11

Implementación de monitores en POSIX Ejemplo: Lectores y Escritores (versión prioridad escritores) void pre_leer() { while ( (nesc > 0) (w_esc > 0) ) { w_lec++; pthread_cond_wait(&cond_lec, &mutex_monitor); w_lec -; nlec++; pthread_cond_signal(&cond_lec); void post_leer() { nlec -; if (nlec == 0) pthread_cond_signal(&cond_esc); void pre_escribir() { while ( (nesc > 0) (nlec > 0) ) { w_esc++; pthread_cond_wait(&cond_esc, &mutex_monitor); w_esc -; nesc++; void post_escribir() { nesc -; if (w_esc > 0) pthread_cond_signal(&cond_esc); else pthread_cond_signal(&cond_lec); EUI-SG/INFOR.UVA.ES ASO_PR02_20041122 23 12