#c #multithreading #pthreads
Вопрос:
Я пытаюсь реализовать библиотеку потоков, используя ассемблерный код, чтобы сохранить регистры в структуре tcb, получить новый поток из очереди e, загрузить его tcb в регистры.
Я использую все 16 регистров общего назначения и eflags. Однако я сталкиваюсь с некоторыми трудностями, потому что ассемблерный код работает неправильно. Он продолжает показывать ошибку сегментации.
Это то, что я сделал в сборке, чтобы переключить контекст:
change_context:
// Saving current context
pushfq
pushq %rax
movq tcb, %rax
popq 0(%rax)
movq %rcx, 8(%rax)
movq %rdx, 16(%rax)
movq %rbx, 24(%rax)
movq %rsi, 32(%rax)
movq %rdi, 40(%rax)
movq %rbp, 48(%rax)
movq %r8, 56(%rax)
movq %r9, 64(%rax)
movq %r10, 72(%rax)
movq %r11, 80(%rax)
movq %r12, 88(%rax)
movq %r13, 96(%rax)
movq %r14, 104(%rax)
movq %r15, 112(%rax)
popq 120(%rax)
movq %rsp, 128(%rax)
// Find new context
call get_next_thread
//Restauring context
movq current_running, %rax
movq 8(%rax), %rcx
movq 16(%rax), %rdx
movq 24(%rax), %rbx
movq 32(%rax), %rsi
movq 40(%rax), %rdi
movq 48(%rax), %rbp
movq 56(%rax), %r8
movq 64(%rax), %r9
movq 72(%rax), %r10
movq 80(%rax), %r11
movq 88(%rax), %r12
movq 96(%rax), %r13
movq 104(%rax), %r14
movq 112(%rax), %r15
pushq 120(%rax)
popfq
movq 128(%rax), %rsp
pushq 0(%rax)
popq %rax
ret
«tcb» — это указатель на текущий блок управления потоком, и он имеет следующую грань:
struct _tcb{
uint64_t registers[15];
uint64_t flags;
uint64_t stack_ptr;
uint64_t *stack;
}
При создании потоков я инициализирую их нулями, за исключением %rdi, указывающего на void *arg, и stack_ptr, указывающего на последнюю позицию стека, куда я помещаю значение start_routine.
Функция создания потока аналогична функции по умолчанию из «pthread.h».
int create_thr(pthread_t *thread,
void *(*start_routine)(void *),
void *arg);
Единственная разница в том, что я не использую атрибуты.
Я отладил его с помощью valgrind и gdb. Я узнал, что его первая жалоба исходит из строки «popq 0(%rax)»; там написано «недопустимая запись размера 8». Позже он получает ошибку сегментации в таких функциях, как printf и usleep. Я использую 64-разрядную версию Linux.
Есть какие-нибудь идеи?
Комментарии:
1. Вы пробовали распечатать значение
%rax
, чтобы проверить, правильный ли это адрес?2. @Аджайбрахмакшатрия, я так и сделал. На нем указан правильный адрес. Проблема обычно заключается в rflags и stack_pointer