Кора ARM: взаимное исключение с помощью разрядного соединения

Учитывая, что на Коре ARM M3 я могу:

  • атомарно считайте единственный бит
  • атомарно установите единственный бит
  • атомарно очистите единственный бит

Как может я комбинировать их для взаимоисключающего набора стиля операций:

try lock
take lock
release lock

Это кажется этим try_lock или take_lock потребовал бы двух операций, которые не будут атомарными.

Мне нужно больше управления для выполнения этого? Отключите глобальные прерывания, сделал бы это, но кажется, что должен быть более хирургический подход.

5
задан Martin Thompson 19 December 2011 в 14:43
поделиться

2 ответа

Ваш rwl_TryLock() не обязательно возвращает ошибку, если блокировка уже удерживается в момент вызова (ваш компилятор должен выдавать хотя бы предупреждение о пути кода, который не имеет возвращаемого значения). Попробуйте сделать следующее:

int rwl_TryLock(volatile uint32_t *lock, int who){

    Var_SetBit_BB((uint32_t)lock, who);
    if(*lock == (1<<who)){ // check that we have exclusive access
        // got the lock!
        return 1;
    } 

    // do not have the lock
    Var_ResetBit_BB((uint32_t)lock, who); // clear the lock flag
    return 0;
}

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

Кроме того, прерывания могут быть отключены/включены на Cortex M3 довольно быстро (это простое обновление регистра NVIC). Вы уверены, что ваша система не может жить с дополнительными несколькими циклами задержки прерывания, чтобы сохранить код для обработки структур данных блокировки простым (что обычно означает, что его легче исправить)?

.
4
ответ дан 14 December 2019 в 08:44
поделиться

Немного информации после некоторого поиска:

" ARM Cortex-M3 битовый биндинг Ядро микроконтроллера ARM предлагает еще один способ реализации семафоров. Доступ на запись к переменным в области псевдонимов битовой полосы вызывает атомарный доступ на чтение-модификацию-запись к ячейке памяти в области битовой полосы на уровне системной шины. Как это переводится в семафоры? Переменная в области битовой полосы может служить контейнером для семафоров. Каждый клиент "владеет" битом в этом контейнере. Всякий раз, когда клиенту нужно затребовать семафор, он устанавливает свой бит, записывая 1 в соответствующее место в области псевдонимов битовой полосы. Затем он считывает контейнер (область битовой полосы) и проверяет, что никакие другие биты не установлены, что означает, что клиент успешно затребовал семафор. В случае, если другие биты установлены, клиент должен снова очистить свой бит и повторить попытку (возможно, после ожидания). " (source)

Вот моя грубая (непроверенная) интерпретация:

/*
 * Frees a lock.
 *
 * @note lock must point to a fully aligned 32 bit integer.
 * (atomically set to 0)
 *
 * @returns 1 if successfull
 */
int rwl_FreeLock(volatile uint32_t *lock){
    *lock = 0;
    return 1; // always successful
}

/*
 * Attempts to acquire a lock
 * @param who is the client taking the lock
 * @lock pointer to the mutex (uint32_t value in memory)
 * @note lock must point to a fully aligned 32 bit integer.
 * (atomically set to 1 only if set to 0)
 */
int rwl_TryLock(volatile uint32_t *lock, int who){
    // initial check of lock
    if(*lock == 0){
        Var_SetBit_BB((uint32_t)lock, who);
        if(*lock == (1<<who)){ // check that we still have exclusive access
            // got the lock!
            return 1;
        } else {
                    // do not have the lock
            Var_ResetBit_BB((uint32_t)lock, who); // clear the lock flag
            return 0;
        }
    }
}

Var_Set_BB / Var_Reset_BB: установка / очистка бита с использованием битового биндинга. (atomic)

Однако, это не работает!!!

1
ответ дан 14 December 2019 в 08:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: