1 /*
2 * linux/kernel/sched.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * 'sched.c' is the main kernel file. It contains scheduling primitives
9 * (sleep_on, wakeup, schedule etc) as well as a number of simple system
10 * call functions (type getpid(), which just extracts a field from
11 * current-task
12 */
/*
* 'sched.c'����Ҫ���ں��ļ������а����йص��ȵĻ�������(sleep_on��wakeup��schedule��)
* �Լ�һЩ��ϵͳ���ú���������getpid()�����ӵ�ǰ�����л�ȡһ���ֶΣ���
*/
// �����ǵ��ȳ���ͷ�ļ�������������ṹtask_struct����1����ʼ��������ݡ�����һЩ�Ժ�
// ����ʽ������й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������
13 #include <linux/sched.h>
14 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
15 #include <linux/sys.h> // ϵͳ����ͷ�ļ�������82��ϵͳ����C��������,��'sys_'��ͷ��
16 #include <linux/fdreg.h> // ����ͷ�ļ����������̿�����������һЩ���塣
17 #include <asm/system.h> // ϵͳͷ�ļ������������û���������/�ж��ŵȵ�Ƕ��ʽ���ꡣ
18 #include <asm/io.h> // ioͷ�ļ�������Ӳ���˿�����/���������䡣
19 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
20
21 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ų�����sigaction�ṹ����������ԭ�͡�
22
// �ú�ȡ�ź�nr���ź�λͼ�ж�Ӧλ�Ķ�������ֵ���źű��1-32�������ź�5��λͼ��ֵ����
// 1<<(5-1) = 16 = 00010000b��
23 #define _S(nr) (1<<((nr)-1))
// ����SIGKILL��SIGSTOP�ź����������źŶ��ǿ�������(��1011,1111,1110,1111,1111b)��
24 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
25
// �ں˵��Ժ�������ʾ�����nr�Ľ��̺š�����״̬���ں˶�ջ�����ֽ�������Լ����
26 void show_task(int nr,struct task_struct * p)
27 {
28 int i,j = 4096-sizeof(struct task_struct);
29
30 printk("%d: pid=%d, state=%d, father=%d, child=%d, ",nr,p->pid,
31 p->state, p->p_pptr->pid, p->p_cptr ? p->p_cptr->pid : -1);
32 i=0;
33 while (i<j && !((char *)(p+1))[i]) // ���ָ���������ݽṹ�Ժ����0���ֽ�����
34 i++;
35 printk("%d/%d chars free in kstack\n\r",i,j);
36 printk(" PC=%08X.", *(1019 + (unsigned long *) p));
37 if (p->p_ysptr || p->p_osptr)
38 printk(" Younger sib=%d, older sib=%d\n\r",
39 p->p_ysptr ? p->p_ysptr->pid : -1,
40 p->p_osptr ? p->p_osptr->pid : -1);
41 else
42 printk("\n\r");
43 }
44
// ��ʾ�������������š����̺š�����״̬���ں˶�ջ�����ֽ�������Լ����
// NR_TASKS��ϵͳ�����ɵ�������(����)����(64��)��������include/kernel/sched.h ��6�С�
45 void show_state(void)
46 {
47 int i;
48
49 printk("\rTask-info:\n\r");
50 for (i=0;i<NR_TASKS;i++)
51 if (task[i])
52 show_task(i,task[i]);
53 }
54
// PC��8253��ʱоƬ������ʱ��Ƶ��ԼΪ1.193180MHz��Linux�ں�ϣ����ʱ�������жϵ�Ƶ����
// 100Hz��Ҳ��ÿ10ms����һ��ʱ���жϡ��������LATCH������8253оƬ�ij�ֵ���μ�438�С�
55 #define LATCH (1193180/HZ)
56
57 extern void mem_use(void); // [??]û���κεط���������øú�����
58
59 extern int timer_interrupt(void); // ʱ���жϴ�������kernel/system_call.s��176����
60 extern int system_call(void); // ϵͳ�����жϴ�������kernel/system_call.s��80����
61
// ÿ�������̣����ں�̬����ʱ�����Լ����ں�̬��ջ�����ﶨ����������ں�̬��ջ�ṹ��
// ���ﶨ���������ϣ�����ṹ��Ա��stack�ַ������Ա������Ϊһ����������ݽṹ�����ں�
// ̬��ջ����ͬһ�ڴ�ҳ�У����ԴӶ�ջ�μĴ���ss���Ի�������ݶ�ѡ�����
62 union task_union {
63 struct task_struct task;
64 char stack[PAGE_SIZE];
65 };
66
// ���ó�ʼ��������ݡ���ʼ������include/kernel/sched.h�У���156�п�ʼ��
67 static union task_union init_task = {INIT_TASK,};
68
// �ӿ�����ʼ����ĵδ���ʱ��ֵȫ�ֱ�����10ms/�δ𣩡�ϵͳʱ���ж�ÿ����һ�μ�һ���δ�
// ǰ������� volatile��Ӣ�Ľ������ı�ġ����ȶ�����˼��������ʵĺ������������
// ָ�����������ݿ��ܻ����ڱ����������Ķ��仯��ͨ���ڳ���������һ������ʱ�� ��������
// �������������ͨ�üĴ����У����� ebx������߷���Ч�ʡ���CPU����ֵ�ŵ� ebx�к�һ��
// �Ͳ����ٹ��ĸñ�����Ӧ�ڴ�λ���е����ݡ�����ʱ�������������ں˳����һ���жϹ��̣�
// �����ڴ��иñ�����ֵ��ebx�е�ֵ��������֮���¡�Ϊ�˽����������ʹ�����volatile
// �������ô��������øñ���ʱһ��Ҫ��ָ���ڴ�λ����ȡ����ֵ�����T��Ҫ�� gcc��Ҫ��
// jiffies �����Ż�������Ҳ��ҪŲ��λ�ã�������Ҫ���ڴ���ȡ��ֵ����Ϊʱ���жϴ�������
// �ȳ����������ֵ��
69 unsigned long volatile jiffies=0;
70 unsigned long startup_time=0; // ����ʱ�䡣��1970:0:0:0��ʼ��ʱ��������
// ������������ۼ���Ҫ������ʱ���������
71 int jiffies_offset = 0; /* # clock ticks to add to get "true
72 time". Should always be less than
73 1 second's worth. For time fanatics
74 who like to syncronize their machines
75 to WWV :-) */
/* Ϊ����ʱ�Ӷ���Ҫ���ӵ�ʱ����������Ի�á���ȷʱ�䡱����Щ�����������
* ���ܺͲ�Ӧ�ó���1�롣��������Ϊ����Щ��ʱ�侫ȷ��Ҫ����̵��ˣ�����ϲ
* ���Լ��Ļ���ʱ����WWVͬ�� :-)
*/
76
77 struct task_struct *current = &(init_task.task); // ��ǰ����ָ�루��ʼ��ָ������0����
78 struct task_struct *last_task_used_math = NULL; // ʹ�ù�Э�����������ָ�롣
79
// ��������ָ�����顣��1���ʼ��ָ���ʼ��������0�����������ݽṹ��
80 struct task_struct * task[NR_TASKS] = {&(init_task.task), };
81
// �����û���ջ����1K�����4K�ֽڡ����ں˳�ʼ�����������б������ں�ջ����ʼ�����
// �Ժ���������0���û�̬��ջ������������0֮ǰ�����ں�ջ���Ժ���������0��1����
// ��̬ջ������ṹ�������ö�ջss:esp�����ݶ�ѡ�����ָ�룩����head.s����23�С�
// ss������Ϊ�ں����ݶ�ѡ�����0x10����ָ��espָ�� user_stack�������һ����档����
// ��ΪIntel CPUִ�ж�ջ����ʱ���ȵݼ���ջָ��spֵ��Ȼ����spָ�봦������ջ���ݡ�
82 long user_stack [ PAGE_SIZE>>2 ] ;
83
84 struct {
85 long * a;
86 short b;
87 } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };
88 /*
89 * 'math_state_restore()' saves the current math information in the
90 * old math state array, and gets the new ones from the current task
91 */
/*
* ����ǰЭ���������ݱ��浽��Э������״̬�����У�������ǰ�����Э������
* ���ݼ��ؽ�Э��������
*/
// �������Ƚ������Ժú������Ա���ԭ�����Э������״̬�������ģ����ָ��µ��Ƚ�
// ���ĵ�ǰ�����Э������ִ��״̬��
92 void math_state_restore()
93 {
// �������û����(��һ��������ǵ�ǰ����)������"��һ������"��ָ�ձ�������ȥ������
94 if (last_task_used_math == current)
95 return;
// �ڷ���Э����������֮ǰҪ�ȷ�WAITָ�����ϸ�����ʹ����Э������������״̬��
96 __asm__("fwait");
97 if (last_task_used_math) {
98 __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
99 }
// ���ڣ�last_task_used_mathָ��ǰ�����Ա���ǰ��������ȥʱʹ�á���ʱ�����ǰ
// �����ù�Э����������ָ���״̬������Ļ�˵���ǵ�һ��ʹ�ã����Ǿ���Э����������ʼ��
// ���������ʹ����Э��������־��
100 last_task_used_math=current;
101 if (current->used_math) {
102 __asm__("frstor %0"::"m" (current->tss.i387));
103 } else {
104 __asm__("fninit"::); // ��Э����������ʼ�����
105 current->used_math=1; // ����ʹ����Э��������־��
106 }
107 }
108
109 /*
110 * 'schedule()' is the scheduler function. This is GOOD CODE! There
111 * probably won't be any reason to change this, as it should work well
112 * in all circumstances (ie gives IO-bound processes good response etc).
113 * The one thing you might take a look at is the signal-handler code here.
114 *
115 * NOTE!! Task 0 is the 'idle' task, which gets called when no other
116 * tasks can run. It can not be killed, and it cannot sleep. The 'state'
117 * information in task[0] is never used.
118 */
/*
* 'schedule()'�ǵ��Ⱥ��������Ǹ��ܺõĴ��룡û���κ����ɶ��������ģ���Ϊ
* �����������еĻ����¹����������ܹ���IO-�߽紦���ܺõ���Ӧ�ȣ���ֻ��һ��
* ��ֵ�����⣬�Ǿ���������źŴ������롣
*
* ע�⣡������0�Ǹ�����('idle')����ֻ�е�û�����������������ʱ�ŵ���
* ���������ܱ�ɱ����Ҳ����˯�ߡ�����0�е�״̬��Ϣ'state'�Ǵ������õġ�
*/
119 void schedule(void)
120 {
121 int i,next,c;
122 struct task_struct ** p; // ����ṹָ���ָ�롣
123
124 /* check alarm, wake up any interruptible tasks that have got a signal */
/* ���alarm�����̵ı�����ʱֵ���������κ��ѵõ��źŵĿ��ж����� */
125
// ���������������һ������ʼѭ�����alarm����ѭ��ʱ������ָ���
126 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
127 if (*p) {
// ������ù�����ʱ��ʱtimeout�������Ѿ���ʱ����λ��ʱ��ʱֵ��������������ڿ�
// �ж�˯��״̬TASK_INTERRUPTIBLE�£�������Ϊ����״̬��TASK_RUNNING����
128 if ((*p)->timeout && (*p)->timeout < jiffies) {
129 (*p)->timeout = 0;
130 if ((*p)->state == TASK_INTERRUPTIBLE)
131 (*p)->state = TASK_RUNNING;
132 }
// ������ù�����Ķ�ʱֵalarm�������Ѿ�����(alarm<jiffies),�����ź�λͼ����SIGALRM
// �źţ�����������SIGALARM�źš�Ȼ����alarm�����źŵ�Ĭ�ϲ�������ֹ���̡�jiffies
// ��ϵͳ�ӿ�����ʼ����ĵδ�����10ms/�δ𣩡�������sched.h��139�С�
133 if ((*p)->alarm && (*p)->alarm < jiffies) {
134 (*p)->signal |= (1<<(SIGALRM-1));
135 (*p)->alarm = 0;
136 }
// ����ź�λͼ�г����������ź���������źţ����������ڿ��ж�״̬����������Ϊ����
// ״̬������'~(_BLOCKABLE & (*p)->blocked)'���ں��Ա��������źţ���SIGKILL��SIGSTOP
// ���ܱ�������
137 if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
138 (*p)->state==TASK_INTERRUPTIBLE)
139 (*p)->state=TASK_RUNNING; //��Ϊ��������ִ�У�״̬��
140 }
141
142 /* this is the scheduler proper: */
/* �����ǵ��ȳ������Ҫ���� */
143
144 while (1) {
145 c = -1;
146 next = 0;
147 i = NR_TASKS;
148 p = &task[NR_TASKS];
// ��δ���Ҳ�Ǵ�������������һ������ʼѭ���������������������������ۡ��Ƚ�ÿ��
// ����״̬�����counter����������ʱ��ĵݼ��δ������ֵ����һ��ֵ������ʱ�仹������
// next��ָ���ĸ�������š�
149 while (--i) {
150 if (!*--p)
151 continue;
152 if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
153 c = (*p)->counter, next = i;
154 }
// ����Ƚϵó���counterֵ������0�Ľ��������ϵͳ��û��һ�������е�������ڣ���ʱc
// ��ȻΪ-1��next=0�������˳�144�п�ʼ��ѭ����ִ��161���ϵ������л��������������
// ÿ�����������Ȩֵ������ÿһ�������counterֵ��Ȼ��ص�125�����±Ƚϡ�counter ֵ
// �ļ��㷽ʽΪ counter = counter /2 + priority��ע�⣬���������̲����ǽ��̵�״̬��
155 if (c) break;
156 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
157 if (*p)
158 (*p)->counter = ((*p)->counter >> 1) +
159 (*p)->priority;
160 }
// ������꣨������sched.h�У��ѵ�ǰ����ָ��currentָ�������Ϊnext�������л�
// �������������С���146����next����ʼ��Ϊ0�������ϵͳ��û���κ��������������ʱ��
// �� next ʼ��Ϊ0����˵��Ⱥ�������ϵͳ����ʱȥִ������0�� ��ʱ����0��ִ��pause()
// ϵͳ���ã����ֻ���ñ�������
161 switch_to(next); // �л��������Ϊnext����������֮��
162 }
163
//// pause()ϵͳ���á�ת����ǰ�����״̬Ϊ���жϵĵȴ�״̬�������µ��ȡ�
// ��ϵͳ���ý����½��̽���˯��״̬��ֱ���յ�һ���źš����ź�������ֹ���̻���ʹ����
// ����һ���źŲ�������ֻ�е�������һ���źţ������źŲ������������أ�pause()��
// �᷵�ء���ʱ pause()����ֵӦ���� -1������ errno����Ϊ EINTR�����ﻹû����ȫʵ��
// ��ֱ��0.95�棩��
164 int sys_pause(void)
165 {
166 current->state = TASK_INTERRUPTIBLE;
167 schedule();
168 return 0;
169 }
170
// �ѵ�ǰ������Ϊָ����˯��״̬�����жϵĻ��жϵģ�������˯�߶���ͷָ��ָ��ǰ����
// ��������p�ǵȴ��������ͷָ�롣ָ���Ǻ���һ��������ַ�ı������������pʹ����ָ���
// ָ����ʽ '**p'��������ΪC��������ֻ�ܴ�ֵ��û��ֱ�ӵķ�ʽ�ñ����ú����ı���øú���
// �����б�����ֵ������ָ��'*p'ָ���Ŀ�꣨����������ṹ����ı䣬���Ϊ�����ĵ��ø�
// ����������ԭ������ָ�������ֵ������Ҫ����ָ��'*p'��ָ�룬��'**p'���μ�����ǰʾ��ͼ��
// pָ���ʹ�������
// ����state������˯��ʹ�õ�״̬��TASK_UNINTERRUPTIBLE��TASK_INTERRUPTIBLE�����ڲ���
// �ж�˯��״̬��TASK_UNINTERRUPTIBLE����������Ҫ�ں˳�������wake_up()������ȷ����֮��
// ���ڿ��ж�˯��״̬��TASK_INTERRUPTIBLE������ͨ���źš�����ʱ���ֶλ��� ����Ϊ����
// ״̬TASK_RUNNING����
// *** ע�⣬���ڱ��ں˴��벻�Ǻܳ��죬���������˯����صĴ������һЩ���⣬�������
171 static inline void __sleep_on(struct task_struct **p, int state)
172 {
173 struct task_struct *tmp;
174
// ��ָ����Ч�����˳�����ָ����ָ�Ķ��������NULL����ָ�뱾������Ϊ0)��
// �����ǰ����������0��������(impossible!)��
175 if (!p)
176 return;
177 if (current == &(init_task.task))
178 panic("task[0] trying to sleep");
// ��tmpָ���Ѿ��ڵȴ������ϵ�����(����еĻ�)������inode->i_wait�����ҽ�˯�߶���ͷ
// �ĵȴ�ָ��ָ��ǰ���������Ͱѵ�ǰ������뵽�� *p�ĵȴ������С�Ȼ��ǰ������
// Ϊָ���ĵȴ�״̬����ִ�����µ��ȡ�
179 tmp = *p;
180 *p = current;
181 current->state = state;
182 repeat: schedule();
// ֻ�е�����ȴ�������ʱ��������ֻ᷵�ص������ʾ�����ѱ���ȷ�ػ��Ѳ�ִ�С�
// ����ȴ������л��еȴ������Ҷ���ͷָ�� *p ��ָ��������ǵ�ǰ����ʱ��˵��
// �ڱ��������ȴ����к����������ȴ����С���������Ӧ��ҲҪ�������������
// ���Լ�Ӧ��˳������Щ���������е������ѣ�������ォ�ȴ�����ͷ��ָ��������Ϊ
// ����״̬�����Լ�����Ϊ�����жϵȴ�״̬�����Լ�Ҫ�ȴ���Щ���������е�������
// ��ִ��ʱ�����ѱ�����Ȼ������ִ�е��ȳ���
183 if (*p && *p != current) {
184 (**p).state = 0;
185 current->state = TASK_UNINTERRUPTIBLE;
186 goto repeat;
187 }
// ִ�е����˵������������������ִ�С���ʱ�ȴ�����ͷָ��Ӧ��ָ����������Ϊ
// �գ���������������⣬������ʾ������Ϣ�����������ͷָ��ָ��������ǰ��������
// ������*p = tmp���� ��ȷʵ��������һ�����������л�������tmp��Ϊ�գ�����
// ����֮�����Ƚ�����е������ڻ��Ѻ�����ʱ���ջ�ѵȴ�����ͷָ���ó�NULL��
188 if (!*p)
189 printk("Warning: *P = NULL\n\r");
190 if (*p = tmp)
191 tmp->state=0;
192 }
193
// ����ǰ������Ϊ���жϵĵȴ�״̬��TASK_INTERRUPTIBLE����������ͷָ��*pָ���ĵȴ�
// ������
194 void interruptible_sleep_on(struct task_struct **p)
195 {
196 __sleep_on(p,TASK_INTERRUPTIBLE);
197 }
198
// �ѵ�ǰ������Ϊ�����жϵĵȴ�״̬��TASK_UNINTERRUPTIBLE��������˯�߶���ͷָ��ָ��
// ��ǰ����ֻ����ȷ�ػ���ʱ�Ż᷵�ء��ú����ṩ�˽������жϴ�������֮���ͬ�����ơ�
199 void sleep_on(struct task_struct **p)
200 {
201 __sleep_on(p,TASK_UNINTERRUPTIBLE);
202 }
203
// ���� *pָ�������*p������ȴ�����ͷָ�롣�����µȴ������Dz����ڵȴ�����ͷָ��
// ���ģ���˻��ѵ���������ȴ����е��������������Ѿ�����ֹͣ����״̬������ʾ
// ������Ϣ��
204 void wake_up(struct task_struct **p)
205 {
206 if (p && *p) {
207 if ((**p).state == TASK_STOPPED) // ����ֹͣ״̬��
208 printk("wake_up: TASK_STOPPED");
209 if ((**p).state == TASK_ZOMBIE) // ���ڽ���״̬��
210 printk("wake_up: TASK_ZOMBIE");
211 (**p).state=0; // ��Ϊ����״̬TASK_RUNNING��
212 }
213 }
214
215 /*
216 * OK, here are some floppy things that shouldn't be in the kernel
217 * proper. They are here because the floppy needs a timer, and this
218 * was the easiest way of doing it.
219 */
/*
* ���ˣ������↑ʼ��һЩ�й����̵��ӳ�����Ӧ�÷����ں˵���Ҫ����
* �еġ������Ƿ�����������Ϊ������Ҫ��ʱ���������������������ġ�
*/
// ����220 -- 281�д������ڴ���������ʱ�����Ķ���δ���֮ǰ���ȿ�һ�¿��豸һ����
// �й�������������floppy.c�������˵���� ���ߵ��Ķ����̿��豸��������ʱ��������
// �δ��롣����ʱ�䵥λ��1���δ� = 1/100�롣
// ��������wait_motor[]���ڴ�ŵȴ�������������������ת�ٵĽ���ָ�롣��������0-3
// �ֱ��Ӧ����A--D������ mon_timer[]��Ÿ�����������������Ҫ�ĵδ�����������Ĭ��
// ����ʱ��Ϊ50���δ�0.5�룩������ moff_timer[] ��Ÿ�����������ͣת֮ǰ��ά��
// ��ʱ�䡣�������趨Ϊ10000���δ�100�룩��
220 static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL};
221 static int mon_timer[4]={0,0,0,0};
222 static int moff_timer[4]={0,0,0,0};
// ���������Ӧ�����������е�ǰ��������Ĵ������üĴ���ÿλ�Ķ������£�
// λ7-4���ֱ����������D-A�����������1 - ������0 - �رա�
// λ3 ��1 - ����DMA���ж�����0 - ��ֹDMA���ж�����
// λ2 ��1 - �������̿������� 0 - ��λ���̿�������
// λ1-0��00 - 11������ѡ����Ƶ�����A-D��
// �������ó�ֵΪ������DMA���ж���������FDC��
223 unsigned char current_DOR = 0x0C;
224
// ָ������������������ת״̬����ȴ�ʱ�䡣
// ����nr -- ������(0--3)������ֵΪ�δ�����
// �ֲ�����selected��ѡ��������־��blk_drv/floppy.c��123�У���mask����ѡ������Ӧ��
// ��������Ĵ����������������λ��mask��4λ�Ǹ��������������־��
225 int ticks_to_floppy_on(unsigned int nr)
226 {
227 extern unsigned char selected;
228 unsigned char mask = 0x10 << nr;
229
// ϵͳ�����4������������Ԥ�����ú�ָ������nrͣת֮ǰ��Ҫ������ʱ�䣨100�룩��Ȼ��
// ȡ��ǰDOR�Ĵ���ֵ����ʱ����mask�У�����ָ������������������־��λ��
230 if (nr>3)
231 panic("floppy_on: nr>3");
232 moff_timer[nr]=10000; /* 100 s = very big :-) */ // ͣתά��ʱ�䡣
233 cli(); /* use floppy_off to turn it off */ // ���жϡ�
234 mask |= current_DOR;
// �����ǰû��ѡ�������������ȸ�λ����������ѡ��λ��Ȼ����ָ������ѡ��λ��
235 if (!selected) {
236 mask &= 0xFC;
237 mask |= nr;
238 }
// �����������Ĵ����ĵ�ǰֵ��Ҫ���ֵ��ͬ������FDC��������˿������ֵ(mask)������
// ���Ҫ�����������ﻹû��������������Ӧ����������������ʱ��ֵ��HZ/2 = 0.5��� 50��
// �δ𣩡����Ѿ���������������������ʱΪ2���δ����������� do_floppy_timer()���ȵ�
// �����жϵ�Ҫ��ִ�б��ζ�ʱ�����Ҫ�ɡ��˺���µ�ǰ��������Ĵ���current_DOR��
239 if (mask != current_DOR) {
240 outb(mask,FD_DOR);
241 if ((mask ^ current_DOR) & 0xf0)
242 mon_timer[nr] = HZ/2;
243 else if (mon_timer[nr] < 2)
244 mon_timer[nr] = 2;
245 current_DOR = mask;
246 }
247 sti(); // ���жϡ�
248 return mon_timer[nr]; // ����������������ʱ��ֵ��
249 }
250
// �ȴ�ָ�������������������һ��ʱ�䣬Ȼ�ء�
// ����ָ����������������������ת���������ʱ��Ȼ��˯�ߵȴ����ڶ�ʱ�жϹ����л�һֱ
// �ݼ��ж������趨����ʱֵ������ʱ���ڣ��ͻỽ������ĵȴ����̡�
251 void floppy_on(unsigned int nr)
252 {
// ���жϡ��������������ʱ��û������һֱ�ѵ�ǰ������Ϊ�����ж�˯��״̬������ȴ�����
// ���еĶ����С�Ȼ���жϡ�
253 cli();
254 while (ticks_to_floppy_on(nr))
255 sleep_on(nr+wait_motor);
256 sti();
257 }
258
// �ùر���Ӧ��������ͣת��ʱ����3�룩��
// ����ʹ�øú�����ȷ�ر�ָ������������������↑��100��֮��Ҳ�ᱻ�رա�
259 void floppy_off(unsigned int nr)
260 {
261 moff_timer[nr]=3*HZ;
262 }
263
// ���̶�ʱ�����ӳ���������������ʱֵ������ر�ͣת��ʱֵ�����ӳ������ʱ�Ӷ�ʱ
// �жϹ����б����ã����ϵͳÿ����һ���δ�(10ms)�ͻᱻ����һ�Σ���ʱ�������↑����
// ͣת��ʱ����ֵ�����ijһ������ͣת��ʱ��������������Ĵ�����������λ��λ��
264 void do_floppy_timer(void)
265 {
266 int i;
267 unsigned char mask = 0x10;
268
269 for (i=0 ; i<4 ; i++,mask <<= 1) {
270 if (!(mask & current_DOR)) // �������DORָ����������������
271 continue;
272 if (mon_timer[i]) { // �������������ʱ�����ѽ��̡�
273 if (!--mon_timer[i])
274 wake_up(i+wait_motor);
275 } else if (!moff_timer[i]) { // �������ͣת��ʱ����
276 current_DOR &= ~mask; // ��λ��Ӧ��������λ������
277 outb(current_DOR,FD_DOR); // ������������Ĵ�����
278 } else
279 moff_timer[i]--; // ��������ͣת��ʱ�ݼ���
280 }
281 }
282
// �����ǹ��ڶ�ʱ���Ĵ��롣������64����ʱ����
283 #define TIME_REQUESTS 64
284
// ��ʱ�������ṹ�Ͷ�ʱ�����顣�ö�ʱ������ר���ڹ������ر�������������ﶨʱ������
// �������Ͷ�ʱ�������ִ�Linuxϵͳ�еĶ�̬��ʱ����Dynamic Timer���������ں�ʹ�á�
285 static struct timer_list {
286 long jiffies; // ��ʱ�δ�����
287 void (*fn)(); // ��ʱ��������
288 struct timer_list * next; // ����ָ����һ����ʱ����
289 } timer_list[TIME_REQUESTS], * next_timer = NULL; // next_timer�Ƕ�ʱ������ͷָ�롣
290
// ���Ӷ�ʱ�����������Ϊָ���Ķ�ʱֵ(�δ���)����Ӧ�Ĵ�������ָ�롣
// ������������floppy.c�����øú���ִ��������ر��������ʱ������
// ����jiffies �C ��10����Ƶĵδ�����*fn()- ��ʱʱ�䵽ʱִ�еĺ�����
291 void add_timer(long jiffies, void (*fn)(void))
292 {
293 struct timer_list * p;
294
// �����ʱ��������ָ��Ϊ�գ����˳���������жϡ�
295 if (!fn)
296 return;
297 cli();
// �����ʱֵ<=0�������̵����䴦�������Ҹö�ʱ�������������С�
298 if (jiffies <= 0)
299 (fn)();
300 else {
// ����Ӷ�ʱ�������У���һ�������
301 for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
302 if (!p->fn)
303 break;
// ����Ѿ������˶�ʱ�����飬��ϵͳ����J��������ʱ�����ݽṹ������Ӧ��Ϣ��������
// ����ͷ��
304 if (p >= timer_list + TIME_REQUESTS)
305 panic("No more time requests free");
306 p->fn = fn;
307 p->jiffies = jiffies;
308 p->next = next_timer;
309 next_timer = p;
// �������ʱֵ��С��������������ʱ��ȥ����ǰ����Ҫ�ĵδ����������ڴ�����ʱ��ʱ
// ֻҪ�鿴����ͷ�ĵ�һ��Ķ�ʱ�Ƿ��ڼ��ɡ�[[?? ��γ������û�п�����ȫ�������
// ����Ķ�ʱ��ֵС��ԭ��ͷһ����ʱ��ֵʱ������������ѭ���У�����ʱ����Ӧ�ý�����
// ������һ����ʱ��ֵ��ȥ�µĵ�1���Ķ�ʱֵ���������1����ʱֵ<=��2�������2��
// ��ʱֵ�۳���1����ֵ���ɣ������������ѭ���н��д�����]]
310 while (p->next && p->next->jiffies < p->jiffies) {
311 p->jiffies -= p->next->jiffies;
312 fn = p->fn;
313 p->fn = p->next->fn;
314 p->next->fn = fn;
315 jiffies = p->jiffies;
316 p->jiffies = p->next->jiffies;
317 p->next->jiffies = jiffies;
318 p = p->next;
319 }
320 }
321 sti();
322 }
323
//// ʱ���ж�C��������������sys_call.s�е�_timer_interrupt��189�У������á�
// ����cpl�ǵ�ǰ��Ȩ��0��3����ʱ���жϷ���ʱ����ִ�еĴ���ѡ����е���Ȩ����
// cpl=0ʱ��ʾ�жϷ���ʱ����ִ���ں˴��룻cpl=3ʱ��ʾ�жϷ���ʱ����ִ���û����롣
// ����һ����������ִ��ʱ��Ƭ����ʱ������������л�����ִ��һ����ʱ���¹�����
324 void do_timer(long cpl)
325 {
326 static int blanked = 0;
327
// �����ж��Ƿ���һ��ʱ�������Ļ������blankout�������blankcount������Ϊ�㣬
// ���ߺ�����ʱ���ʱ��blankintervalΪ0�Ļ�����ô���Ѿ����ں���״̬��������־
// blanked = 1����������Ļ�ָ���ʾ����blankcount������Ϊ�㣬��ݼ�֮�����Ҹ�λ
// ������־��
328 if (blankcount || !blankinterval) {
329 if (blanked)
330 unblank_screen();
331 if (blankcount)
332 blankcount--;
333 blanked = 0;
// ����Ļ���������־δ��λ��������Ļ�������������ú�����־��
334 } else if (!blanked) {
335 blank_screen();
336 blanked = 1;
337 }
// ���Ŵ���Ӳ�̲�����ʱ���⡣���Ӳ�̳�ʱ�����ݼ�֮��Ϊ0�������Ӳ�̷��ʳ�ʱ������
338 if (hd_timeout)
339 if (!--hd_timeout)
340 hd_times_out(); // Ӳ�̷��ʳ�ʱ������blk_drv/hdc��318�У���
341
// ���������������������رշ�����(��0x61�ڷ��������λλ0��1��λ0����8253
// ������2�Ĺ�����λ1����������)��
342 if (beepcount) // ����������ʱ��δ�����chr_drv/console.c,950�У���
343 if (!--beepcount)
344 sysbeepstop();
345
// �����ǰ��Ȩ��(cpl)Ϊ0����ߣ���ʾ���ں˳����ڹ����������ں˴�������ʱ��stime
// ������[ Linus���ں˳���ͳ��Ϊ�����û�(supervisor)�ij���sys_call.s��207��
// �ϵ�Ӣ��ע�͡����ֳƺ�������Intel CPU �ֲᡣ] ���cpl > 0�����ʾ��һ���û�����
// �ڹ���������utime��
346 if (cpl)
347 current->utime++;
348 else
349 current->stime++;
350
// ����ж�ʱ�����ڣ���������1����ʱ����ֵ��1������ѵ���0���������Ӧ�Ĵ�������
// �����ô�������ָ����Ϊ�ա�Ȼ��ȥ�����ʱ����next_timer�Ƕ�ʱ��������ͷָ�롣
351 if (next_timer) {
352 next_timer->jiffies--;
353 while (next_timer && next_timer->jiffies <= 0) {
354 void (*fn)(void); // ���������һ������ָ�붨�壡��L
355
356 fn = next_timer->fn;
357 next_timer->fn = NULL;
358 next_timer = next_timer->next;
359 (fn)(); // ���ö�ʱ����������
360 }
361 }
// �����ǰ���̿�����FDC����������Ĵ�������������λ����λ�ģ���ִ�����̶�ʱ����
362 if (current_DOR & 0xf0)
363 do_floppy_timer();
// �����������ʱ�仹û�꣬���˳��������õ�ǰ�������м���ֵΪ0������������ʱ���ж�ʱ
// �����ں˴����������أ��������ִ�е��Ⱥ�����
364 if ((--current->counter)>0) return;
365 current->counter=0;
366 if (!cpl) return; // �����ں�̬��������counterֵ���е��ȡ�
367 schedule();
368 }
369
// ϵͳ���ù��� - ���ñ�����ʱʱ��ֵ(��)��
// ������seconds����0���������¶�ʱֵ��������ԭ��ʱʱ�̻�ʣ��ļ��ʱ�䡣����0��
// �������ݽṹ�б�����ʱֵalarm�ĵ�λ��ϵͳ�δ�1�δ�Ϊ10���룩������ϵͳ������
// ���ö�ʱ����ʱϵͳ�δ�ֵjiffies��ת���ɵδ�λ�Ķ�ʱֵ֮�ͣ���'jiffies + HZ*��ʱ
// ��ֵ'��������������������Ϊ��λ�Ķ�ʱֵ����˱���������Ҫ�����ǽ������ֵ�λ��ת����
// ���г���HZ = 100�����ں�ϵͳ����Ƶ�ʡ�������include/sched.h��4���ϡ�
// ����seconds���µĶ�ʱʱ��ֵ����λ���롣
370 int sys_alarm(long seconds)
371 {
372 int old = current->alarm;
373
374 if (old)
375 old = (old - jiffies) / HZ;
376 current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
377 return (old);
378 }
379
// ȡ��ǰ���̺�pid��
380 int sys_getpid(void)
381 {
382 return current->pid;
383 }
384
// ȡ�����̺�ppid��
385 int sys_getppid(void)
386 {
387 return current->p_pptr->pid;
388 }
389
// ȡ�û���uid��
390 int sys_getuid(void)
391 {
392 return current->uid;
393 }
394
// ȡ��Ч���û���euid��
395 int sys_geteuid(void)
396 {
397 return current->euid;
398 }
399
// ȡ���gid��
400 int sys_getgid(void)
401 {
402 return current->gid;
403 }
404
// ȡ��Ч�����egid��
405 int sys_getegid(void)
406 {
407 return current->egid;
408 }
409
// ϵͳ���ù��� -- ���Ͷ�CPU��ʹ������Ȩ�����˻�����J����
// Ӧ������incrementΪ����0��ֵ�������ʹ����Ȩ����
410 int sys_nice(long increment)
411 {
412 if (current->priority-increment>0)
413 current->priority -= increment;
414 return 0;
415 }
416
// �ں˵��ȳ���ij�ʼ���ӳ���
417 void sched_init(void)
418 {
419 int i;
420 struct desc_struct * p; // ���������ṹָ�롣
421
// Linuxϵͳ����֮�����ں˲����졣�ں˴���ᱻ�����ġ�Linus���Լ�������������Щ
// �ؼ��Ե����ݽṹ�������POSIX���IJ����ݡ����������������ж���䲢�ޱ�Ҫ������
// ��Ϊ�������Լ��Լ��������ں˴�����ˡ�
422 if (sizeof(struct sigaction) != 16) // sigaction�Ǵ���й��ź�״̬�Ľṹ��
423 panic("Struct sigaction MUST be 16 bytes");
// ��ȫ���������������ó�ʼ��������0��������״̬���������;ֲ����ݱ���������
// FIRST_TSS_ENTRY��FIRST_LDT_ENTRY��ֵ�ֱ���4��5��������include/linux/sched.h
// �У�gdt ��һ�������������飨include/linux/head.h ����ʵ���϶�Ӧ���� head.s ��
// ��234���ϵ�ȫ������������ַ��_gdt������� gdt + FIRST_TSS_ENTRY ��Ϊ
// gdt[FIRST_TSS_ENTRY]������gdt[4]����Ҳ�� gdt �����4��ĵ�ַ�� �μ�
// include/asm/system.h,��65�п�ʼ��
424 set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
425 set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
// ��������������������ע��i=1��ʼ�����Գ�ʼ��������������ڣ�����������ṹ
// �������ļ�include/linux/head.h�С�
426 p = gdt+2+FIRST_TSS_ENTRY;
427 for(i=1;i<NR_TASKS;i++) {
428 task[i] = NULL;
429 p->a=p->b=0;
430 p++;
431 p->a=p->b=0;
432 p++;
433 }
434 /* Clear NT, so that we won't have troubles with that later on */
/* �����־�Ĵ����е�λNT�������Ժ�Ͳ������鷳 */
// EFLAGS�е�NT��־λ���ڿ��������Ƕ���á���NTλ��λʱ����ô��ǰ�ж�����ִ��
// IRETָ��ʱ�ͻ����������л���NTָ��TSS�е�back_link�ֶ��Ƿ���Ч��NT=0ʱ��Ч��
435 __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); // ��λNT��־��
// ������0 �� TSS��ѡ������ص�����Ĵ���tr�����ֲ�����������ѡ������ص��ֲ�����
// �����Ĵ���ldtr�С�ע�⣡���ǽ�GDT����ӦLDT��������ѡ������ص�ldtr��ֻ��ȷ��
// ��һ�Σ��Ժ�������LDT�ļ��أ���CPU����TSS�е�LDT���Զ����ء�
436 ltr(0); // ������include/linux/sched.h ��157-158��
437 lldt(0); // ���в�����0��������š�
// ����������ڳ�ʼ�� 8253��ʱ����ͨ��0��ѡ������ʽ3�������Ƽ�����ʽ��ͨ��0��
// ������Ž����жϿ�����оƬ��IRQ0�ϣ���ÿ10���뷢��һ��IRQ0����LATCH�dz�ʼ
// ��ʱ����ֵ��
438 outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */
439 outb_p(LATCH & 0xff , 0x40); /* LSB */ // ��ʱֵ���ֽڡ�
440 outb(LATCH >> 8 , 0x40); /* MSB */ // ��ʱֵ���ֽڡ�
// ����ʱ���жϴ���������������ʱ���ж��ţ������жϿ����������룬����ʱ���жϡ�
// Ȼ������ϵͳ�����ж��š������������ж���������IDT���������ĺ궨�����ļ�
// include/asm/system.h�е�33��39�д������ߵ�����μ�system.h�ļ���ʼ����˵����
441 set_intr_gate(0x20,&timer_interrupt);
442 outb(inb_p(0x21)&~0x01,0x21);
443 set_system_gate(0x80,&system_call);
444 }
445