VDK: API семафоров Печать
Добавил(а) microsin   

Перевод документации по функциям семафоров из даташита [1]. Подробную информацию про поведение семафоров, мьютексов и потоков VDK см. [2].

[CreateSemaphore]

// Прототип C:
VDK_SemaphoreID VDK_CreateSemaphore(u32 inInitialValue,
                                    u32 inMaxCount,
                                    VDK_Ticks inInitialDelay,
                                    VDK_Ticks inPeriod);
 
// Прототип C++:
VDK::SemaphoreID VDK::CreateSemaphore(u32 inInitialValue,
                                      u32 inMaxCount,
                                      VDK::Ticks inInitialDelay,
                                      VDK::Ticks inPeriod);

Создает и инициализирует динамический семафор (замечание: семафоры также бывают статические, созданные не стадии компиляции проекта). Если значение параметра inPeriod ненулевое, то создается периодический семафор [2].

Параметры:

inInitialValue значение семафора, которое он получает при создании. Нулевое значение показывает, что семафор после создания недоступен. Этот параметр должен быть в диапазоне между 0 и inMaxCount.

inMaxCount максимальное значение счетчика семафора, которое он может достигнуть при публикации семафора (вызов PostSemaphore). Значение inMaxCount == 1 создает двоичный семафор.

inInitialDelay количество элементарных интервалов времени, тиков (Ticks) до момента автоматической публикуции периодического семафора. Значение inInitialDelay должно быть равно или больше 1.

inPeriod задает свойство периода семафора в количестве тиков интервала сна на каждом цикле после того, как семафор первый раз публикуется. Если inPeriod == 0, то создается непериодический семафор, в этом случае параметр inInitialDelay не имеет значения и также может быть равен 0.

Влияние на планировщик: вызов функции не запускает планировщик.

Детерминизм: время выполнения функции не определено.

Возвращаемое значение: новый идентификатор SemaphoreID при успешном завершении или UINT_MAX в случае ошибки.

Обработка ошибок поддерживается только для библиотек с функционалом full instrumentation и error-checking:

kMaxCountExceeded покажет, что inInitialValue больше, чем inMaxCount.

kSemaphoreCreationFailure покажет, что ядро (VDK kernel) не может выделить и/или инициализировать память для семафора.

[DestroySemaphore]

// Прототип C:
void VDK_DestroySemaphore(VDK_SemaphoreID inSemaphoreID);
 
// Прототип C++:
void VDK::DestroySemaphore(VDK::SemaphoreID inSemaphoreID);

Уничтожит семафор, связанный с идентификатором inSemaphoreID (полученным при динамическом создании семафора вызовом функции CreateSemaphore). Уничтожение не произойдет, если имеется хотя бы один поток, ожидающий публикации этого семафора, в этом случае сгенерируется ошибка, обрабатываемая сборкой с библиотеками поддержки функционала fully instrumented и error-checking.

Параметры:

inSemaphoreID обозначает семафор, подлежащий уничтожению (см. SemaphoreID далее в разделе "Типы данных").

Влияние на планировщик: вызов функции не запускает планировщик.

Детерминизм: время выполнения функции не определено.

Обработка ошибок поддерживается только для библиотек с функционалом full instrumentation и error-checking:

kSemaphoreDestructionFailure покажет, что семафор не может быть уничтожен, потому что существуют потоки, заблокированные на нем.

kUnknownSemaphore покажет, что представлен недопустимый SemaphoreID (семафор с таким идентификатором не существует).

[GetSemaphoreValue]

// Прототип C:
u32 VDK_GetSemaphoreValue(VDK_SemaphoreID inSemaphoreID);
 
// Прототип C++:
u32 VDK::GetSemaphoreValue(VDK::SemaphoreID inSemaphoreID);

Возвратит значение (счетчик) указанного семафора.

Параметры:

inSemaphoreID идентификатор семафора, счетчик которого запрашивается.

Влияние на планировщик: вызов функции не запускает планировщик.

Детерминизм: время выполнения функции всегда одинаковое.

Возвращаемое значение: счетчик семафора, если этот семафор существует. Если семафор не существует, то в случае сборки с библиотеками fully instrumented или error-checking будет возвращено UINT_MAX, без таких библиотек возвращаемое значение будет неопределенным.

Обработка ошибок поддерживается только для библиотек с функционалом full instrumentation и error-checking:

kUnknownSemaphore покажет, что представлен недопустимый SemaphoreID (семафор с таким идентификатором не существует).

[InstallMessageControlSemaphore]

// Прототип C:
void VDK_InstallMessageControlSemaphore(VDK_SemaphoreID inSemaphore);
 
// Прототип C++:
void VDK::InstallMessageControlSemaphore(VDK::SemaphoreID inSemaphore);

Настроит семафор со счетчиком для регулирования выделения и удаления потоками маршрутизации (routing threads) объектов сообщения. Начальное значение семафора должно быть установлено на количество свободных сообщений, зарезервированных для использования входящими потоками маршрутизации. Семафор ожидается быть опубликованным (pended) входящими потоками маршрутизации перед каждым выделением сообщения, и публикуется (posted) исходящими потоками маршрутизации после каждого удаления сообщения. При условии, что значение семафора всегда меньше или равно количеству свободных сообщений, выделения сообщений потоками маршрутизации никогда не будет неудачным (хотя потоки маршрутизации могут блокироваться на ожидании публикации семафора) в ожидании, когда станет доступным свободное сообщение.

Параметры:

inSemaphore идентификатор семафора для установки.

Влияние на планировщик: вызов функции не запускает планировщик.

Детерминизм: время выполнения функции всегда одинаковое.

Обработки ошибок нет.

[MakePeriodic]

// Прототип C:
void VDK_MakePeriodic(VDK_SemaphoreID inSemaphoreID,
                      VDK_Ticks inDelay,
                      VDK_Ticks inPeriod);
 
// Прототип C++:
void VDK::MakePeriodic(VDK::SemaphoreID inSemaphoreID,
                       VDK::Ticks inDelay,
                       VDK::Ticks inPeriod);

Направляет планировщик автоматически публиковать указанный семафор после истечения времени inDelay тиков. После каждого inPeriod тиков семафор публикуется и запускается планировщик. Это позволяет работающему потоку захватить сигнал, и если этот поток имеет более высокий приоритет, продолжить свое выполнение.

Чтобы быть периодическим, выполняющийся поток должен повторять последовательность: выполнить задачу, и затем заблокироваться в ожидании (pend) на этом семафоре. Обратите внимание, что это поведение отличается от "засыпания" по завершении активности.

Параметры:

inSemaphoreID идентификатор семафора, который будет сделан периодическим.

inDelay количество тиков перед первой публикацией семафора. Значение inDelay должно быть равно или больше 1, и меньше INT_MAX.

inPeriod количество тиков, в течение которого поток засыпает на каждом цикле после первого цикла блокировки на периодическом семафоре. Значение inPeriod должно быть равно или больше 1, и меньше INT_MAX.

Влияние на планировщик: вызов функции не запускает планировщик.

Детерминизм: время выполнения функции не определено.

Обработка ошибок поддерживается только для библиотек с функционалом full instrumentation и error-checking:

kUnknownSemaphore покажет, что представлен недопустимый SemaphoreID (семафор с таким идентификатором не существует).

kInvalidPeriod покажет, что указан inPeriod, равный 0 или больше, чем INT_MAX.

kInvalidDelay покажет, что указана inDelay, равная 0 или больше, чем INT_MAX. 0 недопустимая задержка, потому что первая публикация семафора не произойдет до появления следующего тика.

kAlreadyPeriodic покажет, что семафор уже периодический, и его нельзя повторно сделать периодическим. Если вызов функции MakePeriodic был сделан для изменения периода семафора, то семафор сначала должен быть сделан непериодическим (см. Функцию RemovePeriodic).

[PendSemaphore]

// Прототип C:
bool VDK_PendSemaphore(VDK_SemaphoreID inSemaphoreID,
                       VDK_Ticks inTimeout);
 
// Прототип C++:
bool VDK::PendSemaphore(VDK::SemaphoreID inSemaphoreID,
                        VDK::Ticks inTimeout);

Наиболее часто используемая функция, предоставляющая механизм синхронизации потоков с помощью блокировки на ожидании (pend) публикации семафора [2].

Если указанный семафор доступен, т. е. его счетчик больше нуля, то счетчик уменьшится на 1, и управление будет передано тому потоку, который в настоящее время имеет самый высокий приоритет (если это поток, который вызвал PendSemaphore, то этот поток разблокируется и продолжит свое выполнение), иначе вызвавший функцию PendSemaphore поток заблокируется на этом семафоре. Если же семафор недоступен (его счетчик равен 0), и задан таймаут как kDoNotWait, то функция PendSemaphore вернет FALSE, и поток продолжит выполнения без блокировки на семафоре.

Если семафор недоступен, и указан любой таймаут, отличающийся от kDoNotWait, то поток приостановит свое выполнение до момента, когда семафор будет опубликован (posted). Если поток не возобновил выполнение после истечения inTimeout тиков, то точка возобновления работы потока поменяется на его функцию ошибки, и поток станет доступен для управления планировщиком (т. е. он может продолжить выполнение в соответствии со своим приоритетом). Это поведение может быть изменено путем наложения по ИЛИ на таймаут константы VDK_kNoTimeoutError языка C (или VDK::kNoTimeoutError на C++). В этом случае не будет произведена обработка ошибки при таймауте, и произойдет простой возврат из функции PendSemaphore, делая поток доступным для управления планировщиком (т. е. он может продолжить выполнение в соответствии со своим приоритетом). Если в параметре inTimeout передан 0, то поток может ждать публикации семафора бесконечно долго.

Параметры:

inSemaphoreID идентификатор семафора, на котором поток должен заблокироваться в ожидании его публикации (доступности).

inTimeout значение меньшее INT_MAX, которое задает максимальное время в тиках, которое поток блокируется (pends) на семафоре. Это значение может быть объединено операцией ИЛИ с константой kNoTimeoutError, если для таймаут не должен обрабатываться функцией ошибки потока. Значение kDoNotWait покажет, что API-функция PendSemaphore не должна приводить к блокировке вывавшего её потока, если семафор недоступен.

Влияние на планировщик: вызов функции запускает планировщик, и может привести к переключению контекста.

Детерминизм: время выполнения функции всегда одинаковое, если семафор доступен.

Возвращаемое значение:

TRUE если:

• Семафор с указанным идентификатором успешно ожидался потоком.

FALSE если:

• Вызов PendSemaphore привел к таймауту, но при этом на значение таймаута inTimeout была наложена константа kNoTimeoutError.
• В качестве inTimeout была указана константа kDoNotWait, и семафор не был доступен.

Обработка ошибок поддерживается только для библиотек с функционалом full instrumentation и error-checking:

kSemaphoreTimeout покажет, что время таймаута истекло до момента доступности семафора. Эта ошибка не будет передана на обработку, если на указанное значение таймаута операцией ИЛИ была наложена константа kNoTimeoutError.

kUnknownSemaphore покажет, что inSemaphoreID недопустимый идентификатор семафора (такой семафор не существует).

kBlockInInvalidRegion покажет, что функция PendSemaphore была вызвана в необслуживаемом (unscheduled) регионе кода [3], что вызывает конфликт планирования процессорного времени.

kDbgPossibleBlockInRegion покажет, что PendSemaphore могла быть вызвана в необслуживаемом регионе, что потенциально может привести к конфликту планирования процессорного времени.

kInvalidTimeout покажет, что указано недопустимое значение таймаута, т. е. оно либо INT_MAX, либо (0 | kNoTimeoutError).

[PostSemaphore]

// Прототип C:
void VDK_PostSemaphore(VDK_SemaphoreID inSemaphoreID);
 
// Прототип C++:
void VDK::PostSemaphore(VDK::SemaphoreID inSemaphoreID);

Наиболее часто используемая функция, предоставляющая механизм синхронизации потоков с помощью публикации (post) семафора [2]. Каждый раз, когда семафор публикуется, его счетчик увеличивается на 1 до тех пор, пока не достигнет максимальное значение, указанное при создании семафора (см. функцию CreateSemaphore). Все последующие публикации, когда счетчик семафора максимальный, не будут давать никакого эффекта.

Обратите внимание, что для обработчиков прерываний (Interrupt Service Routines, ISR) должен использоваться другой интерфейс PostSemaphore, см. C_ISR_PostSemaphore.

Параметры:

inSemaphoreID идентификатор семафора, который должен быть опубликован.

Влияние на планировщик: вызов функции запускает планировщик, и может привести к переключению контекста.

Детерминизм:

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

Обработка ошибок поддерживается только для библиотек с функционалом full instrumentation и error-checking:

kUnknownSemaphore покажет, что inSemaphoreID недопустимый идентификатор семафора (такой семафор не существует).

[C_ISR_PostSemaphore]

// Прототип C:
void VDK_C_ISR_PostSemaphore(VDK_SemaphoreID inSemaphoreID);
 
// Прототип C++:
void VDK::C_ISR_PostSemaphore(VDK::SemaphoreID inSemaphoreID);

Это эквивалент функции PostSemaphore (см. выше), предназначенный для вызова из тела ISR (обработчика прерывания).

Все публикации семафора, которые происходя в домене прерываний, будут обработаны немедленно по возвращении контекста в домен потоков.

Параметры:

inSemaphoreID идентификатор семафора, который должен быть опубликован.

Влияние на планировщик: если есть поток, ожидающий семафора inSemaphoreID, то запустится планировщик перед возвращением в домен потоков.

Детерминизм: время выполнения функции всегда одинаковое.

Обработка ошибок поддерживается только для библиотек с функционалом full instrumentation и error-checking: ядро переходит в KernelPanic с g_KernelPanicCode для кода ошибки kISRError, и с g_KernelPanicError для кода ошибки kUnknownSemaphore, если inSemaphoreID больше, чем максимальное количество семафоров, допустимое в системе.

[RemovePeriodic]

// Прототип C:
void VDK_RemovePeriodic(VDK_SemaphoreID inSemaphoreID);
 
// Прототип C++:
void VDK::RemovePeriodic(VDK::SemaphoreID inSemaphoreID);

Остановит периодические публикации указанного семафора. Попытка вызова RemovePeriodic для непериодического семафора не даст никакого эффекта и вызовет ошибку времени выполнения (run-time error).

Параметры:

inSemaphoreID указывает идентификатор семафора, у которого приостанавливаются периодические публикации.

Влияние на планировщик: вызов функции не запускает планировщик.

Детерминизм: время выполнения функции не определено.

Обработка ошибок поддерживается только для библиотек с функционалом full instrumentation и error-checking:

kUnknownSemaphore покажет, что inSemaphoreID недопустимый идентификатор семафора (такой семафор не существует).

kNonperiodicSemaphore покажет, что семафор inSemaphoreID непериодический.

[Типы данных]

u32 этот тип данных определен в заголовке services_types.h как unsigned int.

SemaphoreID тип семафора, используемый для хранения уникального идентификатора семафора.

enum SemaphoreID
{
   /* Определяется IDDE в заголовочном файле VDK.h */
   ...   // Тут перечисляются идентификаторы семафоров
};

Перечисление в хедере VDK.h будет содержать те идентификаторы, которые автоматически были созданы и существуют в момент загрузки приложения VDK (boot time). Любые динамически созданные семафоры в момент работы приложения VDK (см. описание функции CreateSemaphore) будут иметь ID такого же типа, что позволяет компилятору выполнить проверку типа без возникновения ошибок.

// Определение типа на C:
typedef enum SemaphoreID VDK_SemaphoreID;
 
// Определение типа на C++:
typedef enum SemaphoreID VDK::SemaphoreID;

Ticks

Тип для единицы системного времени. Тики происходят со строго определенными интервалами времени, в этих интервалах срабатывают прерывания, генерируемые аппаратным таймером.

// Определение типа на C:
typedef unsigned int VDK_Ticks;
 
// Определение типа на C++:
typedef unsigned int VDK::Ticks;

[Ссылки]

1. VisualDSP++ 5.0 Kernel (VDK) User’s Guide site:analog.com.
2. VDK: сигналы, взаимодействие потоков и ISR (синхронизация).
3. Специфика использования VDK для процессоров Blackfin.
4. VDK: API мьютексов.
5VDK: API сообщений.
6Чем отличается мьютекс от семафора?