Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions emp-tool/cmake/emp-base.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread -Wall -funroll-loops -Wno-ignored-a
message("${Blue}-- Platform: ${CMAKE_SYSTEM_PROCESSOR}${ColourReset}")
IF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "(aarch64)|(arm64)")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a+simd+crypto+crc")
ELSEIF(WIN32)
# Windows (MinGW-w64): pin a distributable ISA baseline instead of -march=native,
# so the artifact runs on any x86-64-v2-class CPU (AES-NI, SSE4.2, PCLMUL).
# NOTE: -mrdseed is intentionally omitted. emp's PRG only uses _rdseed64_step under
# the ENABLE_RDSEED macro, which the build never defines (enable_rdseed.cmake defines
# the differently-named EMP_ENABLE_RDSEED), so PRG always seeds via std::random_device.
# Keeping RDSEED out of the baseline avoids implying a dependency on that instruction.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -msse4.2 -mpclmul")
ELSE(${CMAKE_SYSTEM_PROCESSOR} MATCHES "(aarch64)|(arm64)")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -maes -mrdseed")
ENDIF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "(aarch64)|(arm64)" )
Expand Down
1 change: 1 addition & 0 deletions emp-tool/emp-tool/circuits/circuit_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "emp-tool/execution/protocol_execution.h"
#include "emp-tool/utils/block.h"
#include "emp-tool/circuits/bit.h"
#include "emp-tool/utils/win_compat.h" // fmemopen shim on Windows (no-op elsewhere)
#include <stdio.h>
#include <fstream>

Expand Down
12 changes: 4 additions & 8 deletions emp-tool/emp-tool/io/highspeed_net_io_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,7 @@
#include "emp-tool/io/io_channel.h"
using std::string;

#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include "emp-tool/utils/win_compat.h"

namespace emp {

Expand Down Expand Up @@ -212,12 +207,13 @@ class HighSpeedNetIO : public IOChannel<HighSpeedNetIO> { public:
void sync() {}

void set_delay_opt(int sock, bool enable_nodelay) {
// cast to const char* for Winsock compatibility (no-op on POSIX)
if (enable_nodelay) {
const int one = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char*)&one, sizeof(one));
} else {
const int zero = 0;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &zero, sizeof(zero));
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char*)&zero, sizeof(zero));
}
}

Expand Down
13 changes: 5 additions & 8 deletions emp-tool/emp-tool/io/net_io_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,7 @@
using std::string;


#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "emp-tool/utils/win_compat.h"

namespace emp {

Expand Down Expand Up @@ -111,12 +106,14 @@ class NetIO: public IOChannel<NetIO> { public:

void set_nodelay() {
const int one=1;
setsockopt(consocket,IPPROTO_TCP,TCP_NODELAY,&one,sizeof(one));
// cast to const char* so it also compiles under Winsock (setsockopt takes
// const char* on Windows vs const void* on POSIX); no-op on POSIX.
setsockopt(consocket,IPPROTO_TCP,TCP_NODELAY,(const char*)&one,sizeof(one));
}

void set_delay() {
const int zero = 0;
setsockopt(consocket,IPPROTO_TCP,TCP_NODELAY,&zero,sizeof(zero));
setsockopt(consocket,IPPROTO_TCP,TCP_NODELAY,(const char*)&zero,sizeof(zero));
}

void flush() {
Expand Down
1 change: 1 addition & 0 deletions emp-tool/emp-tool/utils/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ inline __m128i _mm_aesdeclast_si128 (__m128i a, __m128i RoundKey)
#endif

#include <assert.h>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <iomanip>
Expand Down
1 change: 1 addition & 0 deletions emp-tool/emp-tool/utils/constants.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#ifndef EMP_CONFIG_H__
#define EMP_CONFIG_H__
#include <cstdint>
namespace emp {
const static int AES_BATCH_SIZE = 8;
const static int HASH_BUFFER_SIZE = 1024*8;
Expand Down
5 changes: 5 additions & 0 deletions emp-tool/emp-tool/utils/prg.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ class PRG { public:
block v;
#ifndef ENABLE_RDSEED
uint32_t * data = (uint32_t *)(&v);
#ifdef _WIN32
// Windows has no /dev/urandom; the default token uses the OS CSPRNG (rand_s).
std::random_device rand_div;
#else
std::random_device rand_div("/dev/urandom");
#endif
for (size_t i = 0; i < sizeof(block) / sizeof(uint32_t); ++i)
data[i] = rand_div();
#else
Expand Down
104 changes: 104 additions & 0 deletions emp-tool/emp-tool/utils/win_compat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#ifndef EMP_UTIL_WIN_COMPAT_H__
#define EMP_UTIL_WIN_COMPAT_H__

// Windows (MinGW-w64) portability shim for emp-toolkit.
//
// MinGW already provides <unistd.h> and <pthread.h> (winpthread), so only the
// BSD-socket headers and a couple of POSIX helpers are missing on Windows.
// This header centralizes those differences so the network I/O channels COMPILE
// under MinGW.
//
// SCOPE (P1): compile-only. emp's own NetIO/HighSpeedNetIO socket *runtime* path
// is intentionally NOT ported here — it still uses close() (not closesocket),
// never calls WSAStartup, and does not translate Winsock error codes. That is
// deferred to P2. In pado, real traffic goes through pado's own proxy channel,
// so emp's NetIO is only used as a template type and is not exercised at runtime.
// emp_wsa_init() below is the hook P2 will wire into the NetIO constructor.

#ifdef _WIN32

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>

// The NetIO/HighSpeedNetIO inline method bodies name ssize_t and close(); their
// declarations must be visible even though the socket runtime is not exercised in
// P1 (pado uses its own proxy channel). MinGW-w64 provides these headers.
// NOTE (P1 compile-only): close() here is the CRT file-descriptor close(), NOT a
// socket close — real socket cleanup (closesocket) is deferred to P2.
#include <sys/types.h> // ssize_t
#include <unistd.h> // close()

#if defined(_MSC_VER)
#pragma comment(lib, "ws2_32.lib")
#endif

#include <cstdint>
#include <cstdio>
#include <mutex>
#include <io.h> // _open_osfhandle, _close
#include <fcntl.h> // _O_RDWR, _O_BINARY

// POSIX usleep() shim (argument is microseconds). Windows Sleep() is ms-granular.
#ifndef usleep
static inline void emp_usleep(uint64_t usec) { Sleep((DWORD)((usec + 999) / 1000)); }
#define usleep(us) emp_usleep((uint64_t)(us))
#endif

// POSIX fmemopen() shim. MinGW-w64's CRT has no fmemopen, so BristolFormat's
// "load circuit from an in-memory string" ctor won't compile/link on Windows.
// Back it with a Win32 temp file opened FILE_FLAG_DELETE_ON_CLOSE: the file is
// removed automatically when the handle closes (or at process exit), so nothing
// is left on disk. Binary mode is used deliberately — fmemopen does no newline
// translation either, and the Bristol parser reads with fscanf on whitespace.
#ifndef fmemopen
static inline FILE* emp_fmemopen(const void* buf, size_t size, const char* mode) {
(void)mode;
char dir[MAX_PATH];
DWORD n = GetTempPathA(MAX_PATH, dir);
if (n == 0 || n > MAX_PATH) return NULL;
char path[MAX_PATH];
if (GetTempFileNameA(dir, "emp", 0, path) == 0) return NULL;
HANDLE h = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
NULL);
if (h == INVALID_HANDLE_VALUE) return NULL;
int fd = _open_osfhandle((intptr_t)h, _O_RDWR | _O_BINARY);
if (fd == -1) { CloseHandle(h); return NULL; }
FILE* f = _fdopen(fd, "wb+");
if (!f) { _close(fd); return NULL; }
if (size) fwrite(buf, 1, size, f);
fflush(f);
fseek(f, 0, SEEK_SET);
return f;
}
#define fmemopen(buf, size, mode) emp_fmemopen((buf), (size), (mode))
#endif

// One-time Winsock initialization; safe to call repeatedly.
static inline void emp_wsa_init() {
static std::once_flag once;
std::call_once(once, []() {
WSADATA data;
WSAStartup(MAKEWORD(2, 2), &data);
});
}

#else // !_WIN32 (POSIX)

#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <sys/socket.h>

static inline void emp_wsa_init() {}

#endif // _WIN32

#endif // EMP_UTIL_WIN_COMPAT_H__
Loading