Pause for interrupt
This should make usb/msc a whole lot more efficient by pausing the worker goroutine and waiting for an interrupt to unpause it instead of waiting in a loop and sleeping for 0.1ms each cycle.
In other words, this should make it both faster (no unnecessary delay due to the time.Sleep) and more efficient (no polling).
To make this possible, I've added internal/task.Waiter which allows waiting for a signal from an interrupt. Basically, a goroutine can pause itself and wait for the interrupt to unpause itself when some event happens. I imagine this feature will be useful in many other places in the machine package for example (e.g. inside an SPI transfer using DMA, the goroutine can pause itself and wait for a "transfer finished" interrupt instead of polling using runtime.Gosched or similar).
@mikesmitty can you take a look at the USB logic to verify it is correct? It seems to work under MacOS.
Unfortunately this suffers from a potential hang with -scheduler=cores: scheduleTask takes the scheduler lock from interrupt context which would cause a deadlock when this interrupt happens with the scheduler lock already held. I should try and fix this in a separate PR. So maybe it's best to hold off of merging this PR until that bug is fixed.