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 -- [email protected]
To unsubscribe send an email to [email protected]