Changeset: 48266ba700bb for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/48266ba700bb
Modified Files:
        gdk/gdk.h
        gdk/gdk_atoms.c
        gdk/gdk_bbp.c
        gdk/gdk_private.h
        gdk/gdk_utils.c
        monetdb5/mal/mal.c
        monetdb5/mal/mal_prelude.c
        monetdb5/mal/mal_profiler.c
        monetdb5/modules/mal/tablet.c
        sql/storage/store.c
        tools/mserver/mserver5.c
Branch: default
Log Message:

Fixed a bunch of data races and a lock order inversion.
Starting with a new database and immediately stopping now causes no data
races.


diffs (truncated from 372 to 300 lines):

diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -567,10 +567,10 @@ typedef struct {
 
        ATOMIC_TYPE refs;       /* reference count for this heap */
        bte farmid;             /* id of farm where heap is located */
-       bool cleanhash:1,       /* string heaps must clean hash */
-               dirty:1,        /* specific heap dirty marker */
-               remove:1,       /* remove storage file when freeing */
-               wasempty:1;     /* heap was empty when last saved/created */
+       bool cleanhash;         /* string heaps must clean hash */
+       bool dirty;             /* specific heap dirty marker */
+       bool remove;            /* remove storage file when freeing */
+       bool wasempty;      /* heap was empty when last saved/created */
        storage_t storage;      /* storage mode (mmap/malloc). */
        storage_t newstorage;   /* new desired storage mode at re-allocation. */
        bat parentid;           /* cache id of VIEW parent bat */
@@ -762,6 +762,18 @@ typedef struct {
 /* if the version number is updated, also fix snapshot_bats() in bat_logger.c 
*/
 #define GDKLIBRARY             061046U /* first after Jan2022 */
 
+/* The batRestricted field indicates whether a BAT is readonly.
+ * we have modes: BAT_WRITE  = all permitted
+ *                BAT_APPEND = append-only
+ *                BAT_READ   = read-only
+ * VIEW bats are always mapped read-only.
+ */
+typedef enum {
+       BAT_WRITE,                /* all kinds of access allowed */
+       BAT_READ,                 /* only read-access allowed */
+       BAT_APPEND,               /* only reads and appends allowed */
+} restrict_t;
+
 typedef struct BAT {
        /* static bat properties */
        oid hseqbase;           /* head seq base */
@@ -769,13 +781,12 @@ typedef struct BAT {
        bat batCacheid;         /* index into BBP */
 
        /* dynamic bat properties */
+       restrict_t batRestricted; /* access privileges */
+       bool batTransient;      /* should the BAT persist on disk? */
        bool
         batCopiedtodisk:1,     /* once written */
         batDirtyflushed:1,     /* was dirty before commit started? */
-        batDirtydesc:1,        /* bat descriptor dirty marker */
-        batTransient:1;        /* should the BAT persist on disk? */
-       uint8_t /* adjacent bit fields are packed together (if they fit) */
-        batRestricted:2;       /* access privileges */
+        batDirtydesc:1;        /* bat descriptor dirty marker */
        uint16_t /* adjacent bit fields are packed together (if they fit) */
         selcnt:10;             /* how often used in equi select without hash */
        role_t batRole;         /* role of the bat */
@@ -1232,18 +1243,6 @@ gdk_export gdk_return BATroles(BAT *b, c
 gdk_export void BAThseqbase(BAT *b, oid o);
 gdk_export void BATtseqbase(BAT *b, oid o);
 
-/* The batRestricted field indicates whether a BAT is readonly.
- * we have modes: BAT_WRITE  = all permitted
- *                BAT_APPEND = append-only
- *                BAT_READ   = read-only
- * VIEW bats are always mapped read-only.
- */
-typedef enum {
-       BAT_WRITE,                /* all kinds of access allowed */
-       BAT_READ,                 /* only read-access allowed */
-       BAT_APPEND,               /* only reads and appends allowed */
-} restrict_t;
-
 gdk_export BAT *BATsetaccess(BAT *b, restrict_t mode)
        __attribute__((__warn_unused_result__));
 gdk_export restrict_t BATgetaccess(BAT *b);
diff --git a/gdk/gdk_atoms.c b/gdk/gdk_atoms.c
--- a/gdk/gdk_atoms.c
+++ b/gdk/gdk_atoms.c
@@ -177,6 +177,8 @@ batUnfix(const bat *b)
  * The incremental atom construction uses hardwired properties.  This
  * should be improved later on.
  */
+static MT_Lock GDKatomLock = MT_LOCK_INITIALIZER(GDKatomLock);
+
 int
 ATOMallocate(const char *id)
 {
@@ -187,13 +189,13 @@ ATOMallocate(const char *id)
                return int_nil;
        }
 
-       MT_lock_set(&GDKthreadLock);
+       MT_lock_set(&GDKatomLock);
        t = ATOMindex(id);
        if (t < 0) {
                t = -t;
                if (t == GDKatomcnt) {
                        if (GDKatomcnt == MAXATOMS) {
-                               MT_lock_unset(&GDKthreadLock);
+                               MT_lock_unset(&GDKatomLock);
                                GDKerror("too many types");
                                return int_nil;
                        }
@@ -206,7 +208,7 @@ ATOMallocate(const char *id)
                };
                strcpy(BATatoms[t].name, id);
        }
-       MT_lock_unset(&GDKthreadLock);
+       MT_lock_unset(&GDKatomLock);
        return t;
 }
 
@@ -1925,11 +1927,11 @@ ATOMunknown_find(const char *nme)
        int i, j = 0;
 
        /* first try to find the atom */
-       MT_lock_set(&GDKthreadLock);
+       MT_lock_set(&GDKatomLock);
        for (i = 1; i < MAXATOMS; i++) {
                if (unknown[i]) {
                        if (strcmp(unknown[i], nme) == 0) {
-                               MT_lock_unset(&GDKthreadLock);
+                               MT_lock_unset(&GDKatomLock);
                                return -i;
                        }
                } else if (j == 0)
@@ -1937,14 +1939,14 @@ ATOMunknown_find(const char *nme)
        }
        if (j == 0) {
                /* no space for new atom (shouldn't happen) */
-               MT_lock_unset(&GDKthreadLock);
+               MT_lock_unset(&GDKatomLock);
                return 0;
        }
        if ((unknown[j] = GDKstrdup(nme)) == NULL) {
-               MT_lock_unset(&GDKthreadLock);
+               MT_lock_unset(&GDKatomLock);
                return 0;
        }
-       MT_lock_unset(&GDKthreadLock);
+       MT_lock_unset(&GDKatomLock);
        return -j;
 }
 
@@ -1962,7 +1964,7 @@ ATOMunknown_clean(void)
 {
        int i;
 
-       MT_lock_set(&GDKthreadLock);
+       MT_lock_set(&GDKatomLock);
        for (i = 1; i < MAXATOMS; i++) {
                if(unknown[i]) {
                        GDKfree(unknown[i]);
@@ -1971,5 +1973,5 @@ ATOMunknown_clean(void)
                        break;
                }
        }
-       MT_lock_unset(&GDKthreadLock);
+       MT_lock_unset(&GDKatomLock);
 }
diff --git a/gdk/gdk_bbp.c b/gdk/gdk_bbp.c
--- a/gdk/gdk_bbp.c
+++ b/gdk/gdk_bbp.c
@@ -2566,12 +2566,14 @@ BBPinsert(BAT *bn)
        bn->batCacheid = i;
        bn->creator_tid = MT_getpid();
 
+       MT_lock_set(&GDKswapLock(i));
        BBP_status_set(i, BBPDELETING|BBPHOT);
        BBP_cache(i) = NULL;
        BBP_desc(i) = NULL;
        BBP_refs(i) = 1;        /* new bats have 1 pin */
        BBP_lrefs(i) = 0;       /* ie. no logical refs */
        BBP_pid(i) = MT_getpid();
+       MT_lock_unset(&GDKswapLock(i));
 
 #ifdef HAVE_HGE
        if (bn->ttype == TYPE_hge)
diff --git a/gdk/gdk_private.h b/gdk/gdk_private.h
--- a/gdk/gdk_private.h
+++ b/gdk/gdk_private.h
@@ -421,7 +421,11 @@ ilog2(BUN x)
        b && b->torderidx ? "O" : "",                                   \
        b ? b->timprints ? "I" : b->theap && b->theap->parentid && 
BBP_cache(b->theap->parentid) && BBP_cache(b->theap->parentid)->timprints ? 
"(I)" : "" : ""
 
+#ifdef __SANITIZE_THREAD__
+#define BBP_BATMASK    31
+#else
 #define BBP_BATMASK    ((1 << (SIZEOF_SIZE_T + 5)) - 1)
+#endif
 
 struct PROPrec {
        enum prop_t id;
@@ -469,7 +473,6 @@ extern batlock_t GDKbatLock[BBP_BATMASK 
 extern size_t GDK_mmap_minsize_persistent; /* size after which we use memory 
mapped files for persistent heaps */
 extern size_t GDK_mmap_minsize_transient; /* size after which we use memory 
mapped files for transient heaps */
 extern size_t GDK_mmap_pagesize; /* mmap granularity */
-extern MT_Lock GDKthreadLock;
 extern MT_Lock GDKtmLock;
 
 #define BATcheck(tst, err)                             \
diff --git a/gdk/gdk_utils.c b/gdk/gdk_utils.c
--- a/gdk/gdk_utils.c
+++ b/gdk/gdk_utils.c
@@ -1203,6 +1203,8 @@ GDKprepareExit(void)
        }
 }
 
+static MT_Lock GDKthreadLock = MT_LOCK_INITIALIZER(GDKthreadLock);
+
 void
 GDKreset(int status)
 {
@@ -1334,7 +1336,6 @@ GDKexit(int status)
  */
 
 batlock_t GDKbatLock[BBP_BATMASK + 1];
-MT_Lock GDKthreadLock = MT_LOCK_INITIALIZER(GDKthreadLock);
 
 /* GDKtmLock protects all accesses and changes to BAKDIR and SUBDIR */
 MT_Lock GDKtmLock = MT_LOCK_INITIALIZER(GDKtmLock);
diff --git a/monetdb5/mal/mal.c b/monetdb5/mal/mal.c
--- a/monetdb5/mal/mal.c
+++ b/monetdb5/mal/mal.c
@@ -85,7 +85,6 @@ mal_init(char *modules[], int embedded)
 #endif
        initNamespace();
        initParser();
-       initHeartbeat();
 
        err = malBootstrap(modules, embedded);
        if (err != MAL_SUCCEED) {
@@ -98,6 +97,7 @@ mal_init(char *modules[], int embedded)
                return -1;
        }
        initProfiler();
+       initHeartbeat();
        return 0;
 }
 
diff --git a/monetdb5/mal/mal_prelude.c b/monetdb5/mal/mal_prelude.c
--- a/monetdb5/mal/mal_prelude.c
+++ b/monetdb5/mal/mal_prelude.c
@@ -417,7 +417,7 @@ melFunction(bool command, const char *mo
 }
 
 static str
-malPrelude(Client c, int listing, int no_mapi_server)
+malPrelude(Client c, int listing)
 {
        int i;
        str msg = MAL_SUCCEED;
@@ -443,8 +443,8 @@ malPrelude(Client c, int listing, int no
                        if (msg)
                                return msg;
 
-                       /* skip sql should be last to startup and mapi if 
configured without mapi server */
-                       if (strcmp(mel_module[i].name, "sql") == 0 || 
(no_mapi_server && strcmp(mel_module[i].name, "mapi") == 0))
+                       /* mapi should be last, and sql last before mapi */
+                       if (strcmp(mel_module[i].name, "sql") == 0 || 
strcmp(mel_module[i].name, "mapi") == 0)
                                continue;
                        if (!mel_module[i].inits) {
                                msg = initModule(c, mel_module[i].name);
@@ -456,8 +456,8 @@ malPrelude(Client c, int listing, int no
                        msg = mel_module[i].inits();
                        if (msg)
                                return msg;
-                       /* skip sql should be last to startup and mapi if 
configured without mapi server */
-                       if (strcmp(mel_module[i].name, "sql") == 0 || 
(no_mapi_server && strcmp(mel_module[i].name, "mapi") == 0))
+                       /* mapi should be last, and sql last before mapi */
+                       if (strcmp(mel_module[i].name, "sql") == 0 || 
strcmp(mel_module[i].name, "mapi") == 0)
                                continue;
                        msg = initModule(c, mel_module[i].name);
                        if (msg)
@@ -481,13 +481,15 @@ malIncludeModules(Client c, char *module
                        return msg;
        }
        /* load the mal code for these modules and execute preludes */
-       if ((msg = malPrelude(c, listing, no_mapi_server)) != NULL)
+       if ((msg = malPrelude(c, listing)) != NULL)
+               return msg;
+       msg = initModule(c, "sql");
+       if (msg)
                return msg;
-       for(int i = 0; modules[i]; i++) {
-               if (strcmp(modules[i], "sql") == 0) { /* start now */
-                       initModule(c, modules[i]);
-                       break;
-               }
+       if (!no_mapi_server) {
+               msg = initModule(c, "mapi");
+               if (msg)
+                       return msg;
        }
        return MAL_SUCCEED;
 }
diff --git a/monetdb5/mal/mal_profiler.c b/monetdb5/mal/mal_profiler.c
--- a/monetdb5/mal/mal_profiler.c
+++ b/monetdb5/mal/mal_profiler.c
@@ -751,7 +751,8 @@ str
 stopProfiler(Client cntxt)
 {
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to