Причины, по которым процедура rps использует spinlock с local_irq_disable

Сейчас я изучаю код внутренней сети ядра, особенно код RPS. Вы знаете, есть много функций об этом. Но я сосредоточен на некоторых функциях обработки очереди SMP, таких как enqueue_to_backlog а также process_backlog,

Интересно о синхронизации между двумя ядрами (или одноядерными) с помощью двух функций - enqueue_to_backlog а также process_backlog -.

В этих функциях ядро (A) содержит spin_lock другого ядра (B) для очереди пакетов в input_pkt_queue и планирование напи ядра (B). И ядро (B) также содержит spin_lock для сращивания input_pkt_queue в process_queue ядра (B) и удаление напи график самостоятельно. я знаю это spin_lock следует удерживать, чтобы два ядра не могли обращаться к одной и той же очереди друг другу во время обработки очереди.

Но я не могу понять, почему spin_lock называется с local_irq_disable (или же local_irq_save ). Я думаю, что нет доступа к очередям или rps_lock ядра (B) посредством контекста прерываний (TH), когда прерывания (TH) выгружают текущий контекст (softirq, BH). - Конечно, доступ к napi-структуре для планирования napi может быть получен через TH, но она удерживает отключение irq до тех пор, пока пакет не будет поставлен в очередь. Поэтому мне интересно, почему spin_lock вызывается с отключением irq.

Я думаю, что невозможно исключить текущий контекст (napi, softirq) с помощью другой BH, такой как тасклет. Это правда? И я хочу знать, отключает ли local_irq_disable все ядра irq или буквально только irq текущего ядра? На самом деле, я прочитал книгу о разработке ядра, но мне кажется, что я недостаточно разбираюсь в вытеснении.

Объяснил бы причины, по которым процедура rps используется spin_lock с local_irq_disable ?

1 ответ

Решение

Отключение прерываний влияет на текущее ядро ​​(только). Следовательно, если этот параметр отключен, никакой другой код на том же ядре не сможет помешать обновлению структуры данных. Смысл спин-блокировки состоит в том, чтобы распространить "блокировку" на другие ядра (хотя это совместное, а не аппаратное обеспечение).

Опасно / безответственно брать спин-блокировку в ядре, не отключая прерывания, потому что, когда затем происходит прерывание, текущий код будет приостановлен, и теперь вы препятствуете прогрессу других ядер, пока работает какой-то несвязанный обработчик прерываний (даже если другой пользовательский процесс или тасклет в исходном ядре не сможет выгрузить). Другие ядра могут быть в контексте прерывания или BH, и теперь вы задерживаете всю систему. Предполагается, что спин-блокировки будут удерживаться в течение очень коротких периодов времени для критических обновлений общих структур данных.

Это также хороший способ генерировать тупики. Подумайте, реплицировался ли описанный выше сценарий в другую подсистему (или, возможно, другое устройство в той же подсистеме, но я опишу первое)

Здесь ядро ​​A получает спин-блокировку в подсистеме 1 без отключения прерываний. В то же время ядро ​​B получает спин-блокировку в подсистеме 2 также без отключения прерываний. Теперь, что произойдет, если прерывание, связанное с подсистемой 2, произойдет на ядре A, и при выполнении обработчика прерываний подсистемы 2 ядру A необходимо обновить структуру, защищенную спин-блокировкой, хранящейся в ядре B. Но примерно в то же время подсистема 1 прерывание происходит в ядре B, которому необходимо обновить структуру данных в этой подсистеме. Теперь оба ядра заняты ожиданием спин-блокировки, удерживаемой другим ядром, и вся система зависает до тех пор, пока вы не выполните полный сброс.

Другие вопросы по тегам