如何保存新创建的用户线程的上下文执行,Linux 64在C中构造?

时间:2017-10-01 06:10:53

标签: c linux multithreading

我正在尝试实现一个类似于原始pthread的新用户线程管理库,但仅在C中。只有上下文切换应该是汇编程序。

看起来我从根本上遗漏了一些东西。 我有以下结构用于上下文执行:

enter code here

struct exec_ctx {
uint64_t rbp;
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rsi;
uint64_t rdi;
uint64_t rdx;
uint64_t rcx;
uint64_t rbx;
uint64_t rip;
}__attribute__((packed));

我创建了新的线程结构,我应该将寄存器放入上面提到的变量中,这是上下文执行结构的一部分。我怎么能用C做呢?到处都只谈到setcontext,getcontext,但这不是这里的情况。

另外,我收到的唯一提示是我需要在create函数中使用某种转储堆栈功能....不知道该怎么做。请告知我在哪里可以进一步阅读/如何操作。

提前致谢!

我开始时:

 char *stack;
 stack = malloc(StackSize); 
 if (!stack)
     return -1;

 *(uint64_t *)&stack[StackSize -  8] = (uint64_t)stop;
 *(uint64_t *)&stack[StackSize - 16] = (uint64_t)f;
 pet_thread->ctx.rip = (uint64_t)&stack[StackSize - 16];
 pet_thread->thread_state = Ready;

这是我在堆栈顶部放置一个指向线程函数的指针,以便更容易地调用线程。

1 个答案:

答案 0 :(得分:1)

首先,您不需要保存所有寄存器。由于您的上下文切换是作为一个函数实现的,因此ABI定义为“调用者保存”或“破坏”的任何寄存器都可以安全地省略。 C编译器生成的代码将假设它可能会发生变化。

由于这是学校作业,我不会给你代码来做这件事。我会给你一个大纲。

您的函数需要将寄存器保存到输出微线程的结构加载传入的微线程的寄存器。原因是逻辑上总是有一个寄存器设置“有效”。所以你的函数需要两个参数,即传出微线程的结构和传入的线程的结构。

这两个参数存储在两个寄存器中。那两个你不需要保存。所以你的代码应该具有以下结构(假设你的结构,正如我所说,它太完整了):

# save context
mov [rdi], rbp
add 8, rdi
...

#load context
mov rbp, [rsi]
add 8, rsi
...

如果将其放在单独的.S文件中,您将确保C编译器不会添加任何内容或优化任何内容。

这不是最干净或最有效的解决方案,但它是最简单的。