6.4.1 Эмуляция интерфейсов мьютекса RTOS |
Предыдущая Содержание Следующая |
Прототипами интерфейсов мьютекса в нашей RTOS являются:
▪rtosError_t rtosMutexInit(rtosMutex_t *mutex): инициализация мьютекса для операций блокировки, разблокировки и пробной блокировки. ▪rtosError_t rtosMutexLock(rtosMutex_t *mutex): захват мьютекса, если он не заблокирован; засыпание, если мьютекс уже заблокирован. ▪rtosError_t rtosMutexUnlock(rtosMutex_t *mutex): разблокировка мьютекса, захваченного ранее вызовом rtosMutexLock. ▪rtosError_t rtosMutexTrylock(rtosMutex_t *mutex): захват мьютекса, если он не заблокирован. Возвращает RTOS_AGAIN, если мьютекс уже заблокирован.
Обратите внимание, что все вышеперечисленные интерфейсы возвращают одно из значений enum rtosError_t, находящегося в файле rtosTypes.h. Этот файл RTOS включён в ospl.h.
typedef enum { RTOS_OK, RTOS_AGAIN, RTOS_UNSUPPORTED, ... RTOS_ERROR, }rtosError_t;
Эти функции в качестве аргумента принимают указатель на объект rtosMutex_t. rtosMutex_t эмулируется в файле ospl.h следующим образом:
#ifndef __KERNEL__ typedef pthread_mutex_t rtosMutex_t; <-- определение в пространстве пользователя #else typedef struct semaphore rtosMutex_t; <-- определение в ядре #endif
В пользовательском пространстве интерфейсы мьютекса RTOS эмулируются c использованием мьютексных операций pthread-ов. В ядре они эмулируются с использованием семафоров ядра. Давайте поговорим о реализации этих интерфейсов в нашем OSPL. Функция rtosMutexInit эмулируется в пользовательском пространстве с помощью функции pthread_mutex_init. В ядре используется функция init_MUTEX. init_MUTEX инициализирует семафор значением 1.
rtosError_t rtosMutexInit(rtosMutex_t *mutex){ #ifndef __KERNEL__ pthread_mutex_init(mutex, NULL); #else init_MUTEX(mutex); #endif return RTOS_OK; }
Версия rtosMutexLock для пользовательского пространства использует функцию pthread_mutex_lock. В ядре используется функция down.
rtosError_t rtosMutexLock(rtosMutex_t *mutex){ int err; #ifndef __KERNEL__ err = pthread_mutex_lock(mutex); #else down(mutex); err = 0; #endif return (err == 0) ? RTOS_OK : RTOS_ERROR; }
down автоматически уменьшает счётчик семафора. Семафор захвачен, если после уменьшения счётчик становится нулевым; если счётчик становится отрицательным, то текущая задача помещается в непрерываемый сон на очереди ожидания семафора.Задача пробуждается только когда владелец семафора освобождает его, вызвав функцию up. Недостатком использования down является её врождённый непрерываемый сон. Вы никак не может прекратить выполнение задачи, которая спит в down. Чтобы полностью контролировать выполнение задачи, вместо неё должна использоваться функция down_interruptible. Функция аналогична down, за исключением того, что возвращает -EINTR, если сон прерван. Таким образом новой реализацией rtosMutexLock является:
rtosError_t rtosMutexLock(rtosMutex_t *mutex){ int err; #ifndef __KERNEL__ err = pthread_mutex_lock(mutex); #else err = down_interruptible(mutex); #endif return (err == 0) ? RTOS_OK : RTOS_ERROR; }
Функция rtosMutexUnlock реализована в пользовательском пространстве с помощью функции pthread_mutex_unlock. В ядре используется функция up. up атомарно увеличивает счётчик семафора и пробуждает задачи, спящие (прерываемым или непрерываемым сном) на очереди ожидания семафора.
rtosError_t rtosMutexUnlock(rtosMutex_t *mutex){ int err; #ifndef __KERNEL__ err = pthread_mutex_unlock(mutex); #else up(mutex); err = 0; #endif return (err == 0) ? RTOS_OK : RTOS_ERROR; }
Наконец, rtosMutexTryLock использует pthread_mutex_trylock в пространстве пользователя и функцию down_trylock в ядре. down_trylock не блокируется и немедленно возвращается, если семафор уже захвачен.
rtosError_t rtosMutexTrylock(rtosMutex_t *mutex){ int err; #ifndef __KERNEL__ err = pthread_mutex_trylock(mutex); if (err == 0) return RTOS_OK; if (errno == EBUSY) return RTOS_AGAIN; return RTOS_ERROR; #else err = down_trylock(mutex); if (err == 0) return RTOS_OK; return RTOS_AGAIN; #endif }
Чтобы подвести итог, в Таблице 6.1 перечислены соответствия один-к-одному между интерфейсами мьютекса RTOS и интерфейсами мьютекса Linux.
Таблица 6.1 Интерфейсы мьютекса RTOS и Linux
| |||||||||||||||||
Предыдущая Содержание Следующая |