Skip to contentSkip to conversation

PATCH(?): linux-2.4.4-pre2: fork should run child first

DISCUSSION Adam J. Richter 4 participants 4 messages Apr 14, 2001

lore
Share & tools
lore
#0 lore raw

Rik van Riel <[email protected]> writes, regarding the idea of having do_fork() give all of the parent's remaining time slice to the newly created child:

Quoted 3 lines

It could upset programs which use threads to handle relatively IO poor things (like, waiting on disk IO in a thread, like glibc does to fake async file IO).

Good point.

[...]

Quoted 3 lines

If it turns out to be beneficial to run the child first (you can measure this), why not leave everything the same as it is now but have do_fork() "switch threads" internally ?

That is an elegant idea. Not only would you save a few cycles by
avoiding what's left of the context switch, but, more imporantly, you would be sure that no intervening process could be selected to run between the parent giving up the CPU and the child running (which could otherwise waste an additional full context swtich). Also, you then would not necessarily have to make the parent give up all of its remaining time slice. These two characteristics means that future tweaks to the scheduler would be much less likely to accidentally defeat running of the child first.

As far code cleanliness goes, you get to delete a line
from do_fork ("current->need_resched = 1;"), but I think that's about it. You might even be able to avoid adding "current = p;" to do_fork by having newly allocating task_struct assume the identity of the parent and making the changes to "current", although I wonder if anything else points to the current task or if that might screw up any interrupts that occur during that process.

Adam J. Richter     __     ______________   4880 Stevens Creek Blvd, Suite 104
[email protected]     \ /                  San Jose, California 95129-1034
+1 408 261-6630         | g g d r a s i l   United States of America

fax +1 408 261-6631 "Free Software For The Rest Of Us."

#1 lore raw
Quoted 9 lines · Adam J. Richter

Rik van Riel <[email protected]> writes, regarding the idea of having do_fork() give all of the parent's remaining time slice to the newly created child:

Quoted 3 lines

It could upset programs which use threads to handle relatively IO poor things (like, waiting on disk IO in a thread, like glibc does to fake async file IO).

Good point.

Is it really? If a program is using thread to handle IO things, then:

a) It's not going to create a thread for every IO! So I think the argument is suprious anyway.

b) You _still_ want the child to run first. The child will start the I/O and block, then switching back to the parent. This maximises the I/O thruput without costing you any CPU. (Reasoning: The child running 2nd will increase the latency which automatically reduces the number of ops/second you can get).

Michael.

#2 lore raw
In reply to Adam J. Richter
Quoted 7 lines · Adam J. Richter

[...]

Quoted 3 lines

If it turns out to be beneficial to run the child first (you can measure this), why not leave everything the same as it is now but have do_fork() "switch threads" internally ?

That is an elegant idea.

I doubt it. It sounds like one of those "cool value" ideas that are actually really stupid except they sound cool because you have to think about the twists and turns.

So yes, you could "give" your TLB state to the child, and take the childs state yourself (eventually, when you re-schedule back to the parent). They're supposed to be the same, after all. And by doing so, you could do a "switch_to()" to the child, without actually switching mm state at all. Fine. Cool TLB optimization.

Except you don't actually _have_ any TLB state to optimize away, as you just invalidated it anyway when you did the COW thing on the page tables. So you would only optimize away a "mov xxx,%cr3" - which is the least expensive part of switching TLB's. You would NOT optimize away any actual TLB reloads.

And oh, btw, it also means that you'd better make sure that /proc knows about the fact that the MM state is no longer yours, but your childs, so that a concurrent "ps" doesn't mess us. Maybe it works as-is, and maybe it doesn't.

And what if the guy who did the fork() had done a clone(CLONE_MM) before, or was the child of a vfork'ing parent? We can't give the mm state to the child, because we're sharing it with somebody else who expects to share it with the _parent_. Oh, and the co-thread, btw, might be _using_ those page tables on another CPU at any time.

And oh, there's the small special case of "init", which uses a fork() to create the first user-mode mm state, so we'd have to special-case that one too - we can't let "init_mm" go to a user process. So at the very least it would have to be conditional on both that and the thread case.

There's a ton of reasons why you _really_ don't want to play games here. Switching contexts is tricky enough as it is. Let's not try to be "clever" about it.

So the best you could do is to do a full context switch to the child. Which setting "current->need_resched = 1" will already end up doing. Plus it does the right thing on SMP.

Linus

#3 lore raw
Quoted 7 lines · Linus Torvalds
Quoted 6 lines · Adam J. Richter

[...]

Quoted 3 lines

If it turns out to be beneficial to run the child first (you can measure this), why not leave everything the same as it is now but have do_fork() "switch threads" internally ?

Quoted 5 lines
Quoted 1 line

That is an elegant idea.

I doubt it. It sounds like one of those "cool value" ideas that are actually really stupid except they sound cool because you have to think about the twists and turns.

You're right. Time to put a "don't try to think of cool ideas after going out at night" sign on the wall ;)

cheers,

Rik
--
Linux MM bugzilla: http://linux-mm.org/bugzilla.shtml

Virtual memory is like a game you can't win; However, without VM there's truly nothing to lose...

		http://www.surriel.com/

http://www.conectiva.com/ http://distro.conectiva.com/