| Commit message (Collapse) | Author | Age |
| ... | |
| |
|
|
|
|
| |
This includes async send and recv, driven from the poller. This will
be requierd to support the underlying UDP and ZeroTier transports in
the future. (ZeroTier is getting done first.)
|
| | |
|
| |
|
|
|
|
|
| |
The queue is bound at initialization time of the task, and we call
entries just tasks, so we don't have to pass around a taskq pointer
across all the calls. Further, nni_task_dispatch is now guaranteed
to succeed.
|
| |
|
|
|
|
|
|
|
| |
We need to remember that protocol stops can run synchronously, and
therefore we need to wait for the aio to complete. Further, we need
to break apart shutting down aio activity from deallocation, as we need
to shut down *all* async activity before deallocating *anything*.
Noticed that we had a pipe race in the surveyor pattern too.
|
| |
|
|
|
|
| |
Apparently there are circumstances when a pipedesc may get orphaned form the
pollq. This triggers an assertion failure when it occurs. I am still
trying to understand how this can occur. Stay tuned.
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
| |
We have seen leaks of pipes causing test failures (e.g. the Windows
IPC test) due to EADDRINUSE. This was caused by a case where we
failed to pass the pipe up because the AIO had already been canceled,
and we didn't realize that we had oprhaned the pipe. The fix is to
add a return value to nni_aio_finish, and verify that we did finish
properly, or if we did not then we must free the pipe ourself. (The
zero return from nni_aio_finish indicates that it accepts ownership
of resources passed via the aio.)
|
| |
|
|
|
|
| |
This is only lightly tested, and I expect that there remain
some race conditions. Endpoint logic in particular needs
work.
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
| |
Modern Windows (Vista and later) have light weight Slim Read/Write locks
which only occupy 64 bits, and don't require any memory allocation to
create.
While here clean up a few more unreferenced variables found with the
Microsoft compilers.
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
It turns out that I had to fix a number of subtle asynchronous
handling bugs, but now TCP is fully asynchronous. We need to
change the high-level dial and listen interfaces to be async
as well.
Some of the transport APIs have changed here, and I've elected
to change what we expose to consumers as endpoints into seperate
dialers and listeners. Under the hood they are the same, but
it turns out that its helpful to know the intended use of the
endpoint at initialization time.
Scalability still occasionally hangs on Linux. Investigation
pending.
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The connect & accept logic for IPC is now fully asynchronous.
This will serve as a straight-forward template for TCP. Note that
the upper logic still uses a thread to run this "synchronously", but
that will be able to be removed once the last transport (TCP) is made
fully async.
The unified ipcsock is also now separated, and we anticipate being
able to remove the posix_sock.c logic shortly. Separating out the
endpoint logic from the pipe logic helps makes things clearer, and
may faciliate a day where endpoints have multiple addresses (for
example with a connect() endpoint that uses a round-robin DNS list
and tries to run the entire list in parallel, stopping with the first
connection made.)
The platform header got a little cleanup while we were here.
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
| |
Note that we're going to refactor this again, for both TCP and
IPC, to actually push the endpoint abstraction further down
instead of using a combined "socket" abstraction. This may help
solve other problems, such as parallel outgoing connections.
Nonetheless, most of the work to make POSIX sockets fully async
is now done.
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This eliminates the two threads per pipe that were being used to provide
basic I/O handling, replacing them with a single global thread for now,
that uses poll and nonblocking I/O. This should lead to great scalability.
The infrastructure is in place to easily expand to multiple polling worker
threads. Some thought needs to be given about how to scale this to engage
multiple CPUs. Horizontal scaling may also shorten the poll() lists easing
C10K problem.
We should look into better solutions than poll() for platforms that have
them (epoll on Linux, kqueue on BSD, and event ports on illumos).
Note that the file descriptors start out in blocking mode for now, but
then are placed into non-blocking mode. This is because the negotiation
phase is not yet callback driven, and so needs to be synchronous.
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
| |
As with TCP, we're still using threads under the hood. But this
completes the send/recv logic conversion for POSIX to our AIO framework,
and hence represents a substantial milestone towards full asyncronous
operation.
We still need to do accept/connect operations asynchronously, then making.
Windows overlapped IO work properly. After that, poll/epoll/kqueue, etc.
|
| | |
|
| |
|
|
|
|
|
| |
Transport-level pipe initialization is now sepearate and explicit.
The POSIX send/recv logic still uses threads under the hood, but
makes use of the AIO framework for send/recv. This is a key stepping
stone towards enabling poll() or similar async I/O approaches.
|