Идея в следующем. Чтобы не было разыменование нулевого указателя, нужно, чтобы не было нулевого указателя. Ваш КО. Так сложилось, что однажды я исправил небольшую проблему в ядре Linux, но это была не текущая ветка ядра, а стабильная. В текущей на тот момент эту проблему тоже исправили, но по другому.
Проблема была простая и весьма распространенная. Один поток освобождает буфер, во время, пока второй продолжает его использовать. Состояние гонки. Как избежать этой ситуации? Можно заставить один поток подождать, пока второй использует буфер, решение простое, но не эффективное, порой громоздкое.
Мое решение было другим, а зачем, собственно ждать, пока освободиться буфер, чтобы тут же его стереть? Давайте оставим его в покое, буфер небольшой 512 байт погоды не сделает. Удалим все другие буферы, которые точно в данный момент не используются, а последний оставим. Это намного облегчит процесс синхронизации двух потоков ядра, об этом просто не надо будет думать. А данные, которые останутся в буфере в любом случае могут быть, т.к. поступают туда по прерыванию, и даже если бы мы освободили последний буфер, в тот же момент, по прерыванию возможно выделение нового буфера и запись туда новых данных. Таким образом, получаем эффективное и более простое решение, чем решение в лоб. Пришлось удалять первое исправление и добавлять свое, что сделало исправление намного больше, чем должно было быть.
---
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 6c9b7cd..4f02f9c 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -114,11 +114,14 @@ static void __tty_buffer_flush(struct tty_struct *tty)
{
struct tty_buffer *thead;
- while ((thead = tty->buf.head) != NULL) {
- tty->buf.head = thead->next;
- tty_buffer_free(tty, thead);
+ if (tty->buf.head == NULL)
+ return;
+ while ((thead = tty->buf.head->next) != NULL) {
+ tty_buffer_free(tty, tty->buf.head);
+ tty->buf.head = thead;
}
- tty->buf.tail = NULL;
+ WARN_ON(tty->buf.head != tty->buf.tail);
+ tty->buf.head->read = tty->buf.head->commit;
}
/**
Автор: izyk