phantom-84 писал(а):
esp[-2]: имитирует действия пролога (видимо, содержит значение EBP - можно использовать для задания начального значения EBP);
Да, ebp, ибо при вызове сишной функции уже в её теле происходит
Код:
push ebp
mov ebp, esp
.
.
.
тут что-то делаем
.
.
.
pop ebp
ret
То есть в моем случае имеем дизассемблированный хвост переключалки
Код:
.
.
.
popf ;Выталкиваю флаги из стека нового потока
pop ebp
ret
Все значения корректны у меня, адрес возврата и флаги, но падает из-за #PF...
P.S.:
phantom-84 писал(а):
Да, только перед cli сделай pushf
Сначала не понял зачем, потом въехал - для следующих переключений. Добавил, заработало с popf
Со структурой стекового кадра задачи разобрался вроде, ещё раз спасибо
Добавил две функции - приостановка потока и корректный выход из него
Код:
/*-----------------------------------------------------------------------------
* Suspend thread
*---------------------------------------------------------------------------*/
void thread_suspend(thread_t* thread, bool suspend)
{
thread->suspend = suspend;
}
/*-----------------------------------------------------------------------------
* Correct exit from thread
*---------------------------------------------------------------------------*/
void thread_exit(thread_t* thread)
{
/* Disable all interrupts */
asm volatile ("cli");
/* Remove thread from queue */
list_remove(&thread->list_item);
/* Free thread's memory (handler and stack) */
free(thread->stack);
free(thread);
/* Load to ECX switch function address */
asm volatile ("mov %0, %%ecx"::"a"(&switch_task));
/* Enable all interrupts */
asm volatile ("sti");
/* Jump to switch_task() */
asm volatile ("call *%ecx");
}
В том же линуксе, если поток не зациклен while (1) без pthread_exit(...) наблюдается вывал программы. Тут же столкнулся с тем что такой вот поток
Код:
void task01(void)
{
print_text_XY(0, 10, "I'm task #1");
print_dec_XY(13, 10, count01);
count01++;
}
при выходе закономерно плюет управление в никуда. А вот так
Код:
void task01(void)
{
print_text_XY(0, 10, "I'm task #1");
print_dec_XY(13, 10, count01);
count01++;
thread_exit(thread01);
}
всё норм
P.P.S.: Запилил виртуальные экраны для каждого потока. Теперь всё ровненько без принудительной синхронизации
функция потока стала такого вида
Код:
/*------------------------------------------------------------------------------
// Thread #1
//----------------------------------------------------------------------------*/
void task01(void)
{
char tmp_str[256];
vs01 = (vscreen_t*) get_vscreen();
while (1)
{
vs01->cur_x = 0;
vs01->cur_y = 11;
dec2dec_str(count01, tmp_str);
vprint_text(vs01, "I'm thread #1: ");
vs01->cur_x = 16;
vprint_text(vs01, tmp_str);
count01++;
}
destroy_vscreen(vs01);
thread_exit(thread01);
}
Но скажем при обращении к "куче" всё равно потребна синхронизация, в каждом потоке выполняется маллок при старте