/[lkdp]/lkdp/pm/psched.tex
ViewVC logotype

Diff of /lkdp/pm/psched.tex

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by nayaniabhishek, Tue Nov 5 19:35:42 2002 UTC revision 1.2 by kdlinux2001, Thu Nov 21 13:08:15 2002 UTC
# Line 1  Line 1 
1  \chapter{Process Scheduling}  \chapter{Process Scheduling} \label{sched:all}
2          \section{Task Queues}          \section{Structures} \label{sched:structs}
3          Task queues are dynamic extension to bottom halves. Please, refer to section ~\ref{int:bh} for functional description of bottom halves. Since , botton halves have some limitations:          % TODO include/sched.h only scheduler related stuff
4          \begin{description}          \subsection{struct thread\_info}
5          \item[Fixed in number] There are only a fixed number (32) of bottom halves.          \subsection{Task State structures}
6          \item[single handler] Each bottom half can only be associated with one handler function.  
7          \item[No blocking]  Bottom halves are consumed with a spinlock held so they cannot block.          \section{Wait Queues} \label{sched:waitq} \index{wait\_queue}
8          \end{description}          % TODO
9          So, with task queues, arbitrary number of functions can be chained and processed one after another at a later time.  
10          The task structure is defined in \url{include/linux/tqueue.h} as follows:          \section{Scheduling Basics: TIMER\_BH \& TQUEUE\_BH }
11            The \textit{TIMER\_BH} is a bottom half related with timer interrupt while \textit{TQUEUE\_BH} is a related to periodic task queue. The bottom half is a low-priority function, related to some interrupt. Please, refer to ~\ref{int:bh} for details. The timer interrupt is initialized by the \textit{time\_init} function called from \textit{start\_kernel} function. \footnote{Refer to time\_init in \url{arch/i386/kernel/time.c}}.
12    
13          \begin{verbatim}          \begin{verbatim}
14          struct tq_struct {  
15              struct list_head list;          /* linked list of active bh's */          static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
16              unsigned long sync;             /* must be initialized to zero */  
17              void (*routine)(void *);        /* function to call */          /* Wire cpu IDT entry to s/w handler (and Cobalt APIC to IDT) */
18              void *data;                     /* argument to function */          setup_irq(CO_IRQ_TIMER, &irq0);
19          };  
20          \end{verbatim}          \end{verbatim}
21    
22          A task queue is a linked list of the tasks.          \subsection{Timer basics} \index{timer}
23            Linux programs the programmable interrupt timer to 100 Hz, means timer tick interval is 10 msec. Hence, the \textit{timer\_interrupt} is called every 10 msec. This function \footnote{timer\_interrupt is defined in \url{arch/i386/kernel/time.c}} checks for time stamp coutner (TSC) \footnote{TSC is calibrated at boot up by \textit{calibrate\_tsc()} function. \url{arch/i386/kernel/time.c}} and invokes \textit{do\_timer\_interrupt} function.
24            \begin{verbatim}
25    
26            /* kernel/timer.c */
27            long tick = (1000000 + HZ/2) / HZ;      /* timer interrupt period */
28    
29            /* With HZ = 100 , tick = 10 msec */
30    
31            \end{verbatim}
32    
33            \par Linux kernel also includes Real Time clock. This clock is associated with the CMOS battery. This clock is used to keep track date and time. All process related accounting is done by the timer interrupt running at every 10 msec. \footnote{Refer to "/proc/interrupts" irq0 := timer and irq8 := rtc.}
34    
35          \begin{verbatim}          \begin{verbatim}
36          typedef struct list_head task_queue;  
37          extern task_queue tq_timer, tq_immediate;          #ifdef CONFIG_VISWS
38            /* Clear the interrupt */
39            co_cpu_write(CO_CPU_STAT,co_cpu_read(CO_CPU_STAT) & ~CO_STAT_TIMEINTR);
40            #endif
41               do_timer(regs);
42            #ifndef CONFIG_X86_LOCAL_APIC
43            if (!user_mode(regs))
44                x86_do_profile(regs->eip);
45            #else
46                if (!using_apic_timer)
47                    smp_local_timer_interrupt(regs);
48            #endif
49          \end{verbatim}          \end{verbatim}
50    
51          \par A task queue can be created using the DECLARE\_TASK\_QUEUE() macro while a task onto it can be queued using the queue\_task() function. The task queue then can be processed using run\_task\_queue().          The variable \textit{xtime} is a global variable used to store the cmos time. This is initialised by the \textit{time\_init} function during boot up by calling \textit{get\_cmos\_time()} Refer to \url{kernel/time.c} for these functions.
52          The function run\_task\_queue() checks if the queue is active or not and calls the function from \url{kernel/softirq.c}.  
53  % TODO __run_task_queue          \begin{verbatim}
54          Linux' predefines the following task queues which are consumed at well known points:          /*
55          \begin{description}           * If we have an externally synchronized Linux clock, then update
56          \item[ tq\_timer ] The timer task queue, run on each timer interrupt and when releasing a tty device (closing or releasing a half opened terminal device). Since the timer handler runs in interrupt context, the tq\_timer tasks also run in interrupt context and thus cannot block.           * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
57             * called as close as possible to 500 ms before the new second starts.
58          \item[ tq\_scheduler ] The scheduler task queue, consumed by the scheduler (and also when closing tty devices, like tq\_timer). Since the scheduler executed in the context of the process being re-scheduled, the tq\_scheduler tasks can do anything they like, i.e. block, use process context data etc.           */
59            if ((time_status & STA_UNSYNC) == 0 &&
60          \item[ tq\_immediate ] This is really a bottom half IMMEDIATE\_BH, so drivers can queue\_task(task, \&tq\_immediate) and then mark\_bh(IMMEDIATE\_BH) to be consumed in interrupt context.              xtime.tv_sec > last_rtc_update + 660 &&
61                xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
62          \item[ tq\_disk ] Used by low level block device access (and RAID) to start the actual requests. This task queue is exported to modules but shouldn't be used except for the special purposes which it was designed for. Unless a driver uses its own task queues, it does not need to call run\_tasks\_queues() to process the queue, except under circumstances explained below.              xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
63          \end{description}              if (set_rtc_mmss(xtime.tv_sec) == 0)
64          \par  The tq\_timer and tq\_scheduler task queues are consumed not only in the usual places but elsewhere (closing tty device is an one example). This is because, the drivers can schedule tasks on the queue, and these tasks only make sense while a particular instance of the device is still valid which usually means until the application closes it. So, the driver may need to call run\_task\_queue() to flush the tasks it (and anyone else) has put on the queue, because allowing them to run at a later time may make no sense i.e. the relevant data structures may have been freed/reused by a different instance. So run\_task\_queue() on tq\_timer and tq\_scheduler in places other than timer interrupt and schedule() respectively.                  last_rtc_update = xtime.tv_sec;
65          \section{Structures}              else
66          % include/sched.h                  last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
67          \section{Scheduling Basics: TIMER\_BH \& TQUEUE\_BH }          }
68          % TODO do_timer          \end{verbatim}
69            \par The \textit{do\_timer\_interrupt} function updates the timestaps from real time clock and calls \textit{do\_timer} function. This function performs all the timer interrupt related activities. The function is described below.
70    
71            \subsection{Function do\_timer} \index{do\_timer}
72            \begin{verbatim}
73            void do_timer(struct pt_regs *regs)
74            {
75                jiffies_64++;
76            #ifndef CONFIG_SMP
77                /* SMP process accounting uses the local APIC timer */
78    
79                update_process_times(user_mode(regs));
80            #endif
81                mark_bh(TIMER_BH);
82                if (TQ_ACTIVE(tq_timer))
83                    mark_bh(TQUEUE_BH);
84            }
85            \end{verbatim}
86    
87            The value of jiffies\_64 is set to 0 when kernel booted, it increamentes at every timer interrupt. It also marks the bottom halves related to TIMER and TQUEUE which will execute the functions associated with these bottom halves.
88            % \index {scheduler\_tick}
89            % TODO scheduler tick, SIGVTALRM, SIGPROF, update_one_process
90    
91            \par  The tq\_timer and tq\_scheduler task queues are consumed not only in the usual places but elsewhere (closing tty device is an one example). This is because, the drivers can schedule tasks on the queue, and these tasks only make sense while a particular instance of the device is still valid which usually means until the application closes it. So, the driver may need to call run\_task\_queue() to flush the tasks it (and anyone else) has put on the queue, because allowing them to run at a later time may make no sense i.e. the relevant data structures may have been freed/reused by a different instance. So run\_task\_queue() on tq\_timer and tq\_scheduler in places other than timer interrupt and \textit{schedule()} respectively. Refer to O(1) scheduler algorithm here ~\ref{sched:algo}.
92          \section{The switch\_to function}          \section{The switch\_to function}
93          \section{schedule() algorithm}          \section{schedule() algorithm} \label{sched:algo}
94    

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26