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