-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclock.c
More file actions
169 lines (125 loc) · 3.09 KB
/
clock.c
File metadata and controls
169 lines (125 loc) · 3.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
** SCCS ID: @(#)clock.c 1.1 4/17/15
**
** File: clock.c
**
** Author: CSCI-452 class of 20145
**
** Contributor:
**
** Description: Clock module implementation
*/
#define __SP_KERNEL__
#include <x86arch.h>
#include "startup.h"
#include "clock.h"
#include "process.h"
#include "queue.h"
#include "scheduler.h"
#include "sio.h"
#include "syscall.h"
/*
** PRIVATE DEFINITIONS
*/
/*
** PRIVATE DATA TYPES
*/
/*
** PRIVATE GLOBAL VARIABLES
*/
// pinwheel control variables
static uint32_t _pinwheel; // pinwheel counter
static uint32_t _pindex; // index into pinwheel string
/*
** PUBLIC GLOBAL VARIABLES
*/
uint32_t _system_time; // the current system time
/*
** PRIVATE FUNCTIONS
*/
/*
** _clock_isr(vector,code)
**
** Interrupt handler for the clock module. Spins the pinwheel,
** wakes up sleeping processes, and handles quantum expiration
** for the current process.
*/
static void _clock_isr( int vector, int code ) {
pcb_t *pcb;
// spin the pinwheel
++_pinwheel;
if( _pinwheel == (CLOCK_FREQUENCY / 10) ) {
_pinwheel = 0;
++_pindex;
c_putchar_at( 79, 0, "|/-\\"[ _pindex & 3 ] );
}
// increment the system time
++_system_time;
/*
** wake up any sleeper whose time has come
**
** we give awakened processes preference over the
** current process (when it is scheduled again)
*/
while( !_queue_empty(_sleeping) &&
(uint32_t) _queue_kpeek(_sleeping) <= _system_time ) {
// time to wake up! remove it from the queue
pcb = (pcb_t *) _queue_remove( _sleeping );
if( pcb == NULL ) {
#ifdef DEBUG
_kpanic( "_clock_isr", "NULL from sleep queue remove" );
#else
c_puts( "*** _clock_isr: NULL from sleep queue\n" );
break;
#endif
}
// and schedule it for dispatch
_schedule( pcb );
}
// check the current process to see if it needs to be scheduled
// sanity check!
_current->quantum -= 1;
if( _current->quantum < 1 ) {
_schedule( _current );
_dispatch();
}
#ifdef DUMP_QUEUES
// Approximately every 10 seconds, dump the queues, and
// print the contents of the SIO buffers.
if( (_system_time % SECONDS_TO_TICKS(10)) == 0 ) {
c_printf( "Queue contents @%08x\n", _system_time );
_queue_dump( "ready[0]", _ready[0] );
_queue_dump( "ready[1]", _ready[1] );
_queue_dump( "ready[2]", _ready[2] );
_queue_dump( "ready[3]", _ready[3] );
_queue_dump( "sleep", _sleeping );
_sio_dump();
}
#endif
// tell the PIC we're done
__outb( PIC_MASTER_CMD_PORT, PIC_EOI );
}
/*
** PUBLIC FUNCTIONS
*/
/*
** _clock_modinit()
**
** initialize the clock module
*/
void _clock_modinit( void ) {
uint32_t divisor;
// start the pinwheel
_pinwheel = _pindex = 0;
// return to the epoch
_system_time = 0;
// set the clock to tick at CLOCK_FREQUENCY Hz.
divisor = TIMER_FREQUENCY / CLOCK_FREQUENCY;
__outb( TIMER_CONTROL_PORT, TIMER_0_LOAD | TIMER_0_SQUARE );
__outb( TIMER_0_PORT, divisor & 0xff ); // LSB of divisor
__outb( TIMER_0_PORT, (divisor >> 8) & 0xff ); // MSB of divisor
// register the ISR
__install_isr( INT_VEC_TIMER, _clock_isr );
// announce that we have initialized the clock module
c_puts( " CLOCK" );
}