Skip to content

Commit

Permalink
[socket] Reduce handle manipulations in native (#5378)
Browse files Browse the repository at this point in the history
  • Loading branch information
luhenry committed Aug 31, 2017
1 parent 118a5c7 commit 078463f
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 151 deletions.
2 changes: 1 addition & 1 deletion configure.ac
Expand Up @@ -40,7 +40,7 @@ MONO_VERSION_BUILD=`echo $VERSION | cut -d . -f 3`
# This can be reset to 0 when Mono's version number is bumped
# since it's part of the corlib version (the prefix '1' in the full
# version number is to ensure the number isn't treated as octal in C)
MONO_CORLIB_COUNTER=0
MONO_CORLIB_COUNTER=1
MONO_CORLIB_VERSION=`printf "1%02d%02d%02d%03d" $MONO_VERSION_MAJOR $MONO_VERSION_MINOR 0 $MONO_CORLIB_COUNTER`

AC_DEFINE_UNQUOTED(MONO_CORLIB_VERSION,$MONO_CORLIB_VERSION,[Version of the corlib-runtime interface])
Expand Down
141 changes: 87 additions & 54 deletions mcs/class/System/System.Net.Sockets/Socket.cs
Expand Up @@ -1290,7 +1290,12 @@ public int Receive (byte [] buffer, int offset, int size, SocketFlags socketFlag
ThrowIfBufferOutOfRange (buffer, offset, size);

int nativeError;
int ret = Receive_internal (m_Handle, buffer, offset, size, socketFlags, out nativeError, is_blocking);
int ret;
unsafe {
fixed (byte* pbuffer = buffer) {
ret = Receive_internal (m_Handle, &pbuffer[offset], size, socketFlags, out nativeError, is_blocking);
}
}

errorCode = (SocketError) nativeError;
if (errorCode != SocketError.Success && errorCode != SocketError.WouldBlock && errorCode != SocketError.InProgress) {
Expand All @@ -1315,25 +1320,27 @@ public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags,
int nativeError;
int ret;

/* Only example I can find of sending a byte array reference directly into an internal
* call is in System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs,
* so taking a lead from that... */
WSABUF[] bufarray = new WSABUF[numsegments];
GCHandle[] gch = new GCHandle[numsegments];
try {
unsafe {
fixed (WSABUF* bufarray = new WSABUF[numsegments]) {
for (int i = 0; i < numsegments; i++) {
ArraySegment<byte> segment = buffers[i];

for (int i = 0; i < numsegments; i++) {
ArraySegment<byte> segment = buffers[i];
if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
throw new ArgumentOutOfRangeException ("segment");

if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
throw new ArgumentOutOfRangeException ("segment");
try {} finally {
gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
}

gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
bufarray[i].len = segment.Count;
bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
}
bufarray[i].len = segment.Count;
bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
}

try {
ret = Receive_internal (m_Handle, bufarray, socketFlags, out nativeError, is_blocking);
ret = Receive_internal (m_Handle, bufarray, numsegments, socketFlags, out nativeError, is_blocking);
}
}
} finally {
for (int i = 0; i < numsegments; i++) {
if (gch[i].IsAllocated)
Expand Down Expand Up @@ -1422,7 +1429,11 @@ public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFla
int total = 0;
try {
total = Receive_internal (sockares.socket.m_Handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error, sockares.socket.is_blocking);
unsafe {
fixed (byte* pbuffer = sockares.Buffer) {
total = Receive_internal (sockares.socket.m_Handle, &pbuffer[sockares.Offset], sockares.Size, sockares.SockFlags, out sockares.error, sockares.socket.is_blocking);
}
}
} catch (Exception e) {
sockares.Complete (e);
return;
Expand Down Expand Up @@ -1488,31 +1499,31 @@ public int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
return sockares.Total;
}

static int Receive_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error, bool blocking)
static unsafe int Receive_internal (SafeSocketHandle safeHandle, WSABUF* bufarray, int count, SocketFlags flags, out int error, bool blocking)
{
try {
safeHandle.RegisterForBlockingSyscall ();
return Receive_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error, blocking);
return Receive_internal (safeHandle.DangerousGetHandle (), bufarray, count, flags, out error, blocking);
} finally {
safeHandle.UnRegisterForBlockingSyscall ();
}
}

[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static int Receive_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error, bool blocking);
extern static unsafe int Receive_internal (IntPtr sock, WSABUF* bufarray, int count, SocketFlags flags, out int error, bool blocking);

static int Receive_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, out int error, bool blocking)
static unsafe int Receive_internal (SafeSocketHandle safeHandle, byte* buffer, int count, SocketFlags flags, out int error, bool blocking)
{
try {
safeHandle.RegisterForBlockingSyscall ();
return Receive_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, out error, blocking);
return Receive_internal (safeHandle.DangerousGetHandle (), buffer, count, flags, out error, blocking);
} finally {
safeHandle.UnRegisterForBlockingSyscall ();
}
}

[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static int Receive_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, out int error, bool blocking);
extern static unsafe int Receive_internal(IntPtr sock, byte* buffer, int count, SocketFlags flags, out int error, bool blocking);

#endregion

Expand Down Expand Up @@ -1541,7 +1552,12 @@ internal int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags sock
SocketAddress sockaddr = remoteEP.Serialize();

int nativeError;
int cnt = ReceiveFrom_internal (m_Handle, buffer, offset, size, socketFlags, ref sockaddr, out nativeError, is_blocking);
int cnt;
unsafe {
fixed (byte* pbuffer = buffer) {
cnt = ReceiveFrom_internal (m_Handle, &pbuffer[offset], size, socketFlags, ref sockaddr, out nativeError, is_blocking);
}
}

errorCode = (SocketError) nativeError;
if (errorCode != SocketError.Success) {
Expand Down Expand Up @@ -1672,18 +1688,18 @@ public int EndReceiveFrom(IAsyncResult asyncResult, ref EndPoint endPoint)



static int ReceiveFrom_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error, bool blocking)
static unsafe int ReceiveFrom_internal (SafeSocketHandle safeHandle, byte* buffer, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error, bool blocking)
{
try {
safeHandle.RegisterForBlockingSyscall ();
return ReceiveFrom_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, ref sockaddr, out error, blocking);
return ReceiveFrom_internal (safeHandle.DangerousGetHandle (), buffer, count, flags, ref sockaddr, out error, blocking);
} finally {
safeHandle.UnRegisterForBlockingSyscall ();
}
}

[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static int ReceiveFrom_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error, bool blocking);
extern static unsafe int ReceiveFrom_internal(IntPtr sock, byte* buffer, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error, bool blocking);

#endregion

Expand Down Expand Up @@ -1757,8 +1773,12 @@ public int Send (byte [] buffer, int offset, int size, SocketFlags socketFlags,
int nativeError;
int sent = 0;
do {
sent += Send_internal (
m_Handle, buffer, offset + sent, size - sent, socketFlags, out nativeError, is_blocking);
unsafe {
fixed (byte *pbuffer = buffer) {
sent += Send_internal (m_Handle, &pbuffer[offset + sent], size - sent, socketFlags, out nativeError, is_blocking);
}
}

errorCode = (SocketError)nativeError;
if (errorCode != SocketError.Success && errorCode != SocketError.WouldBlock && errorCode != SocketError.InProgress) {
is_connected = false;
Expand Down Expand Up @@ -1786,28 +1806,32 @@ public int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out
int nativeError;
int ret;

WSABUF[] bufarray = new WSABUF[numsegments];
GCHandle[] gch = new GCHandle[numsegments];
try {
unsafe {
fixed (WSABUF* bufarray = new WSABUF[numsegments]) {
for(int i = 0; i < numsegments; i++) {
ArraySegment<byte> segment = buffers[i];

for(int i = 0; i < numsegments; i++) {
ArraySegment<byte> segment = buffers[i];
if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
throw new ArgumentOutOfRangeException ("segment");

if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
throw new ArgumentOutOfRangeException ("segment");
try {} finally {
gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
}

gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
bufarray[i].len = segment.Count;
bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
}
bufarray[i].len = segment.Count;
bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
}

try {
ret = Send_internal (m_Handle, bufarray, socketFlags, out nativeError, is_blocking);
} finally {
for(int i = 0; i < numsegments; i++) {
if (gch[i].IsAllocated) {
gch[i].Free ();
ret = Send_internal (m_Handle, bufarray, numsegments, socketFlags, out nativeError, is_blocking);
}
}
} finally {
for (int i = 0; i < numsegments; i++) {
if (gch[i].IsAllocated)
gch[i].Free();
}
}

errorCode = (SocketError)nativeError;
Expand Down Expand Up @@ -1890,7 +1914,11 @@ static void BeginSendCallback (SocketAsyncResult sockares, int sent_so_far)
int total = 0;

try {
total = Socket.Send_internal (sockares.socket.m_Handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error, false);
unsafe {
fixed (byte *pbuffer = sockares.Buffer) {
total = Socket.Send_internal (sockares.socket.m_Handle, &pbuffer[sockares.Offset], sockares.Size, sockares.SockFlags, out sockares.error, false);
}
}
} catch (Exception e) {
sockares.Complete (e);
return;
Expand Down Expand Up @@ -1978,31 +2006,31 @@ public int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
return sockares.Total;
}

static int Send_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error, bool blocking)
static unsafe int Send_internal (SafeSocketHandle safeHandle, WSABUF* bufarray, int count, SocketFlags flags, out int error, bool blocking)
{
try {
safeHandle.RegisterForBlockingSyscall ();
return Send_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error, blocking);
return Send_internal (safeHandle.DangerousGetHandle (), bufarray, count, flags, out error, blocking);
} finally {
safeHandle.UnRegisterForBlockingSyscall ();
}
}

[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static int Send_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error, bool blocking);
extern static unsafe int Send_internal (IntPtr sock, WSABUF* bufarray, int count, SocketFlags flags, out int error, bool blocking);

static int Send_internal (SafeSocketHandle safeHandle, byte[] buf, int offset, int count, SocketFlags flags, out int error, bool blocking)
static unsafe int Send_internal (SafeSocketHandle safeHandle, byte* buffer, int count, SocketFlags flags, out int error, bool blocking)
{
try {
safeHandle.RegisterForBlockingSyscall ();
return Send_internal (safeHandle.DangerousGetHandle (), buf, offset, count, flags, out error, blocking);
return Send_internal (safeHandle.DangerousGetHandle (), buffer, count, flags, out error, blocking);
} finally {
safeHandle.UnRegisterForBlockingSyscall ();
}
}

[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static int Send_internal(IntPtr sock, byte[] buf, int offset, int count, SocketFlags flags, out int error, bool blocking);
extern static unsafe int Send_internal(IntPtr sock, byte* buffer, int count, SocketFlags flags, out int error, bool blocking);

#endregion

Expand All @@ -2018,7 +2046,12 @@ public int SendTo (byte [] buffer, int offset, int size, SocketFlags socketFlags
throw new ArgumentNullException("remoteEP");

int error;
int ret = SendTo_internal (m_Handle, buffer, offset, size, socketFlags, remoteEP.Serialize (), out error, is_blocking);
int ret;
unsafe {
fixed (byte *pbuffer = buffer) {
ret = SendTo_internal (m_Handle, &pbuffer[offset], size, socketFlags, remoteEP.Serialize (), out error, is_blocking);
}
}

SocketError err = (SocketError) error;
if (err != 0) {
Expand Down Expand Up @@ -2134,18 +2167,18 @@ public int EndSendTo (IAsyncResult asyncResult)
return sockares.Total;
}

static int SendTo_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error, bool blocking)
static unsafe int SendTo_internal (SafeSocketHandle safeHandle, byte* buffer, int count, SocketFlags flags, SocketAddress sa, out int error, bool blocking)
{
try {
safeHandle.RegisterForBlockingSyscall ();
return SendTo_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, sa, out error, blocking);
return SendTo_internal (safeHandle.DangerousGetHandle (), buffer, count, flags, sa, out error, blocking);
} finally {
safeHandle.UnRegisterForBlockingSyscall ();
}
}

[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static int SendTo_internal (IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error, bool blocking);
extern static unsafe int SendTo_internal (IntPtr sock, byte* buffer, int count, SocketFlags flags, SocketAddress sa, out int error, bool blocking);

#endregion

Expand Down
12 changes: 6 additions & 6 deletions mono/metadata/icall-def.h
Expand Up @@ -467,15 +467,15 @@ HANDLES(ICALL(SOCK_21, "IOControl_internal(intptr,int,byte[],byte[],int&)", ves_
HANDLES(ICALL(SOCK_9, "Listen_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_Listen_internal))
HANDLES(ICALL(SOCK_10, "LocalEndPoint_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal))
HANDLES(ICALL(SOCK_11, "Poll_internal", ves_icall_System_Net_Sockets_Socket_Poll_internal))
HANDLES(ICALL(SOCK_13, "ReceiveFrom_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,System.Net.SocketAddress&,int&,bool)", ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal))
HANDLES(ICALL(SOCK_11a, "Receive_internal(intptr,System.Net.Sockets.Socket/WSABUF[],System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Receive_array_internal))
HANDLES(ICALL(SOCK_12, "Receive_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Receive_internal))
HANDLES(ICALL(SOCK_13, "ReceiveFrom_internal(intptr,byte*,int,System.Net.Sockets.SocketFlags,System.Net.SocketAddress&,int&,bool)", ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal))
HANDLES(ICALL(SOCK_11a, "Receive_internal(intptr,System.Net.Sockets.Socket/WSABUF*,int,System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Receive_array_internal))
HANDLES(ICALL(SOCK_12, "Receive_internal(intptr,byte*,int,System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Receive_internal))
HANDLES(ICALL(SOCK_14, "RemoteEndPoint_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal))
HANDLES(ICALL(SOCK_15, "Select_internal(System.Net.Sockets.Socket[]&,int,int&)", ves_icall_System_Net_Sockets_Socket_Select_internal))
HANDLES(ICALL(SOCK_15a, "SendFile_internal(intptr,string,byte[],byte[],System.Net.Sockets.TransmitFileOptions,int&,bool)", ves_icall_System_Net_Sockets_Socket_SendFile_internal))
HANDLES(ICALL(SOCK_16, "SendTo_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,System.Net.SocketAddress,int&,bool)", ves_icall_System_Net_Sockets_Socket_SendTo_internal))
HANDLES(ICALL(SOCK_16a, "Send_internal(intptr,System.Net.Sockets.Socket/WSABUF[],System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Send_array_internal))
HANDLES(ICALL(SOCK_17, "Send_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Send_internal))
HANDLES(ICALL(SOCK_16, "SendTo_internal(intptr,byte*,int,System.Net.Sockets.SocketFlags,System.Net.SocketAddress,int&,bool)", ves_icall_System_Net_Sockets_Socket_SendTo_internal))
HANDLES(ICALL(SOCK_16a, "Send_internal(intptr,System.Net.Sockets.Socket/WSABUF*,int,System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Send_array_internal))
HANDLES(ICALL(SOCK_17, "Send_internal(intptr,byte*,int,System.Net.Sockets.SocketFlags,int&,bool)", ves_icall_System_Net_Sockets_Socket_Send_internal))
HANDLES(ICALL(SOCK_18, "SetSocketOption_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,object,byte[],int,int&)", ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal))
HANDLES(ICALL(SOCK_19, "Shutdown_internal(intptr,System.Net.Sockets.SocketShutdown,int&)", ves_icall_System_Net_Sockets_Socket_Shutdown_internal))
HANDLES(ICALL(SOCK_20, "Socket_internal(System.Net.Sockets.AddressFamily,System.Net.Sockets.SocketType,System.Net.Sockets.ProtocolType,int&)", ves_icall_System_Net_Sockets_Socket_Socket_internal))
Expand Down
5 changes: 0 additions & 5 deletions mono/metadata/w32socket-internals.h
Expand Up @@ -28,11 +28,6 @@
#define TF_DISCONNECT 0x01
#define TF_REUSE_SOCKET 0x02

typedef struct {
guint32 len;
gpointer buf;
} WSABUF, *LPWSABUF;

typedef struct {
gpointer Head;
guint32 HeadLength;
Expand Down

0 comments on commit 078463f

Please sign in to comment.