MINIX3
This presentation is the property of its rightful owner.
Sponsored Links
1 / 17

Generalidades PowerPoint PPT Presentation


  • 80 Views
  • Uploaded on
  • Presentation posted in: General

MINIX3 CLOCK TASK Cátedra: Diseño e Implementación de Sistemas Operativos UTN-FRSF Tomado de: Operating Systems Design and Implementation, Third Edition. Generalidades. Los temporizadores son esenciales en los Sistemas Operativos Mantener Fecha y Hora Time slice Timeouts Alarmas

Download Presentation

Generalidades

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Generalidades

MINIX3CLOCK TASKCátedra: Diseño e Implementación de Sistemas Operativos UTN-FRSFTomado de: Operating Systems Design and Implementation, Third Edition


Generalidades

Generalidades

  • Los temporizadores son esenciales en los Sistemas Operativos

    • Mantener Fecha y Hora

    • Time slice

    • Timeouts

    • Alarmas

    • Tareas periódicas

    • Accounting

    • Estadísticas

  • La CLOCK Task se compila en el mismo binario que el kernel y accede a todas sus variables y funciones.

  • El término correcto es TIMER

  • Se dispone de un único temporizador en Hardware por lo que hay que virtualizar en varios temporizadores por Software.


Programmable interrupt timer

Programmable Interrupt Timer

  • Dispositivo que permite generar Interrupciones en un plazo especificado.

  • Puede programarse en modo:

    • ONE SHOT: Se generará una única interrupción en un momento dado.

    • SQUARE WAVE: Se generarán interrupciones periódicas.

TIMER_FREQ 1193182 Hz


Mantener la fecha hora

Mantener la Fecha/Hora

  • Contador de 64 bits => Realizar una suma de 64 bits en cada Tick del Timer

  • Segundos y Ticks separados => Realiza una suma de 16 bits cada Tick del Timer y una de 32 bits cada segundo

  • Relativo al tiempo de booteo: Se cuentan solo los ticks desde que el sistema booteo en un contador de 32 bits. (MINIX3)


Temporizadores software

Temporizadores Software

  • Tabla de Vencimientos => Realizar un rastreo de toda la tabla en cada Tick del Timer O(n). Rápida inserción/remoción O(1).

  • Lista Ordenada por Vencimiento => Solo se decrementa el tiempo al vencimiento del primer temporizador O(1). Compleja inserción/remoción O(n).


Timeslice watchdogs

Timeslice/Watchdogs

  • Cuando se inicia un proceso, se inicializa un contador con el timeslice en Tics para ese proceso.

  • Para cada interrupción del reloj (Tick), la TIMER ISR decrementará en 1 el valor del contador.

  • Cuando este contador llegue a tener valor 0, envía un notify() a CLOCK TASK para quitar al proceso de la cabeza de la Cola de READY e insertarlo al final de ella.

  • El planificador que se encargará de poner en marcha otro proceso


Accounting

Accounting

  • Cada vez que se inicia un proceso de USUARIO se mantienen dos contadores (p_user_time, p_sys_time) para contabilizar el uso de CPU.

  • Por cada Tick se actualizan los contadores según si se ha producido una interrupción de Reloj en modo usuario o en modo kernel

    • Modo Usuario: Se incrementa p_user_time del proceso de Usuario

    • Modo Kernel: Se incrementa p_sys_time del proceso de Usuario y el p_user_time del proceso de Sistema interrumpido


Tarea de reloj

Tarea de Reloj

lost_ticks: Lleva la cuenta de ticks que pudiesen haberse perdido a causa de desactivar las interrupciones usando el MONITOR y la BIOS (no es útil).

realtime: Permite calcular la hora del día actual.

proc_ptr->p_ticks_left: Se decrementa en cada tick para controlar el cuanto de ejecución de un proceso en la CPU.

next_timeout: Esta variable registra cuando podrá ocurrir la próxima alarma.


Clock task

Clock Task

10465 /*===========================================================================*

10466 * clock_task *

10467 *===========================================================================*/

10468 PUBLIC void clock_task()

10469 {

10470 /* Main program of clock task. If the call is not HARD_INT it is an error.

10471 */

10472 message m; /* message buffer for both input and output */

10473 int result; /* result returned by the handler */

10474

10475 init_clock(); /* initialize clock task */

10476

10477 /* Main loop of the clock task. Get work, process it. Never reply. */

10478 while (TRUE) {

10479

10480 /* Go get a message. */

10481 receive(ANY, &m);

10482

10483 /* Handle the request. Only clock ticks are expected. */

10484 switch (m.m_type) {

10485 case HARD_INT:

10486 result = do_clocktick(&m); /* handle clock tick */

10487 break;

10488 default: /* illegal request type */

10489 kprintf("CLOCK: illegal request %d from %d.\n", m.m_type,m.m_source);

10490 }

10491 }


Clock task1

Clock Task

10494 /*===========================================================================*

10495 * do_clocktick *

10496 *===========================================================================*/

10497 PRIVATE int do_clocktick(m_ptr)

10498 message *m_ptr; /* pointer to request message */

10499 {

10500 /* Despite its name, this routine is not called on every clock tick. It

10501 * is called on those clock ticks when a lot of work needs to be done.

10502 */

10503

10504 /* A process used up a full quantum. The interrupt handler stored this

10505 * process in 'prev_ptr'. First make sure that the process is not on the

10506 * scheduling queues. Then announce the process ready again. Since it has

10507 * no more time left, it gets a new quantum and is inserted at the right

10508 * place in the queues. As a side-effect a new process will be scheduled.

10509 */

10510 if (prev_ptr->p_ticks_left <= 0 && priv(prev_ptr)->s_flags & PREEMPTIBLE) {

10511 lock_dequeue(prev_ptr); /* take it off the queues */

10512 lock_enqueue(prev_ptr); /* and reinsert it again */

10513 }

10514

10515 /* Check if a clock timer expired and run its watchdog function. */

10516 if (next_timeout <= realtime) {

10517 tmrs_exptimers(&clock_timers, realtime, NULL);

10518 next_timeout = clock_timers == NULL ?

10519 TMR_NEVER : clock_timers->tmr_exp_time;

10520 }

10521

10522 /* Inhibit sending a reply. */

10523 return(EDONTREPLY);

10524 }


Clock task2

Clock Task

10526 /*===========================================================================*

10527 * init_clock *

10528 *===========================================================================*/

10529 PRIVATE void init_clock()

10530 {

10531 /* Initialize the CLOCK's interrupt hook. */

10532 clock_hook.proc_nr = CLOCK;

10533

10534 /* Initialize channel 0 of the 8253A timer to, e.g., 60 Hz. */

10535 outb(TIMER_MODE, SQUARE_WAVE); /* set timer to run continuously */

10536 outb(TIMER0, TIMER_COUNT); /* load timer low byte */

10537 outb(TIMER0, TIMER_COUNT >> 8); /* load timer high byte */

10538 put_irq_handler(&clock_hook, CLOCK_IRQ, clock_handler);/* register handler */

10539 enable_irq(&clock_hook); /* ready for clock interrupts */

10540 }

10542 /*===========================================================================*

10543 * clock_stop *

10544 *===========================================================================*/

10545 PUBLIC void clock_stop()

10546 {

10547 /* Reset the clock to the BIOS rate. (For rebooting) */

10548 outb(TIMER_MODE, 0x36);

10549 outb(TIMER0, 0);

10550 outb(TIMER0, 0);

10551 }


Clock task3

Clock Task

10553 /*===========================================================================*

10554 * clock_handler *

10555 *===========================================================================*/

10556 PRIVATE int clock_handler(hook)

10557 irq_hook_t *hook;

10558 {

10559 /* This executes on each clock tick (i.e., every time the timer chip generates

10560 * an interrupt). It does a little bit of work so the clock task does not have

10561 * to be called on every tick. The clock task is called when:

10562 *

10563 * (1) the scheduling quantum of the running process has expired, or

10564 * (2) a timer has expired and the watchdog function should be run.

10565 *

10566 * Many global global and static variables are accessed here. The safety of

10567 * this must be justified. All scheduling and message passing code acquires a

10568 * lock by temporarily disabling interrupts, so no conflicts with calls from

10569 * the task level can occur. Furthermore, interrupts are not reentrant, the

10570 * interrupt handler cannot be bothered by other interrupts.

10571 *

10572 * Variables that are updated in the clock's interrupt handler:

10573 * lost_ticks:

10574 * Clock ticks counted outside the clock task. This for example

10575 * is used when the boot monitor processes a real mode interrupt.

10576 * realtime:

10577 * The current uptime is incremented with all outstanding ticks.

10578 * proc_ptr, bill_ptr:

10579 * These are used for accounting. It does not matter if proc.c

10580 * is changing them, provided they are always valid pointers,

10581 * since at worst the previous process would be billed.

10582 */


Clock task4

Clock Task

10583 register unsigned ticks;

10585 /* Acknowledge the PS/2 clock interrupt. */

10586 if (machine.ps_mca) outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT);

10588 /* Get number of ticks and update realtime. */

10589 ticks = lost_ticks + 1;

10590 lost_ticks = 0;

10591 realtime += ticks;

10592

10593 /* Update user and system accounting times. Charge the current process for

10594 * user time. If the current process is not billable, that is, if a non-user

10595 * process is running, charge the billable process for system time as well.

10596 * Thus the unbillable process' user time is the billable user's system time.

10597 */

10598 proc_ptr->p_user_time += ticks;

10599 if (priv(proc_ptr)->s_flags & PREEMPTIBLE) {

10600 proc_ptr->p_ticks_left -= ticks;

10601 }

10602 if (! (priv(proc_ptr)->s_flags & BILLABLE)) {

10603 bill_ptr->p_sys_time += ticks;

10604 bill_ptr->p_ticks_left -= ticks;

10605 }

10606

10607 /* Check if do_clocktick() must be called. Done for alarms and scheduling.

10608 * Some processes, such as the kernel tasks, cannot be preempted.

10609 */

10610 if ((next_timeout <= realtime) || (proc_ptr->p_ticks_left <= 0)) {

10611 prev_ptr = proc_ptr; /* store running process */

10612 lock_notify(HARDWARE, CLOCK); /* send notification */

10613 }

10614 return(1); /* reenable interrupts */

10615 }


Clock task5

Clock Task

10617 /*===========================================================================*

10618 * get_uptime *

10619 *===========================================================================*/

10620 PUBLIC clock_t get_uptime()

10621 {

10622 /* Get and return the current clock uptime in ticks. */

10623 return(realtime);

10624 }

10626 /*===========================================================================*

10627 * set_timer *

10628 *===========================================================================*/

10629 PUBLIC void set_timer(tp, exp_time, watchdog)

10630 struct timer *tp; /* pointer to timer structure */

10631 clock_t exp_time; /* expiration realtime */

10632 tmr_func_t watchdog; /* watchdog to be called */

10633 {

10634 /* Insert the new timer in the active timers list. Always update the

10635 * next timeout time by setting it to the front of the active list.

10636 */

10637 tmrs_settimer(&clock_timers, tp, exp_time, watchdog, NULL);

10638 next_timeout = clock_timers->tmr_exp_time;

10639 }


Clock task6

Clock Task

10641 /*===========================================================================*

10642 * reset_timer *

10643 *===========================================================================*/

10644 PUBLIC void reset_timer(tp)

10645 struct timer *tp; /* pointer to timer structure */

10646 {

10647 /* The timer pointed to by 'tp' is no longer needed. Remove it from both the

10648 * active and expired lists. Always update the next timeout time by setting

10649 * it to the front of the active list.

10650 */

10651 tmrs_clrtimer(&clock_timers, tp, NULL);

10652 next_timeout = (clock_timers == NULL) ?

10653 TMR_NEVER : clock_timers->tmr_exp_time;

10654 }

10656 /*===========================================================================*

10657 * read_clock *

10658 *===========================================================================*/

10659 PUBLIC unsigned long read_clock()

10660 {

10661 /* Read the counter of channel 0 of the 8253A timer. This counter counts

10662 * down at a rate of TIMER_FREQ and restarts at TIMER_COUNT-1 when it

10663 * reaches zero. A hardware interrupt (clock tick) occurs when the counter

10664 * gets to zero and restarts its cycle.

10665 */

10666 unsigned count;

10667

10668 outb(TIMER_MODE, LATCH_COUNT);

10669 count = inb(TIMER0);

10670 count |= (inb(TIMER0) << 8);

10672 return count;

10673 }


Synchronous alarms

Synchronous Alarms

User

Process

alarm

PM

sys_setalarm

signal

SYSTASK

set_timer

notify

CLOCK

cause_alarm

HARD_INT

CLOCK ISR


Servicios relacionados

Servicios Relacionados


  • Login