// Copyright 2015 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.

#ifdef __CYGWIN__
#error "don't use the cygwin compiler to build native Windows programs; use MinGW instead"
#endif

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <stdio.h>
#include <stdlib.h>

#include "libcgo.h"
#include "libcgo_windows.h"

static volatile LONG runtime_init_once_gate = 0;
static volatile LONG runtime_init_once_done = 0;

static CRITICAL_SECTION runtime_init_cs;

static HANDLE runtime_init_wait;
static int runtime_init_done;

// No pthreads on Windows, these are always zero.
uintptr_t x_cgo_pthread_key_created;
void (*x_crosscall2_ptr)(void (*fn)(void *), void *, int, size_t);

// Pre-initialize the runtime synchronization objects
void
_cgo_preinit_init() {
	 runtime_init_wait = CreateEvent(NULL, TRUE, FALSE, NULL);
	 if (runtime_init_wait == NULL) {
		fprintf(stderr, "runtime: failed to create runtime initialization wait event.\n");
		abort();
	 }

	 InitializeCriticalSection(&runtime_init_cs);
}

// Make sure that the preinit sequence has run.
void
_cgo_maybe_run_preinit() {
	 if (!InterlockedExchangeAdd(&runtime_init_once_done, 0)) {
			if (InterlockedIncrement(&runtime_init_once_gate) == 1) {
				 _cgo_preinit_init();
				 InterlockedIncrement(&runtime_init_once_done);
			} else {
				 // Decrement to avoid overflow.
				 InterlockedDecrement(&runtime_init_once_gate);
				 while(!InterlockedExchangeAdd(&runtime_init_once_done, 0)) {
						Sleep(0);
				 }
			}
	 }
}

void
x_cgo_sys_thread_create(unsigned long (__stdcall *func)(void*), void* arg) {
	_cgo_beginthread(func, arg);
}

int
_cgo_is_runtime_initialized() {
	 int status;

	 EnterCriticalSection(&runtime_init_cs);
	 status = runtime_init_done;
	 LeaveCriticalSection(&runtime_init_cs);
	 return status;
}

uintptr_t
_cgo_wait_runtime_init_done(void) {
	void (*pfn)(struct cgoContextArg*);

	 _cgo_maybe_run_preinit();
	while (!_cgo_is_runtime_initialized()) {
			WaitForSingleObject(runtime_init_wait, INFINITE);
	}
	pfn = _cgo_get_context_function();
	if (pfn != nil) {
		struct cgoContextArg arg;

		arg.Context = 0;
		(*pfn)(&arg);
		return arg.Context;
	}
	return 0;
}

// Should not be used since x_cgo_pthread_key_created will always be zero.
void x_cgo_bindm(void* dummy) {
	fprintf(stderr, "unexpected cgo_bindm on Windows\n");
	abort();
}

void
x_cgo_notify_runtime_init_done(void* dummy) {
	 _cgo_maybe_run_preinit();

	 EnterCriticalSection(&runtime_init_cs);
	runtime_init_done = 1;
	 LeaveCriticalSection(&runtime_init_cs);

	 if (!SetEvent(runtime_init_wait)) {
		fprintf(stderr, "runtime: failed to signal runtime initialization complete.\n");
		abort();
	}
}

// The traceback function, used when tracing C calls.
static void (*cgo_traceback_function)(struct cgoTracebackArg*);

// The context function, used when tracing back C calls into Go.
static void (*cgo_context_function)(struct cgoContextArg*);

// The symbolizer function, used when symbolizing C frames.
static void (*cgo_symbolizer_function)(struct cgoSymbolizerArg*);

// Sets the traceback, context, and symbolizer functions. Called from
// runtime.SetCgoTraceback.
void x_cgo_set_traceback_functions(struct cgoSetTracebackFunctionsArg* arg) {
	EnterCriticalSection(&runtime_init_cs);
	cgo_traceback_function = arg->Traceback;
	cgo_context_function = arg->Context;
	cgo_symbolizer_function = arg->Symbolizer;
	LeaveCriticalSection(&runtime_init_cs);
}

// Gets the traceback function to call to trace C calls.
void (*(_cgo_get_traceback_function(void)))(struct cgoTracebackArg*) {
	void (*ret)(struct cgoTracebackArg*);

	EnterCriticalSection(&runtime_init_cs);
	ret = cgo_traceback_function;
	LeaveCriticalSection(&runtime_init_cs);
	return ret;
}

// Call the traceback function registered with x_cgo_set_traceback_functions.
//
// On other platforms, this coordinates with C/C++ TSAN. On Windows, there is
// no C/C++ TSAN.
void x_cgo_call_traceback_function(struct cgoTracebackArg* arg) {
	void (*pfn)(struct cgoTracebackArg*);

	pfn = _cgo_get_traceback_function();
	if (pfn == nil) {
		return;
	}

	(*pfn)(arg);
}

// Gets the context function to call to record the traceback context
// when calling a Go function from C code.
void (*(_cgo_get_context_function(void)))(struct cgoContextArg*) {
	void (*ret)(struct cgoContextArg*);

	EnterCriticalSection(&runtime_init_cs);
	ret = cgo_context_function;
	LeaveCriticalSection(&runtime_init_cs);
	return ret;
}

// Gets the symbolizer function to call to symbolize C frames.
void (*(_cgo_get_symbolizer_function(void)))(struct cgoSymbolizerArg*) {
	void (*ret)(struct cgoSymbolizerArg*);

	EnterCriticalSection(&runtime_init_cs);
	ret = cgo_symbolizer_function;
	LeaveCriticalSection(&runtime_init_cs);
	return ret;
}

// Call the symbolizer function registered with x_cgo_set_symbolizer_functions.
//
// On other platforms, this coordinates with C/C++ TSAN. On Windows, there is
// no C/C++ TSAN.
void x_cgo_call_symbolizer_function(struct cgoSymbolizerArg* arg) {
	void (*pfn)(struct cgoSymbolizerArg*);

	pfn = _cgo_get_symbolizer_function();
	if (pfn == nil) {
		return;
	}

	(*pfn)(arg);
}

void _cgo_beginthread(unsigned long (__stdcall *func)(void*), void* arg) {
	int tries;
	HANDLE thandle;

	for (tries = 0; tries < 20; tries++) {
		thandle = CreateThread(NULL, 0, func, arg, 0, NULL);
		if (thandle == 0 && GetLastError() == ERROR_ACCESS_DENIED) {
			// "Insufficient resources", try again in a bit.
			//
			// Note that the first Sleep(0) is a yield.
			Sleep(tries); // milliseconds
			continue;
		} else if (thandle == 0) {
			break;
		}
		CloseHandle(thandle);
		return; // Success!
	}

	fprintf(stderr, "runtime: failed to create new OS thread (%lu)\n", GetLastError());
	abort();
}
