The thread switching code assumed that we will always switch out of a
thread due to being blocked on an unavailable future. This allows
the core to store the blocked thread's context in the synthetic
continuation chained to that future (which switched back to that thread).
That assumption failed in one place: when we create a thread from within a
thread. In that case we switch to the new thread immediately, but forget
all about the old thread. We never come back to the old thread, and anything
that depends on it hangs.
Fix by creating a linked list of active thread contexts. These are all
threads that have been "preempted" by the act of creating a new thread,
terminated by the main, unthreaded, reactor context. This gives us a place
to store those threads and we come back to them and continue where we left
off.
Reported by Pekka.
Instead of issuing a system call for every aio, wait for them to accumulate,
and issue them all at once. This reduces syscall count, and allows the kernel
to batch requests (bu plugging the I/O queues during the call). A poller is
added so that requests are not delayed too much.
Reviewed-by: Pekka Enberg <penberg@cloudius-systems.com>
For some reason, I added a fsync call when the file underlying the
stream gets truncated. That happens when flushing a file, which
size isn't aligned to the requested DMA buffer.
Instead, fsync should only be called when closing the stream, so this
patch changes the code to do that.
Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
When a promise that still tracks its future is destroyed, but after
future::get() or future::then() was called, the promise thinks it was
destroyed before generating a value, and fails an assertion.
Fix be detaching the promise from the future as soon as get() or then()
remove the value.
Following std::async(), seastar::async(func) causes func to be executed
in a seastar thread, where it can block using future<>::get(). Whatever
func returns is converted to a future, and returned as async()s return
value.
Sometimes remote data has to be copied to local cpu, but if data is
already local copy can be avoided. Introduce helper function that moves
or copies data depending on origin cpu.
remove() is a convenient glibc wrapper that will unlink() a file and rmdir() a
directory. It will allow us to operate on both without creating a separate
function for a directory.
Signed-off-by: Glauber Costa <glommer@cloudius-systems.com>
There is a hidden exception that could be thrown insize file::dma_get_bulk()
if file size is not aligned with fstream::_buffer_size. In this case
file::dma_read_bulk() will be given a _buffer_size as a length for the last data
chunk in the file too. file::dma_read_bulk() will get a short read (till EOF)
and then will try to read beyond it (by calling file::read_maybe_eof())
in order to differentiate between I/O error and EOF. file::read_maybe_eof()
will throw a file::eof_error exception to indicate the EOF, it will be caught
by file::dma_read_bulk() and since we have read some "good" bytes by now this
exception won't be forwarded further. However the damage by throwing the exception
has already been done and we want to avoid this in fstream flow (unless there are
real errors).
In order to prevent the above we will always request file::dma_read_bulk() to
read the amount of data it should be able to deliver (not beyond EOF).
Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>