Changeset: 94cb82d10868 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=94cb82d10868
Modified Files:
        clients/Tests/exports.stable.out
        gdk/gdk_system.c
        gdk/gdk_system.h
Branch: default
Log Message:

Implemented semaphores using atomic instructions on capable systems.


diffs (truncated from 350 to 300 lines):

diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -276,6 +276,10 @@ int GDKnr_threads;
 void GDKqsort(void *h, void *t, const void *base, size_t n, int hs, int ts, 
int tpe);
 void GDKqsort_rev(void *h, void *t, const void *base, size_t n, int hs, int 
ts, int tpe);
 void *GDKrealloc(void *pold, size_t size);
+ATOMIC_TYPE volatile GDKsemacnt;
+MT_Sema *volatile GDKsemalist;
+ATOMIC_TYPE volatile GDKsemasleepcnt;
+ATOMIC_TYPE volatile GDKsemawaitcnt;
 void GDKsetenv(str name, str value);
 ssize_t GDKstrFromStr(unsigned char *dst, const unsigned char *src, ssize_t 
len);
 str GDKstrdup(const char *s);
diff --git a/gdk/gdk_system.c b/gdk/gdk_system.c
--- a/gdk/gdk_system.c
+++ b/gdk/gdk_system.c
@@ -71,9 +71,14 @@ MT_Lock MT_system_lock MT_LOCK_INITIALIZ
 ATOMIC_TYPE volatile GDKlockcnt;
 ATOMIC_TYPE volatile GDKlockcontentioncnt;
 ATOMIC_TYPE volatile GDKlocksleepcnt;
+ATOMIC_TYPE volatile GDKsemacnt;
+ATOMIC_TYPE volatile GDKsemawaitcnt;
+ATOMIC_TYPE volatile GDKsemasleepcnt;
 MT_Lock * volatile GDKlocklist;
+MT_Sema * volatile GDKsemalist;
 
-/* merge sort of linked list */
+/* merge sort of linked list
+ * these two functions are nearly identical */
 static MT_Lock *
 sortlocklist(MT_Lock *l)
 {
@@ -131,12 +136,59 @@ sortlocklist(MT_Lock *l)
        return t;
 }
 
+static MT_Sema *
+sortsemalist(MT_Sema *l)
+{
+       MT_Sema *r, *t, *ll = NULL;
+
+       if (l == NULL || l->next == NULL)
+               return l;
+       for (t = r = l; t && t->next; t = t->next->next) {
+               ll = r;
+               r = r->next;
+       }
+       ll->next = NULL;
+       l = sortsemalist(l);
+       r = sortsemalist(r);
+       t = ll = NULL;
+       while (l && r) {
+               if (l->waitcount < r->waitcount ||
+                   (l->waitcount == r->waitcount &&
+                    l->sleep < r->sleep) ||
+                   (l->waitcount == r->waitcount &&
+                    l->sleep == r->sleep &&
+                    l->count <= r->count)) {
+                       if (ll == NULL) {
+                               assert(t == NULL);
+                               t = ll = l;
+                       } else {
+                               ll->next = l;
+                               ll = ll->next;
+                       }
+                       l = l->next;
+               } else {
+                       if (ll == NULL) {
+                               assert(t == NULL);
+                               t = ll = r;
+                       } else {
+                               ll->next = r;
+                               ll = ll->next;
+                       }
+                       r = r->next;
+               }
+       }
+       ll->next = l ? l : r;
+       return t;
+}
+
 void
 GDKlockstatistics(int what)
 {
        MT_Lock *l;
+       MT_Sema *s;
 
        GDKlocklist = sortlocklist(GDKlocklist);
+       GDKsemalist = sortsemalist(GDKsemalist);
        for (l = GDKlocklist; l; l = l->next)
                if (what == 0 ||
                    (what == 1 && l->count) ||
@@ -146,9 +198,16 @@ GDKlockstatistics(int what)
                                l->name ? l->name : "unknown",
                                l->count, l->contention, l->sleep,
                                what != 3 && l->lock ? "\tlocked" : "");
+       for (s = GDKsemalist; s; s = s->next)
+               fprintf(stderr, "#sema %-18s\t" SZFMT "\t" SZFMT "\t" SZFMT 
"\n",
+                       s->name ? s->name : "unknown",
+                       s->count, s->waitcount, s->sleep);
        fprintf(stderr, "#total lock count " SZFMT "\n", (size_t) GDKlockcnt);
        fprintf(stderr, "#lock contention  " SZFMT "\n", (size_t) 
GDKlockcontentioncnt);
        fprintf(stderr, "#lock sleep count " SZFMT "\n", (size_t) 
GDKlocksleepcnt);
+       fprintf(stderr, "#total sema count " SZFMT "\n", (size_t) GDKsemacnt);
+       fprintf(stderr, "#sema wait count  " SZFMT "\n", (size_t) 
GDKsemawaitcnt);
+       fprintf(stderr, "#sema sleep count " SZFMT "\n", (size_t) 
GDKsemasleepcnt);
 }
 #endif
 
diff --git a/gdk/gdk_system.h b/gdk/gdk_system.h
--- a/gdk/gdk_system.h
+++ b/gdk/gdk_system.h
@@ -192,6 +192,51 @@ typedef pthread_mutex_t MT_Lock;
 #define NEED_MT_LOCK_INIT
 #endif
 
+/*
+ * @- MT Semaphore API
+ */
+#if !defined(HAVE_PTHREAD_H) && defined(_MSC_VER)
+
+typedef HANDLE pthread_sema_t;
+gdk_export void pthread_sema_init(pthread_sema_t *s, int flag, int nresources);
+gdk_export void pthread_sema_destroy(pthread_sema_t *s);
+gdk_export void pthread_sema_up(pthread_sema_t *s);
+gdk_export void pthread_sema_down(pthread_sema_t *s);
+
+#elif defined(_AIX) || defined(__MACH__)
+
+typedef struct {
+       int cnt;
+       pthread_mutex_t mutex;
+       pthread_cond_t cond;
+} pthread_sema_t;
+
+gdk_export void pthread_sema_init(pthread_sema_t *s, int flag, int nresources);
+gdk_export void pthread_sema_destroy(pthread_sema_t *s);
+gdk_export void pthread_sema_up(pthread_sema_t *s);
+gdk_export void pthread_sema_down(pthread_sema_t *s);
+
+#else
+
+#define pthread_sema_t         sem_t
+#define pthread_sema_init      sem_init
+#define pthread_sema_destroy   sem_destroy
+#define pthread_sema_up                sem_post
+#define pthread_sema_down(x)   while(sem_wait(x))
+
+#endif
+
+typedef pthread_sema_t MT_Sema;
+
+#define MT_sema_init(s, nr, n)                 \
+       do {                                    \
+               pthread_sema_init((s), 0, nr);  \
+               MT_locktrace_set((s), n);       \
+       } while (0)
+#define MT_sema_destroy(s)     pthread_sema_destroy(s)
+#define MT_sema_up(s, n)       MT_log(pthread_sema_up(s), (s), "MT_up_sema", 
n, stderr)
+#define MT_sema_down(s, n)     MT_log_trace(pthread_sema_down(s), (s), 
"MT_down_sema", n, stderr, s)
+
 #else
 
 /* if NDEBUG is not set, i.e., if assertions are enabled, we maintain
@@ -207,15 +252,31 @@ typedef struct MT_Lock {
 #endif
 } MT_Lock;
 
+typedef struct MT_Sema {
+       int volatile lock;
+       int volatile sema;
+#ifndef NDEBUG
+       size_t count;
+       size_t waitcount;
+       size_t sleep;
+       struct MT_Sema * volatile next;
+       const char *name;
+#endif
+} MT_Sema;
+
 #ifndef NDEBUG
 
 #define MT_LOCK_INITIALIZER(name)      = {0, 0, 0, 0, (struct MT_Lock *) -1, 
name}
 
 gdk_export void GDKlockstatistics(int);
 gdk_export MT_Lock * volatile GDKlocklist;
+gdk_export MT_Sema * volatile GDKsemalist;
 gdk_export ATOMIC_TYPE volatile GDKlockcnt;
 gdk_export ATOMIC_TYPE volatile GDKlockcontentioncnt;
 gdk_export ATOMIC_TYPE volatile GDKlocksleepcnt;
+gdk_export ATOMIC_TYPE volatile GDKsemacnt;
+gdk_export ATOMIC_TYPE volatile GDKsemawaitcnt;
+gdk_export ATOMIC_TYPE volatile GDKsemasleepcnt;
 #ifdef _MSC_VER
 #if SIZEOF_SIZE_T == 8
 #define ATOMIC_XCG_ptr(var, val)       _InterlockedExchange64(&var, val)
@@ -274,6 +335,48 @@ gdk_export ATOMIC_TYPE volatile GDKlocks
                                }                                       \
                } while (!_done);                                       \
        } while (0)
+#define _DBG_SEMA_INIT(s, n)                                   \
+       do {                                                    \
+               (s)->name = n;                                  \
+               (s)->count = 0;                                 \
+               (s)->waitcount = 0;                             \
+               (s)->sleep = 0;                                 \
+               (s)->next = ATOMIC_XCG_ptr(GDKsemalist, (s));   \
+       } while (0)
+#define _DBG_SEMA_DESTROY(s)                                           \
+       do {                                                            \
+               MT_Sema * volatile _p;                                  \
+               int _done = 0;                                          \
+               /* save a copy for statistical purposes */              \
+               _p = GDKmalloc(sizeof(MT_Sema));                        \
+               memcpy(_p, s, sizeof(MT_Sema));                         \
+               _p->next = ATOMIC_XCG_ptr(GDKsemalist, _p);             \
+               do {                                                    \
+                       if (ATOMIC_CAS_ptr(GDKsemalist, (s), (s)->next) == (s)) 
\
+                               break;                                  \
+                       for (_p = GDKsemalist; _p; _p = _p->next)       \
+                               if (ATOMIC_CAS_ptr(_p->next, (s), (s)->next) == 
(s)) { \
+                                       _done = 1;                      \
+                                       break;                          \
+                               }                                       \
+               } while (!_done);                                       \
+       } while (0)
+#define _DBG_SEMA_COUNT_0(s, n)                ATOMIC_INC(GDKsemacnt, dummy, n)
+#define _DBG_SEMA_COUNT_1(s)           ((s)->count++)
+#define _DBG_SEMA_WAIT(s, n)                                           \
+       do {                                                            \
+               (s)->waitcount++;                                       \
+               ATOMIC_INC(GDKsemawaitcnt, dummy, n);                   \
+       } while (0)
+#define _DBG_SEMA_SLEEP(s, n)                                  \
+       do {                                                    \
+               if (_spincnt == 1024)                           \
+                       ATOMIC_INC(GDKsemasleepcnt, dummy, n);  \
+       } while (0)
+#define _DBG_SEMA_COUNT_2(s)                   \
+       do {                                    \
+               (s)->sleep += _spincnt >= 1024; \
+       } while (0)
 
 #else
 
@@ -286,6 +389,13 @@ gdk_export ATOMIC_TYPE volatile GDKlocks
 #define _DBG_LOCK_COUNT_2(l)           ((void) 0)
 #define _DBG_LOCK_INIT(l, n)           ((void) n)
 #define _DBG_LOCK_DESTROY(l)           ((void) 0)
+#define _DBG_SEMA_INIT(s, n)           ((void) n)
+#define _DBG_SEMA_DESTROY(s)           ((void) 0)
+#define _DBG_SEMA_COUNT_0(s, n)                ((void) n)
+#define _DBG_SEMA_COUNT_1(s)           ((void) 0)
+#define _DBG_SEMA_WAIT(s, n)           ((void) n)
+#define _DBG_SEMA_SLEEP(s, n)          ((void) n)
+#define _DBG_SEMA_COUNT_2(s)           ((void) 0)
 
 #endif
 
@@ -316,54 +426,44 @@ gdk_export ATOMIC_TYPE volatile GDKlocks
 /* return 0 on success, -1 on failure to get the lock */
 #define MT_lock_try(l) ((ATOMIC_CAS_int((l)->lock, 0, 1, dummy, dummy) == 0) - 
1)
 
-#endif
-
-/*
- * @- MT Semaphore API
- */
-#if !defined(HAVE_PTHREAD_H) && defined(_MSC_VER)
-
-typedef HANDLE pthread_sema_t;
-gdk_export void pthread_sema_init(pthread_sema_t *s, int flag, int nresources);
-gdk_export void pthread_sema_destroy(pthread_sema_t *s);
-gdk_export void pthread_sema_up(pthread_sema_t *s);
-gdk_export void pthread_sema_down(pthread_sema_t *s);
-
-#elif defined(_AIX) || defined(__MACH__)
-
-typedef struct {
-       int cnt;
-       pthread_mutex_t mutex;
-       pthread_cond_t cond;
-} pthread_sema_t;
-
-gdk_export void pthread_sema_init(pthread_sema_t *s, int flag, int nresources);
-gdk_export void pthread_sema_destroy(pthread_sema_t *s);
-gdk_export void pthread_sema_up(pthread_sema_t *s);
-gdk_export void pthread_sema_down(pthread_sema_t *s);
-
-#else
-
-#define pthread_sema_t         sem_t
-#define pthread_sema_init      sem_init
-#define pthread_sema_destroy   sem_destroy
-#define pthread_sema_up                sem_post
-#define pthread_sema_down(x)   while(sem_wait(x))
+#define MT_sema_init(s, nr, n)                 \
+       do {                                    \
+               (s)->lock = 0;                  \
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to