From 036964ec45372f6012deabcc7cee0a5654a41781 Mon Sep 17 00:00:00 2001
From: Dan Kegel <dank@kegel.com>
Date: Tue, 2 Oct 2012 07:30:15 -0700
Subject: [PATCH 13/14] vcomp: better stubs for _vcomp_atomic_add_i4 etc.

---
 dlls/vcomp/Makefile.in       |    1 +
 dlls/vcomp/atomic.c          |   69 ++++++++++++++++++++++++++
 dlls/vcomp/tests/Makefile.in |    1 +
 dlls/vcomp/tests/atomic.c    |  109 ++++++++++++++++++++++++++++++++++++++++++
 dlls/vcomp/vcomp.spec        |   72 ++++++++++++++--------------
 5 files changed, 216 insertions(+), 36 deletions(-)
 create mode 100644 dlls/vcomp/atomic.c
 create mode 100644 dlls/vcomp/tests/atomic.c

diff --git a/dlls/vcomp/Makefile.in b/dlls/vcomp/Makefile.in
index 9140945..08c3e5b 100644
--- a/dlls/vcomp/Makefile.in
+++ b/dlls/vcomp/Makefile.in
@@ -1,6 +1,7 @@
 MODULE = vcomp.dll
 
 C_SRCS = \
+	atomic.c \
 	fork.c \
 	main.c \
 	work.c
diff --git a/dlls/vcomp/atomic.c b/dlls/vcomp/atomic.c
new file mode 100644
index 0000000..3ad8619
--- /dev/null
+++ b/dlls/vcomp/atomic.c
@@ -0,0 +1,69 @@
+/*
+ * vcomp atomic ops implementation
+ *
+ * Copyright 2012 Dan Kegel
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winternl.h"
+#include "winbase.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(vcomp);
+
+/* FIXME: once our _vcomp_fork actually forks, make these really atomic */
+
+void CDECL _vcomp_atomic_add_i1(char   *p, char   val) { *p += val; }
+void CDECL _vcomp_atomic_add_i2(short  *p, short  val) { *p += val; }
+void CDECL _vcomp_atomic_add_i4(int    *p, int    val) { *p += val; }
+void CDECL _vcomp_atomic_add_i8(INT64  *p, INT64  val) { *p += val; }
+void CDECL _vcomp_atomic_add_r4(float  *p, float  val) { *p += val; }
+void CDECL _vcomp_atomic_add_r8(double *p, double val) { *p += val; }
+void CDECL _vcomp_atomic_and_i1(char   *p, char   val) { *p &= val; }
+void CDECL _vcomp_atomic_and_i2(short  *p, short  val) { *p &= val; }
+void CDECL _vcomp_atomic_and_i4(int    *p, int    val) { *p &= val; }
+void CDECL _vcomp_atomic_and_i8(INT64  *p, INT64  val) { *p &= val; }
+void CDECL _vcomp_atomic_div_i1(char   *p, char   val) { *p /= val; }
+void CDECL _vcomp_atomic_div_i2(short  *p, short  val) { *p /= val; }
+void CDECL _vcomp_atomic_div_i4(int    *p, int    val) { *p /= val; }
+void CDECL _vcomp_atomic_div_i8(INT64  *p, INT64  val) { *p /= val; }
+void CDECL _vcomp_atomic_div_r4(float  *p, float  val) { *p /= val; }
+void CDECL _vcomp_atomic_div_r8(double *p, double val) { *p /= val; }
+void CDECL _vcomp_atomic_mul_i1(char   *p, char   val) { *p *= val; }
+void CDECL _vcomp_atomic_mul_i2(short  *p, short  val) { *p *= val; }
+void CDECL _vcomp_atomic_mul_i4(int    *p, int    val) { *p *= val; }
+void CDECL _vcomp_atomic_mul_i8(INT64  *p, INT64  val) { *p *= val; }
+void CDECL _vcomp_atomic_mul_r4(float  *p, float  val) { *p *= val; }
+void CDECL _vcomp_atomic_mul_r8(double *p, double val) { *p += val; }
+void CDECL _vcomp_atomic_or_i1 (char   *p, char   val) { *p |= val; }
+void CDECL _vcomp_atomic_or_i2 (short  *p, short  val) { *p |= val; }
+void CDECL _vcomp_atomic_or_i4 (int    *p, int    val) { *p |= val; }
+void CDECL _vcomp_atomic_or_i8 (INT64  *p, INT64  val) { *p |= val; }
+void CDECL _vcomp_atomic_sub_i1(char   *p, char   val) { *p -= val; }
+void CDECL _vcomp_atomic_sub_i2(short  *p, short  val) { *p -= val; }
+void CDECL _vcomp_atomic_sub_i4(int    *p, int    val) { *p -= val; }
+void CDECL _vcomp_atomic_sub_i8(INT64  *p, INT64  val) { *p -= val; }
+void CDECL _vcomp_atomic_sub_r4(float  *p, float  val) { *p -= val; }
+void CDECL _vcomp_atomic_sub_r8(double *p, double val) { *p -= val; }
+void CDECL _vcomp_atomic_xor_i1(char   *p, char   val) { *p ^= val; }
+void CDECL _vcomp_atomic_xor_i2(short  *p, short  val) { *p ^= val; }
+void CDECL _vcomp_atomic_xor_i4(int    *p, int    val) { *p ^= val; }
+void CDECL _vcomp_atomic_xor_i8(INT64  *p, INT64  val) { *p ^= val; }
+
diff --git a/dlls/vcomp/tests/Makefile.in b/dlls/vcomp/tests/Makefile.in
index 69d5043..c2776a3 100644
--- a/dlls/vcomp/tests/Makefile.in
+++ b/dlls/vcomp/tests/Makefile.in
@@ -2,6 +2,7 @@ TESTDLL = vcomp.dll
 IMPORTS = vcomp
 
 C_SRCS = \
+	atomic.c \
 	fork.c \
 	work.c
 
diff --git a/dlls/vcomp/tests/atomic.c b/dlls/vcomp/tests/atomic.c
new file mode 100644
index 0000000..9edc573
--- /dev/null
+++ b/dlls/vcomp/tests/atomic.c
@@ -0,0 +1,109 @@
+/*
+ * Unit test suite for vcomp atomic ops.
+ *
+ * Copyright 2012 Dan Kegel
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wine/test.h"
+#include <math.h>
+
+static void CDECL (*p_vcomp_atomic_add_i1)(char  *p, short  val);
+static void CDECL (*p_vcomp_atomic_add_i2)(short  *p, short  val);
+static void CDECL (*p_vcomp_atomic_add_i4)(int    *p, int    val);
+static void CDECL (*p_vcomp_atomic_add_i8)(INT64  *p, INT64  val);
+static void CDECL (*p_vcomp_atomic_add_r4)(float  *p, float  val);
+static void CDECL (*p_vcomp_atomic_add_r8)(double *p, double val);
+
+#define GETFUNC(x) do { p##x = (void*)GetProcAddress(vcomp, #x); ok(p##x != NULL, "Export '%s' not found\n", #x); } while(0)
+
+static BOOL init(void)
+{
+    HMODULE vcomp = LoadLibraryA("vcomp.dll");
+    if(!vcomp) {
+        win_skip("vcomp.dll not installed\n");
+        return FALSE;
+    }
+
+    GETFUNC(_vcomp_atomic_add_i1);
+    GETFUNC(_vcomp_atomic_add_i2);
+    GETFUNC(_vcomp_atomic_add_i4);
+    GETFUNC(_vcomp_atomic_add_i8);
+    GETFUNC(_vcomp_atomic_add_r4);
+    GETFUNC(_vcomp_atomic_add_r8);
+
+    return TRUE;
+}
+
+static void test_atomic_add(void)
+{
+    CHAR i1;
+    INT16 i2;
+    INT32 i4;
+    INT64 i8;
+    float r4;
+    double r8;
+
+    i1 = 0;
+    p_vcomp_atomic_add_i1(&i1, 1);
+    ok(i1 == 1, "1 + 1 == 1\n");
+    i1 = 0x7f;
+    p_vcomp_atomic_add_i1(&i1, 1);
+    ok((0xff & i1) == 0x80, "0x7f + 1 == 0x80 was 0x%x\n", (0xff & i1));
+
+    i2 = 0;
+    p_vcomp_atomic_add_i2(&i2, 1);
+    ok(i2 == 1, "1 + 1 == 1\n");
+    i2 = 0x7fff;
+    p_vcomp_atomic_add_i2(&i2, 1);
+    ok((0xffff & i2) == 0x8000, "0x7fff + 1 == 0x8000, was 0x%x\n", (0xffff & i2));
+
+    i4 = 0;
+    p_vcomp_atomic_add_i4(&i4, 1);
+    ok(i4 == 1, "1 + 1 == 1\n");
+    i4 = 0x7fffffffU;
+    p_vcomp_atomic_add_i4(&i4, 1);
+    ok((0xffffffff & i4) == 0x80000000, "0x7fffffff + 1 == 0x8000000, was 0x%x\n", (0xffffffff & i4));
+
+    i8 = 0;
+    p_vcomp_atomic_add_i8(&i8, 1);
+    ok(i8 == 1, "1 + 1 == 1\n");
+#ifdef _WIN64
+    i8 = 0x7fffffffffffffffL;
+    p_vcomp_atomic_add_i8(&i8, 1);
+    ok(i8 == 0x8000000000000000L, "0x7fffffffffffffffL + 1 == 0x8000000000000000L\n");
+#else
+    i8 = 0x7fffffffffffffffLL;
+    p_vcomp_atomic_add_i8(&i8, 1);
+    ok(i8 == 0x8000000000000000LL, "0x7fffffffffffffffLL + 1 == 0x8000000000000000LL\n");
+#endif
+
+    r4 = 2.0;
+    p_vcomp_atomic_add_r4(&r4, 1.0);
+    ok(r4 < 3.0001 && r4 > 2.9999, "2 + 1 == 3\n");
+
+    r8 = 2.0;
+    p_vcomp_atomic_add_r8(&r8, 1.0);
+    ok(r8 < 3.000001 && r8 > 2.999999, "2 + 1 == 3\n");
+}
+
+START_TEST(atomic)
+{
+    if (!init())
+        return;
+
+    test_atomic_add();
+}
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 1149d76..337c806 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -1,33 +1,33 @@
-@ stub _vcomp_atomic_add_i1
-@ stub _vcomp_atomic_add_i2
-@ stub _vcomp_atomic_add_i4
-@ stub _vcomp_atomic_add_i8
-@ stub _vcomp_atomic_add_r4
-@ stub _vcomp_atomic_add_r8
-@ stub _vcomp_atomic_and_i1
-@ stub _vcomp_atomic_and_i2
-@ stub _vcomp_atomic_and_i4
-@ stub _vcomp_atomic_and_i8
-@ stub _vcomp_atomic_div_i1
-@ stub _vcomp_atomic_div_i2
-@ stub _vcomp_atomic_div_i4
-@ stub _vcomp_atomic_div_i8
-@ stub _vcomp_atomic_div_r4
-@ stub _vcomp_atomic_div_r8
+@ cdecl _vcomp_atomic_add_i1(ptr long)
+@ cdecl _vcomp_atomic_add_i2(ptr long)
+@ cdecl _vcomp_atomic_add_i4(ptr long)
+@ cdecl _vcomp_atomic_add_i8(ptr int64)
+@ cdecl _vcomp_atomic_add_r4(ptr float)
+@ cdecl _vcomp_atomic_add_r8(ptr double)
+@ cdecl _vcomp_atomic_and_i1(ptr long)
+@ cdecl _vcomp_atomic_and_i2(ptr long)
+@ cdecl _vcomp_atomic_and_i4(ptr long)
+@ cdecl _vcomp_atomic_and_i8(ptr int64)
+@ cdecl _vcomp_atomic_div_i1(ptr long)
+@ cdecl _vcomp_atomic_div_i2(ptr long)
+@ cdecl _vcomp_atomic_div_i4(ptr long)
+@ cdecl _vcomp_atomic_div_i8(ptr int64)
+@ cdecl _vcomp_atomic_div_r4(ptr float)
+@ cdecl _vcomp_atomic_div_r8(ptr double)
 @ stub _vcomp_atomic_div_ui1
 @ stub _vcomp_atomic_div_ui2
 @ stub _vcomp_atomic_div_ui4
 @ stub _vcomp_atomic_div_ui8
-@ stub _vcomp_atomic_mul_i1
-@ stub _vcomp_atomic_mul_i2
-@ stub _vcomp_atomic_mul_i4
-@ stub _vcomp_atomic_mul_i8
-@ stub _vcomp_atomic_mul_r4
-@ stub _vcomp_atomic_mul_r8
-@ stub _vcomp_atomic_or_i1
-@ stub _vcomp_atomic_or_i2
-@ stub _vcomp_atomic_or_i4
-@ stub _vcomp_atomic_or_i8
+@ cdecl _vcomp_atomic_mul_i1(ptr long)
+@ cdecl _vcomp_atomic_mul_i2(ptr long)
+@ cdecl _vcomp_atomic_mul_i4(ptr long)
+@ cdecl _vcomp_atomic_mul_i8(ptr int64)
+@ cdecl _vcomp_atomic_mul_r4(ptr float)
+@ cdecl _vcomp_atomic_mul_r8(ptr double)
+@ cdecl _vcomp_atomic_or_i1(ptr long)
+@ cdecl _vcomp_atomic_or_i2(ptr long)
+@ cdecl _vcomp_atomic_or_i4(ptr long)
+@ cdecl _vcomp_atomic_or_i8(ptr int64)
 @ stub _vcomp_atomic_shl_i1
 @ stub _vcomp_atomic_shl_i2
 @ stub _vcomp_atomic_shl_i4
@@ -40,16 +40,16 @@
 @ stub _vcomp_atomic_shr_ui2
 @ stub _vcomp_atomic_shr_ui4
 @ stub _vcomp_atomic_shr_ui8
-@ stub _vcomp_atomic_sub_i1
-@ stub _vcomp_atomic_sub_i2
-@ stub _vcomp_atomic_sub_i4
-@ stub _vcomp_atomic_sub_i8
-@ stub _vcomp_atomic_sub_r4
-@ stub _vcomp_atomic_sub_r8
-@ stub _vcomp_atomic_xor_i1
-@ stub _vcomp_atomic_xor_i2
-@ stub _vcomp_atomic_xor_i4
-@ stub _vcomp_atomic_xor_i8
+@ cdecl _vcomp_atomic_sub_i1(ptr long)
+@ cdecl _vcomp_atomic_sub_i2(ptr long)
+@ cdecl _vcomp_atomic_sub_i4(ptr long)
+@ cdecl _vcomp_atomic_sub_i8(ptr int64)
+@ cdecl _vcomp_atomic_sub_r4(ptr float)
+@ cdecl _vcomp_atomic_sub_r8(ptr double)
+@ cdecl _vcomp_atomic_xor_i1(ptr long)
+@ cdecl _vcomp_atomic_xor_i2(ptr long)
+@ cdecl _vcomp_atomic_xor_i4(ptr long)
+@ cdecl _vcomp_atomic_xor_i8(ptr int64)
 @ cdecl _vcomp_barrier()
 @ stub _vcomp_copyprivate_broadcast
 @ stub _vcomp_copyprivate_receive
-- 
1.7.9.5

