Re: allocating kernel threads from a pool



railrulez@xxxxxxxxx wrote:

I am implementing a user-space threading library (in Linux) that uses
kernel level threads to do IO, so that a user-level thread's IO calls
will not block the entire program. For performance reasons, I want to
create an initial pool of kernel threads, and every time a user-level
thread needs to do IO, it wakes up one of the idle kernel threads to
do the work (and subsequently yields to other user-level threads)

My current implementation strategy is this:

1. During initialization in the main process, create many kernel
threads using clone (with CLONE_VM set), and have them spin in a
while(1) { usleep(LOTS_OF_TIME); } loop.

2. Whenever a user-level thread needs to do IO, it picks a idle child,
and sends it a signal to wake up, using kill(2)

3. The child wakes up (or rather, gets jostled out of bed), and in the
signal handler, it looks up some data structure to find what operation
is required of it and where to dump the output, does the IO, and goes
back to sleep.

Any particular reason why you are not using mutex + condition? Benefits
of using them may be:

1) The implementation is simple and robust: mutex + condition +
container.
2) There is no syscall (kill) involved while posting a command, when
there is no contention, which is ofthen the case.
3) There is not much you can do from within the signal handler. Here
you don't need signals at all.

Another aproach is to create a datagram socketpair(). All your worker
threads are blocked in read() syscall on the same end of the pair. When
another thread writes a pointer to a command to another end of the
socketpair only one of the waiting worker threads is woken up to read
the data. No signal handlers, no mutexes/conditions, can't go simpler.

I don't know if this is a good scheme in the first place, but in any
case, I cant find a clean way to implement this. The problem I'm facing
is that in step 3, I can't find a good way to give the child the
information it needs to do the IO (ie, what function -- read()?
write()? what arguments? etc.) in a clean way. I have two options:

If you do want to use signals, you could use sigqueue() instead of
kill() to pass a pointer to your data along with the signal. That
pointer may be a pointer to a command (command design pattern). The
worker thread will invoke the command. The command contains all the
information reuired to do its job, it only has to be invoked.

Take a look at boost::function and boost::bind:

http://boost.org/doc/html/function.html
http://boost.org/libs/bind/bind.html

#include <unistd.h>
#include <boost/function.hpp>
#include <boost/bind.hpp>

typedef boost::function<void()> cmd;

int main()
{
// create commands
cmd a(boost::bind(write, STDOUT_FILENO, "hello ", sizeof "hello " -
1));
cmd b(boost::bind(write, STDOUT_FILENO, "world\n", sizeof "world\n"
- 1));

// execute them later elsewhere
a();
b();
}

[]

I'd be grateful for any design suggestions, as performance is very
important to me.

If performance is paramount use mutex + condition then.

.



Relevant Pages

  • Re: [PATCH 19-rc1] Fix typos in /Documentation : Misc
    ... +do not have a corresponding kernel virtual address space mapping) and ... This command sets the scale factor for the ABSOLUTE MOUSE POSITIONING mode. ... If you check the source code you will see that what I draw here as a frame ... interrupt-parent: contains the phandle of the interrupt ...
    (Linux-Kernel)
  • [PATCH 19-rc1] Fix typos in /Documentation : Misc
    ... -> bus translation). ... +do not have a corresponding kernel virtual address space mapping) and ... This command sets the scale factor for the ABSOLUTE MOUSE POSITIONING mode. ... If you check the source code you will see that what I draw here as a frame ...
    (Linux-Kernel)
  • Re: how do threads work?
    ... >> A process cannot consider to switch task unless the flow of instructions ... >> kernel for a little help, in the form of regular timer signals. ... If you now ask, how does the kernel deliver signals, then we are no longer ...
    (comp.os.linux.development.system)
  • Re: Comments on the KSE option
    ... think M:N support in the kernel is a good idea. ... When the userland thread library issues a non-blocking ... When the userland thread scheduler switches threads ... It must also poll for blocked signals. ...
    (freebsd-current)
  • Re: system(), popen(), and SIGCHLD
    ... >which need to be added to each command line, ... termination of the child created by systemhave all completed by the ... command executed by that shell. ... and should be affected by signals. ...
    (comp.unix.programmer)