Sei sulla pagina 1di 41

Process Scheduling

Renato de Castro Dutra


COPPE/UFRJ
Jul/2006
Baseado no captulo 4 do livro Linux Kernel Development 2 nd Edition de Robert Love

Agenda
1.
2.
3.
4.
5.
6.

Linux kernel
Escalonador
Runqueue
Vetores de Prioridade
Sleeping e Wakeup
Balanceamento de
Carga

7. Chaveamento de
Contexto
8. System Calls
9. Discusso
10. Futuro do Escalonador
11. Referncias

1.1. Linux Kernel


Linux Kernel 2.6.17.4 (estvel)
Kernel tornou-se preemptivo no Kernel 2.5
Robert Love foi o principal articulador

Linux Kernel 2.4 (estvel)


Kernel no-preemptivo

O que kernel preemptivo ?

1.2. Kernel Preemptivo


Os processos so preemptivos (podem ser interrompidos)
se um processo A entra no estado TASK_RUNNING (processo
runnable), o kernel checa se a prioridade dinmica do processo A
maior que a prioridade do processo que est rodando
Se , a execuo do processo corrente interrompida e o
escalonador chamado para selecionar um outro processo para
rodar (normalmente, o processo A)
Um processo tambm pode entrar em preempo se o timeslice
expira (este valor pr-determinado, calculado dinamicamente)
Se isto ocorre, o campo need_resched do processo corrente
fica ativo, e o escalonador chamado quando o tempo do
interrupt handler termina ( ou seja, kernel libera o interrupt)

Processo preemptivo no suspenso, desde que ele fica no


estado TASK_RUNNING, apenas no usa CPU.

1.3. Escalonador
Funo componente do Kernel que seleciona o
processo que vai rodar primeiro
Pode ser visto como o elemento que divide os
recursos finitos do tempo do processador entre os
processos com estado TASK_RUNNING
a base da multi-tarefa, dando a impresso de que
vrios processos esto rodando simultaneamente
Trs formas de escalonamento:
FIFO
RoundRobin
Prioridade (calculada dinamicamente)

1.4. Escalonamento Baseado em


Prioridade Dinmica

Inicia com uma prioridade default e permite ao escalonador aumentar ou diminuir,


dinamicamente, a prioridade de acordo com seus objetivos.

Duas faixas de Prioridade:


Nice Range (default = 0)
-20
0

+19
Mnimo Timeslice

Mximo Timeslice

Prioridade baixa

Real-Time Range
0

+99
Prioridade baixa

Um processo Real-Time tem sempre maior prioridade do que um


processo normal!

1.5. Timeslice*
Valor numrico que representa quanto tempo uma tarefa
pode rodar at ser interrompida na preempo.
Este valor de Timeslice difcil de estimar, nem deve ser
curto demais, nem longo demais
Curto muito do tempo ser perdido na troca de processos
Longo processos interativos vo se tornar tediosos

Mnimo
5 ms

baixa prioridade

alta prioridade

menos interativo

mais interativo

Default
100 ms

Mximo
800 ms

Processos no precisam gastar todo seu Timeslice em uma rodada somente. Pode rodar em pedaos separados.

Ao fim do Timeslice o processo considerado expirado e s poder rodar aps todos os Timeslices
dos outros processos terem terminado. Ento o escalonador far uma nova atribuio de Timeslices.

*Em alguns sistemas operacionais tambm chamado de quantum ou processor slice

1.6. Equao de Timeslice


164 #define SCALE_PRIO(x, prio) \
165 max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO/2), MIN_TIMESLICE)

Por pior que seja a prioridade do processo, o menor valor de Timeslice ser
MIN_TIMESLICE = 5ms

O processo pode quebrar seu Timeslice utilizando a funo


TIMESLICE_GRANULARITY:

135 #define TIMESLICE_GRANULARITY(p) (GRANULARITY * \


136 (1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)))

1.7. Objetivos para o Kernel 2.5

O(1) scheduler
preemptive kernel
latency improvements
redesigned block layer
improved VM subsystem
improved threading support
new sound layer

1.8. Objetivos para o Escalonador O(1)


Prover complexidade O(1) !
Escalabilidade SMP perfeita Quando
aumenta o nmero de processadores o
escalonamento escalvel.
Afinidade SMP melhorada a troca de
processos entre processadores apenas para fim
de balanceamento da runqueue, evitando efeito
ping-pong.

2. Escalonador O(1)
Escalonador O(1) Decidir qual processo vai rodar em
tempo constante, independente do nmero de processos.
Antigamente O(N):
Lista nica de processos N:
Para cada processo N runnable{
Acha a dignidade deste processo;
Se (este o processo mais digno ainda) {
Lembra isto;
}
}
Roda o processo mais digno;
Mesma prioridade -> Round Robin

Escala linearmente com o nmero de processos !

2.1. Escalonador O(1) (cont.)


O(1) utiliza Listas de Prioridade

Pegue a Lista de Prioridade Mais Alta que tenha processos


Pegue o primeiro processo desta Lista de Prioridade Mais Alta
Rode este processo
Como fazer isto ?
Agradecimentos ao Ingo Molnar!

12
13
14
15
16

*
*
*
*
*

2002-01-04 New ultra-scalable O(1) scheduler by Ingo Molnar:


hybrid priority-list and round-robin design with
an array-switch method of distributing timeslices
and per-CPU runqueues. Cleanups and useful suggestions
by Davide Libenzi, preemptible kernel bits by Robert Love.
Fonte: Linux-kernel-sched_c.htm

2.2. Grfico O(N) x O(1)


Fonte: Timo Hnig Linux Magazin
http://www.linuxmagazin.de/Artikel/ausgabe/2004/02/038_
scheduler/scheduler.html
1 CPU: Pentium III 1 GHz, 512 MByte RAM
2 CPU: Pentium III 850 MHz, 1 GByte RAM
4 CPU: Pentium III 700 MHz, 4 GByte RAM
8 CPU: Pentium III 700 MHz, 8 GByte RAM

v.2.4

v.2.6

3. Runqueue
Estrutura bsica do Escalonador a
runqueue
uma lista de processos runnable em um
dado processador
Adicionalmente contm informao de
escalonamento por processador

3.1. Struct Runqueue


198 struct runqueue {
199 spinlock_t lock;
200
201 /*
202 * nr_running and cpu_load should be in the same
cacheline because
203 * remote CPUs use both these fields when doing load
calculation.
204 */
205 unsigned long nr_running;
206 #ifdef CONFIG_SMP
207 unsigned long cpu_load;
208 #endif
209 unsigned long long nr_switches;
210
211 /*
212 * This is part of a global counter where only the total
sum
213 * over all CPUs matters. A task can increase this counter
on
214 * one CPU and if it got migrated afterwards it may
decrease
215 * it on another CPU. Always updated under the runqueue
lock:
216 */
217 unsigned long nr_uninterruptible;
218
219 unsigned long expired_timestamp;
220 unsigned long long timestamp_last_tick;
221 task_t *curr, *idle;
222 struct mm_struct *prev_mm;
223 prio_array_t *active, *expired, arrays[2];
224 int best_expired_prio;
225 atomic_t nr_iowait;
226
227 #ifdef CONFIG_SMP
228 struct sched_domain *sd;

234 task_t *migration_thread;


270 unsigned long wunt_cnt;
235 struct list_head migration_queue;271 unsigned long wunt_moved;
236 #endif
272
237
273 /* sched_migrate_task()
238 #ifdef CONFIG_SCHEDSTATS
stats */
239 /* latency stats */
274 unsigned long smt_cnt;
240 struct sched_info rq_sched_info; 275
241
276 /* sched_balance_exec()
242 /* sys_sched_yield() stats */ stats */
243 unsigned long yld_exp_empty; 277 unsigned long sbe_cnt;
244 unsigned long yld_act_empty; 278 #endif
245 unsigned long yld_both_empty; 279 };
246 unsigned long yld_cnt;
247
248 /* schedule() stats */
249 unsigned long sched_noswitch;
250 unsigned long sched_switch;
251 unsigned long sched_cnt;
252 unsigned long sched_goidle;
253
254 /* pull_task() stats */
255 unsigned long
pt_gained[MAX_IDLE_TYPES];
256 unsigned long
pt_lost[MAX_IDLE_TYPES];
257
258 /* active_load_balance() stats */
259 unsigned long alb_cnt;
260 unsigned long alb_lost;
261 unsigned long alb_gained;
262 unsigned long alb_failed;
263
264 /* try_to_wake_up() stats */
265 unsigned long ttwu_cnt;
266 unsigned long ttwu_attempts;
267 unsigned long ttwu_moved;
268
269 /* wake_up_new_task() stats */

3.2. Struct Runqueue Clean


struct runqueue{
spinlock_t
lock;
unsigned long
nr_running;
unsigned long
nr_switches;
unsigned long
expired_timestamp;
unsigned long
nr_uninterruptible;;
unsigned long long timestamp_last_tick;
struct task_struct
*curr;
struct tasl_struct
*idel;
struct mm_struct
*prev_mm;
struct prio_array
*active;
struct prio_array
*expired;
struct prio_array
arrays[2];
struct tasl_strucut
*migration_thread;
struct list_head
migration_queue;
atomic_t
nr_iowait;
};

/* spin lock that protects this runqueue */


/* number of runnable tasks */
/* context switch count */
/* time of last array swap */
/* uninterruptible tasks */
/* last scheduler tick */
/* currently running task */
/* this processors idle task */
/* mm_struct of last ran task */
/* active priority array */
/* the expired priority array */
/* the actual priority arrays */
/* migration thread */
/* migration queue */
/* number of tasks waiting in I/O */

Antes de um runqueue ser manipulado deve ser protegido por um lock

3.3. Parnteses
Escalabilidade SMP
Em mquinas uniprocessadas o escalonador O(1)
de Ingor Molnat muito bom, porm como
resolver os problemas inerentes a escalonamento
em SMP/NUMA ?
Escalonamento Multiqueue
SpinLock
Balanceamento de Carga

3.4. Parnteses
SMP, MPP, NUMA
Symmetric Multi-Processor
Non-Uniform Memory Access

Massively Parallel Processor

3.5. Parnteses
Problemas
Deadlock
Condies necessrias e suficientes para ocorrer:

Excluso Mtua somente um processo pode usar um recurso por vez


Hold-and-wait processo pode bloquear um recurso enquanto aguarda
No preemptivo recurso no pode ser removido de um processo rodando
Ciclo no grafo A -> B -> C -> A

Formas de evitar:
Prevention - Prevenir
Avoidance - Evitar
Detection - Detetar

Starvation

3.6. Soluo
Multiqueue Scheduler

3.7. Afinidade entre SMP


Verso 2.4 tinha um problema indesejvel:
Um processo podia ficar pingando de um processador para
outro (efeito Ping-Pong)
time 1 time 2 time 3 time 4 time 5
Process A CPU 0 CPU 1 CPU 0 CPU 1 CPU 0
Process B CPU 1 CPU 0 CPU 1 CPU 0 CPU 1
CPU

Este problema foi solucionado tambm pelas runqueues por


processador e garante a afinidade entre multi-processadores

3.8. Lock

Para garantir que somente um processador possa manipular concorrentemente a


runqueue, esta protegida por um lock. Assim, somente um processador pode
executar o escalonador concorrentemente.
raro um processador diferente da origem da runqueue manipul-lo, porm
possvel.
Funes de lock e unlock:
task_rq_lock()
task_rq_unlock()
Para evitar deadlock o cdigo deve sempre obter o lock na mesma ordem: pelo
endereo de runqueues ascendente (cap. 8)

v.2.4

v.2.6

4. Vetores de Prioridade
Cada runqueue possui dois vetores de prioridade:
Vetor de Prioridade Ativo
Vetor de Prioridade Expirado
So estes vetores que permitem que a complexidade do
algoritmo seja O(1).

4.1. Vetores de Prioridade


Cada vetor de prioridade contm uma fila de processos runnable
por nvel de prioridade.
As filas contm listas de processos runnable em cada nvel de
prioridade
O vetor de prioridade tambm contm um bitmap de prioridade
usado para eficientemente descobrir a tarefa de mais alta
prioridade no sistema.
185 struct prio_array {
186
unsigned int nr_active;
187
unsigned long bitmap[BITMAP_SIZE];
188
struct list_head queue[MAX_PRIO];
189 };

4.2. Vetores de Prioridade


Cada vetor de prioridade contm um campo bitmap que tem ao
menos um bit para toda prioridade no sistema. Inicialmente todos
os bits so 0.
Quando uma tarefa torna-se runnable, o bit correspondente
prioridade da tarefa no bitmap torna-se 1. O problema, ento
achar, na tabela, o processo mais prioritrio dos que tiverem bit 1.
Como a tabela esttica porque o nmero de prioridades fixo
(140), esta busca tem complexidade constante e no depende do
nmero de processos N.
Cada vetor de prioridade tambm contm um vetor queue da struct
list_head, uma fila para cada prioridade e contm todos os
processos que tm o mesmo valor de prioridade (representado pela
varivel nr_active).

4.3. Reclculo de Timeslice


Sistemas antigos faziam esta tarefa em O(N).
Devido aos vetores Ativo e Expirado, este reclculo no precisa
ser feito em O(N).
Vetor de Prioridade Ativo contm todas as tarefas na runqueue
associada em que o Timeslice no expirou.
Vetor de Prioridade Expirado contm todas as tarefas na
runqueue associada em que o Timeslice expirou
Quando o Timeslice da tarefa expira, este movido para o vetor
Expirado, porm, antes, seu Timeslice recalculado.

4.4. Troca de Vetores Ativo / Expirado


2765 array = rq->active;
2766 if (unlikely(!array->nr_active)) {
2767 /*
2768 * Switch the active and expired arrays.
2769 */
2770 schedstat_inc(rq, sched_switch);
2771 rq->active = rq->expired;
2772 rq->expired = array;
2773 array = rq->active;
2774 rq->expired_timestamp = 0;
2775 rq->best_expired_prio = MAX_PRIO;

4.5. Clculo de Prioridade e Timeslice


Prioridade Dinmica leva em conta uma heurstica porque no sabe se
o processo interativo ou no. Se o processo tem muito tempo inativo,
interativo. Se no, no . Implementao -> guarda em sleep_avg (uma
tabela) a razo entre o tempo dormindo e o tempo acordado para cada
processo.
Sleep_avg incrementado quando o processo se torna runnable (at
MAX_SLEEP_AVG) e decrementado a cada tick de tempo que o
MAX_SLEEP_AVG
processo roda (at 0)
0

Bonus/penalty
-5

Default = 10 ms
+5

4.6. Clculo de Prioridade e Timeslice


105 * Here are a few examples of different nice levels:
106 *
107 * TASK_INTERACTIVE(-20): [1, 1, 1, 1, 1, 1,1,1,1,0,0]
108 * TASK_INTERACTIVE(-10): [1,1,1,1,1,1,1,0,0,0,0]
109 * TASK_INTERACTIVE( 0):
[1,1,1,1,0,0,0,0,0,0,0]
110 * TASK_INTERACTIVE( 10): [1,1,0,0,0,0,0,0,0,0,0]
111 * TASK_INTERACTIVE( 19): [0,0,0,0,0,0,0,0,0,0,0]
112 *
113 * (the X axis represents the possible -5 ... 0 ... +5 dynamic
114 * priority range a task can explore, a value of '1' means the
115 * task is rated interactive.)

4.7. Clculo de Prioridade e Timeslice


Timeslice recalculado baseado na prioridade
esttica.
Quando um novo filho criado o pai e o filho
dividem o Timeslice remanescente (como?)
Quando o Timeslice expira, o escalonador inclui a
tarefa no vetor Expirado, recalculando antes o
Timeslice.

5. Sleeping e Wakeup

6. Balanceamento de Carga
load_balance() no Escalonador. Dois mtodos de chamada:
Quando a runqueue est vazia
Pelo timer
A cada 1ms quando o sistema est parado
A cada 200ms quando no
Em sistema uniprocessados no compilado.

7. Chaveamento de Contexto
Manipulado pelo context_switch. Ocorre sempre que um novo
processo chamado para run.
Executa dois trabalhos:
Chama switch_mm() troca o mapeamento de memria virtual
do processo antigo para o novo
Chama switch_to() troca o estado do processador do
processo novo para o antigo, envolvendo atualizao de pilhas
e registradores
Utiliza uma flag need_resched para que o kernel chame o
escalonador pis existe um processo novo para substituir o antigo
Duas formas para ativar a flag
Quando o timeslice de um processo expira o scheduler_tick()
ativa a flag
Quando um processo de maior prioridade acorda o
try_to_wake_up() ativa a flag

8. SystemCalls Relacionadas com


Escalonamento

Splice () e Tee() system calls (fonte: Abril/2006 Linus Torvalds)


Splice() um read/write para um buffer do kernel diretamente.
Tee() um memcpy() de um buffer do Kernel para outro, sem copiar realmente,
apenas incrementando ponteiros de referncia.
Existe um buffer do kernel aleatrio no espao do usurio e que o usurio tem
controle (como buffer do kernel, mais eficiente).
Pode fazer movimento de dado zero-copy.
Exemplo: Direcionar dado de um socket para outro sem copiar isto no espao do
usurio. Assim, possvel direcionar dado que venha de um Encoder MPEG-4 e fazer
um Tee() para duplicar o stream e escrever um dos streams para disco e outro para
socket para um broadcast em tempo real, sem copiar fisicamente na memria.

Aumentam a performance, porque agiliza os processos que precisam


de leitura/escrita.

9. Discusso

A versao 2.6.17 mais rpida em SMP (Symmetric MultiProcessor), porm em mquinas uniprocessadas rpidas
(2GHz) esta diferena no perceptvel.

9.1. Discusso
Comparao entre Linux 2.6.4 e 2.4.25
Test System and Benchmarks

CPU
Motherboard
Chipset
Memory
Storage
OS

Dual Xeon Test Box


2x 3.2GHz Xeons w/ 1MB L3 Cache
MSI Master LS2
Intel E7505
1GB Crucial Registered/ECC PC2700
Western Digital 400JB
Gentoo Linux 1.4
What benchmarks will we run?

picColor Image
software compiling (MySQL source code compiled with make -j 4)
mp3 encoding (BladeEnc)
Apache Static HTML
Apache PHP/MySQL
MySQL Super Smack(SELECT and UPDATE)
dbench v. 2.0 (file server performance)

9.2. Discusso

9.3. Discusso

File Server

10. Futuro do Escalonador

Scheduler Modes classificar workloads em categorias e


permitir que usurios root ajustem o comportamento do
escalonador dinamicamente.
Swappable Scheduler (http://www.gnu.org/software/hurd) usurio especifica qual escalonador deve ser usado
dependendo da aplicao.

11. Referncias

Love, R., Linux Kernel Development 2nd edition, Novell Press, June
2005.
Bovet, D. P., Cesati, M. Understanding The Linux Kernel 1st edition,
OReilly, October 2000.
Aas, J., Understanding the Linux kernel 2.6.8.1 CPU Scheduler
Silicon Graphics Inc., February 2005.
Cross Reference Linux Linux/kernel/sched.c http://lxr.linux.no/source/kernel/sched.c
Love, R., Introducing the 2.6 kernel Linux Journal, may 2003
Heursch, A.C., Grambow, D., Roedel, D., Rzehak, H., Time-critical
tasks in Linux 2.6 Concepts to increase the preemptability of the Linux
kernel Linux Automation Konferenz 2004
Ge, l. Kernel Comparison: Web Serving on 2.4 and 2.6 Linux
Technology Center IBM February 2004

12. Questo _______

Suponha que 5 processos, de P 1 a P5, sejam sucessivamente submetidos para execuo em


intervalos de 1ut (unidade de tempo). O tempo estimado de servio para os processos
respectivamente de: 5, 3, 4, 5 e 2ut, uma poltica de time slice de 2ut igualmente usada para todos
os processos, o critrio de escalonamento adotado o Round Robin e a estratgia para deadlock a
da deteco.

a) Defina e compare as estratgias para:

prevenir (prevention)
evitar (avoidance)
e detectar (detecion) deadlocks.

b) Monte o grfico e determine o turnaround dos processos.

c) Determine o fator de eficincia do mtodo (T s/Tq).

Potrebbero piacerti anche