/// <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); }
/// <summary> /// Crea los bloques de la memoriaPrincipal memoriaPrincipal. /// Se inicializa en ceros /// </summary> public MemoriaPrincipal(Controlador controlador, int id) { this.id = id; for (int i = 0; i < BloquesPorMemoria; ++i) { bloques[i] = new Bloque(id, id * BytesPorMemoria + i * BytesPorBloque, i); } }
/// <summary> /// Constrctor por copia para los hijos /// </summary> /// <param name="bloqueMemoria">Bloque a copiar</param> protected Bloque(Bloque bloque) { this.id = bloque.id; this.direccionInicial = bloque.direccionInicial; this.indiceMemoriaPrincipal = bloque.indiceMemoriaPrincipal; for (int i = 0; i < PalabrasPorBloque; i++) { this.palabras[i] = bloque.palabras[i]; } }
/// <summary> /// Método que devuelve cuantos usuarios comparten un bloque menos yo /// </summary> /// <param name="bloqueMemoria">Bloque para obtener el índice de memoria principal</param> /// <returns>Lista de Caches que comparten el bloqueMemoria</returns> public int CountUsuariosQueComparten(CacheDatos solicitante, Bloque bloque) { Esperar(solicitante); Debug.Assert(EstaBloqueado()); List <int> tmp = new List <int>(usuarios[bloque.IndiceMemoriaPrincipal]); tmp.Remove(solicitante.ID); return(tmp.Count); }
/// <summary> /// Método que devuelve la cache que modificó un bloqueMemoria. /// Devuelve null si nadie ha modificado el bloqueMemoria. /// </summary> /// <param name="solicitante">Solicitante del cambio</param> /// <param name="bloqueMemoria">Bloque para obtener el id</param> /// <returns>Cache que modificó una palabra del bloqueMemoria</returns> public CacheDatos GetUsuarioQueModifica(CacheDatos solicitante, Bloque bloque) { Esperar(solicitante); Debug.Assert(EstaBloqueado()); CacheDatos cache = null; int indice = bloque.IndiceMemoriaPrincipal; if (estados[indice] == EstadosD.Modificado && usuarios[indice].Count == 1) { cache = controlador.CachesDatos[usuarios[indice][0]]; } return(cache); }
/// <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> /// Actualiza la información del bloque con lo último que se tiene desde memoria principal /// </summary> public void ActualizarBloque() { this.bloqueMemoria = controlador.MemoriasPrincipales[id][indiceBloqueMemoria]; }