#include "lwip/opt.h"
#include "lwip/sys.h"
#ifdef _WIN32
#ifdef _MSC_VER
#pragma warning (push, 3)
#endif
#include <windows.h>
#ifdef _MSC_VER
#pragma warning (pop)
#endif
#include <time.h>
#include <lwip/arch.h>
#include <lwip/stats.h>
#include <lwip/debug.h>
#include <lwip/tcpip.h>
#ifndef LWIP_SYS_ARCH_CHECK_NESTED_PROTECT
#define LWIP_SYS_ARCH_CHECK_NESTED_PROTECT 1
#endif
#ifndef LWIP_SYS_ARCH_CHECK_SCHEDULING_UNPROTECTED
#define LWIP_SYS_ARCH_CHECK_SCHEDULING_UNPROTECTED LWIP_TCPIP_CORE_LOCKING
#endif
#define LWIP_WIN32_SYS_ARCH_ENABLE_PROTECT_COUNTER (LWIP_SYS_ARCH_CHECK_NESTED_PROTECT || LWIP_SYS_ARCH_CHECK_SCHEDULING_UNPROTECTED)
static LARGE_INTEGER freq, sys_start_time;
#define SYS_INITIALIZED() (freq.QuadPart != 0)
static DWORD netconn_sem_tls_index;
u32_t
sys_win_rand(void)
{
u32_t ret;
if (SUCCEEDED(BCryptGenRandom(NULL, (PUCHAR)&ret, sizeof(ret), BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {
return ret;
}
LWIP_ASSERT("BCryptGenRandom failed", 0);
return 0;
}
static void
sys_win_rand_init(void)
{
}
static void
sys_init_timing(void)
{
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&sys_start_time);
}
static LONGLONG
sys_get_ms_longlong(void)
{
LONGLONG ret;
LARGE_INTEGER now;
#if NO_SYS
if (!SYS_INITIALIZED()) {
sys_init();
LWIP_ASSERT("initialization failed", SYS_INITIALIZED());
}
#endif
QueryPerformanceCounter(&now);
ret = now.QuadPart-sys_start_time.QuadPart;
return (u32_t)(((ret)*1000)/freq.QuadPart);
}
u32_t
sys_jiffies(void)
{
return (u32_t)sys_get_ms_longlong();
}
u32_t
sys_now(void)
{
return (u32_t)sys_get_ms_longlong();
}
CRITICAL_SECTION critSec;
#if LWIP_WIN32_SYS_ARCH_ENABLE_PROTECT_COUNTER
static int protection_depth;
#endif
static void
InitSysArchProtect(void)
{
InitializeCriticalSection(&critSec);
}
sys_prot_t
sys_arch_protect(void)
{
#if NO_SYS
if (!SYS_INITIALIZED()) {
sys_init();
LWIP_ASSERT("initialization failed", SYS_INITIALIZED());
}
#endif
EnterCriticalSection(&critSec);
#if LWIP_SYS_ARCH_CHECK_NESTED_PROTECT
LWIP_ASSERT("nested SYS_ARCH_PROTECT", protection_depth == 0);
#endif
#if LWIP_WIN32_SYS_ARCH_ENABLE_PROTECT_COUNTER
protection_depth++;
#endif
return 0;
}
void
sys_arch_unprotect(sys_prot_t pval)
{
LWIP_UNUSED_ARG(pval);
#if LWIP_SYS_ARCH_CHECK_NESTED_PROTECT
LWIP_ASSERT("missing SYS_ARCH_PROTECT", protection_depth == 1);
#else
LWIP_ASSERT("missing SYS_ARCH_PROTECT", protection_depth > 0);
#endif
#if LWIP_WIN32_SYS_ARCH_ENABLE_PROTECT_COUNTER
protection_depth--;
#endif
LeaveCriticalSection(&critSec);
}
#if LWIP_SYS_ARCH_CHECK_SCHEDULING_UNPROTECTED
static void
sys_arch_check_not_protected(void)
{
sys_arch_protect();
LWIP_ASSERT("SYS_ARCH_PROTECT before scheduling", protection_depth == 1);
sys_arch_unprotect(0);
}
#else
#define sys_arch_check_not_protected()
#endif
static void
msvc_sys_init(void)
{
sys_win_rand_init();
sys_init_timing();
InitSysArchProtect();
netconn_sem_tls_index = TlsAlloc();
LWIP_ASSERT("TlsAlloc failed", netconn_sem_tls_index != TLS_OUT_OF_INDEXES);
}
void
sys_init(void)
{
msvc_sys_init();
}
#include <stdarg.h>
void
lwip_win32_platform_diag(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
}
#elif __APPLE__
#include <mach/mach_time.h>
u32_t sys_now(void) {
uint64_t now = mach_absolute_time();
mach_timebase_info_data_t info;
mach_timebase_info(&info);
now = now * info.numer / info.denom / NSEC_PER_MSEC;
return (u32_t)(now);
}
#elif __linux
#include <sys/time.h>
u32_t sys_now(void)
{
struct timeval te;
gettimeofday(&te, NULL);
return te.tv_sec*1000LL + te.tv_usec/1000;
}
#elif __unix
#elif __posix
#endif