// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"

#define DWORD_MAX 0xffffffff

#pragma dynimport runtime·CreateIoCompletionPort CreateIoCompletionPort "kernel32.dll"
#pragma dynimport runtime·GetQueuedCompletionStatus GetQueuedCompletionStatus "kernel32.dll"
#pragma dynimport runtime·WSAGetOverlappedResult WSAGetOverlappedResult "ws2_32.dll"

extern void *runtime·CreateIoCompletionPort;
extern void *runtime·GetQueuedCompletionStatus;
extern void *runtime·WSAGetOverlappedResult;

#define INVALID_HANDLE_VALUE ((uintptr)-1)

// net_op must be the same as beginning of net.operation. Keep these in sync.
typedef struct net_op net_op;
struct net_op
{
	// used by windows
	Overlapped	o;
	// used by netpoll
	PollDesc*	pd;
	int32	mode;
	int32	errno;
	uint32	qty;
};

typedef struct OverlappedEntry OverlappedEntry;
struct OverlappedEntry
{
	uintptr	key;
	net_op*	op;  // In reality it's Overlapped*, but we cast it to net_op* anyway.
	uintptr	internal;
	uint32	qty;
};

static void handlecompletion(G **gpp, net_op *o, int32 errno, uint32 qty);

static uintptr iocphandle = INVALID_HANDLE_VALUE;  // completion port io handle

void
runtime·netpollinit(void)
{
	iocphandle = (uintptr)runtime·stdcall(runtime·CreateIoCompletionPort, 4, INVALID_HANDLE_VALUE, (uintptr)0, (uintptr)0, (uintptr)DWORD_MAX);
	if(iocphandle == 0) {
		runtime·printf("netpoll: failed to create iocp handle (errno=%d)\n", runtime·getlasterror());
		runtime·throw("netpoll: failed to create iocp handle");
	}
	return;
}

int32
runtime·netpollopen(uintptr fd, PollDesc *pd)
{
	USED(pd);
	if(runtime·stdcall(runtime·CreateIoCompletionPort, 4, fd, iocphandle, (uintptr)0, (uintptr)0) == 0)
		return -runtime·getlasterror();
	return 0;
}

int32
runtime·netpollclose(uintptr fd)
{
	// nothing to do
	USED(fd);
	return 0;
}

void
runtime·netpollarm(PollDesc* pd, int32 mode)
{
	USED(pd, mode);
	runtime·throw("unused");
}

// Polls for completed network IO.
// Returns list of goroutines that become runnable.
G*
runtime·netpoll(bool block)
{
	OverlappedEntry entries[64];
	uint32 wait, qty, key, flags, n, i;
	int32 errno;
	net_op *op;
	G *gp;

	if(iocphandle == INVALID_HANDLE_VALUE)
		return nil;
	gp = nil;
	wait = 0;
	if(block)
		wait = INFINITE;
retry:
	if(runtime·GetQueuedCompletionStatusEx != nil) {
		n = nelem(entries) / runtime·gomaxprocs;
		if(n < 8)
			n = 8;
		if(block)
			m->blocked = true;
		if(runtime·stdcall(runtime·GetQueuedCompletionStatusEx, 6, iocphandle, entries, (uintptr)n, &n, (uintptr)wait, (uintptr)0) == 0) {
			m->blocked = false;
			errno = runtime·getlasterror();
			if(!block && errno == WAIT_TIMEOUT)
				return nil;
			runtime·printf("netpoll: GetQueuedCompletionStatusEx failed (errno=%d)\n", errno);
			runtime·throw("netpoll: GetQueuedCompletionStatusEx failed");
		}
		m->blocked = false;
		for(i = 0; i < n; i++) {
			op = entries[i].op;
			errno = 0;
			qty = 0;
			if(runtime·stdcall(runtime·WSAGetOverlappedResult, 5, runtime·netpollfd(op->pd), op, &qty, (uintptr)0, (uintptr)&flags) == 0)
				errno = runtime·getlasterror();
			handlecompletion(&gp, op, errno, qty);
		}
	} else {
		op = nil;
		errno = 0;
		qty = 0;
		if(block)
			m->blocked = true;
		if(runtime·stdcall(runtime·GetQueuedCompletionStatus, 5, iocphandle, &qty, &key, &op, (uintptr)wait) == 0) {
			m->blocked = false;
			errno = runtime·getlasterror();
			if(!block && errno == WAIT_TIMEOUT)
				return nil;
			if(op == nil) {
				runtime·printf("netpoll: GetQueuedCompletionStatus failed (errno=%d)\n", errno);
				runtime·throw("netpoll: GetQueuedCompletionStatus failed");
			}
			// dequeued failed IO packet, so report that
		}
		m->blocked = false;
		handlecompletion(&gp, op, errno, qty);
	}
	if(block && gp == nil)
		goto retry;
	return gp;
}

static void
handlecompletion(G **gpp, net_op *op, int32 errno, uint32 qty)
{
	int32 mode;

	if(op == nil)
		runtime·throw("netpoll: GetQueuedCompletionStatus returned op == nil");
	mode = op->mode;
	if(mode != 'r' && mode != 'w') {
		runtime·printf("netpoll: GetQueuedCompletionStatus returned invalid mode=%d\n", mode);
		runtime·throw("netpoll: GetQueuedCompletionStatus returned invalid mode");
	}
	op->errno = errno;
	op->qty = qty;
	runtime·netpollready(gpp, op->pd, mode);
}
