ENLACES DEL CURSO

pag_3

les recomiendo ir estudiando cada post que hago ya que asi no se perderan , trato de ser lo mas explicito ya que muchas veces nos explican algo pero de una forma que es como que no le hayan explicado entonces espero que me expresen sus problemas y plantear sus soluciones ..bueno empezemos !!!!

anteriormente habia explicado como diseñar una plantilla de los proyectos , comenzare explicando

Project 1: Threads 

2.2.2 Alarm Clock
nos pide reimplementar el timer_sleep() definido en "devices/timer.c" , pero primero se tiene que entender cual es el problema ya que !si no entendemos el problema no vamos a poder repararlo!!! .

se sabe que en un sistema multitareas se visualiza que varias aplicaciones( en este caso procesos ) se pueden ejecutar al mismo tiempo , !pero! ¿que es lo que en realidad pasa internamente en el sistema operativo.?,bueno lo que pasa es que el sistema cuenta con un timer(temporizador o reloj) el cual tiene un tiempo predeterminado para cada proceso entonces cuando un proceso se le sede el procesador entonces al transcurrir el tiempo definido para el se le expropia pero nosotros no podemos visualizar eso ya que el tiempo es tan pero tan corto que se simula como si el sistema este ejecutando varias aplicaciones(procesos) al mismo tiempo .

mas adelante estare explicacando todo el proceso de ejecucion de procesos en un sistema operativo.

pero siguiendo con el problema  en pintos el timer que esta definido en timer_sleep() no funciona de manera correcta ya que en vez de dormir el proceso por un tiempo definido y mandar a la lista de espera ,entonces este se encuentra en un bucle infinito pidiendo que se le de lugar para poder ejecutarse por lo que consume recursos del procesador !!que es lo que todos queremos evitar!! hasta que se le acaba el tiempo al thread_yield (o thread actual) entonces este puede ejecutarse.

se los planteare de otra manera supongan que ustedes tienen que esperar turno para que les den sus examenes y el maestro sea el sistema operativo, pero como estan tan ansiosos de saber su nota ustedes estan preguntando a cada momento ya me toca mi turno maestro pero como hay personas que van primero que ustedes entonces usteden tienen que espera , pero ustedes insisten y preguntan ya me toca mi turno como en un ciclo hasta que llega un momento que ya les toca su turno pero que pasa ustedes han desgastado recursos innecesarios en este caso saliba , entonces hubiera sido mejor si se vieran calmado un momento y esperar correctamente su turno y asi no se hubieran extresado , !!cierto !! entonces eso es lo que ocurre ...

entonces nuestra mision sera reparar eso !!hasta ahorita"!! a medida que vayamos avanzando el proyecto se ira poniendo mas interesante de lo normal jejeje ya saben a lo que me refiero..

bueno yo ofresco mi solucion que es esta :

que hace esta funcion :

/* Suspends execution of the calling thread until time has advanced by at least x timer ticks. Unless the system is otherwise idle, the thread need not wake up after exactly x ticks. Just put it on the ready queue after they have waited for the right amount of time.. */

/*suspende la ejecucion de un thread que fue llamado hasta un cierto tiempo por la cantidad de tiempo en ticks . a menos que el sistema este inactivo, el thread no necesita ser despertado antes del tiempo establecido en ticks . solo se pone en la cola de  procesos listos despues despues de concluir con el tiempo establecido*/

  esta funcion esta definida en "devices/timer.c"

void timer_sleep (int64_t ticks){

/* Old Implementation
int64_t start = timer_ticks (); */

ASSERT (intr_get_level () == INTR_ON);
/* Old Implementation
while (timer_elapsed (start) < ticks)
thread_yield (); */

/* My Implementation */
set_alarm (ticks);
/* == My Implementation */
}

en esta funcion tengo una funcion implementada la cual la llamo set_alarm(ticks) a la cual le mando el tiempo el cual necesito que el proceso este dormido para que de alguna manera no haga peticiones en el cual solo me consuma recursos en el procesador .. bien siguiendo con la explicacion les explicare la funcion set_alarm(ticks)

antes que todo necesitamos incluir la libreria alarm.h en dentro de timer.c debido a que la funcion que implemente la tengo definida en "alarm.c" , dentro de alarm.h esta definida la llamada del archivo alarm.c entonces no caigan en el error de definir en timer.c la llamada del archivo alarm.c ok ....

/* My Implementation */
#include "threads/alarm.h"
/* == My Implementation */

en todas las implementaciones que haga ire poniendo /*My implementation*/ y las que tenia pintos */Old implementation*/ ok siguiendo con la explicacion  set_alarm (ticks);

  set_alarm (ticks) esta funcion esta definida en alarm.c  de la siguiente manera

/* Initialize the alarm object */
void set_alarm (int64_t t){

struct thread *thrd;
struct alarm *alrm;

thrd = thread_current (); /* the current thread */

/* if t == 0 then do nothing */
if (t == 0)
return;

ASSERT (thrd->status == THREAD_RUNNING);

alrm = &thrd->alrm;

alrm->thrd = thrd;

alrm->ticks = t + timer_ticks (); /* set the tick count to t plus current timer ticks */
alrm->magic = ALARM_MAGIC;

/* add to alarm_list, critical section */
intr_disable ();
list_push_back (&alarm_list, &alrm->elem);

/* block the thread */

thread_block ();
intr_enable ();
}


esta funcion  al inicio se declara dos punteros del tipo thread y otro del tipo alarm el cual nos ayudara a manejar los espacios de memoria de cada tipo . 

tambien recibe el tiempo en el cual el thread estara dormido , si se analiza el codigo alguien se preguntara para que se usa o para que sirve la funcion ASSERT( ) ; bueno se los explicare un ASSERT en su traduccion literal significa "afirmacion" es una macro que devuelve un error en caso de fallo y finaliza el programa, Esta macro se expande como un bloque "if", en el que se comprueba la condición 'test' y, dependiendo de si es o no verdadera, puede abortar el programa. Si 'test' se evalúa como cero(es decir, si es falsa) entonces se aborta el programa mediante la función abort () y se imprime un mensaje en stderr en el que se incluyen la condición 'test'.  entonces si   ASSERT (thrd->status == THREAD_RUNNING); es verdadero entonces seguira la siguiente linea   alrm = &thrd->alrm;  el cual  alarm apunta al espacio de memoria del thread y   alrm->thrd = thrd;   alarm el atributo thrd apunta a thrd recordemos que thrd es un puntero del tipo thrd ok ... siguiendo

  alrm->ticks = t + timer_ticks (); /* set the tick count to t plus current timer ticks */ /*se establece la cantida de ticks enviados de parametros con la variable t + la cantidad actual de ticks */

/* Returns the number of timer ticks since the OS booted. */ //*retorna el numero de ticks desde el inicio del  sistema operativo */
esta funcion esta definida en timer.c

int64_t timer_ticks (void) {
enum intr_level old_level = intr_disable ();
int64_t t = ticks;
intr_set_level (old_level);
barrier ();
return t;
}

 alrm->magic = ALARM_MAGIC;  este es un atributo que tiene el objeto alarm por lo cual pintos trae definido un valor como se muestra aqui :

#define ALARM_MAGIC 0x67452301 /* magic number for ALARM_MAGIC */

esta funcion esta definida en thread.c
thread_block ();

/* Puts the current thread to sleep. It will not be scheduled
again until awoken by thread_unblock().

This function must be called with interrupts turned off. It
is usually a better idea to use one of the synchronization
primitives in synch.h. */

void
thread_block (void)
{
ASSERT (!intr_context ());
ASSERT (intr_get_level () == INTR_OFF);

thread_current ()->status = THREAD_BLOCKED;
schedule ();
}

esta es una de las partes mas importante en esta funcion , desabilitamos las interrupciones pero ¿ por que ? o mejor dicho que es una interrupcion ?
Una petición de interrupción IRQ ("Interrupt Request") es una señal que se origina en un dispositivo hardware (por ejemplo, un periférico), para indicar al procesador que algo requiere su atención inmediata. pero en este caso las desactivamos debido a que queremos asignarle un tiempo de espera para luego ser ejecutado capich ... luego establecemos en la lista de alarma un elemento de alarma ..

 /* add to alarm_list, critical section */
intr_disable ();
  list_push_back (&alarm_list, &alrm->elem);
/* block the thread */


intr_enable ();
esta funcion esta definida en interrup.c

/* Enables interrupts and returns the previous interrupt status. */ /*Habilita las interrupciones y devuelve el estado de interrupción anterior*/

enum intr_level
intr_enable (void)
{
enum intr_level old_level = intr_get_level ();
ASSERT (!intr_context ());

  /* Enable interrupts by setting the interrupt flag.
 See [IA32-v2b] "STI" and [IA32-v3a] 5.8.1 "Masking Maskable
Hardware Interrupts". */

asm volatile ("sti");

return old_level;
}

ahora ya explique la funcion pero debemos implementarla
dentro de la funcion timer_sleep(); en timer.c

/* Sleeps for approximately TICKS timer ticks. Interrupts must
be turned on. */
void
timer_sleep (int64_t ticks)
{
/* Old Implementation
int64_t start = timer_ticks (); */

ASSERT (intr_get_level () == INTR_ON);
/* Old Implementation
while (timer_elapsed (start) < ticks)
thread_yield (); */

/* My Implementation */
set_alarm (ticks);
/* == My Implementation */
}

 timer_sleep(int64 ticks_t ticks) recibe de parametros los ticks estos estan establecidos en la funcion

/* Sleep for approximately NUM/DENOM seconds. */
static void
real_time_sleep (int64_t num, int32_t denom)
{
/* Convert NUM/DENOM seconds into timer ticks, rounding down.

(NUM / DENOM) s
---------------------- = NUM * TIMER_FREQ / DENOM ticks.
1 s / TIMER_FREQ ticks
*/
int64_t ticks = num * TIMER_FREQ / denom;

ASSERT (intr_get_level () == INTR_ON);
if (ticks > 0)
{
/* We're waiting for at least one full timer tick. Use
timer_sleep() because it will yield the CPU to other
processes. */
timer_sleep (ticks);
}
else
{
/* Otherwise, use a busy-wait loop for more accurate
sub-tick timing. */
real_time_delay (num, denom);
}
}

bueno con esto concluyo con 2.2.2 Alarm Clock del proyecto  2. Project 1: Threads
http://www.scs.stanford.edu/10wi-cs140/pintos/pintos_2.html#SEC27

CAPICH ......