jippie's answer has the technical details, but it's possible that you're misunderstanding the sleep modes of the AVRs. The microcontrollers operate on a different realm than we're used to desktop computers working, and in fact clobber some of the same words to mean things that software developers don't expect.
The following is what I've gathered, as a software guy myself. I whole-heartedly welcome modifications to my post to correct things that I've gotten wrong!
The silicon is divided up into various building blocks for functionality. Timers, IO, SRAM, clock generator, execution core. The embedded world considers these peripherals. I got this wrong constantly, assuming peripherals were the things plugged into the outside of the MCU, since, well, that's what they are on a desktop computer.
What this means, in many cases, is that when the AVR is going to sleep it will shut down these other parts of the silicon. The first to go are some timers, followed perhaps by the main clock generator. The quick shutdown and startup of these peripherals means that microcontrollers are constantly flitting in and out of various sleep states, contrary to a big SLEEP, NOT SLEEP like a desktop computer. A pseudocode example making a dozen incorrect assumptions, of a ficticous serial communication:
// bad, the loop burns CPU time for no benefit
int message = 2830;
int counter = 0;
while (counter++ < 32) {
sendBit(PIN_TX, message & (2 << counter));
_delay_us(2500); // cpu spinwait is here
}
// better, uses sleeps
int message = 2830;
int counter = 0;
function sendData() {
sendBit(PIN_TX, message & (2 << counter++));
if (counter >= 32)
TIMER_A = DISABLED;
}
TIMER_A = TIMER_INCREMENT | TIMER_OVERFLOW_CALLBACK | ONE_PER_MICROSECOND;
TIMER_A_MAX = 2500;
TIMER_A_CALLBACK = &sendData;
DEFAULT_POWERSTATE = SLEEP3;
Again, you'll have to forgive the vague handwavey code. The idea here is that the serial communication has to wait a given number of microseconds between bits, and there's two ways to do that. One is by a spinwait, the other is interrupts. An interrupt will allow the MCU to service other interrupts while its waiting, or if nothing is going on, it will power down to a lower sleep mode. The corresponding equivalent in software development is yielding a thread vs. while (true);
Very little of this answers your original question, and I'm writing it as an answer to help attach additional information about how sleep can impact microcontrollers in ways that aren't necessarily intuitive to software developers.
edit:
To accomplish the wake-up cycle you're asking about would look something like the following:
function buttonPress() { _set_power_mode(FULL); }
void main() {
while (true) {
_set_power_mode(SLEEP2);
// button press logic here
}
}
This is vaguely how I remember my MSP430 working, and all things considered the microcontrollers tend to follow roughly the same rules. _set_power_mode of a deep enough sleep was a blocking call. In spirit true to how my projects usually go, the AVR probably does it completely differently and my answer is totally moot.