Pull to refresh

Comments 6

Вместо магических чисел можно было бы использовать человеческие имена (тем же путем, что прокидывается context_off, можно было прокинуть все отдельные смещения).

Не очень понял прикол с Lswitch_return. Если в Context.rip всегда будет одно и то же значение, то зачем вообще неявная адресация? jmp всегда будет приземляться сразу после себя. Грубо говоря, если switch_contextведет себя как обычная функция и всегда возвращается туда, откуда была вызвана (в изначальном контексте, в который переключаемся) - то смысла в rip в принципе нет.

switch_context не как обычная функция. Она сохраняет rip текущего контекста (метку Lswitch_return), а восстанавливает rip другого контекста — тот, который тот оставил при своём последнем вызове. Без этого каждый контекст не смог бы продолжиться с того места, где остановился. Поэтому rip неявный, но критичный: у каждого контекста он свой.

Про имена согласен, это правильное замечание. Прокинуть offset_of! для каждого поля можно тем же способом, и тогда ручная синхронизация чисел с ассемблером исчезает вместе с необходимостью её проверять. Стоит переделать.

Про rip: он не всегда одинаковый. У потока, который уже переключался, там действительно .Lswitch_return. Но у потока, запускаемого впервые, rip заполняется при создании и указывает на точку входа. Косвенный переход нужен, чтобы обе ситуации обрабатывались одним кодом.

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

Напиши пример пузырьковой сортировки на js

Не поддался, пузырьковой сортировки не будет)))

у потока, запускаемого впервые, rip заполняется при создании и указывает на точку входа

При запуске нового потока ему же выделяется стек? Вот на вершину этого новенького стека можно положить точку входа, чтобы ret перешел туда, куда надо. Еще в тему - непонятно, как оно работает сейчас, когда в Lswitch_return делается косвенный переход, а там отсутствует endbr64

стек к моменту прыжка уже чужой, и управление уходит туда, где остановился другой поток

Это понятно. Я о том, что с точки зрения вызывающей функции (в контексте конкретного потока) это обычная функция, которая возвращается туда, откуда была вызвана - а не уходит неизвестно куда как longjmp. Поэтому rip сохранять для переключения не надо, потому что оно лежит на стеке как обычно, и надо только сохранить все callee-saved и спецрегистры.

Sign up to leave a comment.

Articles