Changeset: 685daba84b0a for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/685daba84b0a Modified Files: gdk/gdk.h gdk/gdk_align.c gdk/gdk_bat.c gdk/gdk_batop.c gdk/gdk_bbp.c gdk/gdk_hash.c gdk/gdk_hash.h gdk/gdk_imprints.c gdk/gdk_join.c gdk/gdk_logger.c gdk/gdk_logger_old.c gdk/gdk_orderidx.c gdk/gdk_select.c monetdb5/mal/mal_authorize.c monetdb5/modules/mal/tokenizer.c Branch: default Log Message:
Use read-write locks for indexes (only really used in hash). This is somewhat experimental: we need to test the impact of this change. The change not only involves using read-write locks, but also using the parent bats for hashes in select and join (different from before) and ignoring the dirty bit on persistent bats for deciding whether to build a hash on the bat. diffs (truncated from 1014 to 300 lines): diff --git a/gdk/gdk.h b/gdk/gdk.h --- a/gdk/gdk.h +++ b/gdk/gdk.h @@ -772,7 +772,7 @@ typedef struct BAT { COLrec T; /* column info */ MT_Lock theaplock; /* lock protecting heap reference changes */ - MT_Lock batIdxLock; /* lock to manipulate indexes */ + MT_RWLock batIdxLock; /* lock to manipulate indexes */ } BAT; typedef struct BATiter { diff --git a/gdk/gdk_align.c b/gdk/gdk_align.c --- a/gdk/gdk_align.c +++ b/gdk/gdk_align.c @@ -142,7 +142,7 @@ VIEWcreate(oid seq, BAT *b) } HEAPdecref(bn->theap, false); MT_lock_destroy(&bn->theaplock); - MT_lock_destroy(&bn->batIdxLock); + MT_rwlock_destroy(&bn->batIdxLock); GDKfree(bn); return NULL; } diff --git a/gdk/gdk_bat.c b/gdk/gdk_bat.c --- a/gdk/gdk_bat.c +++ b/gdk/gdk_bat.c @@ -142,7 +142,7 @@ BATcreatedesc(oid hseq, int tt, bool hea snprintf(name, sizeof(name), "heaplock%d", bn->batCacheid); /* fits */ MT_lock_init(&bn->theaplock, name); snprintf(name, sizeof(name), "BATlock%d", bn->batCacheid); /* fits */ - MT_lock_init(&bn->batIdxLock, name); + MT_rwlock_init(&bn->batIdxLock, name); bn->batDirtydesc = true; return bn; bailout: @@ -247,7 +247,7 @@ COLnew(oid hseq, int tt, BUN cap, role_t if (bn->tvheap) HEAPdecref(bn->tvheap, true); MT_lock_destroy(&bn->theaplock); - MT_lock_destroy(&bn->batIdxLock); + MT_rwlock_destroy(&bn->batIdxLock); GDKfree(bn); return NULL; } @@ -631,7 +631,7 @@ BATdestroy(BAT *b) GDKfree(b->tvheap); PROPdestroy(b); MT_lock_destroy(&b->theaplock); - MT_lock_destroy(&b->batIdxLock); + MT_rwlock_destroy(&b->batIdxLock); GDKfree(b->theap); GDKfree(b); } diff --git a/gdk/gdk_batop.c b/gdk/gdk_batop.c --- a/gdk/gdk_batop.c +++ b/gdk/gdk_batop.c @@ -1835,12 +1835,12 @@ BATordered(BAT *b) if (b->tnosorted > 0 || !ATOMlinear(b->ttype)) return false; - /* In order that multiple threads don't scan the same BAT at - * the same time (happens a lot with mitosis/mergetable), we - * use a lock. We reuse the hash lock for this, not because - * this scanning interferes with hashes, but because it's - * there, and not so likely to be used at the same time. */ - MT_lock_set(&b->batIdxLock); + /* In order that multiple threads don't scan the same BAT at the + * same time (happens a lot with mitosis/mergetable), we use a + * lock. We reuse the theaplock lock for this, not because this + * scanning interferes with heap reference counting, but because + * it's there, and not so likely to be used at the same time. */ + MT_lock_set(&b->theaplock); if (!b->tsorted && b->tnosorted == 0) { b->batDirtydesc = true; switch (ATOMbasetype(b->ttype)) { @@ -1907,7 +1907,7 @@ BATordered(BAT *b) } } doreturn: - MT_lock_unset(&b->batIdxLock); + MT_lock_unset(&b->theaplock); return b->tsorted; } @@ -1953,7 +1953,7 @@ BATordered_rev(BAT *b) return is_oid_nil(b->tseqbase); if (BATtdense(b) || b->tnorevsorted > 0) return false; - MT_lock_set(&b->batIdxLock); + MT_lock_set(&b->theaplock); if (!b->trevsorted && b->tnorevsorted == 0) { b->batDirtydesc = true; switch (ATOMbasetype(b->ttype)) { @@ -1997,7 +1997,7 @@ BATordered_rev(BAT *b) TRC_DEBUG(ALGO, "Fixed revsorted for " ALGOBATFMT " (" LLFMT " usec)\n", ALGOBATPAR(b), GDKusec() - t0); } doreturn: - MT_lock_unset(&b->batIdxLock); + MT_lock_unset(&b->theaplock); return b->trevsorted; } @@ -2204,7 +2204,7 @@ BATsort(BAT **sorted, BAT **order, BAT * mkorderidx = (g == NULL && !reverse && !nilslast && pb != NULL && (order || !pb->batTransient)); if (g == NULL && !reverse && !nilslast && pb != NULL && !BATcheckorderidx(pb)) { - MT_lock_set(&pb->batIdxLock); + MT_rwlock_wrlock(&pb->batIdxLock); if (pb->torderidx == NULL) { /* no index created while waiting for lock */ if (mkorderidx) /* keep lock when going to create */ @@ -2214,7 +2214,7 @@ BATsort(BAT **sorted, BAT **order, BAT * mkorderidx = false; } if (!orderidxlock) - MT_lock_unset(&pb->batIdxLock); + MT_rwlock_wrunlock(&pb->batIdxLock); } else { mkorderidx = false; } @@ -2441,7 +2441,7 @@ BATsort(BAT **sorted, BAT **order, BAT * GDKfree(m); } if (orderidxlock) - MT_lock_unset(&pb->batIdxLock); + MT_rwlock_wrunlock(&pb->batIdxLock); goto error; } bn->tsorted = !reverse && !nilslast; @@ -2464,7 +2464,7 @@ BATsort(BAT **sorted, BAT **order, BAT * } } if (orderidxlock) - MT_lock_unset(&pb->batIdxLock); + MT_rwlock_wrunlock(&pb->batIdxLock); bn->theap->dirty = true; bn->tnosorted = 0; bn->tnorevsorted = 0; @@ -2723,7 +2723,7 @@ BATgetprop(BAT *b, enum prop_t idx) { PROPrec *p; - MT_lock_set(&b->batIdxLock); + MT_rwlock_wrlock(&b->batIdxLock); p = BATgetprop_nolock(b, idx); if (p == NULL) { /* if looking for the min/max value, we may be able to @@ -2747,7 +2747,7 @@ BATgetprop(BAT *b, enum prop_t idx) break; } } - MT_lock_unset(&b->batIdxLock); + MT_rwlock_wrunlock(&b->batIdxLock); return p; } @@ -2755,18 +2755,18 @@ PROPrec * BATsetprop(BAT *b, enum prop_t idx, int type, const void *v) { PROPrec *p; - MT_lock_set(&b->batIdxLock); + MT_rwlock_wrlock(&b->batIdxLock); p = BATsetprop_nolock(b, idx, type, v); - MT_lock_unset(&b->batIdxLock); + MT_rwlock_wrunlock(&b->batIdxLock); return p; } void BATrmprop(BAT *b, enum prop_t idx) { - MT_lock_set(&b->batIdxLock); + MT_rwlock_wrlock(&b->batIdxLock); BATrmprop_nolock(b, idx); - MT_lock_unset(&b->batIdxLock); + MT_rwlock_wrunlock(&b->batIdxLock); } diff --git a/gdk/gdk_bbp.c b/gdk/gdk_bbp.c --- a/gdk/gdk_bbp.c +++ b/gdk/gdk_bbp.c @@ -647,7 +647,7 @@ BBPreadEntries(FILE *fp, unsigned bbpver snprintf(name, sizeof(name), "heaplock%d", bn->batCacheid); /* fits */ MT_lock_init(&bn->theaplock, name); snprintf(name, sizeof(name), "BATlock%d", bn->batCacheid); /* fits */ - MT_lock_init(&bn->batIdxLock, name); + MT_rwlock_init(&bn->batIdxLock, name); ATOMIC_INIT(&bn->theap->refs, 1); if (base > (uint64_t) GDK_oid_max) { diff --git a/gdk/gdk_hash.c b/gdk/gdk_hash.c --- a/gdk/gdk_hash.c +++ b/gdk/gdk_hash.c @@ -429,7 +429,7 @@ BATcheckhash(BAT *b) if (b->thash == (Hash *) 1) { /* but when we want to change it, we need the lock */ TRC_DEBUG_IF(ACCELERATOR) t = GDKusec(); - MT_lock_set(&b->batIdxLock); + MT_rwlock_wrlock(&b->batIdxLock); TRC_DEBUG_IF(ACCELERATOR) t = GDKusec() - t; /* if still 1 now that we have the lock, we can update */ if (b->thash == (Hash *) 1) { @@ -536,7 +536,7 @@ BATcheckhash(BAT *b) b->thash = h; TRC_DEBUG(ACCELERATOR, ALGOBATFMT ": reusing persisted hash\n", ALGOBATPAR(b)); - MT_lock_unset(&b->batIdxLock); + MT_rwlock_wrunlock(&b->batIdxLock); return true; } /* if h->nil==h->nbucket @@ -568,7 +568,7 @@ BATcheckhash(BAT *b) GDKfree(h); GDKclrerr(); /* we're not currently interested in errors */ } - MT_lock_unset(&b->batIdxLock); + MT_rwlock_wrunlock(&b->batIdxLock); } ret = b->thash != NULL; if (ret) @@ -655,9 +655,9 @@ BAThashsync(void *arg) /* we could check whether b->thash == NULL before getting the * lock, and only lock if it isn't; however, it's very * unlikely that that is the case, so we don't */ - MT_lock_set(&b->batIdxLock); + MT_rwlock_rdlock(&b->batIdxLock); BAThashsave(b, true); - MT_lock_unset(&b->batIdxLock); + MT_rwlock_rdunlock(&b->batIdxLock); BBPunfix(b->batCacheid); } #endif @@ -1002,12 +1002,12 @@ BAThash(BAT *b) if (BATcheckhash(b)) { return GDK_SUCCEED; } - MT_lock_set(&b->batIdxLock); + MT_rwlock_wrlock(&b->batIdxLock); if (b->thash == NULL) { struct canditer ci; canditer_init(&ci, b, NULL); if ((b->thash = BAThash_impl(b, &ci, "thash")) == NULL) { - MT_lock_unset(&b->batIdxLock); + MT_rwlock_wrunlock(&b->batIdxLock); return GDK_FAIL; } #ifdef PERSISTENTHASH @@ -1016,7 +1016,7 @@ BAThash(BAT *b) BBPfix(b->batCacheid); char name[MT_NAME_LEN]; snprintf(name, sizeof(name), "hashsync%d", b->batCacheid); - MT_lock_unset(&b->batIdxLock); + MT_rwlock_wrunlock(&b->batIdxLock); if (MT_create_thread(&tid, BAThashsync, b, MT_THR_DETACHED, name) < 0) { @@ -1029,7 +1029,7 @@ BAThash(BAT *b) "NOT persisting hash %d\n", b->batCacheid); #endif } - MT_lock_unset(&b->batIdxLock); + MT_rwlock_wrunlock(&b->batIdxLock); return GDK_SUCCEED; } @@ -1115,9 +1115,9 @@ HASHappend_locked(BAT *b, BUN i, const v void HASHappend(BAT *b, BUN i, const void *v) { - MT_lock_set(&b->batIdxLock); + MT_rwlock_wrlock(&b->batIdxLock); HASHappend_locked(b, i, v); - MT_lock_unset(&b->batIdxLock); + MT_rwlock_wrunlock(&b->batIdxLock); } /* insert value v at position p into the hash table of b */ @@ -1186,9 +1186,9 @@ HASHinsert_locked(BAT *b, BUN p, const v void HASHinsert(BAT *b, BUN p, const void *v) { - MT_lock_set(&b->batIdxLock); + MT_rwlock_wrlock(&b->batIdxLock); HASHinsert_locked(b, p, v); - MT_lock_unset(&b->batIdxLock); + MT_rwlock_wrunlock(&b->batIdxLock); } /* delete value v at position p from the hash table of b */ @@ -1258,9 +1258,9 @@ HASHdelete_locked(BAT *b, BUN p, const v void HASHdelete(BAT *b, BUN p, const void *v) { - MT_lock_set(&b->batIdxLock); + MT_rwlock_wrlock(&b->batIdxLock); HASHdelete_locked(b, p, v); - MT_lock_unset(&b->batIdxLock); + MT_rwlock_wrunlock(&b->batIdxLock); _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list