Skip to contentSkip to conversation

top stack (l)users for 2.5.69

DISCUSSION Chuck Ebbert 4 participants 4 messages May 8, 2003

lore
Share & tools
lore
#0 lore raw
Quoted 9 lines

I have no idea, what a 'typical processor' might look like. But the thing most CPU seem to have in common is that they save two registers either on the stack or into other registers that only exist for this purpose (SRR on PPC).

Once that has happened, the OS has the job to figure out where it's stack (or equivalent) is located, *without* clobbering the registers. Once that is done, it can save all the registern on the stack, including SRR.

On i386 the CPU automatically switches to the stack corresponding to
the privilege level (PL) of the interrupt handler, then pushes the instruction pointer and flags onto that stack. It is theoretically possible to write unprivileged interrupt handlers by using conforming code segments, in which case a stack switch will not occur, but such a handler cannot touch anything but registers and stack so it's not very useful.

#1 lore raw
Quoted 10 lines · Chuck Ebbert
Quoted 9 lines

I have no idea, what a 'typical processor' might look like. But the
thing most CPU seem to have in common is that they save two registers either on the stack or into other registers that only exist for this purpose (SRR on PPC).

Once that has happened, the OS has the job to figure out where it's stack (or equivalent) is located, *without* clobbering the registers. Once that is done, it can save all the registern on the stack, including SRR.

Quoted 7 lines

On i386 the CPU automatically switches to the stack corresponding to
the privilege level (PL) of the interrupt handler, then pushes the instruction pointer and flags onto that stack. It is theoretically possible to write unprivileged interrupt handlers by using conforming code segments, in which case a stack switch will not occur, but such a handler cannot touch anything but registers and stack so it's not very useful.

In particular, the interrupt stack is the kernel stack of the current task. This is (in part) what leads to stack overflows. If the current task is running in the kernel, using a significant hunk of its stack, an interrupt is limited to the balance of that stack. And if that interrupt triggers a soft irq that runs, say, a network stack, and that softirq handler in turn gets interrupted, we've got, effectively, three processes sharing the stack. And of course hard interrupts can be nested, so it's pretty damn difficult to specify a safe upper limit for stack usage.

Signature · 1 line
/Jonathan Lundell.
#2 lore raw
Quoted 3 lines · Jonathan Lundell

In particular, the interrupt stack is the kernel stack of the current task. This is (in part) what leads to stack overflows. If the current task is running in the kernel, using a significant hunk of its stack, an interrupt is limited to the balance of that stack. And if that interrupt triggers a soft irq that runs, say, a network stack, and that softirq handler in turn gets interrupted, we've got, effectively, three processes sharing the stack. And of course hard interrupts can be nested, so it's pretty damn difficult to specify a safe upper limit for stack usage.

This is the sort of things that would severely limit our ability to shrink the kernel stack. While it's perhaps feasible to shrink kernel stack usage for typical syscalls, exactly the situation you describe is unpredictable and very difficult to avoid.

My suggestion would be that if we do manage to get typical stack usage down to the point where we can go to a 4K stack, then interrupt handlers would have to be rewritten to recognize whether or not the interrupt arrived on a user process kernel stack and then move the context over to the "interrupt stack". The overhead would be low enough that it's worth doing so that we could reduce process kernel stack size. Whenever an interrupt service routine is itself interrupted, the interrupt stack check code would realize that it is already using the interrupt stack and not move the context. Here, then, we would need only one single interrupt stack which we would size for worst case; so if we made it 8 or 12K, that's 8 or 12K once for each CPU which is allowed to receive interrupts, not once per process.

You like? :)

#3 lore raw
Quoted 3 lines · Timothy Miller

My suggestion would be that if we do manage to get typical stack usage down to the point where we can go to a 4K stack, then interrupt handlers would have to be rewritten to recognize whether or not the interrupt arrived on a user process kernel stack and then move the context over to the "interrupt stack". The overhead would be low enough that it's worth doing so that we could reduce process kernel stack size. Whenever an interrupt service routine is itself interrupted, the interrupt stack check code would realize that it is already using the interrupt stack and not move the context. Here, then, we would need only one single interrupt stack which we would size for worst case; so if we made it 8 or 12K, that's 8 or 12K once for each CPU which is allowed to receive interrupts, not once per process.

You like? :)

It makes sense to me. But this thread has gone in a circle, I think.

Quoted 2 lines · Martin J. Bligh

There are patches to make i386 do this (and use 4K stacks as a config option) from Dave Hansen and Ben LaHaise in 2.5-mjb tree.

(the message context was a separate interrupt stack)

Signature · 1 line
/Jonathan Lundell.