1: /* This file contains the code and data for the clock task. The clock task 2: * accepts six message types: 3: * 4: * HARD_INT: a clock interrupt has occurred 5: * GET_UPTIME: get the time since boot in ticks 6: * GET_TIME: a process wants the real time in seconds 7: * SET_TIME: a process wants to set the real time in seconds 8: * SET_ALARM: a process wants to be alerted after a specified interval 9: * SET_SYNC_AL: set the sync alarm 10: * 11: * 12: * The input message is format m6. The parameters are as follows: 13: * 14: * m_type CLOCK_PROC FUNC NEW_TIME 15: * --------------------------------------------- 16: * | HARD_INT | | | | 17: * |------------+----------+---------+---------| 18: * | GET_UPTIME | | | | 19: * |------------+----------+---------+---------| 20: * | GET_TIME | | | | 21: * |------------+----------+---------+---------| 22: * | SET_TIME | | | newtime | 23: * |------------+----------+---------+---------| 24: * | SET_ALARM | proc_nr | | delta | 25: * |------------+----------+---------+---------| 26: * | SET_SYNC_AL| proc_nr | | delta | 27: * --------------------------------------------- 28: * NEW_TIME, DELTA_CLICKS, and SECONDS_LEFT all refer to the same field in 29: * the message, depending upon the message type. 30: * 31: * Reply messages are of type OK, except in the case of a HARD_INT, to 32: * which no reply is generated. For the GET_* messages the time is returned 33: * in the NEW_TIME field, and for the SET_ALARM and SET_SYNC_AL the time 34: * in seconds remaining until the alarm is returned is returned in the same 35: * field. 36: * 37: * When an alarm goes off, if the caller is a user process, a SIGALRM signal 38: * is sent to it. If it is a task, a function specified by the caller will 39: * be invoked. This function may, for example, send a message, but only if 40: * it is certain that the task will be blocked when the timer goes off. A 41: * synchronous alarm sends a message to the synchronous alarm task, which 42: * in turn can dispatch a message to another server. This is the only way 43: * to send an alarm to a server, since servers cannot use the function-call 44: * mechanism available to tasks and servers cannot receive signals. 45: */ 46: 47: #include "kernel.h" 48: #include <stddef.h> 49: #include <signal.h> 50: #include <minix/callnr.h> 51: #include <minix/com.h> 52: #include "proc.h" 53: 54: /* Constant definitions. */ 55: #define MILLISEC 100 /* how often to call the scheduler (msec) */ 56: #define SCHED_RATE (MILLISEC*HZ/1000) /* number of ticks per schedule */ 57: 58: /* Clock parameters. */ 59: #if (CHIP == INTEL) 60: #define COUNTER_FREQ (2*TIMER_FREQ) /* counter frequency using square wave */ 61: #define LATCH_COUNT 0x00 /* cc00xxxx, c = channel, x = any */ 62: #define SQUARE_WAVE 0x36 /* ccaammmb, a = access, m = mode, b = BCD */ 63: /* 11x11, 11 = LSB then MSB, x11 = sq wave */ 64: #define TIMER_COUNT ((unsigned) (TIMER_FREQ/HZ)) /* initial value for counter*/ 65: #define TIMER_FREQ 1193182L /* clock frequency for timer in PC and AT */ 66: 67: #define CLOCK_ACK_BIT 0x80 /* PS/2 clock interrupt acknowledge bit */ 68: #endif 69: 70: #if (CHIP == M68000) 71: #define TIMER_FREQ 2457600L /* timer 3 input clock frequency */ 72: #endif 73: 74: /* Clock task variables. */ 75: PRIVATE clock_t realtime; /* real time clock */ 76: PRIVATE time_t boot_time; /* time in seconds of system boot */ 77: PRIVATE timer_t *timers; /* list of active timers */ 78: PRIVATE clock_t next_timer; /* when the first timer expires */ 79: PRIVATE timer_t tmr_alarm[NR_PROCS]; /* timers for alarm(2) */ 80: 81: /* Variables changed by interrupt handler */ 82: PRIVATE clock_t pending_ticks; /* ticks seen by low level only */ 83: PRIVATE int sched_ticks = SCHED_RATE; /* counter: when 0, call scheduler */ 84: PRIVATE struct proc *prev_ptr; /* last user process run by clock task */ 85: 86: FORWARD _PROTOTYPE( void do_clocktick, (void) ); 87: FORWARD _PROTOTYPE( void do_get_time, (message *m_ptr) ); 88: FORWARD _PROTOTYPE( void do_getuptime, (message *m_ptr) ); 89: FORWARD _PROTOTYPE( void do_set_time, (message *m_ptr) ); 90: FORWARD _PROTOTYPE( void do_setalarm, (message *m_ptr, int handler, 91: tmr_func_t function) ); 92: FORWARD _PROTOTYPE( void init_clock, (void) ); 93: FORWARD _PROTOTYPE( void cause_alarm, (timer_t *tp) ); 94: FORWARD _PROTOTYPE( void cause_synalarm, (timer_t *tp) ); 95: FORWARD _PROTOTYPE( int clock_handler, (irq_hook_t *hook) ); 96: 97: /*===========================================================================* 98: * clock_task * 99: *===========================================================================*/ 100: PUBLIC void clock_task() 101: { 102: /* Main program of clock task. It corrects realtime by adding pending 103: * ticks seen only by the interrupt service, then it determines which 104: * of the 6 possible calls this is by looking at 'mc.m_type'. Then 105: * it dispatches. 106: */ 107: message mc; /* message buffer for both input and output */ 108: int opcode; 109: 110: init_clock(); /* initialize clock task */ 111: 112: /* Main loop of the clock task. Get work, process it, sometimes reply. */ 113: while (TRUE) { 114: receive(ANY, &mc); /* go get a message */ 115: opcode = mc.m_type; /* extract the function code */ 116: 117: lock(); 118: realtime += pending_ticks; /* transfer ticks from low level handler */ 119: pending_ticks = 0; /* so we don't have to worry about them */ 120: unlock(); 121: 122: switch (opcode) { 123: case HARD_INT: do_clocktick(); break; 124: case GET_UPTIME: do_getuptime(&mc); break; 125: case GET_TIME: do_get_time(&mc); break; 126: case SET_TIME: do_set_time(&mc); break; 127: case SET_ALARM: do_setalarm(&mc, CLOCK, cause_alarm); break; 128: case SET_SYNC_AL:do_setalarm(&mc, SYN_ALRM_TASK, cause_synalarm); break; 129: default: panic("clock task got bad message", mc.m_type); 130: } 131: 132: /* Send reply, except for clock tick. */ 133: mc.m_type = OK; 134: if (opcode != HARD_INT) send(mc.m_source, &mc); 135: } 136: } 137: 138: /*===========================================================================* 139: * do_clocktick * 140: *===========================================================================*/ 141: PRIVATE void do_clocktick() 142: { 143: /* Despite its name, this routine is not called on every clock tick. It 144: * is called on those clock ticks when a lot of work needs to be done. 145: */ 146: 147: register struct proc *rp; 148: register int proc_nr; 149: timer_t *tp; 150: struct proc *p; 151: 152: if (next_timer <= realtime) { 153: /* One or more timers may have expired. If so move the expired timers 154: * to the per-task expired timers list and alert the task. 155: */ 156: while ((tp = timers) != NULL && tp->tmr_exp_time <= realtime) { 157: timers = tp->tmr_next; 158: p= proc_addr(tp->tmr_task); 159: if (p->p_exptimers == NULL && p != proc_ptr) { 160: interrupt(tp->tmr_task); 161: } 162: tp->tmr_next = p->p_exptimers; 163: p->p_exptimers = tp; 164: } 165: 166: /* When does the next timer expire? */ 167: next_timer = timers == NULL ? TMR_NEVER : timers->tmr_exp_time; 168: 169: /* It's possible that one of the clock's own timers expired. */ 170: tmr_exptimers(); 171: } 172: 173: /* If a user process has been running too long, pick another one. */ 174: if (--sched_ticks == 0) { 175: if (bill_ptr == prev_ptr) lock_sched(); /* process has run too long */ 176: sched_ticks = SCHED_RATE; /* reset quantum */ 177: prev_ptr = bill_ptr; /* new previous process */ 178: } 179: } 180: 181: /*===========================================================================* 182: * tmr_settimer * 183: *===========================================================================*/ 184: PUBLIC void tmr_settimer(tp, task, exp_time, fp) 185: timer_t *tp; 186: int task; 187: clock_t exp_time; 188: tmr_func_t fp; 189: { 190: /* Activate a timer to run function 'fp' at time 'exp_time'. The timer 191: * is to be owned by the given task. (Usually the clock task, the calling 192: * task itself or the synchronous alarm task.) 193: */ 194: timer_t **atp; 195: 196: if (tp->tmr_exp_time != TMR_NEVER) tmr_clrtimer(tp); 197: tp->tmr_task = task; 198: tp->tmr_exp_time = exp_time; 199: tp->tmr_func = fp; 200: 201: /* Put the timer in the list of active timers with the first to expire in 202: * front. 203: */ 204: for (atp = &timers; *atp != NULL; atp = &(*atp)->tmr_next) { 205: if (exp_time < (*atp)->tmr_exp_time) break; 206: } 207: tp->tmr_next = *atp; 208: *atp = tp; 209: 210: /* The new timer may be the first. */ 211: next_timer = timers->tmr_exp_time; 212: } 213: 214: /*===========================================================================* 215: * tmr_clrtimer * 216: *===========================================================================*/ 217: PUBLIC void tmr_clrtimer(tp) 218: timer_t *tp; 219: { 220: /* Deactivate a timer by removing it from the active and expired lists. */ 221: timer_t **atp; 222: struct proc *p; 223: 224: tp->tmr_exp_time = TMR_NEVER; 225: 226: for (atp = &timers; *atp != NULL; atp = &(*atp)->tmr_next) { 227: if (*atp == tp) { 228: *atp = tp->tmr_next; 229: return; 230: } 231: } 232: 233: p = proc_addr(tp->tmr_task); 234: for (atp = &p->p_exptimers; *atp != NULL; atp = &(*atp)->tmr_next) { 235: if (*atp == tp) { 236: *atp = tp->tmr_next; 237: return; 238: } 239: } 240: } 241: 242: /*===========================================================================* 243: * tmr_exptimers * 244: *===========================================================================*/ 245: PUBLIC void tmr_exptimers() 246: { 247: /* One or more timers of the caller may have expired. Run the functions 248: * they reference and deactivate the timers. This function must be called 249: * by the clock task if its main timer expires, or by a task in its main 250: * loop if p_exptimers is non-NULL. 251: */ 252: timer_t *tp; 253: struct proc *p; 254: 255: p = proc_ptr; 256: 257: while ((tp = p->p_exptimers) != NULL) { 258: p->p_exptimers = tp->tmr_next; 259: tp->tmr_exp_time = TMR_NEVER; 260: (*tp->tmr_func)(tp); 261: } 262: } 263: 264: /*===========================================================================* 265: * do_getuptime * 266: *===========================================================================*/ 267: PRIVATE void do_getuptime(m_ptr) 268: message *m_ptr; /* pointer to request message */ 269: { 270: /* Get and return the current clock uptime in ticks. */ 271: 272: m_ptr->NEW_TIME = realtime; /* current uptime */ 273: } 274: 275: /*===========================================================================* 276: * get_uptime * 277: *===========================================================================*/ 278: PUBLIC clock_t get_uptime() 279: { 280: /* Get and return the current clock uptime in ticks. This function is 281: * designed to be called from other tasks, so they can get uptime without 282: * the overhead of messages. It has to be careful about pending_ticks. 283: */ 284: 285: clock_t uptime; 286: 287: lock(); 288: uptime = realtime + pending_ticks; 289: unlock(); 290: return(uptime); 291: } 292: 293: /*===========================================================================* 294: * do_get_time * 295: *===========================================================================*/ 296: PRIVATE void do_get_time(m_ptr) 297: message *m_ptr; /* pointer to request message */ 298: { 299: /* Get and return the current clock time in seconds. */ 300: 301: m_ptr->NEW_TIME = boot_time + realtime/HZ; /* current real time */ 302: } 303: 304: /*===========================================================================* 305: * do_set_time * 306: *===========================================================================*/ 307: PRIVATE void do_set_time(m_ptr) 308: message *m_ptr; /* pointer to request message */ 309: { 310: /* Set the real time clock. Only the superuser can use this call. */ 311: 312: boot_time = m_ptr->NEW_TIME - realtime/HZ; 313: } 314: 315: /*===========================================================================* 316: * do_setalarm * 317: *===========================================================================*/ 318: PRIVATE void do_setalarm(m_ptr, handler, function) 319: message *m_ptr; /* pointer to request message */ 320: int handler; /* CLOCK or SYN_ALRM_TASK */ 321: tmr_func_t function; /* cause_alarm or cause_synalarm */ 322: { 323: /* A process requests an alarm signal or a synchronous alarm. */ 324: 325: register struct proc *rp; 326: int proc_nr; /* which process wants the alarm */ 327: long delta_ticks; /* in how many clock ticks does he want it? */ 328: timer_t *tp; 329: 330: /* Extract the parameters from the message. */ 331: proc_nr = m_ptr->CLOCK_PROC_NR; /* process to interrupt later */ 332: delta_ticks = m_ptr->DELTA_TICKS; /* how many ticks to wait */ 333: 334: rp = proc_addr(proc_nr); 335: tp = &tmr_alarm[proc_nr]; 336: 337: /* Return the number of seconds left on the old timer. */ 338: if (tp->tmr_exp_time <= realtime || tp->tmr_exp_time == TMR_NEVER) { 339: m_ptr->SECONDS_LEFT = 0; 340: } else { 341: m_ptr->SECONDS_LEFT = (tp->tmr_exp_time - realtime + (HZ-1)) / HZ; 342: } 343: 344: /* Clear or set the new timer. */ 345: if (delta_ticks == 0) { 346: tmr_clrtimer(tp); 347: } else { 348: tmr_arg(tp)->ta_int = proc_nr; 349: tmr_settimer(tp, handler, get_uptime() + delta_ticks, function); 350: } 351: } 352: 353: /*===========================================================================* 354: * cause_alarm * 355: *===========================================================================*/ 356: PRIVATE void cause_alarm(tp) 357: timer_t *tp; 358: { 359: /* Routine called if a timer goes off for a process that requested an SIGALRM 360: * signal using the alarm(2) system call. The timer argument contains the 361: * process number of the process to signal. 362: */ 363: 364: cause_sig(tmr_arg(tp)->ta_int, SIGALRM); 365: } 366: 367: /*===========================================================================* 368: * cause_synalarm * 369: *===========================================================================*/ 370: PRIVATE void cause_synalarm(tp) 371: timer_t *tp; 372: { 373: /* Routine called if a timer goes off and the process requested a synchronous 374: * alarm. Send that process a CLOCK_INT message. 375: */ 376: message mess; 377: 378: mess.m_type= CLOCK_INT; 379: send(tmr_arg(tp)->ta_int, &mess); 380: } 381: 382: /*===========================================================================* 383: * syn_alrm_task * 384: *===========================================================================*/ 385: PUBLIC void syn_alrm_task() 386: { 387: /* Main program of the synchronous alarm task. 388: * All this task ever does is expire timers that call the cause_synalarm 389: * function that sends processes a CLOCK_INT message. These alarm messages 390: * are called synchronous alarms because, unlike a signals or the timers 391: * run by the CLOCK task, a synchronous alarm is received by a process 392: * when it is in a known part of its code, that is, when it has issued 393: * a call to receive a message. 394: */ 395: message mess; 396: 397: while (TRUE) { 398: tmr_exptimers(); /* send synchronous alarms */ 399: 400: receive(HARDWARE, &mess); /* wait for an interrupt */ 401: } 402: } 403: 404: /*===========================================================================* 405: * cancel_alarm * 406: *===========================================================================*/ 407: PUBLIC void cancel_alarm(proc_nr) 408: int proc_nr; /* process to cancel alarm for */ 409: { 410: /* Cancel the alarm timer of a process, probably because it has exited. */ 411: 412: tmr_clrtimer(&tmr_alarm[proc_nr]); 413: } 414: 415: /*===========================================================================* 416: * clock_handler * 417: *===========================================================================*/ 418: PRIVATE int clock_handler(hook) 419: irq_hook_t *hook; 420: { 421: /* This executes on every clock tick (i.e., every time the timer chip 422: * generates an interrupt). It does a little bit of work so the clock 423: * task does not have to be called on every tick. 424: * 425: * Switch context to do_clocktick if an alarm has gone off. 426: * Also switch there to reschedule if the reschedule will do something. 427: * This happens when 428: * (1) quantum has expired 429: * (2) current process received full quantum (as clock sampled it!) 430: * (3) something else is ready to run. 431: * Also call TTY and PRINTER and let them do whatever is necessary. 432: * 433: * Many global global and static variables are accessed here. The safety 434: * of this must be justified. Most of them are not changed here: 435: * k_reenter: 436: * This safely tells if the clock interrupt is nested. 437: * proc_ptr, bill_ptr: 438: * These are used for accounting. It does not matter if proc.c 439: * is changing them, provided they are always valid pointers, 440: * since at worst the previous process would be billed. 441: * next_timer, realtime, sched_ticks, bill_ptr, prev_ptr, 442: * rdy_head[USER_Q]: 443: * These are tested to decide whether to call interrupt(). It 444: * does not matter if the test is sometimes (rarely) backwards 445: * due to a race, since this will only delay the high-level 446: * processing by one tick, or call the high level unnecessarily. 447: * The variables which are changed require more care: 448: * rp->user_time, rp->sys_time: 449: * These are protected by explicit locks in system.c. They are 450: * not properly protected in dmp.c (the increment here is not 451: * atomic) but that hardly matters. 452: * pending_ticks: 453: * This is protected by explicit locks in clock.c. Don't 454: * update realtime directly, since there are too many 455: * references to it to guard conveniently. 456: * lost_ticks: 457: * Clock ticks counted outside the clock task. 458: * sched_ticks, prev_ptr: 459: * Updating these competes with similar code in do_clocktick(). 460: * No lock is necessary, because if bad things happen here 461: * (like sched_ticks going negative), the code in do_clocktick() 462: * will restore the variables to reasonable values, and an 463: * occasional missed or extra sched() is harmless. 464: * 465: * Are these complications worth the trouble? Well, they make the system 15% 466: * faster on a 5MHz 8088, and make task debugging much easier since there are 467: * no task switches on an inactive system. 468: */ 469: 470: register struct proc *rp; 471: register unsigned ticks; 472: clock_t now; 473: 474: if (ps_mca) { 475: /* Acknowledge the PS/2 clock interrupt. */ 476: outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT); 477: } 478: 479: /* Update user and system accounting times. 480: * First charge the current process for user time. 481: * If the current process is not the billable process (usually because it 482: * is a task), charge the billable process for system time as well. 483: * Thus the unbillable tasks' user time is the billable users' system time. 484: */ 485: if (k_reenter != 0) 486: rp = proc_addr(HARDWARE); 487: else 488: rp = proc_ptr; 489: ticks = lost_ticks + 1; 490: lost_ticks = 0; 491: rp->user_time += ticks; 492: if (rp != bill_ptr && rp != proc_addr(IDLE)) bill_ptr->sys_time += ticks; 493: 494: pending_ticks += ticks; 495: now = realtime + pending_ticks; 496: if (tty_timeout <= now) tty_wakeup(now); /* possibly wake up TTY */ 497: #if (CHIP == INTEL) && ENABLE_PRINTER 498: pr_restart(); /* possibly restart printer */ 499: #endif 500: #if (CHIP == M68000) 501: kb_timer(); /* keyboard repeat */ 502: if (sched_ticks == 1) fd_timer(); /* floppy deselect */ 503: #endif 504: 505: if (next_timer <= now 506: || (sched_ticks == 1 && bill_ptr == prev_ptr 507: && rdy_head[USER_Q] != NIL_PROC) 508: ) { 509: interrupt(CLOCK); 510: return 1; /* Reenable interrupts */ 511: } 512: 513: if (--sched_ticks == 0) { 514: /* If bill_ptr == prev_ptr, no ready users so don't need sched(). */ 515: sched_ticks = SCHED_RATE; /* reset quantum */ 516: prev_ptr = bill_ptr; /* new previous process */ 517: } 518: return 1; /* Reenable clock interrupt */ 519: } 520: 521: #if (CHIP == INTEL) 522: 523: /*===========================================================================* 524: * init_clock * 525: *===========================================================================*/ 526: PRIVATE void init_clock() 527: { 528: /* Initialize channel 0 of the 8253A timer to e.g. 60 Hz. */ 529: static irq_hook_t clock_hook; 530: 531: outb(TIMER_MODE, SQUARE_WAVE); /* set timer to run continuously */ 532: outb(TIMER0, TIMER_COUNT); /* load timer low byte */ 533: outb(TIMER0, TIMER_COUNT >> 8); /* load timer high byte */ 534: put_irq_handler(&clock_hook, CLOCK_IRQ, clock_handler);/* register handler */ 535: enable_irq(&clock_hook); /* ready for clock interrupts */ 536: } 537: 538: /*===========================================================================* 539: * clock_stop * 540: *===========================================================================*/ 541: PUBLIC void clock_stop() 542: { 543: /* Reset the clock to the BIOS rate. (For rebooting) */ 544: 545: outb(TIMER_MODE, 0x36); 546: outb(TIMER0, 0); 547: outb(TIMER0, 0); 548: } 549: 550: /*==========================================================================* 551: * micro_delay * 552: *==========================================================================*/ 553: PUBLIC void micro_delay(micros) 554: unsigned long micros; 555: { 556: /* Delay some microseconds. */ 557: struct micro_state ms; 558: 559: micro_start(&ms); 560: while (micro_elapsed(&ms) < micros) {} 561: } 562: 563: /*==========================================================================* 564: * micro_start * 565: *==========================================================================*/ 566: PUBLIC void micro_start(msp) 567: struct micro_state *msp; 568: { 569: /* Prepare for calls to micro_elapsed(). */ 570: msp->prev_count = 0; 571: msp->accum_count = 0; 572: } 573: 574: /*==========================================================================* 575: * micro_elapsed * 576: *==========================================================================*/ 577: PUBLIC unsigned long micro_elapsed(msp) 578: struct micro_state *msp; 579: { 580: /* Return the number of microseconds since the call to micro_start(). Must 581: * be polled rapidly. 582: * 583: * Micro_elapsed() is used by micro_delay() to busy wait until some 584: * number of microseconds have elapsed. Micro_elapsed() can also be 585: * used to poll a device for some time. 586: */ 587: unsigned count; 588: 589: /* Read the counter of channel 0 of the 8253A timer. This counter counts 590: * down at a rate of TIMER_FREQ and restarts at TIMER_COUNT-1 when it 591: * reaches zero. We count each tick here, unlike the main task that cares 592: * more about the HZ per second restarts. 593: */ 594: lock(); 595: outb(TIMER_MODE, LATCH_COUNT); 596: count = inb(TIMER0); 597: count |= (inb(TIMER0) << 8); 598: unlock(); 599: 600: /* Add difference between previous and new count unless the counter has 601: * increased (restarted its cycle). In that case add 1, which should be 602: * correct when polling rapidly. 603: */ 604: msp->accum_count += count <= msp->prev_count ? (msp->prev_count - count) : 1; 605: msp->prev_count = count; 606: 607: /* Return the number of microseconds counted, avoiding overflow. */ 608: if (msp->accum_count < ULONG_MAX / 1000000) { 609: /* Precise for about 3600 us. */ 610: return msp->accum_count * 1000000 / TIMER_FREQ; 611: } else { 612: /* Longer periods need not be so precise. */ 613: return msp->accum_count / TIMER_FREQ * 1000000; 614: } 615: } 616: #endif /* (CHIP == INTEL) */ 617: 618: 619: #if (CHIP == M68000) 620: #include "staddr.h" 621: #include "stmfp.h" 622: 623: /*===========================================================================* 624: * init_clock * 625: *===========================================================================*/ 626: PRIVATE void init_clock() 627: { 628: /* Initialize the timer C in the MFP 68901. 629: * Reducing to HZ is not possible by hardware. The resulting interrupt 630: * rate is further reduced by software with a factor of 4. 631: * Note that the expression below works for both HZ=50 and HZ=60. 632: */ 633: do { 634: MFP->mf_tcdr = TIMER_FREQ/(64*4*HZ); 635: } while ((MFP->mf_tcdr & 0xFF) != TIMER_FREQ/(64*4*HZ)); 636: MFP->mf_tcdcr |= (T_Q064<<4); 637: } 638: #endif /* (CHIP == M68000) */