Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New windows implementation strategies from wepoll #1034

Merged
merged 46 commits into from
Jul 19, 2019
Merged

New windows implementation strategies from wepoll #1034

merged 46 commits into from
Jul 19, 2019

Conversation

PerfectLaugh
Copy link
Contributor

Currently this passed most of the test suite. Except for a test in Token documentation.

https://gist.github.com/PerfectLaugh/07fb4766be01e797a678357706828f1d

Copy link
Collaborator

@Thomasdezeeuw Thomasdezeeuw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for doing this @PerfectLaugh. This one of the major blocking points for v0.7 so I've been looking forward to this for a while.

I've left some comments, but I didn't review the actual implementation as I don't know enough about IOCP to review this.

@carllerche
Copy link
Member

cc @piscisaureus

@PerfectLaugh
Copy link
Contributor Author

Now all the test suite is passed.

trace!("returning");
Ok(())
}
// Codes to emulate ET in mio
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PerfectLaugh
Can you elaborate a bit on how this works?
In wepoll there's no way I can emulate edge-triggered, because I don't know when the user has attempted to read/write from a socket, so I don't know when to re-submit the AFD_POLL overlappped operation. I think in mio's case it might be possible because we can know when a socket read/write results in WSAEWOULDBLOCK.
But I don't see how that works here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This work is in tcp.rs udp.rs. where I hooked all possible calls the WouldBlock could appear.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the codes here is to eliminate those events that have been read. So we can simulate proper ET behavior (probably?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain how this code eliminates events that have been read?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code simply rely on assumption that mio can control and intercept every aspects that user will do to this socket. With this assumption (As long as rawsocket is not being manipulated by external library or raw api calls), we can wipe down the interests that user hasn't done it, simulating the ET behavior.

@SergejJurecko
Copy link

Strangely this compiles in debug but not release mode (x86_64-pc-windows-msvc)

@PerfectLaugh
Copy link
Contributor Author

Strangely this compiles in debug but not release mode (x86_64-pc-windows-msvc)

Fixed.

/// fn register(&self, registry: &Registry, token: Token, interests: Interests)
/// -> io::Result<()>
/// {
/// SourceRawSocket::new(&self.raw_socket).register(registry, token, interests)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This usage is rather expensive if we're creating a new Arc<Mutex<..>> each call to register. If we can't do without the SockState we might need to go for a different design.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is we need to simulate ET behavior. Then we do need SockState to maintain what interests have been read

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is fine, but would the example still work then? It throws about the same after each call to (re)register doesn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. You are right. I cannot hold all the actions user took on the RawSocket.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then the library will need to take level trigger approach rather than edge trigger

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or just remove SourceRawSocket

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove it for now then and we'll find another approach later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed


pub fn cancel(&self, iosb: &mut IO_STATUS_BLOCK) -> io::Result<()> {
unsafe {
if iosb.u.Status != STATUS_PENDING {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The IO_STATUS_BLOCK can be updated by the kernel any time when the operation is pending.
So it should probably be wrapped in an UnsafeCell and be pinned.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UnsafeCell has no Deref trait implemented therefore cannot be pinned. I used the Box instead.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you can guarantee that certain memory doesn't move it can be pinned, then you don't need to use Box. But these kind of optimisations can be done later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uploaded new code. Please check

@PerfectLaugh
Copy link
Contributor Author

Please check the documentation I added also. My English is the worst of the world and I don't want any syntax/grammar error.

/// and once complete they'll be put back in.
buffers: Mutex<BufferPool>,
pub struct SockState {
iosb: Pin<IoStatusBlock>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this Pin is current. I didn't following the entire previous discussion but I think IoStatusBlock can't move right? If that is the case it need to implemented !Pin (by using std::marker::PhantomPinned). Next it needs to be allocated in memory where it won't move, likely on the heap. The easier way to do that is to use Pin<Box<IoStatusBlock>>. Later we can figure out if we can remove the box by making SockState pinned.

Also note that all methods on IoStatusBlock should accept Pin<&mut Self> rather then &mut self (see the std::future::Future trait for an example).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SockState is wrapped by Arc<Mutex> all the time. I think it is actually safe not using Pin though.
I will do Pin<Box> for now.

}
events.events.push(Event::new(Ready::READABLE, token));
continue;
unsafe {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you reduce this unsafe block and add a comment why it is safe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot because the logic is connected. It is better to put this still.

// We use the status info in IO_STATUS_BLOCK to determine the socket poll status. It is unsafe to use a pointer of IO_STATUS_BLOCK.

@Thomasdezeeuw
Copy link
Collaborator

@PerfectLaugh can you not mention me via @ in commits, now I'm going to get an email from GitHub every time something happens with that commit, thanks.

@PerfectLaugh
Copy link
Contributor Author

@PerfectLaugh can you not mention me via @ in commits, now I'm going to get an email from GitHub every time something happens with that commit, thanks.

sorry

@carllerche
Copy link
Member

I would like to get this PR merged sooner than later. Any non critical follow up change can be tracked in a follow up issue.

@Thomasdezeeuw @piscisaureus could you list out any changes that are blocking merging this?

@Thomasdezeeuw
Copy link
Collaborator

I'm fine with merging now, all my comments can be fixed later.

@Thomasdezeeuw Thomasdezeeuw self-requested a review July 19, 2019 16:28
@carllerche carllerche mentioned this pull request Jul 19, 2019
16 tasks
@carllerche
Copy link
Member

I opened #1041 to track changes. Once we get the 👍 from @piscisaureus, I will merge this and extract all remaining items & questions into #1041.

Copy link
Contributor

@piscisaureus piscisaureus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@carllerche carllerche left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 Thanks for doing this @PerfectLaugh 👍 💯

@carllerche carllerche merged commit 65f19dd into tokio-rs:master Jul 19, 2019
@Thomasdezeeuw
Copy link
Collaborator

Thank you @PerfectLaugh you've helped us with one of the major blockers for Mio v0.7!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants