Sistemas Operativos Control 1

2 horas

Agosto de 2000

Pregunta 1

Implemente un sistema de sincronización en base a mensajes, equivalente al del nSystem, usando Monitores. Suponga que cada thread del sistema tiene un monitor asociado, y las primitivas se usan como sigue:

val = task->monitor.Send(&value);
value_ptr = task->monitor.Receive(&task_id);
task_id->monitor.Reply(val);

Implemente el monitor con esas tres operaciones.

Monitor Messages {

condition send, reply, null;
void *msg = NULL;
int reply_msg;
nTask send_pid;

int Send(void *ptr)
{
    if( msg != NULL )
        null.wait;

    msg = ptr;
    send_pid = My_pid();
    send.signal;
    reply.wait;
    return reply_msg;
}

void *Receive(nTask *p)
{
    void *msg2;

    if( msg == NULL )
        send.wait;
    *p = send_pid;
    msg2 = msg;
    msg = NULL;
    null.signal;
    return(msg2);
}

void Reply(int val)
{
    reply_msg = val;
    reply.signal;
}
}

Pregunta 2

Se propone la siguiente solución con semáforos para múltiples productores y múltiples consumidores con un solo buffer:

Init_sem(mutex, 1);
Init_sem(vacio, 1);
Init_sem(lleno, 0);

Productor()                      Consumidor()
{                                {
    for(;;)                          for(;;)
      {                                {
        c = Producir();                  P(mutex);
        P(mutex);                        P(lleno);
        P(vacio);                        c = buffer;
        buffer = c;                      V(vacio);
        V(lleno);                        V(mutex);
        V(mutex);                        Consumir(c);
      }                                }
}                                }

Revise si está correcta, explique porqué y proponga mejoras.

No está correcto, al llamar a P(mutex) dejamos el semáforo tomado y si nos bloqueamos en vacio o lleno, nadie podrá sacarnos de ahí. En este caso, una solución eliminando mutex está correcta aunque existen múltiples productores y consumidores porque vacio y lleno van dejando pasar de a uno cada vez, nunca produciéndose el caso de tener un buffer vacío y lleno al mismo tiempo.

Pregunta 3

Quiero implementar paralelismo de alto nivel en C, para aprovechar la existencia de múltiples procesadores. Para ello quiero evaluar la invocación de una función en paralelo con su llamador hasta que el resultado sea realmente requerido. Para ello usao dos primitivas: future y touch. La primera recibe una función y sus parámetros y me retorna un ``futuro", que es donde dejará el resultado una vez que termine. Ese ``futuro" puede ser utilizado (retornado, pasado de parámetro, etc) de ahí en adelante. Sin embargo, cuando requiera conocer el resultado de la función, debe invocar touch sobre ese ``futuro". Esta invocación se queda bloqueada hasta que termine la evaluación de la función (si fuese necesario) y retorna el valor retornado por esa función. Ejemplo:

FUTURE *fut;

fut = future(f, args);
/* aqui f y este thread siguen en paralelo */
...
res = touch(fut); /* espero que termine */
/* Ahora uso res, retornado por f */

Implemente future y touch utilizando cualquier primitiva de sincronización vista en clases.

FUTURE *future(f, args)
{
    fut = (FUTURE *)malloc(sizeof (FUTURE));
    fut->key = NO_ESTA;
    fut->task = EmitTask(Wrapper, fut, f, args);
    return fut;
}

Wrapper(fut, f, args)
{
    fut->res = f(args);
    unlock(fut->key);
    Exit();
}

touch(FUTURE *fut)
{
    lock(fut->key);
    unlock(fut->key);
    return(fut->res);
}

About this document ...

Sistemas Operativos Control 1

This document was generated using the LaTeX2HTML translator Version 95 (Thu Jan 19 1995) Copyright © 1993, 1994, Nikos Drakos, Computer Based Learning Unit, University of Leeds.

The command line arguments were:
latex2html -no_navigation -split 0 -t PautaC1 pautaC1.tex.

The translation was initiated by on Tue Sep 12 12:15:08 CLT 2000


José M. Piquer
Tue Sep 12 12:15:08 CLT 2000