LINUX.ORG.RU

непонятки у Лава

 ,


0

0

в двух своих книгах Роберт Лав обращает внимание на то, что «простые интерфейсы для сна» хоть и широко используются, но их использование может привести к конкуренции. Дословно, «возможен переход в приостановленое состояние _после_ того как соответствующее событие произошло».

И тут же приводится пример рекомендующегося метода, который ничем не отличается от того самого, простого, интерфейса о котором я подумал сразу как начал читать главу. Метод один-в-один повторяет код макроса wait_event_interruptible. В то же время в LDD эти макросы активно используются, и авторы по этому поводу нисколько не комплексуют.

вот и вопрос, предлагается не использовать сам макрос, а разворачивать его? или Лав имел ввиду что-то другое под «простыми интерфейсами»?

Ответ на: комментарий от tailgunner

%)

ну вот какие простые методы для перехода в приостановленное состояние (с ожиданием условия) есть?

первое, что приходит на ум - wait_evet_interruptible и компания. ну вот отрывок из LKD-3:

Some simple interfaces for sleeping used to be in wide use. These interfaces, however, have races: It is possible to go to sleep after the condition becomes true. In that case, the task might sleep indefinitely.Therefore, the recommended method for sleeping in the kernel is a bit more complicated:

/* ‘q’ is the wait queue we wish to sleep on */
DEFINE_WAIT(wait);
add_wait_queue(q, &wait);
while (!condition) {
/* condition is the event that we are waiting for */
    prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE);
    if (signal_pending(current))
    /* handle signal */
        schedule();
}
finish_wait(&q, &wait);

но кусок кода - копия макроса wait_event_interruptible правда дальше есть пример функции

static ssize_t inotify_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
из inotify_user.c в котором не используется wait_event_interruptible, а просто этот цикл с некоторыми поправками . Но там и логика чуть посложнее.

а спрашивал я про то, что имел ввиду Лав под «simple interfaces for sleeping»? не на wait_event_* он же кивал?...

// ну и видимо, в случаях с не cлишком простой логикой следует макрос разворачивать, как это сделано в inotify_read

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от metawishmaster

Откуда ты взял этот код? По-моему, он в самом деле racy. Классический - вот:

#define __wait_event_interruptible(wq, condition, ret)                  \
do {                                                                    \
        DEFINE_WAIT(__wait);                                            \
                                                                        \
        for (;;) {                                                      \
                prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);      \
                if (condition)                                          \
                        break;                                          \
                if (!signal_pending(current)) {                         \
                        schedule();                                     \
                        continue;                                       \
                }                                                       \
                ret = -ERESTARTSYS;                                     \
                break;                                                  \
        }                                                               \
        finish_wait(&wq, &__wait);                                      \
} while (0)

здесь всё по учебнику (написанному до Лова):

1) заносим себя в очередь и ставим себе статус INTERRUPTIBLE;

2) проверяем условие;

3) если условие не выполняется - спим;

если событие происходит между 1 и 2, мы вывалимся при проверке условия; если между 2 и 3, то статус INTERRUPTIBLE будет сброшен, и планировщик не даст нам уснуть.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

код из R.Love - «Linux Kernel Development - 3», стр. 59. у него-то тоже все понятно, вроде бы: - занеслись в очередь

- пока нет условия спим

- под «/* handle signal */» я понял возврат -ERESTARTSYS

- если нет сигнала, то шедулимся

тогда про какие рейсы Лов говорил?... какие функци/макросы он имел ввиду?..

хотя, это уже похоже на какие-то странные вопросы %)

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от metawishmaster

тогда про какие рейсы Лов говорил?

Если в его коде событие приходит после проверки условия и перед prepare_to_wait, можно уснуть навсегда.

tailgunner ★★★★★
()

сначала я подумал что тут про Осознанные Сноведения и ТС ошибся топиком

bga_ ★★★★
()
Ответ на: комментарий от tailgunner

хм... действительно

тогда уж что-то типа

...
while(1) {
    prepare_to_wait(...)
    if (condition)
        break;
    if (signal_pending(current))
        return -ERESTARTSYS;
    ...
}
...

спасибо за разъяснения :)

metawishmaster ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.