Все данные в памяти можно считать «общим ресурсом», если оба потока могут получить к нему доступ *. Единственный ресурс, которым они не будут делиться между процессорами, это данные в регистрах, которые абстрагированы в C.
Есть две причины, по которым вы бы практически не рассматривали возможность совместного использования двух ресурсов (даже если они на самом деле не означают, что два потока теоретически не могут получить к ним доступ, какой-то кошмарный код иногда может их обойти).
- Только один поток может / делает доступ к нему. Ясно, что если только один поток обращается к переменной, тогда не может быть условий гонки. По этой причине локальные переменные и однопоточные программы не нуждаются в механизмах блокировки.
- Значение постоянное. Вы не можете получить разные результаты в зависимости от порядка доступа, если значение никогда не изменится.
Программа, которую вы показали здесь, является неполной, поэтому трудно сказать, но каждая переменная, к которой обращаются без блокировки, должна соответствовать одному из критериев для этой программы, чтобы быть потокобезопасной.
Существуют некоторые неочевидные способы удовлетворения критериям, например, если переменная постоянна или ограничена одним потоком только в определенном контексте.
Вы привели два примера строк, которые не были заблокированы. Для первой строки.
dev = container_of(inode->i_cdev, struct scull_dev, cdev);
Эта строка на самом деле не обращается к каким-либо переменным, она просто вычисляет, где должна быть структура, содержащая cdev
. Не может быть условий гонки, потому что никто не имеет доступа к вашим указателям (хотя они имеют доступ к тому, на что они указывают), они доступны только внутри функции (это не соответствует тому, на что они указывают). Это соответствует критериям (1).
Другой пример:
int quantum = dev->quantum, qset = dev->qset;
Это немного сложнее сказать без контекста, но я думаю, что предполагается, что dev->quantum
и dev->qset
никогда не изменятся во время вызова функции. Это подтверждается тем фактом, что они вызываются только в scull_init_module
, который должен вызываться только один раз в самом начале. Я считаю, что это соответствует критериям (2).
, который предлагает другой способ изменения общей переменной без блокировки, если вы знаете, что другие потоки не будут пытаться получить к ней доступ, пока вы не закончили по какой-то другой причине (например, они еще не существуют)
Короче говоря, вся память распределяется, но иногда вы можете сойти с рук, как будто это не так.
* Возможно, может существовать система, в которой каждый процессор имеет некоторый объем ОЗУ, который может использовать только он, но это не типичный случай.