/// <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); }
/// <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); }
/// <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); }