我应该在C中实现一个userlevel线程库。为此,我需要实现yield()
,createThread()
和destroyThread()
函数。我相信我已经掌握了基本知识:
为了跟踪线程,我将使用ThreadControlBlock
个元素(在操作系统中类似PCBs)的队列,如下所示:
struct ThreadControlBlock {
int ThreadId,
u_context *context };
我们可以使用setcontext()
函数族来“保存”和“加载”上下文。
在程序初始化时,初始化ThreadQueue而不使用任何元素。
现在我没有得到的部分:当一个线程调用yield()
时,我获取当前上下文并将其保存在ThreadControlBlock
中并放入队列中。然后获取队列中的第一个元素并在其中加载上下文,然后继续执行。
问题是,如果我这样做,说我是一个调用yield()
的线程,下一个线程是我自己。如果我正在保存上下文并再次加载它,那么在重新输入时我不会在我所在的位置(在调用yield()
之前)吗?这会继续下去吗?
答案 0 :(得分:1)
当线程调用yield()
时,您必须保存即将从yield()
调用返回的线程的状态。不要在yield()
之前保存上下文。
答案 1 :(得分:0)
在yield()
实现中检查下一个线程是否是当前线程并将该案例视为无操作是完全合理的。
答案 2 :(得分:0)
如果除了当前线程之外没有其他线程可以运行那么除了从yield返回之外没有别的事可做。在这种情况下,我不打算调用swapcontext,只需检测并返回。
我认为你实际处理的是在调用yield时没有线程(包括当前线程)时该怎么做。处理此问题的一种简单方法是使用空闲线程,该线程仅在运行队列(就绪线程)为空时运行。这个主题可能只是:
{
while (1) {
yield();
pause();
}
}
这允许程序进入睡眠状态(通过暂停)直到信号发生。希望信号将是一些使其他线程准备好运行的事件,因此下一次调用yield将运行另一个线程,而不是再次运行空闲线程。
答案 3 :(得分:0)
如果您正在切换到另一个任务,那么同样的问题实际上也适用 - 因为其他任务在同一点(它将要切换到第二个任务)保存其上下文。使用setcontext()
和getcontext()
,您需要使用静态变量来跟踪您是在切换还是切换出来:
static volatile int switched;
switched = 0;
getcontext(current->context);
if (!switched)
{
switched = 1;
setcontext(next->context);
}
或者,您可以使用swapcontext(current->context, next->context);