1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/rcore-os-rCore-Tutorial

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
part-6.md 4 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 29.11.2024 21:14 7f8a4fd

Условные переменные

Типичный интерфейс условных переменных (conditional variable) выглядит следующим образом:

  • wait: текущий поток начинает ожидать эту условную переменную.
  • notify_one: позволяет продолжить выполнение одному из потоков, ожидающих эту условную переменную.
  • notify_all: позволяет продолжить выполнение всем потокам, ожидающим эту условную переменную.

Отличие условной переменной от мьютекса в том, что при использовании мьютекса вызывающий разблокировку должен быть тем же, кто его заблокировал. В то время как условная переменная может быть уведомлена любым источником. Кроме того, мьютекс требует, чтобы каждая операция lock сопровождалась операцией unlock, а условная переменная позволяет многократно вызывать notify, но гарантирует, что количество выполнений потоков, ожидавших через wait, не превысит количество вызовов notify.

После добавления условной переменной к входному потоку, поток, вызвавший sys_read, может перейти в состояние ожидания и не будет выбран планировщиком, что позволит избежать ненужного использования ресурсов процессора.

Настройка планировщика

Чтобы продолжить использование существующего алгоритма планирования без значительных изменений, мы создаём отдельный «спящий» раздел для пула потоков, который изолирован от планировщика. Когда поток переходит в состояние ожидания, он удаляется из планировщика, чтобы предотвратить его последующее ненужное пробуждение.

pub struct Processor {
    /// Текущий выполняемый поток
    current_thread: Option<Arc<Thread>>,
    /// Планировщик, отслеживающий активные потоки
    scheduler: SchedulerImpl<Arc<Thread>>,
    /// Спящие потоки
    sleeping_threads: HashSet<Arc<Thread>>,
}

Реализация условных переменных

Условные переменные используются в структурах, связанных с ожиданием и пробуждением, таких как входные потоки. Условная переменная хранит все потоки, ожидающие её.

#[derive(Default)]
pub struct Condvar {
    /// Все потоки, ожидающие эту условную переменную
    watchers: Mutex<VecDeque<Arc<Thread>>>,
}

Когда поток вызывает sys_read и буфер пуст, он добавляется к watcher условной переменной и удаляется из активных потоков в Processor. Когда происходит прерывание клавиатуры и символы считываются, поток возвращается в планировщик для следующего вызова.

Открытое размышление: что произойдёт, если несколько потоков одновременно ожидают ввода? Есть ли решение этой проблемы?

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/rcore-os-rCore-Tutorial.git
git@api.gitlife.ru:oschina-mirror/rcore-os-rCore-Tutorial.git
oschina-mirror
rcore-os-rCore-Tutorial
rcore-os-rCore-Tutorial
master