From: Nadav Har'El <n...@scylladb.com>
Committer: Nadav Har'El <n...@scylladb.com>
Branch: master

Implement feenableexcept() and friends

Implement the functions feenableexcept(), fedisableexcept() and
fegetexcept(), non-standard glibc functions which allows controlling
which FPU events generate a floating point exception.

Signed-off-by: Nadav Har'El <n...@scylladb.com>
Message-Id: <20170110013215.25950-3-...@scylladb.com>

---
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -849,6 +849,7 @@ objects += arch/$(arch)/interrupt.o
 objects += arch/$(arch)/pci.o
 objects += arch/$(arch)/msi.o
 objects += arch/$(arch)/power.o
+objects += arch/$(arch)/feexcept.o

 $(out)/arch/x64/string-ssse3.o: CXXFLAGS += -mssse3

diff --git a/arch/aarch64/feexcept.cc b/arch/aarch64/feexcept.cc
--- a/arch/aarch64/feexcept.cc
+++ b/arch/aarch64/feexcept.cc
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 ScyllaDB, Ltd.
+ *
+ * This work is open source software, licensed under the terms of the
+ * BSD license as described in the LICENSE file in the top-level directory.
+ */
+
+#include <osv/types.h>
+#include <osv/stubbing.hh>
+#include <fenv.h>
+// Note that musl's fenv.h does not define feenableexcept and friends, so
+// we need to 'extern "C"' them here, as no header file does this.
+
+extern "C"
+int feenableexcept(int mask)
+{
+    WARN_STUBBED();
+    // The feenableexcept says it returns -1 on failure.
+    return -1;
+}
+
+extern "C"
+int fedisableexcept(int mask)
+{
+    WARN_STUBBED();
+    return -1;
+}
+
+extern "C"
+int fegetexcept()
+{
+    WARN_STUBBED();
+    return -1;
+}
diff --git a/arch/x64/feexcept.cc b/arch/x64/feexcept.cc
--- a/arch/x64/feexcept.cc
+++ b/arch/x64/feexcept.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 ScyllaDB, Ltd.
+ *
+ * This work is open source software, licensed under the terms of the
+ * BSD license as described in the LICENSE file in the top-level directory.
+ */
+
+#include <osv/types.h>
+#include <fenv.h>
+
+int feenableexcept(int mask)
+{
+    // The feenableexcept() manual page suggests that -1 should be returned
+ // on failure, and theoretically this could include the case that invalid
+    // bits are passed in mask. But in practice, the Linux implementation
+    // simply ignores invalid bits, and never returns -1.
+    mask &= FE_ALL_EXCEPT;
+
+    // Update the the x87 control word. Note that:
+ // 1. We need to leave the other bits (non-exception related) unchanged.
+    // 2. A 1 bit means disable exception (opposite of our "mask")
+    // 3. This function is supposed to only enable exceptions.
+    u16 cw;
+    asm volatile("fstcw %0" : "=m"(cw));
+    // Save the previous set of enabled exceptions, for returning later.
+    int ret = (~cw) & FE_ALL_EXCEPT;
+    cw &= ~mask;
+    asm volatile("fldcw %0" : : "m"(cw));
+
+    // Also update the SSE control and status register (here the relevant
+    // bits start at bit 7).
+    u32 csr;
+    asm volatile("stmxcsr %0" : "=m"(csr));
+    csr &= ~(mask << 7);
+    asm volatile("ldmxcsr %0" : : "m"(csr));
+
+    return ret;
+}
+
+int fedisableexcept(int mask)
+{
+    mask &= FE_ALL_EXCEPT;
+
+    u16 cw;
+    asm volatile("fstcw %0" : "=m"(cw));
+    int ret = (~cw) & FE_ALL_EXCEPT;
+    cw |= mask;
+    asm volatile("fldcw %0" : : "m"(cw));
+
+    u32 csr;
+    asm volatile("stmxcsr %0" : "=m"(csr));
+    csr |= mask << 7;
+    asm volatile("ldmxcsr %0" : : "m"(csr));
+
+    return ret;
+}
+
+int fegetexcept()
+{
+    u16 cw;
+    asm volatile("fstcw %0" : "=m"(cw));
+    return (~cw) & FE_ALL_EXCEPT;
+}

--
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to