Exemplo n.º 1
0
        private void EnviarAMemoriaBloqueVSiModificado(BloqueCacheDatos bloqueV)
        {
            if (bloqueV.Estado != EstadosB.Invalido)
            {
                Directorio directorioBloqueV = bloqueV.Directorio;

                // Bloqueo directorio de BloqueV
                directorioBloqueV.Bloquear(this.Nombre);
                bloqueados.Add(directorioBloqueV);

                // Se pregunta si el bloque a reemplazar en mi cache está modificado
                if (bloqueV.Estado == EstadosB.Modificado)
                {
                    // Envio el bloque a memoria
                    // Este método modifica tanto la cache como el directorio (U en directorio e I en Cache)
                    bloqueV.EnviarAMemoria();
                }
                else
                {
                    bloqueV.Invalidar();
                }

                // Desbloqueo el directorio del BloqueV
                directorioBloqueV.Desbloquear(this.Nombre);
                bloqueados.Remove(directorioBloqueV);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Trae un bloque de memoria o desde otra cache
        /// </summary>
        /// <param name="bloque">Bloque</param>
        /// <param name="controlador">Controlador</param>
        /// <param name="cache">Cache dueña del bloque</param>
        /// <param name="vieneDeMemoria">Indica si viene de memoria (true) o de otra cache (false)</param>
        public static BloqueCacheDatos TraerBloqueCacheDatos(Bloque bloque, Controlador controlador, CacheDatos cache, bool vieneDeMemoria)
        {
            // Se copian los datos del bloque
            BloqueCacheDatos bloqueCache = new BloqueCacheDatos(controlador, cache);

            bloqueCache.id = bloque.ID;
            bloqueCache.direccionInicial       = bloque.Direccion;
            bloqueCache.indiceMemoriaPrincipal = bloque.IndiceMemoriaPrincipal;
            for (int i = 0; i < PalabrasPorBloque; ++i)
            {
                bloqueCache.palabras[i] = bloque[i];
            }

            // Asigna el controlador y la cache
            bloqueCache.controlador = controlador;
            bloqueCache.cache       = cache;

            Debug.Assert(cache.EstaBloqueado());
            Debug.Assert(bloqueCache.Directorio.EstaBloqueado());

            // Se espera que el bloque venga de memoria
            bloqueCache.EsperarTraida(vieneDeMemoria);

            // Se pone el bloque como compartido
            bloqueCache.estado = EstadosB.Compartido;

            // Me pongo en la cache
            cache[bloqueCache.IndiceCache] = bloqueCache;

            // Se refleja el cambio en el directorio
            // Se pone como compartido en el directorio
            bloqueCache.Directorio.AgregarUsuarioBloque(cache, bloqueCache);

            return(bloqueCache);
        }
Exemplo n.º 3
0
        public void ModificarBloque(CacheDatos solicitante, BloqueCacheDatos bloque)
        {
            Esperar(solicitante);

            Debug.Assert(EstaBloqueado());
            Debug.Assert(usuarios[bloque.IndiceMemoriaPrincipal].Count == 1);

            Estados[bloque.IndiceMemoriaPrincipal] = EstadosD.Modificado;
        }
Exemplo n.º 4
0
        /// <summary>
        /// Se elimina cache de la lista respectiva
        /// </summary>
        /// <param name="solicitante">Cache de datos que ya no es usuaria del bloqueMemoria</param>
        /// <param name="bloqueMemoria">Bloque ya no utilizado</param>
        public void EliminarUsuarioBloque(CacheDatos solicitante, BloqueCacheDatos bloque)
        {
            Esperar(solicitante);

            Debug.Assert(EstaBloqueado());
            Debug.Assert(usuarios[bloque.IndiceMemoriaPrincipal].Contains(solicitante.ID));
            Debug.Assert(bloque.ID == this.id);

            usuarios[bloque.IndiceMemoriaPrincipal].Remove(solicitante.ID);
            if (usuarios[bloque.IndiceMemoriaPrincipal].Count == 0)
            {
                estados[bloque.IndiceMemoriaPrincipal] = EstadosD.Uncached;
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Agrega una cache como usuaria de un bloque. Siempre se agregan los bloques en C.
        /// </summary>
        /// <param name="solicitante">Cache de datos usuaria del bloqueMemoria</param>
        /// <param name="bloqueMemoria">Bloque siendo utilizado</param>
        public void AgregarUsuarioBloque(CacheDatos solicitante, BloqueCacheDatos bloque)
        {
            Esperar(solicitante);

            // Debido a la implementación los bloques siempre se agregan como compartidos al directorio
            // Si la cache los modifica, luego llama al método de ModificarBloque del directorio
            Debug.Assert(EstaBloqueado());
            Debug.Assert(estados[bloque.IndiceMemoriaPrincipal] != EstadosD.Modificado);
            Debug.Assert(bloque.Estado != EstadosB.Modificado);
            Debug.Assert(!usuarios[bloque.IndiceMemoriaPrincipal].Contains(solicitante.ID));
            Debug.Assert(bloque.ID == this.id);
            Debug.Assert(solicitante[bloque.IndiceCache].Direccion == bloque.Direccion);

            usuarios[bloque.IndiceMemoriaPrincipal].Add(solicitante.ID);
            estados[bloque.IndiceMemoriaPrincipal] = EstadosD.Compartido;
        }
Exemplo n.º 6
0
        /// <summary>
        /// Se invalida el bloqueMemoria en todas las cachés que lo usen
        /// </summary>
        /// <param name="solicitante">Cache de Datos solicitante</param>
        /// <param name="bloqueMemoria">Bloque para obtener la dirección</param>
        public void InvalidarBloque(CacheDatos solicitante, Bloque bloque)
        {
            Esperar(solicitante);

            // Solo se puede invalidar un bloqueMemoria si alguien lo está compartiendo
            Debug.Assert(EstaBloqueado());
            Debug.Assert(estados[bloque.IndiceMemoriaPrincipal] == EstadosD.Compartido);
            Debug.WriteLine("Cache " + solicitante.ID + ": Invalidando a quienes comparten el bloque " + bloque.Direccion);

            //Obtengo quienes son las caches que tienen bloqueN compartido
            List <int> lectores = usuarios[bloque.IndiceMemoriaPrincipal];

            // Creo una copia de la lista de lectores sin la cache solicitante
            // Si es que se encuentra
            List <int> tmp = new List <int>(lectores);

            tmp.Remove(solicitante.ID);

            // TODO Mejorar este código para que reintente sobre las caches
            // Mientras no falle consecutivamente en todas
            foreach (int id in tmp)
            {
                CacheDatos cache = controlador.CachesDatos[id];

                // Bloqueo la cache
                cache.Bloquear(this.Nombre);

                BloqueCacheDatos bloqueCache = cache[bloque.IndiceCache];

                Debug.Assert(bloqueCache.Direccion == bloque.Direccion);

                // Invalido el bloque
                bloqueCache.Invalidar();

                // Debloqueo la cache
                cache.Desbloquear(this.Nombre);
            }

            // O no hay nadie compartiendo el bloque o la solicitante es la unica que lo comparte
            Debug.Assert(lectores.Count == 0 || lectores[0] == solicitante.ID && lectores.Count == 1);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Método que realmente se encarga de ejecutar la lógica de leer una palabra.
        /// Si no puede bloquear algo, tira una excepción del tipo RebootNeededException.
        /// </summary>
        /// <param name="info">Información de la palabra que se quiere leer</param>
        /// <returns>Palabra que se quiere leer</returns>
        private int Leer(InformacionPalabra info)
        {
            int palabraLeida = -1;

            // Se bloquea la cache
            this.Bloquear(this.Nombre);
            bloqueados.Add(this);

            // Se pregunta si es Hit
            if (!info.EsHit())
            {
                // Se envia el bloqueV a memoria si está modificado
                EnviarAMemoriaBloqueVSiModificado(this[info.IndiceCache]);

                // Bloqueo el directorio que contiene la palabra que busco
                info.Directorio.Bloquear(this.Nombre);
                bloqueados.Add(info.Directorio);

                // Consulto el directorio del bloqueMemoria que contiene la palabra que busco
                // para ver si alguna cache lo tiene modificado
                CacheDatos modificante = info.Directorio.GetUsuarioQueModifica(this, info.Bloque);

                if (modificante == null)
                {
                    // Traigo el bloqueMemoria de memoria
                    BloqueCacheDatos.TraerBloqueCacheDatos(info.Bloque, controlador, this, true);
                }
                else
                {
                    // Bloqueo la cache que modificó el dato
                    modificante.Bloquear(this.Nombre);
                    bloqueados.Add(modificante);

                    // Se envía el bloque en la cache modificante a memoria
                    modificante[info.IndiceCache].EnviarAMemoria();

                    // Se actualiza la información del bloque con lo último de memoria
                    info.ActualizarBloque();

                    // Traigo el dato de la cache modificante
                    BloqueCacheDatos.TraerBloqueCacheDatos(info.Bloque, controlador, this, false);

                    // Desbloqueo la cache que modificó el dato
                    modificante.Desbloquear(this.Nombre);
                    bloqueados.Remove(modificante);
                }

                // Desbloqueo el directorio
                info.Directorio.Desbloquear(this.Nombre);
                bloqueados.Remove(info.Directorio);
            }

            // Leo la palabra
            palabraLeida = this[info.IndiceCache][info.IndicePalabra];

            // Desbloqueo la cache
            this.Desbloquear(this.Nombre);
            bloqueados.Remove(this);

            // Devuelvo la palabra leída
            return(palabraLeida);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Método que escribe una palabra en una dirección de memoria
        /// </summary>
        /// <param name="info">Guarda información de donde debe escribirse la palabra</param>
        /// <param name="palabra">Palabra que se quiere escribir</param>
        public void Escribir(InformacionPalabra info, int palabra)
        {
            //Se bloquea mi cache
            this.Bloquear(this.Nombre);
            bloqueados.Add(this);

            // Si es hit
            if (info.EsHit())
            {
                BloqueCacheDatos bloqueN = this[info.IndiceCache];

                if (bloqueN.Estado == EstadosB.Modificado)
                {
                    // Si está en mi cache modificado nada más lo escribo
                    bloqueN[info.IndicePalabra] = palabra;
                    bloqueN.Estado = EstadosB.Modificado;
                }
                else
                {
                    // Si lo tengo compartido, bloqueo el directorio correspondiente
                    info.Directorio.Bloquear(this.Nombre);
                    bloqueados.Add(info.Directorio);

                    // Invalido a todos quienes compartan el bloque
                    info.Directorio.InvalidarBloque(this, info.Bloque);

                    // Escribo la palabra
                    bloqueN[info.IndicePalabra] = palabra;
                    bloqueN.Estado = EstadosB.Modificado;
                    info.Directorio.ModificarBloque(this, bloqueN);

                    // Desbloqueo el directorio
                    info.Directorio.Desbloquear(this.Nombre);
                    bloqueados.Remove(info.Directorio);
                }
            }
            else
            {
                // Se envia el bloqueV a memoria si está modificado
                EnviarAMemoriaBloqueVSiModificado(this[info.IndiceCache]);

                // Bloqueo el directorio que contiene la palabra que busco
                info.Directorio.Bloquear(this.Nombre);
                bloqueados.Add(info.Directorio);

                // Consulto el directorio del bloqueMemoria que contiene la palabra que busco
                // para ver si alguna cache lo tiene modificado
                CacheDatos modificante = info.Directorio.GetUsuarioQueModifica(this, info.Bloque);

                if (modificante == null)    //Si no hay nadie que esté modificando en bloque

                {
                    if (info.Directorio.CountUsuariosQueComparten(this, info.Bloque) > 0)
                    {
                        //Se les invalida el BloqueN a todas las caches que lo tengan compartido
                        info.Directorio.InvalidarBloque(this, info.Bloque);
                    }

                    // Traigo el bloqueMemoria de memoria
                    // El constructor pone el bloque en la cache
                    BloqueCacheDatos.TraerBloqueCacheDatos(info.Bloque, controlador, this, true);
                }
                else
                {
                    // Bloqueo la cache que modificó el dato
                    modificante.Bloquear(this.Nombre);
                    bloqueados.Add(modificante);

                    // Se envía el bloque en la cache modificante a memoria
                    modificante[info.IndiceCache].EnviarAMemoria();

                    // Se actualiza la información del bloque
                    info.ActualizarBloque();

                    // Traigo el dato desde la cache modificante
                    BloqueCacheDatos.TraerBloqueCacheDatos(info.Bloque, controlador, this, false);

                    // Desbloqueo la cache que modificó el dato
                    modificante.Desbloquear(this.Nombre);
                    bloqueados.Remove(modificante);
                }

                // Escribo la palabra
                this[info.IndiceCache][info.IndicePalabra] = palabra;
                this[info.IndiceCache].Estado = EstadosB.Modificado;
                this[info.IndiceCache].Directorio.ModificarBloque(this, this[info.IndiceCache]);

                // Desbloqueo el directorio
                info.Directorio.Desbloquear(this.Nombre);
                bloqueados.Remove(info.Directorio);
            }

            // Desbloqueo mi cache
            this.Desbloquear(this.Nombre);
            bloqueados.Remove(this);
        }