Changeset: be419310b1ae for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=be419310b1ae
Modified Files:
        MonetDB.spec
        configure.ag
        debian/control
        gdk/gdk_atomic.h
        monetdb5/mal/mal_dataflow.c
Branch: default
Log Message:

Introduce atomic instructions on pointers.
This also means we have to say goodbye to libatomic_ops since it does
not support pointer operations.


diffs (truncated from 308 to 300 lines):

diff --git a/MonetDB.spec b/MonetDB.spec
--- a/MonetDB.spec
+++ b/MonetDB.spec
@@ -213,10 +213,6 @@ Summary: MonetDB development files
 Group: Applications/Databases
 Requires: %{name}%{?_isa} = %{version}-%{release}
 Requires: %{name}-stream-devel%{?_isa} = %{version}-%{release}
-%if 0%{?rhel} >= 7
-# RHEL >= 7
-Requires: libatomic_ops-devel
-%endif
 
 %description devel
 MonetDB is a database management system that is developed from a
diff --git a/configure.ag b/configure.ag
--- a/configure.ag
+++ b/configure.ag
@@ -2337,39 +2337,6 @@ AC_SUBST([LIBLAS_LIBS])
 
 AM_CONDITIONAL([HAVE_LIDAR], [test "x$have_lidar" = xyes -o "x$have_lidar" = 
xauto])
 
-org_have_atomic_ops=auto
-have_atomic_ops=$org_have_atomic_ops
-AC_ARG_WITH([atomic-ops],
-       [AS_HELP_STRING([--with-atomic-ops],
-               [use atomic_ops library (default=auto)])],
-       [have_atomic_ops=$withval])
-AS_VAR_IF([have_atomic_ops], [no], [], [
-       PKG_CHECK_MODULES([atomic_ops], [atomic_ops], [have_atomic_ops=yes],
-               [have_atomic_ops=no; why_not_atomic_ops="(atomic_ops library 
not found)"])
-       AS_VAR_IF([have_atomic_ops], [yes], [
-               AS_CASE([$GCC-$CC],
-               [-*icc*], [
-                       # Even with libatomic_ops available, compilation with
-                       # atomic_ops enabled fails with Intel's icc (version 
11.1);
-                       # hence, we refrain from from using atomic_ops with icc.
-                       have_atomic_ops=no
-                       why_not_atomic_ops="(atomic_ops do not compile with 
Intel's icc)"],
-               [
-                       # On some systems, notably OpenIndiana, atomic_ops may
-                       # seem to be installed in that there is a pkg-config
-                       # file for it, but that file contains incorrect
-                       # information, and can not, in fact, be used.  The
-                       # bogus pkg-config file for atomic_ops is part of the
-                       # library/gc package.
-                       save_CFLAGS="$CFLAGS"
-                       CFLAGS="$CFLAGS $atomic_ops_CFLAGS"
-                       AC_CHECK_HEADERS([atomic_ops.h], [have_atomic_ops=yes], 
[have_atomic_ops=no why_not_atomic_ops="(atomic_ops was incorrectly installed 
(happens on at least Solaris/OpenIndiana))"])
-                       CFLAGS="$save_CFLAGS"
-                       AS_VAR_IF([have_atomic_ops], [yes], [
-                               AC_DEFINE([HAVE_LIBATOMIC_OPS], 1, [Define if 
you have the libatomic_ops library])
-                               CFLAGS="$CFLAGS $atomic_ops_CFLAGS"
-                               LIBS="$LIBS $atomic_ops_LIBS"])])])])
-
 #    checks for header files
 AC_HEADER_STDBOOL
 # NOTE: these header files are in alphabetical order to ease maintenance
@@ -2988,7 +2955,6 @@ done
 AS_ECHO([''])
 AS_ECHO(["* Available features/extensions:"])
 for comp in \
-       'atomic_ops ' \
        'bz2        ' \
        'curl       ' \
        'fits       ' \
diff --git a/debian/control b/debian/control
--- a/debian/control
+++ b/debian/control
@@ -34,7 +34,7 @@ Description: MonetDB core library
 
 Package: libmonetdb-dev
 Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, libatomic-ops-dev,
+Depends: ${shlibs:Depends}, ${misc:Depends},
  libmonetdb17, libmonetdb-stream-dev
 Description: MonetDB development files
  MonetDB is a database management system that is developed from a
diff --git a/gdk/gdk_atomic.h b/gdk/gdk_atomic.h
--- a/gdk/gdk_atomic.h
+++ b/gdk/gdk_atomic.h
@@ -38,27 +38,7 @@
 /* define this if you don't want to use atomic instructions */
 /* #define NO_ATOMIC_INSTRUCTIONS */
 
-#if defined(HAVE_LIBATOMIC_OPS) && !defined(NO_ATOMIC_INSTRUCTIONS)
-
-#include <atomic_ops.h>
-
-#define ATOMIC_TYPE                    AO_t
-#define ATOMIC_VAR_INIT(val)           (val)
-#define ATOMIC_INIT(var, val)          (*(var) = (val))
-
-#define ATOMIC_GET(var)                        AO_load_full(var)
-#define ATOMIC_SET(var, val)           AO_store_full(var, (AO_t) (val))
-#define ATOMIC_ADD(var, val)           AO_fetch_and_add(var, (AO_t) (val))
-#define ATOMIC_SUB(var, val)           AO_fetch_and_add(var, (AO_t) -(val))
-#define ATOMIC_INC(var)                        (AO_fetch_and_add1(var) + 1)
-#define ATOMIC_DEC(var)                        (AO_fetch_and_sub1(var) - 1)
-
-#define ATOMIC_FLAG                    AO_TS_t
-#define ATOMIC_FLAG_INIT               { AO_TS_INITIALIZER }
-#define ATOMIC_CLEAR(var)              AO_CLEAR(var)
-#define ATOMIC_TAS(var)        (AO_test_and_set_full(var) != AO_TS_CLEAR)
-
-#elif defined(HAVE_STDATOMIC_H) && !defined(__INTEL_COMPILER) && 
!defined(__STDC_NO_ATOMICS__) && !defined(NO_ATOMIC_INSTRUCTIONS)
+#if defined(HAVE_STDATOMIC_H) && !defined(__INTEL_COMPILER) && 
!defined(__STDC_NO_ATOMICS__) && !defined(NO_ATOMIC_INSTRUCTIONS)
 
 #include <stdatomic.h>
 
@@ -93,6 +73,11 @@
 #define ATOMIC_INC(var)                (atomic_fetch_add(var, 1) + 1)
 #define ATOMIC_DEC(var)                (atomic_fetch_sub(var, 1) - 1)
 
+#define ATOMIC_PTR_TYPE(typ)           typ
+#define ATOMIC_PTR_INIT(var, val)      atomic_init(var, val)
+#define ATOMIC_GET_PTR(var)            atomic_load(var)
+#define ATOMIC_SET_PTR(var, val)       atomic_store(var, val)
+
 #define ATOMIC_FLAG            atomic_flag
 /* ATOMIC_FLAG_INIT is already defined by the include file */
 #define ATOMIC_CLEAR(var)      atomic_flag_clear(var)
@@ -102,6 +87,19 @@
 
 #include <intrin.h>
 
+/* On Windows, with Visual Studio 2005, the compiler uses acquire
+ * semantics for read operations on volatile variables and release
+ * semantics for write operations on volatile variables.
+ *
+ * With Visual Studio 2003, volatile to volatile references are
+ * ordered; the compiler will not re-order volatile variable
+ * access. However, these operations could be re-ordered by the
+ * processor.
+ *
+ * See
+ * 
https://docs.microsoft.com/en-us/windows/desktop/Sync/synchronization-and-multiprocessor-issues
+ */
+
 #if SIZEOF_SSIZE_T == 8
 
 #define ATOMIC_TYPE            volatile int64_t
@@ -143,6 +141,11 @@
 
 #endif
 
+#define ATOMIC_PTR_TYPE(typ)           volatile PVOID
+#define ATOMIC_PTR_INIT(var, val)      (*(var) = (val))
+#define ATOMIC_GET_PTR(var)            (*(var))
+#define ATOMIC_SET_PTR(var, val)       _InterlockedExchangePointer((volatile 
PVOID*) (var), (PVOID) (val))
+
 #define ATOMIC_FLAG            int
 #define ATOMIC_FLAG_INIT       { 0 }
 #define ATOMIC_CLEAR(var)      _InterlockedExchange(var, 0)
@@ -169,6 +172,11 @@
 #define ATOMIC_INC(var)                __atomic_add_fetch(var, 1, 
__ATOMIC_SEQ_CST)
 #define ATOMIC_DEC(var)                __atomic_sub_fetch(var, 1, 
__ATOMIC_SEQ_CST)
 
+#define ATOMIC_PTR_TYPE(typ)           typ
+#define ATOMIC_PTR_INIT(var, val)      (*(var) = (val))
+#define ATOMIC_GET_PTR(var)            __atomic_load_n(var, __ATOMIC_SEQ_CST)
+#define ATOMIC_SET_PTR(var, val)       __atomic_store_n(var, (val), 
__ATOMIC_SEQ_CST)
+
 #define ATOMIC_FLAG            char
 #define ATOMIC_FLAG_INIT       { 0 }
 #define ATOMIC_CLEAR(var)      __atomic_clear(var, __ATOMIC_SEQ_CST)
@@ -257,6 +265,40 @@ ATOMIC_DEC(ATOMIC_TYPE *var)
        return new;
 }
 
+#define ATOMIC_PTR_TYPE(typ)           ATOMIC_PTR
+
+typedef struct {
+       void *val;
+       pthread_mutex_t lck;
+} ATOMIC_PTR;
+
+static inline void
+ATOMIC_PTR_INIT(ATOMIC_PTR *var, void *val)
+{
+       pthread_mutex_init(&var->lck, 0);
+       var->val = val;
+}
+
+static inline void *
+ATOMIC_GET_PTR(ATOMIC_PTR *var)
+{
+       void *old;
+       pthread_mutex_lock(&var->lck);
+       old = var->val;
+       pthread_mutex_unlock(&var->lck);
+       return old;
+}
+
+static inline void *
+ATOMIC_SET_PTR(ATOMIC_PTR *var, void *val)
+{
+       void *new;
+       pthread_mutex_lock(&var->lck);
+       new = var->val = val;
+       pthread_mutex_unlock(&var->lck);
+       return new;
+}
+
 typedef struct {
        bool flg;
        pthread_mutex_t lck;
diff --git a/monetdb5/mal/mal_dataflow.c b/monetdb5/mal/mal_dataflow.c
--- a/monetdb5/mal/mal_dataflow.c
+++ b/monetdb5/mal/mal_dataflow.c
@@ -80,7 +80,7 @@ typedef struct DATAFLOW {
 static struct worker {
        MT_Id id;
        enum {IDLE, RUNNING, JOINING, EXITED} flag;
-       Client cntxt;                           /* client we do work for (NULL 
-> any) */
+       ATOMIC_PTR_TYPE(Client) cntxt; /* client we do work for (NULL -> any) */
        MT_Sema s;
 } workers[THREADS];
 
@@ -336,9 +336,7 @@ DFLOWworker(void *T)
                fprintf(stderr,"DFLOWworker:Could not allocate GDKerrbuf\n");
        else
                GDKclrerr();
-       MT_lock_set(&dataflowLock);
-       cntxt = t->cntxt;
-       MT_lock_unset(&dataflowLock);
+       cntxt = ATOMIC_GET_PTR(&t->cntxt);
        if (cntxt) {
                /* wait until we are allowed to start working */
                MT_sema_down(&t->s);
@@ -346,9 +344,7 @@ DFLOWworker(void *T)
        while (1) {
                if (fnxt == 0) {
                        MT_thread_setworking(NULL);
-                       MT_lock_set(&dataflowLock);
-                       cntxt = t->cntxt;
-                       MT_lock_unset(&dataflowLock);
+                       cntxt = ATOMIC_GET_PTR(&t->cntxt);
                        fe = q_dequeue(todo, cntxt);
                        if (fe == NULL) {
                                if (cntxt) {
@@ -493,6 +489,7 @@ DFLOWinitialize(void)
 {
        int i, limit;
        int created = 0;
+       static bool first = true;
 
        MT_lock_set(&mal_contextLock);
        if (todo) {
@@ -510,14 +507,17 @@ DFLOWinitialize(void)
                snprintf(name, sizeof(name), "DFLOWsema%d", i);
                MT_sema_init(&workers[i].s, 0, name);
                workers[i].flag = IDLE;
+               if (first)                              /* only initialize once 
*/
+                       ATOMIC_PTR_INIT(&workers[i].cntxt, NULL);
        }
+       first = false;
        limit = GDKnr_threads ? GDKnr_threads - 1 : 0;
        if (limit > THREADS)
                limit = THREADS;
        MT_lock_set(&dataflowLock);
        for (i = 0; i < limit; i++) {
                workers[i].flag = RUNNING;
-               workers[i].cntxt = NULL;
+               ATOMIC_SET_PTR(&workers[i].cntxt, NULL);
                char name[16];
                snprintf(name, sizeof(name), "DFLOWworker%d", i);
                if ((workers[i].id = THRcreate(DFLOWworker, (void *) 
&workers[i], MT_THR_JOINABLE, name)) == 0)
@@ -780,9 +780,7 @@ DFLOWscheduler(DataFlow flow, struct wor
        }
        /* release the worker from its specific task (turn it into a
         * generic worker) */
-       MT_lock_set(&dataflowLock);
-       w->cntxt = NULL;
-       MT_lock_unset(&dataflowLock);
+       ATOMIC_SET_PTR(&w->cntxt, NULL);
        /* wrap up errors */
        assert(flow->done->last == 0);
        if (flow->error ) {
@@ -854,7 +852,7 @@ runMALdataflow(Client cntxt, MalBlkPtr m
                        for (i = 0; i < THREADS; i++) {
                                if (workers[i].flag == EXITED) {
                                        workers[i].flag = JOINING;
-                                       workers[i].cntxt = NULL;
+                                       ATOMIC_SET_PTR(&workers[i].cntxt, NULL);
                                        joined = 1;
                                        MT_lock_unset(&dataflowLock);
                                        MT_join_thread(workers[i].id);
@@ -874,16 +872,17 @@ runMALdataflow(Client cntxt, MalBlkPtr m
 
                                /* doing a recursive call: copy specificity from
                                 * current worker to new worker */
-                               workers[i].cntxt = NULL;
+                               ATOMIC_SET_PTR(&workers[i].cntxt, NULL);
                                for (j = 0; j < THREADS; j++) {
                                        if (workers[j].flag == RUNNING && 
workers[j].id == pid) {
-                                               workers[i].cntxt = 
workers[j].cntxt;
+                                               
ATOMIC_SET_PTR(&workers[i].cntxt,
+                                                                          
ATOMIC_GET_PTR(&workers[j].cntxt));
                                                break;
                                        }
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to