linux pthread_mutex_lock работает только со второй попытки - PullRequest
1 голос
/ 07 мая 2020

Изменить: я прикрепляю фрагмент, я инициализировал attr, и все вызовы были хорошими.

Я пытался использовать мьютекс с PRIO_PROTECT, но первый вызов возвращает EINVAL, а второй вызов возвращает ноль \ успех. вот что я сделал:

pthread_mutexattr_setprioceiling(&attr, 99);
pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_PROTECT);
pthread_mutex_init(&plock, &attr);
pthread_mutexattr_destroy(&attr);
ret = pthread_mutex_lock(&plock);  //now ret == EINVAL
ret = pthread_mutex_lock(&plock);  // ret == 0

Я понимаю, что EINVAL означает, что приоритет вызывающего абонента выше потолка, поэтому у меня есть 2 вопроса:

  1. почему со второй попытки работает?

  2. Как снизить приоритет нити до потолка? а точнее выставить потолок на приоритет нити?

Ответы [ 2 ]

3 голосов
/ 07 мая 2020

Отсутствует вызов pthread_mutexattr_init.


PTHREAD_PRIO_PROTECT означает:

Когда поток владеет одним или несколькими не- устойчивые мьютексы, инициализированные протоколом PTHREAD_PRIO_PROTECT, , он должен выполняться с наивысшим из его приоритета или наивысшим из верхних пределов приоритета всех ненадежных мьютексов, принадлежащих этому потоку и инициализированных этим атрибутом, независимо от того, другие потоки заблокированы на любом из этих ненадежных мьютексов или нет.

Это означает, что pthread_mutex_lock устанавливает приоритет текущего потока на max(current_priority, prioceiling). Ваш prioceiling - 99, и для такого приоритета требуется поток с классом планирования в реальном времени (FIFO или циклический).

Фактически, любой приоритет для pthread_mutexattr_setprioceiling требует класса планирования в реальном времени:

Значения prioceiling находятся в максимальном диапазоне приоритеты определены SCHED_FIFO.

Это потому, что функции, которые вы хотите использовать, принадлежат POSIX расширениям реального времени , а класс планирования по умолчанию SCHED_OTHER - для :

Эта политика определена для того, чтобы разрешить строго соответствующим приложениям иметь возможность переносным образом указывать, что им больше не нужна политика планирования в реальном времени.

Если вы запускаете свое приложение с sudo chrt --fifo 1 <app>, оно назначает вашему процессу класс планирования FIFO с приоритетом 1, что позволяет ему успешно блокировать мьютекс при первом вызове.


Относительно того, почему второй вызов завершается успешно, когда 1-й не работает, это кажется недокументированным поведением, если я не ошибаюсь, и , вероятно, ошибка в glib c.

0 голосов
/ 08 мая 2020

Вы пытаетесь поднять текущий приоритет исполняемого кода или просто защитить некоторые данные.

Если вы просто пытаетесь защитить некоторые данные ...

pthread_mutex_t  myMutex = PTHREAD_MUTEX_INITIALIZER;

тогда, когда вы хотите использовать mutex:

pthread_mutex_lock( &myMutex );
... // manipulate the 'critical' data

Затем, когда вы будете готовы разрешить другому потоку доступ к тем же данным.

... // finished manipulation of the 'critical' data
pthread_mutex_unlock( &myMutex );

Примечание: существуют другие значения для инициализации, но указанное выше значение макроса является наиболее часто встречается.

...