Системные вызовы в UNIX-подобных ОС являются реентерабельными (т.е. несколько системных вызовов могут выполняться параллельно). Существуют ли какие-либо ограничения порядка этих системных вызовов в смысле отношения C / C ++ 11, возникающего до?
Например, давайте рассмотрим следующую программу с 3 потоками (в псевдокоде):
// thread 1
store x 1
store y 2
// thread 2
store y 1
store x 2
// thread 3
Thread.join(1 and 2)
wait((load x) == 1 && (load y) == 1)
Здесь, предположим, x
а также y
общие местоположения, и все load
а также store
У вас спокойный порядок. (ПРИМЕЧАНИЕ: при непринужденном атомном доступе расы не считаются ошибками; они намеренный в смысле семантики C / C ++ 11.) Эта программа может завершиться, поскольку (1) компилятор может переупорядочить store x 1
а также store y 2
и затем (2) выполнить store y 2
, store y 1
, store x 2
, а потом store x 1
так (3) поток 3 может читать x = 1
а также y = 1
в то же время.
Я хотел бы знать, если следующая программа также может прекратить. Здесь некоторые системные вызовы syscall1()
& syscall2()
вставляются в тему 1 & 2 соответственно:
// thread 1
store x 1
syscall1()
store y 2
// thread 2
store y 1
syscall2()
store x 2
// thread 3
Thread.join(1 and 2)
wait((load x) == 1 && (load y) == 1)
Программа кажется невозможным завершить. Тем не менее, в отсутствие ограничений порядка системных вызовов, я думаю, эта программа может завершиться. Вот причина. предполагать syscall1()
а также syscall2()
не сериализуются и могут выполняться параллельно. Затем компилятор, с полным знанием семантики syscall1()
а также syscall2()
, может все еще изменить порядок store x 1
& syscall1()
а также store y 2
,
Поэтому я хотел бы спросить, существуют ли какие-либо ограничения порядка системных вызовов, вызываемых различными потоками. Если возможно, я хотел бы знать авторитетный источник для такого рода вопросов.
системный вызов (перечисленные в Системные вызовы (2)…) является элементарный работа, с точки зрения прикладной программы на земле пользователя.
Каждый системный вызов (по определению) вызывает ядро через несколько не замужем Машинный код инструкция (SYSENTER
, SYSCALL
, INT
…); детали зависят от процессора (его набор инструкций) и ABI. ядро это делает бизнес (обработки вашего системного вызова — который может быть успешным или неудачным), но ваша пользовательская программа видит только элементарный шаг. Иногда этот шаг (во время которого ядру дается контроль) может длиться долгое время (например, минуты или часы).
Итак, ваша программа в пользовательская земля работает на виртуальной машине низкого уровня, предоставленной пользовательский режим машинные инструкции вашего процессора, дополненные одной «виртуальной» инструкцией системного вызова (способной выполнить любой системный вызов, реализованный ядром).
Это не запрещает вашей программе глючить из-за условий гонки.
Других решений пока нет …