Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing a User-Level Threads Package

I have been tasked in a class to create a user level thread library in C. I was wondering if anyone could give me a list of things to read up on to accomplish this. I have a good idea as to where to start, but any resources on user level threads and some applicable aspects of the C language that might help would be extremely valuable.

I am very unclear as to how I would implement a scheduler for such. Assume that I have a pretty good understanding of the C language and some of its more helpful library functions.

like image 342
SirensOfTitan Avatar asked Feb 04 '12 22:02

SirensOfTitan


People also ask

How are user level threads implemented?

In general, user-level threads can be implemented using one of four models. All models maps user-level threads to kernel-level threads. A kernel thread is similar to a process in a non-threaded (single-threaded) system. The kernel thread is the unit of execution that is scheduled by the kernel to execute on the CPU.

How do I create a user-level thread?

User-level threads can be created in different ways. One of them is through context switching . There will be a single process and we change the context in a round-robin fashion. We change the context to some different thread after every short time interval.


1 Answers

I’ve done this for a homework assignment without writing any assembler at all. The thread switch mechanism was setjmp/longjmp. What this involved was allocating memory for each thread’s stack, then very carefully massaging the values in the jmp_buff so execution jumps to the next thread’s stack.

See also Russ Cox’s pretty readable libtask.

Edit in response to OP’s comment: In deciding when to switch threads there are two main directions: preemptive & cooperative. In the preemptive model, you’ll have something like a timer signal that causes execution flow to jump to a central dispatcher thread, which chooses the next thread to run. In a cooperative model, threads “yield” to each other, either explicitly (e.g., by calling a yield() function you’ll provide) or implicitly (e.g., requesting a lock held by another thread).

Take a look at the API of libtask for an example of the cooperative model, particularly the description of the function taskyield(). That’s the explicit yield I mentioned. There are also the non-blocking I/O functions which include an implicit yield—the current “task” is put on hold until the I/O completes, but the other tasks get their chance to run.

like image 126
J. C. Salomon Avatar answered Sep 30 '22 02:09

J. C. Salomon