The idea behind a thread is it being a lightweight process that has less "of its own" than a normal process. There are nearly infinitely many in-between forms, and there's a form above it (jobs, see also WinNT scheduling). You can have stuff Windows calls fibers, which are threads that avoid the kernel-land switch, or stuff in between with a dozen options (try the Linux clone() call).kmcguire wrote: Yeah. It makes sense not to have to switch CR3 as much as possible. It wastes CPU cycles. And, for a web-server you would want to thread it up so that clients do not sit waiting in a line, instead they start getting something right away, and using the CR3 switch is going to be a performance drain when it could have been made simplier by using the process and thread model. Even for the example he uses above, it would be smarter to not switch CR3, it is no reason to do so expect to protect threads from each other.
Brendan's idea is another form, that has slightly more overhead due to switching than a normal thread would have. This causes you to have to limit the number of switches, which leads to this design. If you made the switch lighter you'd use more threads as it's easier to program.
You could generalize the idea as well. What if you made a "request queue"? On this queue you put all deferred function calls, in order of calling. Then, you can make deferred calls to stuff like writes in an operating system or stuff like that. You would make a form of call that takes a function pointer and an argument structure pointer.
I also played with the idea of a thread-call, which would be useful for a number of things, first of which is replacing the ugly C-style interfacing for making a new thread in c++ code. You just tell it to tcall a certain funciton and it does.
I'm still not entirely sure you can use variable arguments, but if you can, all the better. Might be a problem with C++ name mangling as ... is put as z, but I think the linker knows about that.
You'd have one or two threads running in the background to catch dcalls and to execute them. You'd use them for stuff that's "do and forget", stuff you'd use a servant for in ancient Rome. Sending a message, writing a complex structure, reading 20 buffers simultaneously (yes, you can use 20 dcalls at once and wait for them all to complete, so that the read ordering is left to the disk level and can be quite optimized)...
Of course, there's a real-time version (soft) of tcall, so you can use it to create realtime threads. Pri is a relative variable, higher pri threads get all the time until complete, low pri threads get the rt-leftovers. RT execution time is limited to +- 70% of all cpu time. There's no load factor, since this is determined automatically (and it's near impossible to get right for all computers, so it'd be pointless).
Code: Select all
void dcall(void *(*)(...), ...);
void tcall(void *(*)(...), ...);
void tcall_rt(int pri, void *(*)(...), ...);