[Phi] adding basic host emulation for development without access to a
Xeon Phi
This commit is contained in:
@@ -235,6 +235,28 @@ To bring forth the driver:
|
||||
zig build phi --release=[fast|safe|small]
|
||||
```
|
||||
|
||||
To build Phi without a Xeon Phi card, enable host emulation:
|
||||
|
||||
```
|
||||
zig build phi -Dphi-host-emulation=true --release=[fast|safe|small]
|
||||
```
|
||||
|
||||
In this mode the daemon is compiled natively through Zig's `std.Build` C compilation support and installed as `zig-out/bin/phi_device-host`. The driver exposes one synthetic Phi physical device and communicates with the daemon over an IPv4 TCP socket bound only to `127.0.0.1`. The client socket is implemented directly with Zig's `std.Io.net` API; it does not reuse daemon C transport functions or load `libmicmgmt` or `libscif`.
|
||||
|
||||
The driver first connects to an already-running daemon. If none is listening, it launches its embedded daemon locally and retries the connection. The temporary embedded executable removes its own filesystem entry after launch. The daemon may also be started manually:
|
||||
|
||||
```
|
||||
./zig-out/bin/phi_device-host
|
||||
```
|
||||
|
||||
The loopback port defaults to `43616` and may be selected at build time for both the driver and daemon:
|
||||
|
||||
```
|
||||
zig build phi -Dphi-host-emulation=true -Dphi-emulation-port=43617
|
||||
```
|
||||
|
||||
Builds without `-Dphi-host-emulation=true` retain the real Xeon Phi path: the daemon is cross-compiled with the configured `k1om-mpss-linux-gcc`, deployed over SSH/SCP, and communicates through SCIF.
|
||||
|
||||
And for those who seek another manner of building:
|
||||
|
||||
```
|
||||
|
||||
@@ -11,6 +11,7 @@ const ImplementationDesc = struct {
|
||||
vulkan_version: std.SemanticVersion,
|
||||
custom: ?*const fn (
|
||||
*std.Build,
|
||||
*Step.Options,
|
||||
*Step.Compile,
|
||||
*std.Build.Module,
|
||||
*std.Build.Module,
|
||||
@@ -20,37 +21,32 @@ const ImplementationDesc = struct {
|
||||
std.builtin.OptimizeMode,
|
||||
bool,
|
||||
) anyerror!void = null,
|
||||
options: ?*const fn (*std.Build, *Step.Options) anyerror!void = null,
|
||||
};
|
||||
|
||||
const implementations = [_]ImplementationDesc{
|
||||
.{
|
||||
.name = "ape",
|
||||
.icd_name = "ape",
|
||||
.root_source_file = "src/ape/lib.zig",
|
||||
.vulkan_version = .{ .major = 1, .minor = 0, .patch = 0 },
|
||||
.custom = customApe,
|
||||
},
|
||||
.{
|
||||
.name = "soft",
|
||||
.root_source_file = "src/software/lib.zig",
|
||||
.vulkan_version = .{ .major = 1, .minor = 0, .patch = 0 },
|
||||
.custom = customSoft,
|
||||
.options = optionsSoft,
|
||||
},
|
||||
.{
|
||||
.name = "flint",
|
||||
.root_source_file = "src/intel/lib.zig",
|
||||
.vulkan_version = .{ .major = 1, .minor = 0, .patch = 0 },
|
||||
.custom = customFlint,
|
||||
.options = optionsFlint,
|
||||
},
|
||||
.{
|
||||
.name = "phi",
|
||||
.root_source_file = "src/phi/lib.zig",
|
||||
.vulkan_version = .{ .major = 1, .minor = 0, .patch = 0 },
|
||||
.custom = customPhi,
|
||||
.options = optionsPhi,
|
||||
},
|
||||
.{
|
||||
.name = "ape",
|
||||
.icd_name = "ape",
|
||||
.root_source_file = "src/ape/lib.zig",
|
||||
.vulkan_version = .{ .major = 1, .minor = 0, .patch = 0 },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -149,7 +145,8 @@ pub fn build(b: *std.Build) !void {
|
||||
|
||||
const use_llvm = b.option(bool, "use-llvm", "LLVM build") orelse (b.release_mode != .off);
|
||||
|
||||
for (implementations) |impl| {
|
||||
var implementation_modules: [implementations.len]*std.Build.Module = undefined;
|
||||
for (implementations, 0..) |impl, impl_index| {
|
||||
const lib_mod = b.createModule(.{
|
||||
.root_source_file = b.path(impl.root_source_file),
|
||||
.target = target,
|
||||
@@ -161,6 +158,7 @@ pub fn build(b: *std.Build) !void {
|
||||
},
|
||||
});
|
||||
|
||||
implementation_modules[impl_index] = lib_mod;
|
||||
lib_mod.addSystemIncludePath(vulkan_headers.path("include"));
|
||||
|
||||
const lib = b.addLibrary(.{
|
||||
@@ -172,12 +170,11 @@ pub fn build(b: *std.Build) !void {
|
||||
|
||||
options.addOption(std.SemanticVersion, b.fmt("{s}_vulkan_version", .{impl.name}), impl.vulkan_version);
|
||||
|
||||
if (impl.custom) |func| {
|
||||
func(b, lib, lib_mod, base_mod, vulkan, base_c_mod, target, optimize, use_llvm) catch continue;
|
||||
}
|
||||
|
||||
if (impl.options) |func| {
|
||||
func(b, options) catch continue;
|
||||
if (std.mem.eql(u8, impl.name, "ape")) {
|
||||
for (implementations[0..impl_index], implementation_modules[0..impl_index]) |child_impl, child_mod|
|
||||
lib_mod.addImport(child_impl.name, child_mod);
|
||||
} else if (impl.custom) |func| {
|
||||
func(b, options, lib, lib_mod, base_mod, vulkan, base_c_mod, target, optimize, use_llvm) catch continue;
|
||||
}
|
||||
|
||||
const icd_file = b.addWriteFile(
|
||||
@@ -426,45 +423,11 @@ fn addMultithreadedCTS(b: *std.Build, target: std.Build.ResolvedTarget, impl: *c
|
||||
return &run.step;
|
||||
}
|
||||
|
||||
// Ape specialized functions
|
||||
|
||||
fn customApe(
|
||||
b: *std.Build,
|
||||
lib: *Step.Compile,
|
||||
lib_mod: *std.Build.Module,
|
||||
base_mod: *std.Build.Module,
|
||||
vulkan: *std.Build.Module,
|
||||
base_c_mod: *std.Build.Module,
|
||||
target: std.Build.ResolvedTarget,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
use_llvm: bool,
|
||||
) !void {
|
||||
for (implementations) |impl| {
|
||||
if (std.mem.eql(u8, impl.name, "ape"))
|
||||
continue;
|
||||
|
||||
const mod = b.createModule(.{
|
||||
.root_source_file = b.path(impl.root_source_file),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.imports = &.{
|
||||
.{ .name = "base", .module = base_mod },
|
||||
.{ .name = "vulkan", .module = vulkan },
|
||||
},
|
||||
});
|
||||
|
||||
if (impl.custom) |func| {
|
||||
func(b, lib, mod, base_mod, vulkan, base_c_mod, target, optimize, use_llvm) catch continue;
|
||||
}
|
||||
|
||||
lib_mod.addImport(impl.name, mod);
|
||||
}
|
||||
}
|
||||
|
||||
// Soft specialized functions
|
||||
|
||||
fn customSoft(
|
||||
b: *std.Build,
|
||||
options: *Step.Options,
|
||||
_: *Step.Compile,
|
||||
lib_mod: *std.Build.Module,
|
||||
_: *std.Build.Module,
|
||||
@@ -482,9 +445,7 @@ fn customSoft(
|
||||
|
||||
lib_mod.addImport("soft_c", base_c_mod);
|
||||
lib_mod.addImport("spv", spv.module("spv"));
|
||||
}
|
||||
|
||||
fn optionsSoft(b: *std.Build, options: *Step.Options) !void {
|
||||
const single_threaded_option = b.option(bool, "soft-single-threaded", "Single threaded runtime mode") orelse false;
|
||||
const shaders_simd_option = b.option(bool, "soft-shader-simd", "Shaders SIMD acceleration") orelse true;
|
||||
const compute_dump_early_results_table_option = b.option(u32, "soft-compute-dump-early-results-table", "Dump compute shaders results table before invocation");
|
||||
@@ -502,6 +463,7 @@ fn optionsSoft(b: *std.Build, options: *Step.Options) !void {
|
||||
|
||||
fn customFlint(
|
||||
b: *std.Build,
|
||||
_: *Step.Options,
|
||||
_: *Step.Compile,
|
||||
lib_mod: *std.Build.Module,
|
||||
_: *std.Build.Module,
|
||||
@@ -519,15 +481,11 @@ fn customFlint(
|
||||
}));
|
||||
}
|
||||
|
||||
fn optionsFlint(b: *std.Build, options: *Step.Options) !void {
|
||||
_ = b;
|
||||
_ = options;
|
||||
}
|
||||
|
||||
// Phi specialized functions
|
||||
|
||||
fn customPhi(
|
||||
b: *std.Build,
|
||||
options: *Step.Options,
|
||||
lib: *Step.Compile,
|
||||
lib_mod: *std.Build.Module,
|
||||
_: *std.Build.Module,
|
||||
@@ -537,15 +495,52 @@ fn customPhi(
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
use_llvm: bool,
|
||||
) !void {
|
||||
const daemon_remote_path = b.option(
|
||||
[]const u8,
|
||||
"phi-daemon-remote-path",
|
||||
"Path where the Xeon Phi daemon is copied on the card",
|
||||
) orelse "/tmp/phi_device.mic";
|
||||
|
||||
const daemon_host_prefix = b.option(
|
||||
[]const u8,
|
||||
"phi-daemon-host-prefix",
|
||||
"Host prefix used to reach cards over ssh/scp; card N uses <prefix>N",
|
||||
) orelse "mic";
|
||||
|
||||
options.addOption([]const u8, "phi_daemon_remote_path", daemon_remote_path);
|
||||
options.addOption([]const u8, "phi_daemon_host_prefix", daemon_host_prefix);
|
||||
|
||||
const host_emulation = b.option(
|
||||
bool,
|
||||
"phi-host-emulation",
|
||||
"Run the Phi device daemon on the host over a loopback TCP socket",
|
||||
) orelse false;
|
||||
const emulation_port = b.option(
|
||||
u16,
|
||||
"phi-emulation-port",
|
||||
"Loopback TCP port used by Phi host emulation",
|
||||
) orelse 43616;
|
||||
|
||||
options.addOption(bool, "phi_host_emulation", host_emulation);
|
||||
options.addOption(u16, "phi_emulation_port", emulation_port);
|
||||
|
||||
lib_mod.addImport("phi_c", base_c_mod);
|
||||
|
||||
const miclib = b.lazyDependency("miclib", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.@"use-llvm" = use_llvm,
|
||||
}) orelse return error.UnresolvedDependency;
|
||||
if (host_emulation) {
|
||||
lib_mod.addImport("miclib", b.createModule(.{
|
||||
.root_source_file = b.path("src/phi/mic_stub.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
}));
|
||||
} else {
|
||||
const miclib = b.lazyDependency("miclib", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.@"use-llvm" = use_llvm,
|
||||
}) orelse return error.UnresolvedDependency;
|
||||
|
||||
lib_mod.addImport("miclib", miclib.module("miclib"));
|
||||
lib_mod.addImport("miclib", miclib.module("miclib"));
|
||||
}
|
||||
|
||||
const phi_protocol_c = b.addTranslateC(.{
|
||||
.root_source_file = b.path("src/phi/shared/Protocol.h"),
|
||||
@@ -556,20 +551,10 @@ fn customPhi(
|
||||
|
||||
lib_mod.addImport("phi_protocol_c", phi_protocol_c.createModule());
|
||||
|
||||
// To avoid duplicated options due to Ape's custom function
|
||||
if (!std.mem.eql(u8, lib.name, "vulkan_phi")) {
|
||||
const daemon = try addPhiCardDaemon(b, optimize, "k1om-mpss-linux-gcc", null);
|
||||
const embedded_daemon = addEmbeddedPhiDaemon(b, daemon);
|
||||
lib_mod.addAnonymousImport("phi_daemon", .{
|
||||
.root_source_file = embedded_daemon,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const build_card = b.option(
|
||||
bool,
|
||||
"phi-build-daemon",
|
||||
"Build Xeon Phi card daemon",
|
||||
"Build the Phi device daemon",
|
||||
) orelse true;
|
||||
|
||||
if (!build_card)
|
||||
@@ -587,8 +572,11 @@ fn customPhi(
|
||||
"MPSS sysroot path",
|
||||
);
|
||||
|
||||
const daemon = try addPhiCardDaemon(b, optimize, cc, sysroot);
|
||||
const install_daemon = b.addInstallFile(daemon, "lib/phi_device.mic");
|
||||
const daemon = try addPhiDaemon(b, optimize, host_emulation, emulation_port, cc, sysroot);
|
||||
const install_daemon = b.addInstallFile(
|
||||
daemon,
|
||||
if (host_emulation) "bin/phi_device-host" else "lib/phi_device.mic",
|
||||
);
|
||||
lib.step.dependOn(&install_daemon.step);
|
||||
|
||||
const embedded_daemon = addEmbeddedPhiDaemon(b, daemon);
|
||||
@@ -597,24 +585,17 @@ fn customPhi(
|
||||
});
|
||||
}
|
||||
|
||||
fn optionsPhi(b: *std.Build, options: *Step.Options) !void {
|
||||
const daemon_remote_path = b.option(
|
||||
[]const u8,
|
||||
"phi-daemon-remote-path",
|
||||
"Path where the Xeon Phi daemon is copied on the card",
|
||||
) orelse "/tmp/phi_device.mic";
|
||||
fn addPhiDaemon(
|
||||
b: *std.Build,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
host_emulation: bool,
|
||||
emulation_port: u16,
|
||||
cc: []const u8,
|
||||
sysroot: ?[]const u8,
|
||||
) !std.Build.LazyPath {
|
||||
if (host_emulation)
|
||||
return addPhiHostDaemon(b, optimize, emulation_port);
|
||||
|
||||
const daemon_host_prefix = b.option(
|
||||
[]const u8,
|
||||
"phi-daemon-host-prefix",
|
||||
"Host prefix used to reach cards over ssh/scp; card N uses <prefix>N",
|
||||
) orelse "mic";
|
||||
|
||||
options.addOption([]const u8, "phi_daemon_remote_path", daemon_remote_path);
|
||||
options.addOption([]const u8, "phi_daemon_host_prefix", daemon_host_prefix);
|
||||
}
|
||||
|
||||
fn addPhiCardDaemon(b: *std.Build, optimize: std.builtin.OptimizeMode, cc: []const u8, sysroot: ?[]const u8) !std.Build.LazyPath {
|
||||
const cmd = b.addSystemCommand(&.{cc});
|
||||
|
||||
cmd.addArgs(&.{
|
||||
@@ -649,6 +630,7 @@ fn addPhiCardDaemon(b: *std.Build, optimize: std.builtin.OptimizeMode, cc: []con
|
||||
"src/phi/mic/Daemon.c",
|
||||
"src/phi/mic/Logger.c",
|
||||
"src/phi/mic/Memory.c",
|
||||
"src/phi/mic/Transport.c",
|
||||
// Add new files here
|
||||
};
|
||||
|
||||
@@ -656,14 +638,46 @@ fn addPhiCardDaemon(b: *std.Build, optimize: std.builtin.OptimizeMode, cc: []con
|
||||
cmd.addFileArg(b.path(source));
|
||||
}
|
||||
|
||||
cmd.addArgs(&.{
|
||||
"-lscif",
|
||||
"-o",
|
||||
});
|
||||
|
||||
cmd.addArgs(&.{ "-lscif", "-o" });
|
||||
return cmd.addOutputFileArg("phi_device.mic");
|
||||
}
|
||||
|
||||
fn addPhiHostDaemon(b: *std.Build, optimize: std.builtin.OptimizeMode, emulation_port: u16) std.Build.LazyPath {
|
||||
const daemon_mod = b.createModule(.{
|
||||
.target = b.graph.host,
|
||||
.optimize = optimize,
|
||||
.link_libc = true,
|
||||
});
|
||||
daemon_mod.addIncludePath(b.path("src/phi/mic"));
|
||||
daemon_mod.addIncludePath(b.path("src/phi/shared"));
|
||||
daemon_mod.addCMacro("PHI_HOST_EMULATION", "1");
|
||||
daemon_mod.addCMacro("PHI_TRANSPORT_PORT", b.fmt("{d}", .{emulation_port}));
|
||||
daemon_mod.addCSourceFiles(.{
|
||||
.files = &.{
|
||||
"src/phi/mic/main.c",
|
||||
"src/phi/mic/Buffer.c",
|
||||
"src/phi/mic/CommandBuffer.c",
|
||||
"src/phi/mic/Daemon.c",
|
||||
"src/phi/mic/Logger.c",
|
||||
"src/phi/mic/Memory.c",
|
||||
"src/phi/mic/Transport.c",
|
||||
},
|
||||
.flags = &.{
|
||||
"-std=c11",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wno-unused-parameter",
|
||||
},
|
||||
});
|
||||
daemon_mod.linkSystemLibrary("pthread", .{});
|
||||
|
||||
const daemon = b.addExecutable(.{
|
||||
.name = "phi_device-host",
|
||||
.root_module = daemon_mod,
|
||||
});
|
||||
return daemon.getEmittedBin();
|
||||
}
|
||||
|
||||
fn addEmbeddedPhiDaemon(b: *std.Build, daemon: std.Build.LazyPath) std.Build.LazyPath {
|
||||
const wf = b.addWriteFiles();
|
||||
_ = wf.addCopyFile(daemon, "phi_device.mic");
|
||||
|
||||
+36
-2
@@ -81,8 +81,11 @@ pub fn create(instance: *base.Instance, physical_device: *base.PhysicalDevice, a
|
||||
const phi_physical_device: *PhiPhysicalDevice = @alignCast(@fieldParentPtr("interface", physical_device));
|
||||
|
||||
const transport = PhiTransport.init(instance, phi_physical_device.scif_node_id) catch blk: {
|
||||
// If the first connection failed, upload and launch the daemon on the card.
|
||||
try uploadAndLaunchDaemon(instance, allocator, phi_physical_device.mic_device_num);
|
||||
// If the first connection failed, launch the daemon on the selected device.
|
||||
if (comptime config.phi_host_emulation)
|
||||
try launchHostDaemon(instance, allocator)
|
||||
else
|
||||
try uploadAndLaunchDaemon(instance, allocator, phi_physical_device.mic_device_num);
|
||||
|
||||
const max_connect_attempts = 3;
|
||||
for (0..max_connect_attempts) |attempt| {
|
||||
@@ -242,6 +245,37 @@ pub fn getDeviceGroupSurfacePresentModesKHR(_: *Interface, _: *base.SurfaceKHR)
|
||||
return .{ .local_bit_khr = true };
|
||||
}
|
||||
|
||||
fn launchHostDaemon(instance: *base.Instance, allocator: std.mem.Allocator) VkError!void {
|
||||
const io = instance.io();
|
||||
const process_id = std.os.linux.getpid();
|
||||
const thread_id = std.Thread.getCurrentId();
|
||||
|
||||
const local_path = std.fmt.allocPrint(allocator, "/tmp/ape_phi_device_{d}_{d}.host", .{ process_id, thread_id }) catch return VkError.OutOfHostMemory;
|
||||
defer allocator.free(local_path);
|
||||
errdefer std.Io.Dir.deleteFileAbsolute(io, local_path) catch {};
|
||||
|
||||
std.Io.Dir.writeFile(.cwd(), io, .{
|
||||
.sub_path = local_path,
|
||||
.data = daemon_binary,
|
||||
}) catch |err| {
|
||||
std.log.scoped(.PhiDevice).err("Failed to write embedded Phi host daemon: {s}", .{@errorName(err)});
|
||||
return VkError.InitializationFailed;
|
||||
};
|
||||
|
||||
const launch_command = std.fmt.allocPrint(
|
||||
allocator,
|
||||
"chmod +x {s} && (nohup {s} --unlink-on-start >/tmp/phi_device_host.log 2>&1 </dev/null &)",
|
||||
.{ local_path, local_path },
|
||||
) catch return VkError.OutOfHostMemory;
|
||||
defer allocator.free(launch_command);
|
||||
|
||||
std.log.scoped(.PhiDevice).debug(
|
||||
"Launching Phi host daemon on 127.0.0.1:{d}",
|
||||
.{config.phi_emulation_port},
|
||||
);
|
||||
try runHostCommand(instance, allocator, &.{ "sh", "-c", launch_command });
|
||||
}
|
||||
|
||||
fn uploadAndLaunchDaemon(instance: *base.Instance, allocator: std.mem.Allocator, mic_device_num: u32) VkError!void {
|
||||
const io = instance.io();
|
||||
const process_id = std.os.linux.getpid();
|
||||
|
||||
+13
-1
@@ -61,7 +61,8 @@ fn destroy(interface: *Interface, allocator: std.mem.Allocator) VkError!void {
|
||||
self.threaded.deinit();
|
||||
allocator.destroy(self);
|
||||
|
||||
mic.unload();
|
||||
if (comptime !lib.config.phi_host_emulation)
|
||||
mic.unload();
|
||||
}
|
||||
|
||||
fn requestPhysicalDevices(interface: *Interface, allocator: std.mem.Allocator, _: []base.drm.Card) VkError!void {
|
||||
@@ -69,6 +70,17 @@ fn requestPhysicalDevices(interface: *Interface, allocator: std.mem.Allocator, _
|
||||
return;
|
||||
}
|
||||
|
||||
if (comptime lib.config.phi_host_emulation) {
|
||||
const physical_device = try PhiPhysicalDevice.createEmulated(allocator, interface);
|
||||
errdefer physical_device.interface.release(allocator) catch @panic("Caught an error while handling an error");
|
||||
|
||||
const dispatchable = try Dispatchable(base.PhysicalDevice).wrap(allocator, &physical_device.interface);
|
||||
errdefer dispatchable.destroy(allocator);
|
||||
|
||||
interface.physical_devices.append(allocator, dispatchable) catch return VkError.OutOfHostMemory;
|
||||
return;
|
||||
}
|
||||
|
||||
mic.load() catch |err| {
|
||||
std.log.scoped(.MIC).err("Failed to load libmicmgmt: {s}", .{@errorName(err)});
|
||||
return VkError.InitializationFailed;
|
||||
|
||||
@@ -34,6 +34,21 @@ scif_node_id: u16,
|
||||
mic_device_num: u32,
|
||||
|
||||
pub fn create(allocator: std.mem.Allocator, instance: *base.Instance, mic_device: mic.Device, mic_device_num: u32) VkError!*Self {
|
||||
if (comptime lib.config.phi_host_emulation) {
|
||||
return VkError.InitializationFailed;
|
||||
} else {
|
||||
return createInternal(allocator, instance, mic_device, mic_device_num);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn createEmulated(allocator: std.mem.Allocator, instance: *base.Instance) VkError!*Self {
|
||||
if (comptime lib.config.phi_host_emulation)
|
||||
return createInternal(allocator, instance, null, 0)
|
||||
else
|
||||
return VkError.InitializationFailed;
|
||||
}
|
||||
|
||||
fn createInternal(allocator: std.mem.Allocator, instance: *base.Instance, mic_device: ?mic.Device, mic_device_num: u32) VkError!*Self {
|
||||
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||
errdefer allocator.destroy(self);
|
||||
|
||||
@@ -61,29 +76,37 @@ pub fn create(allocator: std.mem.Allocator, instance: *base.Instance, mic_device
|
||||
|
||||
@memset(interface.props.device_name[0..], 0);
|
||||
|
||||
if (mic_device.pciConfig()) |pci_value| {
|
||||
var pci = pci_value;
|
||||
defer pci.deinit();
|
||||
if (comptime lib.config.phi_host_emulation) {
|
||||
interface.props.vendor_id = 0x8086;
|
||||
interface.props.device_id = 0x2250;
|
||||
const name = "Intel(R) Xeon Phi(TM) Coprocessor Host Emulation [Phi ApeDriver]";
|
||||
@memcpy(interface.props.device_name[0..name.len], name);
|
||||
} else {
|
||||
const device = mic_device.?;
|
||||
if (device.pciConfig()) |pci_value| {
|
||||
var pci = pci_value;
|
||||
defer pci.deinit();
|
||||
|
||||
interface.props.vendor_id = pci.vendorId() catch 0;
|
||||
interface.props.device_id = pci.deviceId() catch 0;
|
||||
interface.props.vendor_id = pci.vendorId() catch 0;
|
||||
interface.props.device_id = pci.deviceId() catch 0;
|
||||
|
||||
for (pci_ids[0..]) |pci_info| {
|
||||
if (pci_info.id != pci.deviceId() catch 0)
|
||||
continue;
|
||||
for (pci_ids[0..]) |pci_info| {
|
||||
if (pci_info.id != pci.deviceId() catch 0)
|
||||
continue;
|
||||
|
||||
const len = @min(vk.MAX_PHYSICAL_DEVICE_NAME_SIZE, pci_info.name.len);
|
||||
@memcpy(interface.props.device_name[0..len], pci_info.name[0..len]);
|
||||
const len = @min(vk.MAX_PHYSICAL_DEVICE_NAME_SIZE, pci_info.name.len);
|
||||
@memcpy(interface.props.device_name[0..len], pci_info.name[0..len]);
|
||||
|
||||
const driver_mark = " [Phi ApeDriver]";
|
||||
const driver_mark = " [Phi ApeDriver]";
|
||||
|
||||
@memcpy(interface.props.device_name[len .. len + driver_mark.len], driver_mark);
|
||||
@memcpy(interface.props.device_name[len .. len + driver_mark.len], driver_mark);
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
} else |err| {
|
||||
std.log.scoped(.MIC).err("Failed to fetch device PCI config: {s}", .{@errorName(err)});
|
||||
return VkError.InitializationFailed;
|
||||
}
|
||||
} else |err| {
|
||||
std.log.scoped(.MIC).err("Failed to fetch device PCI config: {s}", .{@errorName(err)});
|
||||
return VkError.InitializationFailed;
|
||||
}
|
||||
|
||||
interface.props.pipeline_cache_uuid = @splat(0);
|
||||
@@ -224,24 +247,31 @@ pub fn create(allocator: std.mem.Allocator, instance: *base.Instance, mic_device
|
||||
};
|
||||
}
|
||||
|
||||
if (mic_device.memoryInfo()) |memory_value| {
|
||||
var memory = memory_value;
|
||||
defer memory.deinit();
|
||||
|
||||
interface.mem_props.memory_heap_count = 2;
|
||||
|
||||
interface.mem_props.memory_heap_count = 2;
|
||||
if (comptime lib.config.phi_host_emulation) {
|
||||
interface.mem_props.memory_heaps[0] = .{
|
||||
.size = memory.size() catch 0,
|
||||
.size = std.process.totalSystemMemory() catch 0,
|
||||
.flags = .{ .device_local_bit = true },
|
||||
};
|
||||
interface.mem_props.memory_heaps[1] = .{
|
||||
.size = std.process.totalSystemMemory() catch 0,
|
||||
.flags = .{},
|
||||
};
|
||||
} else |err| {
|
||||
std.log.scoped(.MIC).err("Failed to fetch device memory infos: {s}", .{@errorName(err)});
|
||||
return VkError.InitializationFailed;
|
||||
} else {
|
||||
const device = mic_device.?;
|
||||
if (device.memoryInfo()) |memory_value| {
|
||||
var memory = memory_value;
|
||||
defer memory.deinit();
|
||||
|
||||
interface.mem_props.memory_heaps[0] = .{
|
||||
.size = memory.size() catch 0,
|
||||
.flags = .{ .device_local_bit = true },
|
||||
};
|
||||
} else |err| {
|
||||
std.log.scoped(.MIC).err("Failed to fetch device memory infos: {s}", .{@errorName(err)});
|
||||
return VkError.InitializationFailed;
|
||||
}
|
||||
}
|
||||
interface.mem_props.memory_heaps[1] = .{
|
||||
.size = std.process.totalSystemMemory() catch 0,
|
||||
.flags = .{},
|
||||
};
|
||||
|
||||
interface.features = .{
|
||||
.shader_float_64 = .true,
|
||||
|
||||
+67
-18
@@ -5,33 +5,54 @@ const scif = @import("scif.zig");
|
||||
|
||||
const VkError = base.VkError;
|
||||
const proto = lib.proto;
|
||||
const Endpoint = if (lib.config.phi_host_emulation) std.Io.net.Stream else scif.epd_t;
|
||||
|
||||
const Self = @This();
|
||||
|
||||
epd: scif.epd_t,
|
||||
epd: Endpoint,
|
||||
sequence: u64 = 1,
|
||||
mutex: std.Io.Mutex = .init,
|
||||
instance: *base.Instance,
|
||||
|
||||
pub fn init(instance: *base.Instance, node_id: u16) VkError!Self {
|
||||
try scif.load();
|
||||
errdefer scif.unload();
|
||||
const epd = if (comptime lib.config.phi_host_emulation) blk: {
|
||||
const address: std.Io.net.IpAddress = .{
|
||||
.ip4 = .loopback(lib.config.phi_emulation_port),
|
||||
};
|
||||
const stream = address.connect(instance.io(), .{ .mode = .stream }) catch |err| {
|
||||
std.log.scoped(.PhiTransport).err(
|
||||
"TCP connection to 127.0.0.1:{d} failed: {s}",
|
||||
.{ lib.config.phi_emulation_port, @errorName(err) },
|
||||
);
|
||||
return VkError.InitializationFailed;
|
||||
};
|
||||
break :blk stream;
|
||||
} else blk: {
|
||||
try scif.load();
|
||||
errdefer scif.unload();
|
||||
|
||||
const epd = scif.open();
|
||||
if (epd < 0) {
|
||||
std.log.scoped(.PhiTransport).err("SCIF open failed", .{});
|
||||
return VkError.InitializationFailed;
|
||||
}
|
||||
errdefer _ = scif.close(epd);
|
||||
const endpoint = scif.open();
|
||||
if (endpoint < 0) {
|
||||
std.log.scoped(.PhiTransport).err("SCIF open failed", .{});
|
||||
return VkError.InitializationFailed;
|
||||
}
|
||||
errdefer _ = scif.close(endpoint);
|
||||
|
||||
var dst: scif.PortId = .{
|
||||
.node = node_id,
|
||||
.port = @intCast(proto.PHI_SCIF_PORT),
|
||||
var dst: scif.PortId = .{
|
||||
.node = node_id,
|
||||
.port = @intCast(proto.PHI_SCIF_PORT),
|
||||
};
|
||||
|
||||
if (scif.connect(endpoint, &dst) < 0) {
|
||||
std.log.scoped(.PhiTransport).err("SCIF connection to node {d} port {d} failed", .{ dst.node, dst.port });
|
||||
return VkError.InitializationFailed;
|
||||
}
|
||||
break :blk endpoint;
|
||||
};
|
||||
|
||||
if (scif.connect(epd, &dst) < 0) {
|
||||
std.log.scoped(.PhiTransport).err("SCIF connection to node {d} port {d} failed", .{ dst.node, dst.port });
|
||||
return VkError.InitializationFailed;
|
||||
errdefer {
|
||||
closeEndpoint(epd, instance.io());
|
||||
if (comptime !lib.config.phi_host_emulation)
|
||||
scif.unload();
|
||||
}
|
||||
|
||||
var self: Self = .{
|
||||
@@ -50,8 +71,9 @@ pub fn deinit(self: *Self) void {
|
||||
std.log.scoped(.PhiTransport).warn("Failed to shut down remote session: {s}", .{@errorName(err)});
|
||||
};
|
||||
|
||||
_ = scif.close(self.epd);
|
||||
scif.unload();
|
||||
closeEndpoint(self.epd, self.instance.io());
|
||||
if (comptime !lib.config.phi_host_emulation)
|
||||
scif.unload();
|
||||
std.log.scoped(.PhiTransport).info("Closed connection", .{});
|
||||
}
|
||||
|
||||
@@ -99,6 +121,16 @@ pub fn statusToErr(status: c_int) VkError {
|
||||
}
|
||||
|
||||
fn writeAll(self: *Self, bytes: []const u8) VkError!void {
|
||||
if (comptime lib.config.phi_host_emulation) {
|
||||
var buffer: [0]u8 = .{};
|
||||
var writer = self.epd.writer(self.instance.io(), &buffer);
|
||||
writer.interface.writeAll(bytes) catch |err| {
|
||||
std.log.scoped(.PhiTransport).err("TCP send failed: {s}", .{@errorName(err)});
|
||||
return VkError.InitializationFailed;
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
var offset: usize = 0;
|
||||
while (offset < bytes.len) {
|
||||
const written = scif.send(self.epd, bytes[offset..].ptr, bytes.len - offset, scif.send_block);
|
||||
@@ -110,6 +142,16 @@ fn writeAll(self: *Self, bytes: []const u8) VkError!void {
|
||||
}
|
||||
|
||||
fn readAll(self: *Self, bytes: []u8) VkError!void {
|
||||
if (comptime lib.config.phi_host_emulation) {
|
||||
var buffer: [0]u8 = .{};
|
||||
var reader = self.epd.reader(self.instance.io(), &buffer);
|
||||
reader.interface.readSliceAll(bytes) catch |err| {
|
||||
std.log.scoped(.PhiTransport).err("TCP receive failed: {s}", .{@errorName(err)});
|
||||
return VkError.InitializationFailed;
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
var offset: usize = 0;
|
||||
while (offset < bytes.len) {
|
||||
const read = scif.recv(self.epd, bytes[offset..].ptr, bytes.len - offset, scif.recv_block);
|
||||
@@ -120,6 +162,13 @@ fn readAll(self: *Self, bytes: []u8) VkError!void {
|
||||
}
|
||||
}
|
||||
|
||||
fn closeEndpoint(endpoint: Endpoint, io: std.Io) void {
|
||||
if (comptime lib.config.phi_host_emulation)
|
||||
endpoint.close(io)
|
||||
else
|
||||
_ = scif.close(endpoint);
|
||||
}
|
||||
|
||||
fn handshake(self: *Self) VkError!void {
|
||||
const request_payload: proto.PhiHelloRequest = .{
|
||||
.host_protocol_version = proto.PHI_PROTOCOL_VERSION,
|
||||
|
||||
@@ -44,7 +44,7 @@ static PhiStatus ExecuteCommand(PhiCommandReader* reader, const PhiCmdHeader* co
|
||||
return PHI_STATUS_BAD_MESSAGE;
|
||||
}
|
||||
|
||||
int HandleWorkExecution(scif_epd_t endpoint, const PhiMessageHeader* header)
|
||||
int HandleWorkExecution(PhiEndpoint endpoint, const PhiMessageHeader* header)
|
||||
{
|
||||
PhiWorkExecutionRequest request;
|
||||
PhiWorkExecutionReply reply = {
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
typedef struct PhiCommandReader
|
||||
{
|
||||
scif_epd_t endpoint;
|
||||
PhiEndpoint endpoint;
|
||||
uint64_t remaining;
|
||||
} PhiCommandReader;
|
||||
|
||||
int HandleWorkExecution(scif_epd_t endpoint, const PhiMessageHeader* header);
|
||||
int HandleWorkExecution(PhiEndpoint endpoint, const PhiMessageHeader* header);
|
||||
int PhiDrainCommandReader(PhiCommandReader* reader);
|
||||
PhiStatus PhiReadCommandData(PhiCommandReader* reader, void* data, uint64_t size);
|
||||
|
||||
|
||||
+17
-33
@@ -3,7 +3,7 @@
|
||||
#include <Logger.h>
|
||||
#include <Memory.h>
|
||||
|
||||
static int HandleHello(scif_epd_t endpoint, const PhiMessageHeader* header)
|
||||
static int HandleHello(PhiEndpoint endpoint, const PhiMessageHeader* header)
|
||||
{
|
||||
PhiHelloRequest request;
|
||||
PhiHelloReply reply = {
|
||||
@@ -32,41 +32,25 @@ static int HandleHello(scif_epd_t endpoint, const PhiMessageHeader* header)
|
||||
return SendReply(endpoint, header, &reply, sizeof(reply));
|
||||
}
|
||||
|
||||
scif_epd_t StartDaemon()
|
||||
PhiEndpoint StartDaemon(void)
|
||||
{
|
||||
PhiLogInfo("Starting the daemon...");
|
||||
|
||||
scif_epd_t endpoint = scif_open();
|
||||
if(endpoint < 0)
|
||||
{
|
||||
PhiLogError("Failed to create SCIF endpoint");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(scif_bind(endpoint, PHI_SCIF_PORT) < 0)
|
||||
{
|
||||
PhiLogError("Failed to bind SCIF port");
|
||||
scif_close(endpoint);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(scif_listen(endpoint, 16) < 0)
|
||||
{
|
||||
PhiLogError("Could not listen to SCIF port");
|
||||
scif_close(endpoint);
|
||||
return 0;
|
||||
}
|
||||
PhiEndpoint endpoint = PhiTransportListen(PHI_TRANSPORT_PORT);
|
||||
if(endpoint == PHI_ENDPOINT_INVALID)
|
||||
PhiLogError("Could not listen on the Phi transport");
|
||||
|
||||
PhiLogInfo("Daemon started");
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
void ShutdownDaemon(scif_epd_t endpoint)
|
||||
void ShutdownDaemon(PhiEndpoint endpoint)
|
||||
{
|
||||
PhiLogInfo("Shuting down the daemon...");
|
||||
scif_close(endpoint);
|
||||
PhiLogInfo("Shutting down the daemon...");
|
||||
PhiTransportClose(endpoint);
|
||||
}
|
||||
|
||||
int HandlePacket(scif_epd_t endpoint)
|
||||
int HandlePacket(PhiEndpoint endpoint)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
@@ -123,14 +107,14 @@ int HandlePacket(scif_epd_t endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
int ReadAll(scif_epd_t endpoint, void* data, size_t size)
|
||||
int ReadAll(PhiEndpoint endpoint, void* data, size_t size)
|
||||
{
|
||||
uint8_t* bytes = data;
|
||||
size_t offset = 0;
|
||||
|
||||
while(offset < size)
|
||||
{
|
||||
int got = scif_recv(endpoint, bytes + offset, size - offset, SCIF_RECV_BLOCK);
|
||||
ssize_t got = PhiTransportReceive(endpoint, bytes + offset, size - offset);
|
||||
if(got <= 0)
|
||||
return -1;
|
||||
offset += (size_t)got;
|
||||
@@ -139,14 +123,14 @@ int ReadAll(scif_epd_t endpoint, void* data, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WriteAll(scif_epd_t endpoint, const void* data, size_t size)
|
||||
int WriteAll(PhiEndpoint endpoint, const void* data, size_t size)
|
||||
{
|
||||
const uint8_t* bytes = data;
|
||||
size_t offset = 0;
|
||||
|
||||
while(offset < size)
|
||||
{
|
||||
int sent = scif_send(endpoint, (void*)(bytes + offset), size - offset, SCIF_SEND_BLOCK);
|
||||
ssize_t sent = PhiTransportSend(endpoint, bytes + offset, size - offset);
|
||||
if(sent <= 0)
|
||||
return -1;
|
||||
offset += (size_t)sent;
|
||||
@@ -155,7 +139,7 @@ int WriteAll(scif_epd_t endpoint, const void* data, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SendReply(scif_epd_t endpoint, const PhiMessageHeader* request, const void* payload, uint64_t payload_size)
|
||||
int SendReply(PhiEndpoint endpoint, const PhiMessageHeader* request, const void* payload, uint64_t payload_size)
|
||||
{
|
||||
PhiMessageHeader reply = {
|
||||
.magic = PHI_PROTOCOL_MAGIC,
|
||||
@@ -171,7 +155,7 @@ int SendReply(scif_epd_t endpoint, const PhiMessageHeader* request, const void*
|
||||
return WriteAll(endpoint, payload, (size_t)payload_size);
|
||||
}
|
||||
|
||||
int SendStatus(scif_epd_t endpoint, const PhiMessageHeader* request, PhiStatus status)
|
||||
int SendStatus(PhiEndpoint endpoint, const PhiMessageHeader* request, PhiStatus status)
|
||||
{
|
||||
PhiFreeMemoryReply reply = {
|
||||
.result = {
|
||||
@@ -183,7 +167,7 @@ int SendStatus(scif_epd_t endpoint, const PhiMessageHeader* request, PhiStatus s
|
||||
return SendReply(endpoint, request, &reply, sizeof(reply));
|
||||
}
|
||||
|
||||
int DrainPayload(scif_epd_t endpoint, uint64_t size)
|
||||
int DrainPayload(PhiEndpoint endpoint, uint64_t size)
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
|
||||
|
||||
+9
-10
@@ -3,18 +3,17 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <scif.h>
|
||||
|
||||
#include <Protocol.h>
|
||||
#include <Transport.h>
|
||||
|
||||
scif_epd_t StartDaemon();
|
||||
void ShutdownDaemon(scif_epd_t endpoint);
|
||||
PhiEndpoint StartDaemon(void);
|
||||
void ShutdownDaemon(PhiEndpoint endpoint);
|
||||
|
||||
int DrainPayload(scif_epd_t endpoint, uint64_t size);
|
||||
int HandlePacket(scif_epd_t endpoint);
|
||||
int ReadAll(scif_epd_t endpoint, void* data, size_t size);
|
||||
int SendReply(scif_epd_t endpoint, const PhiMessageHeader* request, const void* payload, uint64_t payload_size);
|
||||
int SendStatus(scif_epd_t endpoint, const PhiMessageHeader* request, PhiStatus status);
|
||||
int WriteAll(scif_epd_t endpoint, const void* data, size_t size);
|
||||
int DrainPayload(PhiEndpoint endpoint, uint64_t size);
|
||||
int HandlePacket(PhiEndpoint endpoint);
|
||||
int ReadAll(PhiEndpoint endpoint, void* data, size_t size);
|
||||
int SendReply(PhiEndpoint endpoint, const PhiMessageHeader* request, const void* payload, uint64_t payload_size);
|
||||
int SendStatus(PhiEndpoint endpoint, const PhiMessageHeader* request, PhiStatus status);
|
||||
int WriteAll(PhiEndpoint endpoint, const void* data, size_t size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -84,6 +84,7 @@ void PhiLog(PhiLogLevel level, const char* fmt, const char* file, const char* fu
|
||||
va_end(argptr);
|
||||
|
||||
fputc('\n', out);
|
||||
fflush(out);
|
||||
|
||||
if(level == PHI_LOG_LEVEL_FATAL)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <Logger.h>
|
||||
#include <Memory.h>
|
||||
|
||||
int HandleAllocMemory(scif_epd_t endpoint, const PhiMessageHeader* header)
|
||||
int HandleAllocMemory(PhiEndpoint endpoint, const PhiMessageHeader* header)
|
||||
{
|
||||
PhiAllocMemoryRequest request;
|
||||
PhiAllocMemoryReply reply = {
|
||||
@@ -42,7 +42,7 @@ int HandleAllocMemory(scif_epd_t endpoint, const PhiMessageHeader* header)
|
||||
return SendReply(endpoint, header, &reply, sizeof(reply));
|
||||
}
|
||||
|
||||
int HandleFreeMemory(scif_epd_t endpoint, const PhiMessageHeader* header)
|
||||
int HandleFreeMemory(PhiEndpoint endpoint, const PhiMessageHeader* header)
|
||||
{
|
||||
PhiFreeMemoryRequest request;
|
||||
PhiFreeMemoryReply reply = {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <Daemon.h>
|
||||
|
||||
int HandleAllocMemory(scif_epd_t endpoint, const PhiMessageHeader* header);
|
||||
int HandleFreeMemory(scif_epd_t endpoint, const PhiMessageHeader* header);
|
||||
int HandleAllocMemory(PhiEndpoint endpoint, const PhiMessageHeader* header);
|
||||
int HandleFreeMemory(PhiEndpoint endpoint, const PhiMessageHeader* header);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
#include <Transport.h>
|
||||
|
||||
#ifdef PHI_HOST_EMULATION
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static struct sockaddr_in PhiLoopbackAddress(uint16_t port)
|
||||
{
|
||||
struct sockaddr_in address = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(port),
|
||||
.sin_addr = {
|
||||
.s_addr = htonl(INADDR_LOOPBACK),
|
||||
},
|
||||
};
|
||||
return address;
|
||||
}
|
||||
|
||||
PhiEndpoint PhiTransportAccept(PhiEndpoint endpoint)
|
||||
{
|
||||
return accept(endpoint, NULL, NULL);
|
||||
}
|
||||
|
||||
int PhiTransportClose(PhiEndpoint endpoint)
|
||||
{
|
||||
return close(endpoint);
|
||||
}
|
||||
|
||||
PhiEndpoint PhiTransportListen(uint16_t port)
|
||||
{
|
||||
PhiEndpoint endpoint = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(endpoint == PHI_ENDPOINT_INVALID)
|
||||
return PHI_ENDPOINT_INVALID;
|
||||
|
||||
const int reuse_address = 1;
|
||||
if(setsockopt(endpoint, SOL_SOCKET, SO_REUSEADDR, &reuse_address, sizeof(reuse_address)) < 0)
|
||||
{
|
||||
PhiTransportClose(endpoint);
|
||||
return PHI_ENDPOINT_INVALID;
|
||||
}
|
||||
|
||||
const struct sockaddr_in address = PhiLoopbackAddress(port);
|
||||
if(bind(endpoint, (const struct sockaddr*)&address, sizeof(address)) < 0 || listen(endpoint, 16) < 0)
|
||||
{
|
||||
PhiTransportClose(endpoint);
|
||||
return PHI_ENDPOINT_INVALID;
|
||||
}
|
||||
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
ssize_t PhiTransportReceive(PhiEndpoint endpoint, void* data, size_t size)
|
||||
{
|
||||
return recv(endpoint, data, size, 0);
|
||||
}
|
||||
|
||||
ssize_t PhiTransportSend(PhiEndpoint endpoint, const void* data, size_t size)
|
||||
{
|
||||
#ifdef MSG_NOSIGNAL
|
||||
return send(endpoint, data, size, MSG_NOSIGNAL);
|
||||
#else
|
||||
return send(endpoint, data, size, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
PhiEndpoint PhiTransportAccept(PhiEndpoint endpoint)
|
||||
{
|
||||
struct scif_portID peer;
|
||||
PhiEndpoint client = PHI_ENDPOINT_INVALID;
|
||||
if(scif_accept(endpoint, &peer, &client, SCIF_ACCEPT_SYNC) < 0)
|
||||
return PHI_ENDPOINT_INVALID;
|
||||
return client;
|
||||
}
|
||||
|
||||
int PhiTransportClose(PhiEndpoint endpoint)
|
||||
{
|
||||
return scif_close(endpoint);
|
||||
}
|
||||
|
||||
PhiEndpoint PhiTransportListen(uint16_t port)
|
||||
{
|
||||
PhiEndpoint endpoint = scif_open();
|
||||
if(endpoint == PHI_ENDPOINT_INVALID)
|
||||
return PHI_ENDPOINT_INVALID;
|
||||
|
||||
if(scif_bind(endpoint, port) < 0 || scif_listen(endpoint, 16) < 0)
|
||||
{
|
||||
PhiTransportClose(endpoint);
|
||||
return PHI_ENDPOINT_INVALID;
|
||||
}
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
ssize_t PhiTransportReceive(PhiEndpoint endpoint, void* data, size_t size)
|
||||
{
|
||||
return scif_recv(endpoint, data, size, SCIF_RECV_BLOCK);
|
||||
}
|
||||
|
||||
ssize_t PhiTransportSend(PhiEndpoint endpoint, const void* data, size_t size)
|
||||
{
|
||||
return scif_send(endpoint, (void*)data, size, SCIF_SEND_BLOCK);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef APE_PHI_TRANSPORT_H
|
||||
#define APE_PHI_TRANSPORT_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef PHI_HOST_EMULATION
|
||||
typedef int PhiEndpoint;
|
||||
#else
|
||||
#include <scif.h>
|
||||
typedef scif_epd_t PhiEndpoint;
|
||||
#endif
|
||||
|
||||
#define PHI_ENDPOINT_INVALID ((PhiEndpoint) - 1)
|
||||
|
||||
PhiEndpoint PhiTransportAccept(PhiEndpoint endpoint);
|
||||
int PhiTransportClose(PhiEndpoint endpoint);
|
||||
|
||||
PhiEndpoint PhiTransportListen(uint16_t port);
|
||||
ssize_t PhiTransportReceive(PhiEndpoint endpoint, void* data, size_t size);
|
||||
ssize_t PhiTransportSend(PhiEndpoint endpoint, const void* data, size_t size);
|
||||
|
||||
#endif
|
||||
+25
-11
@@ -2,24 +2,37 @@
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef PHI_HOST_EMULATION
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <Daemon.h>
|
||||
#include <Logger.h>
|
||||
|
||||
static void* HandleClient(void* const argument)
|
||||
{
|
||||
scif_epd_t client = (scif_epd_t)(intptr_t)argument;
|
||||
PhiEndpoint client = (PhiEndpoint)(intptr_t)argument;
|
||||
|
||||
(void)HandlePacket(client);
|
||||
scif_close(client);
|
||||
PhiTransportClose(client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
scif_epd_t endpoint = StartDaemon();
|
||||
#ifdef PHI_HOST_EMULATION
|
||||
if(argc == 2 && strcmp(argv[1], "--unlink-on-start") == 0)
|
||||
(void)unlink(argv[0]);
|
||||
#else
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
#endif
|
||||
|
||||
PhiEndpoint endpoint = StartDaemon();
|
||||
pthread_attr_t client_thread_attributes;
|
||||
|
||||
if(endpoint == 0)
|
||||
if(endpoint == PHI_ENDPOINT_INVALID)
|
||||
return 1;
|
||||
|
||||
if(pthread_attr_init(&client_thread_attributes) != 0 ||
|
||||
@@ -32,22 +45,23 @@ int main(void)
|
||||
|
||||
for(;;)
|
||||
{
|
||||
struct scif_portID peer;
|
||||
scif_epd_t client;
|
||||
PhiEndpoint client = PhiTransportAccept(endpoint);
|
||||
|
||||
if(scif_accept(endpoint, &peer, &client, SCIF_ACCEPT_SYNC) < 0)
|
||||
if(client == PHI_ENDPOINT_INVALID)
|
||||
{
|
||||
if(errno == EINTR)
|
||||
continue;
|
||||
PhiLogError("Could not accept SCIF connection");
|
||||
PhiLogError("Could not accept transport connection");
|
||||
break;
|
||||
}
|
||||
|
||||
PhiLogInfo("Host connected to the daemon");
|
||||
|
||||
pthread_t client_thread;
|
||||
if(pthread_create(&client_thread, &client_thread_attributes, HandleClient, (void*)(intptr_t)client) != 0)
|
||||
{
|
||||
PhiLogError("Could not create SCIF client thread");
|
||||
scif_close(client);
|
||||
PhiLogError("Could not create transport client thread");
|
||||
PhiTransportClose(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
pub const Device = struct {};
|
||||
|
||||
pub fn unload() void {}
|
||||
@@ -8,6 +8,10 @@
|
||||
#define PHI_PROTOCOL_VERSION 1u
|
||||
#define PHI_SCIF_PORT 43616u
|
||||
|
||||
#ifndef PHI_TRANSPORT_PORT
|
||||
#define PHI_TRANSPORT_PORT PHI_SCIF_PORT
|
||||
#endif
|
||||
|
||||
typedef enum PhiPacketType
|
||||
{
|
||||
PHI_PACKET_HELLO = 1,
|
||||
|
||||
Reference in New Issue
Block a user