LINUX.ORG.RU

блокировка чтения-записи для спин-блокировки KERNEL


0

2

Здравствуйте.

Есть вопрос по использованию блокировок чтения-записи для спин-блокировок в ядре. А точнее, как часто можно их захватывать. Выбор пал на спин-блокировки, по причине, не перевода задачи в блокированное состояние и переключение контекста.

Есть структура (двусвязный список), для примера:

struct list {
        rw_lock_t *list_lock;
        char *pointer;
        struct list *next;
        struct list *prev;
}

Для доступа на чтение к pointer захватываем блокировки read_lock и read_unlock соответственно. Происходит это достаточно часто... Может 1000, а может и 10000 раз в секунду (точно не измерял). Соответственно для записи write_lock и write_unlock. Запись происходит редко...

Собственно, в момент захвата блокировки, в рандомный момент ядро падает в панику. т.е. может упасть через минуту работы а может и больше... Падает на ф-ции чтения состояния блокировки, точно не помню как называется.

И по этому вопрос, как часто эти блокировки можно захватывать?

И какое кол-во их(блокировок) можно «наплодить»? т.к. структкра может разростись до 1000-10000 записей...

А может я что-то делаю не так?

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



Последнее исправление: Inversiya (всего исправлений: 2)

Ответ на: комментарий от i-rinat

Нет... Не нужно этого, по моему...

т.к. при записи может изменяется только одна запись, а блокироваться будет весь список...

Или так лучше?

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

Если список во время исполнения не изменяется, почему он именно список, а не статически заданный массив? У тебя указатель на rwlock_t куда указывает?

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

список то изменяется.

Если нам нужно изменить что-то по указателю, то просто захватываем блокировку на запись и изменяем.

Если нам нужно добавить записи, то выделяем память под новый элемент структуры, заполняем её. После захватываем блокировку на запись у последнего элемента, меняем значение *next на только что выделенный элемент. Если нужно добавить в середину списка, просто запоминаем старые значения *next и *prev и при блокировке меняем на новые... так же не забывая про соседей...

С удалением примерно так же...

list_lock это указатель на тип rwlock_t. Собственно указатель на саму блокировку (если можно так выразиться). при создании нового элемента списка инитим её rwlock_init(&list_lock) и потом в ходе работы «захватываем» read_lock(&list_lock)... Для каждого элемента списка, блокировка своя...

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

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

так же не забывая про соседей...

Список замкнут в кольцо.

list_lock это указатель на тип rwlock_t

Похоже, ты используешь случайное место в памяти под спинлок. Эдакая русская рулетка.

i-rinat ★★★★★
()
Ответ на: комментарий от Inversiya

а, да.. при удалении/добавлении в середине списка, блокировка захватывается у предыдущего элемента.. соответственно все читальщики стопаются на нём, и не идут дальше. Все выделения или удаления делаются вне блокировки на запись.. Во время блокировки на запись, делаются только изменения в указателях, next prev или pointer. что-бы минимизировать время прибывания в блокировке на запись

Inversiya
() автор топика
Ответ на: комментарий от i-rinat

нет, список у меня не кольцо. у него есть начало и есть конец.

А вот про место в памяти дли спилока, расскажите пожалуйста поподробнее...

Inversiya
() автор топика

Отсутствует полный изолированный рабочий пример, а он бы очень помог автору.

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

ядро падает в панику

вы бы хоть само сообщение привели, а то конкретики ноль, одни ваши домыслы в тексте.

Любых блокировок может быть сколь угодно большое количество, насколько я знаю. И все ваши алгоритмы должны корректно работать на любом подходящем по семантике виде реализации блокировки, выбор реализации (спин, не спин) - уже вопрос оптимизации. У вас пока проблема с корректностью работы.

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

место в памяти дли спилока

Спинлок — это просто число. Всё остальное определяется способом работы с этим числом. Как указатель на int бесполезен без самого int, так и указатель на rwlock_t бесполезен без самого rwlock_t.

i-rinat ★★★★★
()
Ответ на: комментарий от Krieger_Od

Пример, прямо сейчас выложить не могу... не нашёл по быстрому... т.к этот код я писал давно.. (выше я об этом писал)

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

Вообще я 200 раз пересмотрел код, вроде там было всё ок.. )) И при захвате неинициалированной/несуществующей блокировки, ядро себя не так ведёт.. ))) (наступал на эти грабли)

Но вы наверное правы... надо найти код и протестировать ещё раз...

Я собственно интересовался именно количеством и частотой захвата блокировки...

А так, пойду искать/писать код... и тестить...

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

ааа... блин тупанул... сори...

У меня там не указатель...

Просто по памяти писал...

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