ARM Cortex: мьютекс с использованием бит-бэндинга

Учитывая это, на ARM Cortex M3 я могу:

  • атомарно прочитать один бит
  • атомарно установить один бит
  • атомарно очистить один бит

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

try lock
take lock
release lock

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

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


person JeffV    schedule 18.05.2010    source источник


Ответы (4)


Ваш 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). Вы уверены, что ваша система не может жить с дополнительными несколькими циклами задержки прерывания, чтобы код для обработки структур данных блокировки был простым (что обычно означает, что его легче исправить)?

person Michael Burr    schedule 22.05.2010

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

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

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

/*
 * 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: установить / сбросить бит с использованием бандинга. (атомный)

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

person JeffV    schedule 21.05.2010
comment
Если две вещи попытаются получить доступ к блокировке, может показаться, что оба доступа могут сообщить об ошибке. Лучшим подходом было бы использование спин-петли ldrex / strex. Как уже было сказано, в какой степени доступ к битовой полосе гарантирован атомарно при наличии таких вещей, как DMA и тому подобное? Если запись DMA и запись в полосе битов происходят примерно одновременно, гарантируется ли, что запись DMA не произойдет между аспектами «чтение» и «запись» записи в битовой полосе? - person supercat; 13.06.2012

Бит-бандаж не сработает в этой ситуации. Это просто действительно изящный способ установки битов в файлах регистров устройства и в вашей памяти. Используйте инструкции Load Exclusive и Store Exclusive, чтобы реализовать свой семафор / мьютекс. Вот пример документа, который вы можете использовать, который реализует семафор, используя эти инструкции, и подробно описывает, как это работает.

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0439b/CHDDIGAC.html

При этом вы можете уменьшить объем памяти, занимаемый вашими мьютексами, используя битовые диапазоны ...

person Robert Stoddard    schedule 09.07.2013

Я никогда не использовал бит-бандаж на ARM; Вместо этого я предпочитаю использовать для всех таких операций исключительную загрузку / условное хранилище. Используйте цикл для эксклюзивной загрузки старого значения, вычисления нового значения и использования условного хранилища для его обратной записи. Цикл до тех пор, пока условное хранилище не завершится успешно (что, вероятно, произойдет во второй раз, если не в первый).

person supercat    schedule 16.12.2011