ARM Cortex: мьютекс с использованием битовых полос - PullRequest
5 голосов
/ 18 мая 2010

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

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

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

try lock
take lock
release lock

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

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

Ответы [ 4 ]

4 голосов
/ 22 мая 2010

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

2 голосов
/ 10 июля 2013

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

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

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

1 голос
/ 21 мая 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: установить / очистить бит, используя битовую полосу. (Атомный)

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

0 голосов
/ 16 декабря 2011

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

...