Hey guys, I was looking at the code of kestrel, in particular here: https://github.com/aspnet/KestrelHttpServer/blob/dev/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/Libuv.cs#L431
And I wondered, isn't sizeof(WSABUF) on windows 8/12 for 32/64 bit systems?
WSABUF consists of ULONG and a pointer, a ULONG according to http://stackoverflow.com/questions/384502/what-is-the-bit-size-of-long-on-64-bit-windows it is 4 bytes (or uint) even on 64bit windows.
I looked at the reference source code, and it seems to be a (int, intptr) too: http://referencesource.microsoft.com/#System/net/System/Net/_OSSOCK.cs,29
corefx: https://github.com/dotnet/corefx/blob/master/src/Common/src/Interop/Windows/Winsock/WSABuffer.cs#L12-L13
How is the current definition of uv_buf_t working on windows?
Alignment. There are 4 bytes of padding in WSABUF after len so buf is aligned to an 8-byte boundary (on 64-bit).
What does the alignment?
A struct member will normally start at an address that matches it's alignment requirement. On 64-bit the pointer should be 8-byte aligned. Since the preceding member takes 4 bytes, the compiler inserts 4 bytes of padding after it so that buf starts at an 8-byte boundary.
Some code:
#include <WinSock2.h>
int main()
{
WSABUF buf;
printf("sizeof(WSABUF): %d\n", sizeof(WSABUF));
printf("sizeof(WSABUF.len): %d\n", sizeof(buf.len));
printf("sizeof(WSABUF.buf): %d\n", sizeof(buf.buf));
printf("WSABUF.len: %p\n", &buf.len);
printf("WSABUF.buf: %p\n", &buf.buf);
return 0;
}
Output:
sizeof(WSABUF): 16
sizeof(WSABUF.len): 4
sizeof(WSABUF.buf): 8
WSABUF.len: 000000475A7FF6C8
WSABUF.buf: 000000475A7FF6D0
So the jit does the same for this?
[StructLayout(LayoutKind.Sequential)]
internal struct WSABuffer
{
internal int Length; // Length of Buffer
internal IntPtr Pointer;// Pointer to Buffer
}
StructLayout(LayoutKind.Sequential) means maintain the order otherwise it may swap the two fields for tighter packing.
StructLayout(LayoutKind.Explicit) is for exact specified positioning, when you additionally have to use FieldOffset attributes on the fields to specify their positions; and they can be overlapped for example in EventDescriptor
@txdv Yes:
[StructLayout(LayoutKind.Sequential)]
struct WSABuffer
{
internal int Length; // Length of Buffer
internal IntPtr Pointer;// Pointer to Buffer
}
class Program
{
static unsafe void Main(string[] args)
{
var s = new WSABuffer();
int* pLength = &s.Length;
IntPtr* pPointer = &s.Pointer;
IntPtr addrLength = (IntPtr)pLength;
IntPtr addrPointer = (IntPtr)pPointer;
Console.WriteLine(addrLength.ToString("x"));
Console.WriteLine(addrPointer.ToString("x"));
}
}
Output:
f3c1ffebc8
You are my hero!
Thank you very much.
Most helpful comment
@txdv Yes:
Output: