Использование примитивов синхронизации (event.h, mutex.h, rwlock.h, semaphore.h, condvar.h)

27 января 2025

ID libkos_sync_api

Библиотека libkos предоставляет API, позволяющие использовать следующие примитивы синхронизации:

  • события (event.h);
  • мьютексы (mutex.h);
  • блокировки чтения-записи (rwlock.h);
  • семафоры (semaphore.h);
  • условные переменные (condvar.h).

Заголовочные файлы находятся в KasperskyOS SDK по пути sysroot-*-kos/include/kos.

API предназначены для синхронизации потоков исполнения, принадлежащих одному и тому же процессу.

События

Событие – примитив синхронизации, который используется для уведомления одного или нескольких потоков исполнения о выполнении требуемого этим потокам условия. Уведомляемый поток исполнения ожидает, когда событие перейдет из несигнального состояния в сигнальное, а уведомляющий поток исполнения изменяет состояние этого события.

Типовой сценарий использования API для работы с событиями включает следующие шаги:

  1. Инициализация события вызовом функции KosEventInit().
  2. Использование события потоками исполнения:
    • Ожидание перехода события из несигнального состояния в сигнальное вызовом функции KosEventWait() или KosEventWaitTimeout() (на стороне уведомляемых потоков исполнения).
    • Изменение состояния события вызовами функций KosEventSet() и KosEventReset() (на стороне уведомляющих потоков исполнения).

Сведения о функциях API для работы с событиями приведены в таблице ниже.

Функции event.h

Мьютексы

Мьютекс – примитив синхронизации, который обеспечивает взаимоисключающее исполнение критических секций (участков кода, в которых осуществляется обращение к разделяемым между потоками исполнения ресурсам). Один поток захватывает мьютекс и исполняет критическую секцию, а другие потоки, чтобы исполнить критические секции, пытаются захватить этот мьютекс, ожидая его освобождения. Мьютекс может быть освобожден только тем потоком исполнения, которым он захвачен. Можно использовать рекурсивный мьютекс, который может быть захвачен одним потоком исполнения несколько раз.

Типовой сценарий использования API для работы с мьютексами включает следующие шаги:

  1. Инициализация мьютекса вызовом функции KosMutexInit() или KosMutexInitEx().
  2. Использование мьютекса потоками исполнения:
    1. Захват мьютекса вызовом функции KosMutexTryLock(), KosMutexLock() или KosMutexLockTimeout().
    2. Освобождение мьютекса вызовом функции KosMutexUnlock().

Сведения о функциях API для работы с мьютексами приведены в таблице ниже.

Функции mutex.h

Блокировки чтения-записи

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

Типовой сценарий использования API для работы с блокировками чтения-записи включает следующие шаги:

  1. Инициализация блокировки чтения-записи вызовом функции KosRWLockInit().
  2. Использование блокировки чтения-записи потоками исполнения:
    1. Захват блокировки чтения-записи для записи (вызовом функции KosRWLockWrite() или KosRWLockTryWrite()) или для чтения (вызовом функции KosRWLockRead() или KosRWLockTryRead()).
    2. Освобождение блокировки-чтения вызовом функции KosRWLockUnlock().

Сведения о функциях API для работы с блокировками чтения-записи приведены в таблице ниже.

Функции rwlock.h

Семафоры

Семафор – примитив синхронизации, основанный на счетчике, значение которого может быть атомарно изменено. Значение счетчика обычно отражает число доступных разделяемых между потоками исполнения ресурсов. Для исполнения критической секции поток ожидает, пока значение счетчика не станет больше нуля. Если значение счетчика больше нуля, то оно уменьшается на единицу, и поток исполняет критическую секцию. После исполнения критической секции поток исполнения сигнализирует семафор, в результате чего значение счетчика увеличивается.

Типовой сценарий использования API для работы с семафорами включает следующие шаги:

  1. Инициализация семафора вызовом функции KosSemaphoreInit().
  2. Использование семафора потоками исполнения:
    1. Ожидание семафора вызовом функции KosSemaphoreWait(), KosSemaphoreWaitTimeout() или KosSemaphoreTryWait().
    2. Сигнализация семафора вызовом функции KosSemaphoreSignal() или KosSemaphoreSignalN().
  3. Освобождение ресурсов семафора вызовом функции KosSemaphoreDeinit().

Сведения о функциях API для работы с семафорами приведены в таблице ниже.

Функции semaphore.h

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

Условная переменная – примитив синхронизации, который используется для уведомления одного или нескольких потоков исполнения о выполнении требуемого этим потокам условия. Условная переменная используется совместно с мьютексом. Уведомляющий и уведомляемый потоки захватывают мьютекс для исполнения критических секций. Уведомляемый поток при исполнении критической секции проверяет, выполняется ли требуемое ему условие (например, подготовлены ли данные уведомляющим потоком). Если условие выполняется, то уведомляемый поток исполняет критическую секцию и освобождает мьютекс. Если условие не выполняется, то уведомляемый поток блокируется на условной переменной, ожидая выполнения условия. При этом мьютекс автоматически освобождается. Уведомляющий поток при исполнении критической секции проверяет, выполняется ли условие, требуемое уведомляемому потоку. Если условие выполняется, то уведомляющий поток сигнализирует об этом через условную переменную и освобождает мьютекс. Уведомляемый поток, заблокированный в ожидании выполнения требуемого ему условия, возобновляет исполнение критической секции, автоматически захватывая мьютекс. После исполнения критической секции уведомляемый поток освобождает мьютекс.

Типовой сценарий использования API для работы с условными переменными включает следующие шаги:

  1. Инициализация условной переменной и мьютекса.

    Чтобы инициализировать условную переменную, нужно вызвать функцию KosCondvarInit().

  2. Использование условной переменной и мьютекса потоками исполнения.

Использование условной переменной и мьютекса на стороне уведомляемых потоков исполнения включает следующие шаги:

  1. Захват мьютекса.
  2. Проверка выполнения условия.
  3. Ожидание выполнения условия вызовом функции KosCondvarWait() или KosCondvarWaitTimeout().

    После возврата функции KosCondvarWait() или KosCondvarWaitTimeout() обычно нужно снова проверить, что условие выполняется, так как другой уведомляемый поток исполнения также получил сигнал и мог сделать условие снова недействительным. (Например, другой поток мог извлечь данные, подготовленные уведомляющим потоком). Для этого нужно использовать следующую конструкцию:

    while(<условие>)

    <вызов KosCondvarWait() или KosCondvarWaitTimeout()>

  4. Освобождение мьютекса.

Использование условной переменной и мьютекса на стороне уведомляющих потоков исполнения включает следующие шаги:

  1. Захват мьютекса.
  2. Проверка выполнения условия.
  3. Сигнализация о выполнении условия вызовом функции KosCondvarSignal() или KosCondvarBroadcast().
  4. Освобождение мьютекса.

Сведения о функциях API для работы с условными переменными приведены в таблице ниже.

Функции condvar.h

Вам помогла эта статья?
Что нам нужно улучшить?
Спасибо за ваш отзыв, вы помогаете нам становиться лучше!
Спасибо за ваш отзыв, вы помогаете нам становиться лучше!