Commit Graph
1807 Commits
Author SHA1 Message Date
Carl Lerche f2005a78ca timer: fix loom test (#2346)
Fixes a test from a PR that was written before the recent loom upgrade.
A change in the details how loom executes models resulted in the test to
start failing. The fix is to reduce the number of iterations performed
by the test.
2020-03-26 15:23:33 -07:00
Brian L. Troutwine 3fb213a861 timer: improve memory ordering in Inner's increment (#2107)
This commit improves the memory ordering in the implementation of
Inner's increment function. The former code did a sequentially
consistent load of self.num, then entered a loop with a sequentially
consistent compare and swap on the same, bailing out with and Err only
if the loaded value was MAX_TIMEOUTS. The use of SeqCst means that all
threads must observe all relevant memory operations in the same order,
implying synchronization between all CPUs.

This commit adjusts the implementation in two key ways. First, the
initial load of self.num is now down with Relaxed ordering. If two
threads entered this code simultaneously, formerly, tokio required
that one proceed before the other, negating their parallelism. Now,
either thread may proceed without coordination. Second, the SeqCst
compare_and_swap is changed to a Release, Relaxed
compare_exchange_weak. The first memory ordering referrs to success:
if the value is swapped the load of that value for comparison will be
Relaxed and the store will be Release. The second memory ordering
referrs to failure: if the value is not swapped the load is
Relaxed. The _weak variant may spuriously fail but will generate
better code.

These changes mean that it is possible for more loops to be taken per
call than strictly necessary but with greater parallelism available on
this operation, improved energy consumption as CPUs don't have to
coordinate as much.
2020-03-26 13:04:08 -07:00
Christofer Nolander 6cf1a5b6b8 time: fix DelayQueue rewriting delay on insert after Poll::Ready (#2285)
When the queue was polled and yielded an index from the wheel, the delay
until the next item was never updated. As a result, when one item was
yielded from `poll_idx` the following insert erronously updated the
delay to the instant of the inserted item.

Fixes: #1700
2020-03-26 12:54:56 -07:00
Carl Lerche 1cb1e291c1 rt: track loom changes + tweak queue (#2315)
Loom is having a big refresh to improve performance and tighten up the
concurrency model. This diff tracks those changes.

Included in the changes is the removal of `CausalCell` deferred checks.
This is due to it technically being undefined behavior in the C++11
memory model. To address this, the work-stealing queue is updated to
avoid needing this behavior. This is done by limiting the queue to have
one concurrent stealer.
2020-03-26 12:23:12 -07:00
Carl Lerche 186196b911 stream: iter() should yield every so often. (#2343) 2020-03-25 14:56:24 -07:00
Tudor Sidea 57ba37c978 time: fix repeated pause/resume of time (#2253)
The resume function was breaking the guarantee that Instants should
never be less than any previously measured Instants when created.

Altered the pause and resume function such that they will not break this
guarantee. After resume, the time should continue from where it left
off.

Created test to prove that the advanced function still works as
expected.

Added additional tests for the pause/advance/resume functions.
2020-03-23 22:20:07 -07:00
Eliza Weisman acf8a7da7a sync: new internal semaphore based on intrusive lists (#2325)
## Motivation

Many of Tokio's synchronization primitives (`RwLock`, `Mutex`,
`Semaphore`, and the bounded MPSC channel) are based on the internal
semaphore implementation, called `semaphore_ll`. This semaphore type
provides a lower-level internal API for the semaphore implementation
than the public `Semaphore` type, and supports "batch" operations, where
waiters may acquire more than one permit at a time, and batches of
permits may be released back to the semaphore.

Currently, `semaphore_ll` uses an atomic singly-linked list for the
waiter queue. The linked list implementation is specific to the
semaphore. This implementation therefore requires a heap allocation for
every waiter in the queue. These allocations are owned by the semaphore,
rather than by the task awaiting permits from the semaphore. Critically,
they are only _deallocated_ when permits are released back to the
semaphore, at which point it dequeues as many waiters from the front of
the queue as can be satisfied with the released permits. If a task
attempts to acquire permits from the semaphore and is cancelled (such as
by timing out), their waiter nodes remain in the list until they are
dequeued while releasing permits. In cases where large numbers of tasks
are cancelled while waiting for permits, this results in extremely high
memory use for the semaphore (see #2237).

## Solution

@Matthias247 has proposed that Tokio adopt the approach used in his
`futures-intrusive` crate: using an _intrusive_ linked list to store the
wakers of tasks waiting on a synchronization primitive. In an intrusive
list, each list node is stored as part of the entry that node
represents, rather than in a heap allocation that owns the entry.
Because futures must be pinned in order to be polled, the necessary
invariant of such a list --- that entries may not move while in the list
--- may be upheld by making the waiter node `!Unpin`. In this approach,
the waiter node can be stored inline in the future, rather than
requiring  separate heap allocation, and cancelled futures may remove
their nodes from the list.

This branch adds a new semaphore implementation that uses the intrusive
list added to Tokio in #2210. The implementation is essentially a hybrid
of the old `semaphore_ll` and the semaphore used in `futures-intrusive`:
while a `Mutex` around the wait list is necessary, since the intrusive
list is not thread-safe, the permit state is stored outside of the mutex
and updated atomically. 

The mutex is acquired only when accessing the wait list — if a task 
can acquire sufficient permits without waiting, it does not need to
acquire the lock. When releasing permits, we iterate over the wait
list from the end of the queue until we run out of permits to release,
and split off all the nodes that received enough permits to wake up
into a separate list. Then, we can drain the new list and notify those
wakers *after* releasing the lock. Because the split operation only
modifies the pointers on the head node of the split-off list and the
new tail node of the old list, it is O(1) and does not require an
allocation to return a variable length number of waiters to notify.


Because of the intrusive list invariants, the API provided by the new
`batch_semaphore` is somewhat different than that of `semaphore_ll`. In
particular, the `Permit` type has been removed. This type was primarily
intended allow the reuse of a wait list node allocated on the heap.
Since the intrusive list means we can avoid heap-allocating waiters,
this is no longer necessary. Instead, acquiring permits is done by
polling an `Acquire` future returned by the `Semaphore` type. The use of
a future here ensures that the waiter node is always pinned while
waiting to acquire permits, and that a reference to the semaphore is
available to remove the waiter if the future is cancelled.
Unfortunately, the current implementation of the bounded MPSC requires a
`poll_acquire` operation, and has methods that call it while outside of
a pinned context. Therefore, I've left the old `semaphore_ll`
implementation in place to be used by the bounded MPSC, and updated the
`Mutex`, `RwLock`, and `Semaphore` APIs to use the new implementation.
Hopefully, a subsequent change can update the bounded MPSC to use the
new semaphore as well.

Fixes #2237

Signed-off-by: Eliza Weisman <[email protected]>
2020-03-23 13:45:48 -07:00
MarinPostma 2258de5147 io: impl as RawFd / AsRawHandle for stdio (#2335)
Fixes: #2311
2020-03-22 22:25:49 -07:00
Carl Lerche dd27f1a259 rt: remove unsafe from shell runtime. (#2333)
Since the original shell runtime was implemented, utilities have been
added to encapsulate `unsafe`. The shell runtime is now able to use
those utilities and not include its own `unsafe` code.
2020-03-20 21:06:50 -07:00
Nikhil Benesch 5fd1b8f67c util: Prepare 0.3.1 release (#2330) 2020-03-18 20:05:55 -04:00
Nikhil Benesch 9e58b37ad5 tokio-util: fix minimum supported version of tokio (#2326)
tokio-util uses tokio::stream::StreamExt, which was not introduced until
tokio v0.2.5. The current dependency specification is incorrect, and
breaks with cargo update -Z minimal-versions.
2020-03-18 18:18:53 -04:00
Daniel Müller c3b830110a sync: Add RwLock::into_inner method (#2321)
Add RwLock::into_inner method that consumes the lock and returns
the wrapped value.

Fixes: #2320
2020-03-18 11:52:11 -07:00
Alice Ryhl 602ad2e0ba runtime: update the documentation around Handle (#2328)
This PR was prompted by having encountered a few cases of people not noticing that Runtime::handle can be cloned, and therefore not realizing it could be moved to another thread.
2020-03-17 22:59:26 +01:00
Jon Gjengset 06a4d895ec Add cooperative task yielding (#2160)
A single call to `poll` on a top-level task may potentially do a lot of
work before it returns `Poll::Pending`. If a task runs for a long period
of time without yielding back to the executor, it can starve other tasks
waiting on that executor to execute them, or drive underlying resources.
See for example rust-lang/futures-rs#2047, rust-lang/futures-rs#1957,
and rust-lang/futures-rs#869. Since Rust does not have a runtime, it is
difficult to forcibly preempt a long-running task.

Consider a future like this one:

```rust
use tokio::stream::StreamExt;
async fn drop_all<I: Stream>(input: I) {
    while let Some(_) = input.next().await {}
}
```

It may look harmless, but consider what happens under heavy load if the
input stream is _always_ ready. If we spawn `drop_all`, the task will
never yield, and will starve other tasks and resources on the same
executor.

This patch adds a `coop` module that provides an opt-in mechanism for
futures to cooperate with the executor to avoid starvation. This
alleviates the problem above:

```
use tokio::stream::StreamExt;
async fn drop_all<I: Stream>(input: I) {
    while let Some(_) = input.next().await {
        tokio::coop::proceed().await;
    }
}
```

The call to [`proceed`] will coordinate with the executor to make sure
that every so often control is yielded back to the executor so it can
run other tasks.

The implementation uses a thread-local counter that simply counts how
many "cooperation points" we have passed since the task was first
polled. Once the "budget" has been spent, any subsequent points will
return `Poll::Pending`, eventually making the top-level task yield. When
it finally does yield, the executor resets the budget before
running the next task.

The budget per task poll is currently hard-coded to 128. Eventually, we
may want to make it dynamic as more cooperation points are added. The
number 128 was chosen more or less arbitrarily to balance the cost of
yielding unnecessarily against the time an executor may be "held up".

At the moment, all the tokio leaf futures ("resources") call into coop,
but external futures have no way of doing so. We probably want to
continue limiting coop points to leaf futures in the future, but may
want to also enable third-party leaf futures to cooperate to benefit the
ecosystem as a whole. This is reflected in the methods marked as `pub`
in `mod coop` (even though the module is only `pub(crate)`). We will
likely also eventually want to expose `coop::limit`, which enables
sub-executors and manual `impl Future` blocks to avoid one sub-task
spending all of their poll budget.

Benchmarks (see tokio-rs/tokio#2160) suggest that the overhead of `coop`
is marginal.
2020-03-16 17:17:56 -04:00
Alice Ryhl fce6845f2b Document common cargo commands (#2293)
* Document common cargo commands
* Add loom command
2020-03-15 13:02:39 +01:00
th0114nd 826fc21abf Keep lock until sender notified (#2302) 2020-03-08 20:46:19 -07:00
Thomas Whiteway bc8dcdeb58 Add foo.txt and bar.txt to .gitignore (#2294) 2020-03-06 13:00:33 -05:00
Carl Lerche a78b1c65cc rt: cleanup and simplify scheduler (scheduler v2.5) (#2273)
A refactor of the scheduler internals focusing on simplifying and
reducing unsafety. There are no fundamental logic changes.

* The state transitions of the core task component are refined and
reduced.
* `basic_scheduler` has most unsafety removed.
* `local_set` has most unsafety removed.
* `threaded_scheduler` limits most unsafety to its queue implementation.
2020-03-05 10:31:37 -08:00
5ede2e4d6b util: Prepare 0.3.0 release (#2296)
Signed-off-by: Lucio Franco <[email protected]>
Co-authored-by: David Barsky <[email protected]>
Co-authored-by: Eliza Weisman <[email protected]>
2020-03-04 17:27:18 -05:00
Lucio FrancoandMarkus Westerlind 9d4d076189 codec: change Encoder to take &Item (#1746)
Co-authored-by: Markus Westerlind <[email protected]>
2020-03-04 15:54:41 -05:00
Jean-Christophe BEGUE 1eb6131321 codec: Add Framed::with_capacity (#2215) 2020-03-02 11:40:54 -05:00
Jeffrey Czyz 17a6f6fabf macros: fix select! documentation formatting (#2283) 2020-02-29 07:17:49 -08:00
Carl Lerche ecc23c084a chore: prepare v0.2.13 release (#2282)
Includes a quick bug fix
tokio-0.2.13
2020-02-28 13:51:24 -08:00
Hiro Saito 937ae11f37 macros: fix unresolved import in pin! (#2281) 2020-02-28 09:36:27 -08:00
Alice Ryhl f0d18653a6 runtime: add threaded_scheduler to examples (#2277)
It can be pretty confusing when the core_threads example does not call
threaded_scheduler, when actually building such a runtime results in
panics if you try to spawn something on it:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=866b3af344b0d6aad170ac9cbc9d57ed
2020-02-27 14:03:18 -08:00
Carl Lerche 06bcbe8dcf sync: refactor intrusive linked list (#2279)
Allow storing the intrusive linked-list pointers in an arbitrary
location in the node. This is in preparation for using the linked list
in the scheduler.

In order to make using the intrusive linked list more flexible, a trait
is introduced to abstract mapping an entry to raw pointers and the next
/ prev pointers. This also pushes more unsafety onto the user.
2020-02-27 13:45:28 -08:00
Carl Lerche bfdfb46fcd chore: delete unused file (#2280)
The `blocking` module is not referenced in code. The file is left over
from an earlier refactor.
2020-02-27 11:57:35 -08:00
Carl Lerche c6fc1db698 chore: prepare v0.2.12 release (#2278)
Also includes `tokio-macros` v0.2.5.
tokio-macros-0.2.5 tokio-0.2.12
2020-02-27 10:18:01 -08:00
Akshay Narayan d44ce338af tcp: Update listener docs (#2276)
* Update listener docs
* re-wrap text and add links
2020-02-26 21:16:13 +01:00
Carl Lerche 8b7ea0ff5c sync: adds Notify for basic task notification (#2210)
`Notify` provides a synchronization primitive similar to thread park /
unpark, except for tasks.
2020-02-26 11:40:10 -08:00
Thomas Whiteway 7207bf355e time: avoid needing to poll DelayQueue after insertion (#2217)
If an entry is inserted in the queue before the next deadline, the
DelayQueue needs to update the Delay tracking the next time to poll.

If there is an existing Delay, reset that rather than replacing it as if
it's already been polled the task will be waiting for a notification
before it will poll again, and dropping the Delay means that that
notification will never be performed.
2020-02-26 10:55:08 -08:00
David Kellum a4c4ac254b docs: macros doc(cfg) workarounds (#2225)
This is a workaround for the fact that the doc(cfg) from outer cfg_*
macros doesn't get applied correctly. Its included in the rt-threaded
branch only, which is what is used for doc.rs via all-features.
2020-02-26 10:38:54 -08:00
Akshay Narayan 0589acc9ff Implement Stream for Listener types (#2275)
The Incoming types currently don't take ownership of the listener, but
in most cases, users who want to use the Listener as a stream will only
want to use the stream from that point on. So, implement Stream directly
on the Listener types.
2020-02-26 13:38:41 -05:00
Carl Lerche 1dadc701c0 macros: add assignment form to pin! (#2274)
Allows combining assignment to a binding and pinning it.
2020-02-25 20:06:54 -08:00
Kevin Leimkuhler 10f1507cf4 process: Wake up read and write on EPOLLERR (#2218)
## Motivation

#2174

On epoll platforms, the read end of a pipe closing is signaled to the write end
through the `EPOLLERR` event [[1](http://man7.org/linux/man-pages/man2/epoll_ctl.2.html)]. If readiness is not registered for this
event, it will silently pass through `epoll_wait` calls.

Additionally, this specific case that `EPOLLERR` is triggered leaves the write
end of the pipe (parent process) waiting for a wakeup that never occurs.

## Solution

Similar to the `HUP` event on Unix platforms, errors are now always masked
through registrations so that both read and write ends of a connection are made
aware of errors.

In cases where pipes are used and the read end closes, write ends that are
waiting for a wakeup are properly notified and try to write again. This allows
a client to observe `BrokenPipe` and go through the proper cleanup and/or
restablishment of connection.

Closes #2174

Signed-off-by: Kevin Leimkuhler <[email protected]>
2020-02-25 13:27:44 -08:00
Jake b9cc032d3b mpsc: add Sender::send_timeout (#2227) 2020-02-25 09:06:02 -08:00
Thomas 4213b79461 tokio: fix broken contributing guide link (#2267)
The link to the contributing guide in the tokio sub crate was
referencing a non-existent file. This updates the link to reference
the repo root's CONTRIBUTING.md file.

Fixes: #2266
2020-02-22 21:00:58 -08:00
Matt Butcher 7b8ce356c3 sync: fixed a small typo in sync docs (#2262)
Signed-off-by: Matt Butcher <[email protected]>
2020-02-20 11:38:28 -05:00
Alice Ryhl 0605abacfc sync: Use yield rather than block on read method (#2258) 2020-02-20 11:36:08 -05:00
Eliza Weisman b37e4a4380 sync: improve RwLock API docs (#2252)
Currently, the documentation for `tokio::sync::RwLock` states that it
has an unspecified priority policy dependent on the operating system.
This is incorrect: Tokio's `RwLock` is fairly queued. The incorrect
documentation appears to have been copied from the `std::sync::RwLock`
docs, for which this *is* the case.

This commit corrects the documentation to describe the actual priority
policy.

Signed-off-by: Eliza Weisman <[email protected]>
2020-02-18 12:43:29 -08:00
Tudor Sidea 41576e6c48 Added Ord and Hash as derived traits for tokio::time::Instant (#2239)
The added derived traits mirror the traits of std::time::Instant. As
tokio::time::Instant is just a wrapper around std::time::Instant, it
should also derive all the traits std::time::Instant derives.
2020-02-17 11:18:19 -05:00
Waffle Lapkin 09b5f47381 Add Mutex::into_inner method (#2250)
Add `Mutex::into_inner` method that consumes mutex
and return underlying value.

Fixes: #2211
2020-02-17 11:16:48 -05:00
Jon Gjengset fc65951731 UnixStream::poll_shutdown is not a no-op (#2245) 2020-02-14 12:22:29 -05:00
Jon Gjengset 564da5c128 Test some more mpsc behavior with loom (#2246) 2020-02-14 12:03:57 -05:00
Luca Bruno 466dd4a851 rt: lazily detect number of CPUs (#2238)
This tweaks the runtime builder default to defer and lazily
auto-detect the number of CPUs. This is done in order to
avoid performing useless operations which may be expensive
on some platforms (e.g. Linux, where it is coupled to CPU
frequency probing).

Ref: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7d5905dc14a87805a59f3c5bf70173aac2bb18f8
2020-02-13 10:07:06 -08:00
Jon Gjengset 2eed6d00f5 Avoid race in tcp_accept::no_extra_poll (#2236) 2020-02-12 15:53:56 -05:00
Jon Gjengset c1232a6520 io: avoid unnecessary wake in registration (#2221)
See discussion in #2222. This wake/notify call has been there in one
form or another since the very early days of tokio. Currently though, it
is not clear that it is needed; the contract for polling is that you
must keep polling until you get `Pending`, so doing a wakeup when we are
about to return `Ready` is premature.
2020-02-12 11:09:44 -08:00
lord 5e75b0446d Fix doc comment spelling in lib.rs (#2233) 2020-02-11 16:09:40 -05:00
Christian Vallentin d49e6ae1b3 Fixed typos in examples (#2231) 2020-02-11 10:56:32 -05:00
Wade Mealing 874264a4ef Correct link to the guide on tokio.rs (#2229)
The current link to tokio.rs/docs 404's.  This change redirects the "guides" link to the docs overview (which may be what was intended).
2020-02-11 10:56:13 -05:00