summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-09-26 14:12:45 +0000
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-09-26 14:12:45 +0000
commit810c662c9b55908101ca085293c52c3239ef22d1 (patch)
treea8a6877615c44dd7fde786e3a770642cab497eff
parentf0bd730338be67a7c5c8fd65ef8b4d9f851860bb (diff)
Add FD_WANT_SINGLE_WRITE to efficiently replace FD_WANT_POLL_WRITE
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11762 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--include/socketengine.h31
-rw-r--r--src/inspsocket.cpp4
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp6
-rw-r--r--src/modules/extra/m_ssl_openssl.cpp8
-rw-r--r--src/socketengines/socketengine_epoll.cpp20
-rw-r--r--src/socketengines/socketengine_iocp.cpp4
-rw-r--r--src/socketengines/socketengine_kqueue.cpp12
-rw-r--r--src/socketengines/socketengine_poll.cpp7
-rw-r--r--src/socketengines/socketengine_ports.cpp4
-rw-r--r--src/socketengines/socketengine_select.cpp4
10 files changed, 61 insertions, 39 deletions
diff --git a/include/socketengine.h b/include/socketengine.h
index 9c45bcf21..1a0a61670 100644
--- a/include/socketengine.h
+++ b/include/socketengine.h
@@ -71,8 +71,10 @@ enum EventMask
FD_WANT_NO_WRITE = 0x10,
/** Give a write event at all times when writes will not block.
*
- * You probably don't need to use this state; try your write first, and
- * then use FD_WANT_FAST_WRITE.
+ * You probably shouldn't use this state; if it's likely that the write
+ * will not block, try it first, then use FD_WANT_FAST_WRITE if it
+ * fails. If it's likely to block (or you are using polling-style reads)
+ * then use FD_WANT_SINGLE_WRITE.
*/
FD_WANT_POLL_WRITE = 0x20,
/** Give a write event when writes don't block any more
@@ -95,19 +97,23 @@ enum EventMask
* FD_WANT_FAST_WRITE when writing data to a mostly-unblocked socket.
*/
FD_WANT_EDGE_WRITE = 0x80,
+ /** Request a one-shot poll-style write notification. The socket will
+ * return to the FD_WANT_NO_WRITE state before HandleEvent is called.
+ */
+ FD_WANT_SINGLE_WRITE = 0x100,
/** Mask for all write events */
- FD_WANT_WRITE_MASK = 0xF0,
+ FD_WANT_WRITE_MASK = 0x1F0,
/** Add a trial read. During the next DispatchEvents invocation, this
* will call HandleEvent with EVENT_READ unless reads are known to be
- * blocking. Useful for edge-triggered reads; does nothing if
- * FD_READ_WILL_BLOCK has been set on this EventHandler.
+ * blocking.
*/
- FD_ADD_TRIAL_READ = 0x100,
+ FD_ADD_TRIAL_READ = 0x1000,
/** Assert that reads are known to block. This cancels FD_ADD_TRIAL_READ.
+ * Reset by SE before running EVENT_READ
*/
- FD_READ_WILL_BLOCK = 0x200,
+ FD_READ_WILL_BLOCK = 0x2000,
/** Add a trial write. During the next DispatchEvents invocation, this
* will call HandleEvent with EVENT_WRITE unless writes are known to be
@@ -117,15 +123,14 @@ enum EventMask
* send() syscall, or to ensure that writes are blocking when attempting
* to use FD_WANT_FAST_WRITE.
*/
- FD_ADD_TRIAL_WRITE = 0x1000,
+ FD_ADD_TRIAL_WRITE = 0x4000,
/** Assert that writes are known to block. This cancels FD_ADD_TRIAL_WRITE.
+ * Reset by SE before running EVENT_WRITE
*/
- FD_WRITE_WILL_BLOCK = 0x2000,
+ FD_WRITE_WILL_BLOCK = 0x8000,
- /** Mask for trial read/write items */
- FD_TRIAL_NOTE_MASK = 0x1100,
- /** Mask for read/write blocking notifications */
- FD_BLOCK_NOTE_MASK = 0x2200
+ /** Mask for trial read/trial write */
+ FD_TRIAL_NOTE_MASK = 0x5000
};
class InspIRCd;
diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp
index 6348d7982..004d679ed 100644
--- a/src/inspsocket.cpp
+++ b/src/inspsocket.cpp
@@ -97,7 +97,7 @@ BufferedSocketError BufferedSocket::BeginConnect(const irc::sockets::sockaddrs&
this->state = I_CONNECTING;
- if (!ServerInstance->SE->AddFd(this, FD_WANT_NO_READ | FD_WANT_POLL_WRITE))
+ if (!ServerInstance->SE->AddFd(this, FD_WANT_NO_READ | FD_WANT_SINGLE_WRITE))
return I_ERR_NOMOREFDS;
this->Timeout = new SocketTimeout(this->GetFd(), this, timeout, ServerInstance->Time());
@@ -414,6 +414,8 @@ void BufferedSocket::DoWrite()
this->OnConnected();
if (GetIOHook())
GetIOHook()->OnStreamSocketConnect(this);
+ else
+ ServerInstance->SE->ChangeEventMask(this, FD_WANT_FAST_READ | FD_WANT_EDGE_WRITE);
}
this->StreamSocket::DoWrite();
}
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp
index c65b8528a..3362e9378 100644
--- a/src/modules/extra/m_ssl_gnutls.cpp
+++ b/src/modules/extra/m_ssl_gnutls.cpp
@@ -540,12 +540,12 @@ class ModuleSSLGnuTLS : public Module
else if (ret > 0)
{
sendq = sendq.substr(ret);
- ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_WRITE);
+ ServerInstance->SE->ChangeEventMask(user, FD_WANT_SINGLE_WRITE);
return 0;
}
else if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
{
- ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_WRITE);
+ ServerInstance->SE->ChangeEventMask(user, FD_WANT_SINGLE_WRITE);
return 0;
}
else if (ret == 0)
@@ -585,7 +585,7 @@ class ModuleSSLGnuTLS : public Module
{
// gnutls_handshake() wants to write() again.
session->status = ISSL_HANDSHAKING_WRITE;
- ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_POLL_WRITE);
+ ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_SINGLE_WRITE);
}
}
else
diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp
index e72bdc816..645add4c2 100644
--- a/src/modules/extra/m_ssl_openssl.cpp
+++ b/src/modules/extra/m_ssl_openssl.cpp
@@ -450,7 +450,7 @@ class ModuleSSLOpenSSL : public Module
}
else if (err == SSL_ERROR_WANT_WRITE)
{
- ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_POLL_WRITE);
+ ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_SINGLE_WRITE);
return 0;
}
else
@@ -501,7 +501,7 @@ class ModuleSSLOpenSSL : public Module
else if (ret > 0)
{
buffer = buffer.substr(ret);
- ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_WRITE);
+ ServerInstance->SE->ChangeEventMask(user, FD_WANT_SINGLE_WRITE);
return 0;
}
else if (ret == 0)
@@ -515,7 +515,7 @@ class ModuleSSLOpenSSL : public Module
if (err == SSL_ERROR_WANT_WRITE)
{
- ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_WRITE);
+ ServerInstance->SE->ChangeEventMask(user, FD_WANT_SINGLE_WRITE);
return 0;
}
else if (err == SSL_ERROR_WANT_READ)
@@ -554,7 +554,7 @@ class ModuleSSLOpenSSL : public Module
}
else if (err == SSL_ERROR_WANT_WRITE)
{
- ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_POLL_WRITE);
+ ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_SINGLE_WRITE);
session->status = ISSL_HANDSHAKING;
return true;
}
diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp
index 672ff4a7b..059798d25 100644
--- a/src/socketengines/socketengine_epoll.cpp
+++ b/src/socketengines/socketengine_epoll.cpp
@@ -58,12 +58,12 @@ EPollEngine::~EPollEngine()
static int mask_to_epoll(int event_mask)
{
int rv = 0;
- if (event_mask & (FD_WANT_POLL_READ | FD_WANT_POLL_WRITE))
+ if (event_mask & (FD_WANT_POLL_READ | FD_WANT_POLL_WRITE | FD_WANT_SINGLE_WRITE))
{
// we need to use standard polling on this FD
if (event_mask & (FD_WANT_POLL_READ | FD_WANT_FAST_READ))
rv |= EPOLLIN;
- if (event_mask & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE))
+ if (event_mask & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE))
rv |= EPOLLOUT;
}
else
@@ -182,16 +182,28 @@ int EPollEngine::DispatchEvents()
eh->HandleEvent(EVENT_ERROR, errcode);
continue;
}
+ int mask = eh->GetEventMask();
+ if (events[j].events & EPOLLIN)
+ mask &= ~FD_READ_WILL_BLOCK;
+ if (events[j].events & EPOLLOUT)
+ {
+ mask &= ~FD_WRITE_WILL_BLOCK;
+ if (mask & FD_WANT_SINGLE_WRITE)
+ {
+ int nm = mask & ~FD_WANT_SINGLE_WRITE;
+ OnSetEvent(eh, mask, nm);
+ mask = nm;
+ }
+ }
+ SetEventMask(eh, mask);
if (events[j].events & EPOLLIN)
{
ReadEvents++;
- SetEventMask(eh, eh->GetEventMask() & ~FD_READ_WILL_BLOCK);
eh->HandleEvent(EVENT_READ);
}
if (events[j].events & EPOLLOUT)
{
WriteEvents++;
- SetEventMask(eh, eh->GetEventMask() & ~FD_WRITE_WILL_BLOCK);
eh->HandleEvent(EVENT_WRITE);
}
}
diff --git a/src/socketengines/socketengine_iocp.cpp b/src/socketengines/socketengine_iocp.cpp
index e09fb4d0a..c253bf0a6 100644
--- a/src/socketengines/socketengine_iocp.cpp
+++ b/src/socketengines/socketengine_iocp.cpp
@@ -91,7 +91,7 @@ bool IOCPEngine::AddFd(EventHandler* eh, int event_mask)
ServerInstance->Logs->Log("SOCKET",DEBUG, "New fake fd: %u, real fd: %u, address 0x%p", *fake_fd, eh->GetFd(), eh);
/* post a write event if there is data to be written */
- if (event_mask & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE))
+ if (event_mask & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE))
WantWrite(eh);
/* we're all good =) */
@@ -183,7 +183,7 @@ void IOCPEngine::OnSetEvent(EventHandler* eh, int old_mask, int new_mask)
return;
/* Post event - write begin */
- if((new_mask & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE)) && !eh->GetExt("windows_writeevent", m_writeEvent))
+ if((new_mask & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE)) && !eh->GetExt("windows_writeevent", m_writeEvent))
{
ULONG_PTR completion_key = (ULONG_PTR)*fake_fd;
Overlapped * ov = new Overlapped(SOCKET_IO_EVENT_WRITE_READY, 0);
diff --git a/src/socketengines/socketengine_kqueue.cpp b/src/socketengines/socketengine_kqueue.cpp
index c9734e85d..1a783153e 100644
--- a/src/socketengines/socketengine_kqueue.cpp
+++ b/src/socketengines/socketengine_kqueue.cpp
@@ -76,7 +76,7 @@ bool KQueueEngine::AddFd(EventHandler* eh, int event_mask)
return false;
}
- if (event_mask & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE)) {
+ if (event_mask & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE)) {
// ...and sometimes want to write
WantWrite(eh);
}
@@ -148,7 +148,7 @@ void KQueueEngine::OnSetEvent(EventHandler* eh, int old_mask, int new_mask)
eh->GetFd(), strerror(errno));
}
}
- if ((new_mask & FD_WANT_EDGE_WRITE) && !(old_mask & FD_WANT_EDGE_WRITE))
+ if ((new_mask & (FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE)) && !(old_mask & (FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE)))
{
// new one-shot write
struct kevent ke;
@@ -184,11 +184,11 @@ int KQueueEngine::DispatchEvents()
if (ke_list[j].filter == EVFILT_WRITE)
{
WriteEvents++;
- /* When mask is FD_WANT_FAST_WRITE, we set a one-shot
- * write, so we need to clear that bit to detect when it
- * set again.
+ /* When mask is FD_WANT_FAST_WRITE or FD_WANT_SINGLE_WRITE,
+ * we set a one-shot write, so we need to clear that bit
+ * to detect when it set again.
*/
- const int bits_to_clr = FD_WANT_FAST_WRITE | FD_WRITE_WILL_BLOCK;
+ const int bits_to_clr = FD_WANT_SINGLE_WRITE | FD_WANT_FAST_WRITE | FD_WRITE_WILL_BLOCK;
SetEventMask(eh, eh->GetEventMask() & ~bits_to_clr);
eh->HandleEvent(EVENT_WRITE);
}
diff --git a/src/socketengines/socketengine_poll.cpp b/src/socketengines/socketengine_poll.cpp
index 6f50e2798..a72d21d1f 100644
--- a/src/socketengines/socketengine_poll.cpp
+++ b/src/socketengines/socketengine_poll.cpp
@@ -63,7 +63,7 @@ static int mask_to_poll(int event_mask)
int rv = 0;
if (event_mask & (FD_WANT_POLL_READ | FD_WANT_FAST_READ))
rv |= POLLIN;
- if (event_mask & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE))
+ if (event_mask & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE))
rv |= POLLOUT;
return rv;
}
@@ -208,7 +208,10 @@ int PollEngine::DispatchEvents()
if (events[index].revents & POLLOUT)
{
- SetEventMask(eh, eh->GetEventMask() & ~FD_WRITE_WILL_BLOCK);
+ int mask = eh->GetEventMask();
+ mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE);
+ SetEventMask(eh, mask);
+ events[index].events = mask_to_poll(mask);
eh->HandleEvent(EVENT_WRITE);
}
}
diff --git a/src/socketengines/socketengine_ports.cpp b/src/socketengines/socketengine_ports.cpp
index a99806fc4..d23857f50 100644
--- a/src/socketengines/socketengine_ports.cpp
+++ b/src/socketengines/socketengine_ports.cpp
@@ -60,7 +60,7 @@ static int mask_to_events(int event_mask)
int rv = 0;
if (event_mask & (FD_WANT_POLL_READ | FD_WANT_FAST_READ))
rv |= POLLRDNORM;
- if (event_mask & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE))
+ if (event_mask & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE))
rv |= POLLWRNORM;
return rv;
}
@@ -132,7 +132,7 @@ int PortsEngine::DispatchEvents()
{
int mask = eh->GetEventMask();
if (events[i].portev_events & POLLWRNORM)
- mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_FAST_WRITE);
+ mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE);
if (events[i].portev_events & POLLRDNORM)
mask &= ~FD_READ_WILL_BLOCK;
// reinsert port for next time around, pretending to be one-shot for writes
diff --git a/src/socketengines/socketengine_select.cpp b/src/socketengines/socketengine_select.cpp
index f089fd698..eacfc0fbf 100644
--- a/src/socketengines/socketengine_select.cpp
+++ b/src/socketengines/socketengine_select.cpp
@@ -89,7 +89,7 @@ int SelectEngine::DispatchEvents()
int state = eh->GetEventMask();
if (state & (FD_WANT_POLL_READ | FD_WANT_FAST_READ))
FD_SET (i, &rfdset);
- if (state & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE))
+ if (state & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE))
FD_SET (i, &wfdset);
FD_SET (i, &errfdset);
}
@@ -134,7 +134,7 @@ int SelectEngine::DispatchEvents()
if (FD_ISSET (i, &wfdset))
{
WriteEvents++;
- SetEventMask(eh, eh->GetEventMask() & ~FD_WRITE_WILL_BLOCK);
+ SetEventMask(eh, eh->GetEventMask() & ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE));
ev->HandleEvent(EVENT_WRITE);
}
}