Beispiel #1
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);
        }
Beispiel #2
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);
        }
Beispiel #3
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);
        }