Linux Kernel (Ядро линукса) (часть 1)


Функция try_to_wake_up

Функция try_to_wake_up будит спящий или остановленный процесс, переводя его в состояние task running и занося его в очередь на выполнение, принадлежащую локальному процессору. Например, эта функция вызывается, когда нужно возобновить выполнение процессов в очереди ожидания или процессов, ждущих сигнала

В качестве параметров функция принимает:

- указатель на дескриптор (р) процесса, который следует разбудить;
- маску состояний процесса (state), который можно разбудить;
- флаг (sync), запрещающий разбуженному процессу вытеснять текущий процесс, работающий на локальном процессоре.

Функция выполняет следующие действия:

1. Вызывает функцию task_rq_iock, чтобы отключить локальные прерывания и получить блокировку очереди на выполнение rq, принадлежащей процессору, который последним выполнял процесс (это может быть процессор, отличный от локального). Локальный номер этого процессора хранится В ПОЛе p->thread_info->cpu.
2. Проверяет, принадлежит ли состояние p->state данного процесса маске состояний state, переданной функции в качестве аргумента. Если это не так, функция переходит к шагу , чтобы завершить свою работу.
3. Если поле р->аггау не содержит null, значит, процесс уже стоит в очереди на выполнение, и функция переходит к шагу .
4. В многопроцессорных системах функция проверяет, должен ли пробуждаемый процесс мигрировать из очереди на выполнение, принадлежащей
процессору, выполнявшему этот процесс последним в очередь какого- либо другого процессора. Функция выбирает целевую очередь на выполнение, руководствуясь некоторыми эвристическими правилами. Например:
• если какой-нибудь процессор в системе простаивает, функция выбирает его очередь на выполнение в качестве целевой. Предпочтение отдается процессору, ранее выполнявшему процесс, и локальному процессору именно в этом порядке;
• если рабочая нагрузка процессора, выполнявшего процесс последним, значительно ниже, чем у локального процессора, функция выбирает прежнюю очередь на выполнение в качестве целевой;
• если процесс выполнялся недавно, функция выбирает прежнюю очередь на выполнение в качестве целевой (аппаратный кэш, возможно, еще содержит данные процесса);
• если перенос процесса на локальный процессор уменьшает дисбаланс между процессорами, целевой становится локальная очередь на выполнение
По окончании этого шага функция определила целевой процессор, который будет выполнять разбуженный процесс, и, соответственно, очередь rq, в которую следует поставить этот процесс.
5. Если процесс находится в состоянии task uninterruptible, функция уменьшает значение в поле nr uninterruptibie целевой очереди на выполнение и записывает -1 в поле p->activated дескриптора процесса.
6. Вызывает функцию activate tasko, которая, со своей стороны, выполняет следующие действия:
• вызывает функцию sched ciocko для получения текущей отметки времени в наносекундах. Если целевым является не локальный процессор, функция компенсирует сдвиг прерываний от локального таймера с помощью отметок времени, соответствующих последним прерываниям от таймеров на локальном и целевом процессорах:
now = (sched_clock() — this_rq()->timestamp_last_tick)
+ rq->timestamp_last_tick;
• вызывает функцию recaic task prio , передавая ей указатель на дескриптор процесса и отметку времени, полученную на предыдущем шаге. Функция recaic task prio описана в следующем разделе;
• устанавливает значение поля p->activated
• записывает в поле p->timestamp отметку времени, полученную на шаге ;
• заносит дескриптор процесса в список активных процессов:
enqueue_task(р, rq->active); rq->nr_running++;
7. Если либо целевой процессор не является локальным, либо флаг sync не установлен, функция проверяет, не превышает ли динамический приоритет нового выполняемого процесса приоритет текущего процесса в очереди rq (p->prio curr->prio). Если это так, функция вызывает функцию resched taskO, ЧТОбы ВЫТеСНИТЬ процесс rq->curr. В ОДНОПрОцессорных системах последняя функция просто вызывает функцию set_tsk_need_resched , чтобы установить флаг ТI F_NEED_RESCHED ДЛЯ процесса rq->curr. В многопроцессорных системах функция resched_ task , кроме того, проверяет, было ли равно нулю старое значение флага tif need resched, отличается ли целевой процессор от локального и сброшен ли флаг tif polling nrflag у процесса rq->curr (то есть целевой процесс не занимается активным опросом состояния флага tif_need_ resched у данного процесса). Если это условие выполнено, функция reschedtaskO вызывает функцию smpsendreschedule , чтобы ВОЗбу- дить межпроцессорное прерывание и форсировать перепланирование процессов на целевом процессоре.
8. Записывает в поле p->state данного процесса значение task running.
9. Вызывает функцию task_rq_uniock, чтобы разблокировать очередь на выполнение rq и заново включить локальные прерывания.
10. Возвращает (если процесс успешно разбужен) или 0 (если процесс разбужен не был).

Предыдущая страница | 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 | Следующая страница




Возможно, Вас также заинтересует:

ОС Knoppix - это Linux без про...

ВведениеЕсли вы цените свое время, умеете считать деньги и знаете стоимость информации, то эта книга...

Linux Kernel (Ядро линукса) (ч...

Спин-блокировкаСпин-блокировка необходима в многопроцессорной системе, потому что могут возникнуть...

Linux Kernel (Ядро линукса) (ч...

Копирование при записи В системах Unix первых поколений создание процесса было реализовано довольно...

Linux Kernel (Ядро линукса) (ч...

Буферы блоков и головы буферовУ каждого буфера есть дескриптор голова буфера, имеющий тип buffer...