Changeset: a1850d0d9fc4 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/a1850d0d9fc4
Modified Files:
        sql/backends/monet5/sql_gencode.c
        sql/include/sql_catalog.h
        sql/storage/sql_storage.h
        sql/storage/store.c
Branch: Jan2022
Log Message:

Use instantiation lock per function. If the locks are shared, a dealock can 
occur


diffs (197 lines):

diff --git a/sql/backends/monet5/sql_gencode.c 
b/sql/backends/monet5/sql_gencode.c
--- a/sql/backends/monet5/sql_gencode.c
+++ b/sql/backends/monet5/sql_gencode.c
@@ -1107,7 +1107,7 @@ backend_create_mal_func(mvc *m, sql_func
 {
        if (f->instantiated)
                return 0;
-       lock_function(m->store, f->base.id);
+       MT_lock_set(&f->function_lock);
        if (!f->instantiated) {
                char *F = NULL, *fn = NULL;
                bit side_effect = f->side_effect;
@@ -1117,29 +1117,29 @@ backend_create_mal_func(mvc *m, sql_func
                (void) F;
                if (strlen(f->mod) >= IDLENGTH) {
                        (void) sql_error(m, 01, SQLSTATE(42000) "MAL module 
name '%s' too large for the backend", f->mod);
-                       unlock_function(m->store, f->base.id);
+                       MT_lock_unset(&f->function_lock);
                        return -1;
                }
                if (mal_function_find_implementation_address(m, f) < 0) {
-                       unlock_function(m->store, f->base.id);
+                       MT_lock_unset(&f->function_lock);
                        return -1;
                }
                if (!backend_resolve_function(&clientid, f)) {
                        (void) sql_error(m, 02, SQLSTATE(3F000) "MAL external 
name %s.%s not bound (%s.%s)", f->mod, f->imp, f->s->base.name, f->base.name);
                        _DELETE(f->imp);
-                       unlock_function(m->store, f->base.id);
+                       MT_lock_unset(&f->function_lock);
                        return -1;
                }
                if (side_effect != f->side_effect) {
                        (void) sql_error(m, 02, SQLSTATE(42000) "Side-effect 
value from the SQL %s %s.%s doesn't match the MAL definition %s.%s\n"
                                                         "Either re-create the 
%s, or fix the MAL definition and restart the database", fn, f->s->base.name, 
f->base.name, f->mod, f->imp, fn);
                        _DELETE(f->imp);
-                       unlock_function(m->store, f->base.id);
+                       MT_lock_unset(&f->function_lock);
                        return -1;
                }
                f->instantiated = TRUE; /* make sure 'instantiated' gets set 
after 'imp' */
        }
-       unlock_function(m->store, f->base.id);
+       MT_lock_unset(&f->function_lock);
        return 0;
 }
 
@@ -1153,7 +1153,7 @@ backend_create_sql_func(backend *be, sql
        if (f->instantiated || (m->forward && m->forward->base.id == 
f->base.id))
                return res;
 
-       lock_function(m->store, f->base.id);
+       MT_lock_set(&f->function_lock);
        if (!f->instantiated) {
                MalBlkPtr curBlk = NULL;
                InstrPtr curInstr = NULL;
@@ -1171,7 +1171,7 @@ backend_create_sql_func(backend *be, sql
                if (r)
                        r = sql_processrelation(m, r, 1, 1, 0);
                if (!r) {
-                       unlock_function(m->store, f->base.id);
+                       MT_lock_unset(&f->function_lock);
                        return -1;
                }
 
@@ -1179,7 +1179,7 @@ backend_create_sql_func(backend *be, sql
                /* for debug builds we keep the SQL function name in the MAL 
function name to make it easy to debug */
                if (strlen(f->base.name) + 21 >= IDLENGTH) { /* 20 bits for u64 
number + '%' */
                        (void) sql_error(m, 01, SQLSTATE(42000) "MAL function 
name '%s' too large for the backend", f->base.name);
-                       unlock_function(m->store, f->base.id);
+                       MT_lock_unset(&f->function_lock);
                        return -1;
                }
                (void) snprintf(befname, IDLENGTH, "%%" LLFMT "%s", 
store_function_counter(m->store), f->base.name);
@@ -1334,7 +1334,7 @@ cleanup:
                memcpy(be, &bebackup, sizeof(backend));
                c->curprg = symbackup;
        }
-       unlock_function(m->store, f->base.id);
+       MT_lock_unset(&f->function_lock);
        return res;
 }
 
diff --git a/sql/include/sql_catalog.h b/sql/include/sql_catalog.h
--- a/sql/include/sql_catalog.h
+++ b/sql/include/sql_catalog.h
@@ -516,6 +516,7 @@ typedef struct sql_func {
                        */
        sql_schema *s;
        sql_allocator *sa;
+       MT_Lock function_lock; /* protecting concurrent function 
instantiations. Only used in MAL and SQL functions */
 } sql_func;
 
 typedef struct sql_subfunc {
diff --git a/sql/storage/sql_storage.h b/sql/storage/sql_storage.h
--- a/sql/storage/sql_storage.h
+++ b/sql/storage/sql_storage.h
@@ -335,8 +335,6 @@ extern lng store_hot_snapshot(struct sql
 extern lng store_hot_snapshot_to_stream(struct sqlstore *store, stream *s);
 
 extern ulng store_function_counter(struct sqlstore *store);
-extern void lock_function(struct sqlstore *store, sqlid id);
-extern void unlock_function(struct sqlstore *store, sqlid id);
 
 extern ulng store_oldest(struct sqlstore *store);
 extern ulng store_get_timestamp(struct sqlstore *store);
@@ -461,7 +459,6 @@ extern int sql_trans_copy_key(sql_trans 
 extern int sql_trans_copy_idx(sql_trans *tr, sql_table *t, sql_idx *i, sql_idx 
**ires);
 extern int sql_trans_copy_trigger(sql_trans *tr, sql_table *t, sql_trigger 
*tri, sql_trigger **tres);
 
-#define NR_FUNCTION_LOCKS 16
 #define NR_TABLE_LOCKS 64
 #define NR_COLUMN_LOCKS 512
 #define TRANSACTION_ID_BASE    (1ULL<<63)
@@ -473,7 +470,6 @@ typedef struct sqlstore {
        MT_Lock lock;                   /* lock protecting concurrent writes 
(not reads, ie use rcu) */
        MT_Lock commit;                 /* protect transactions, only single 
commit (one wal writer) */
        MT_Lock flush;                  /* flush lock protecting concurrent 
writes (not reads, ie use rcu) */
-       MT_Lock function_locks[NR_FUNCTION_LOCKS];              /* protecting 
concurrent function instantiations */
        MT_Lock table_locks[NR_TABLE_LOCKS];            /* protecting 
concurrent writes to tables (storage) */
        MT_Lock column_locks[NR_COLUMN_LOCKS];          /* protecting 
concurrent writes to columns (storage) */
        list *active;                   /* list of running transactions */
diff --git a/sql/storage/store.c b/sql/storage/store.c
--- a/sql/storage/store.c
+++ b/sql/storage/store.c
@@ -30,18 +30,6 @@ store_function_counter(sqlstore *store)
        return ts;
 }
 
-void
-lock_function(sqlstore *store, sqlid id)
-{
-       MT_lock_set(&store->function_locks[id&(NR_FUNCTION_LOCKS-1)]);
-}
-
-void
-unlock_function(sqlstore *store, sqlid id)
-{
-       MT_lock_unset(&store->function_locks[id&(NR_FUNCTION_LOCKS-1)]);
-}
-
 static ulng
 store_timestamp(sqlstore *store)
 {
@@ -128,6 +116,8 @@ func_destroy(sqlstore *store, sql_func *
                /* clean backend code */
                backend_freecode(sql_shared_module_name, 0, f->imp);
        }
+       if (f->lang == FUNC_LANG_SQL || f->lang == FUNC_LANG_MAL)
+               MT_lock_destroy(&f->function_lock);
        if (f->res)
                list_destroy2(f->res, store);
        list_destroy2(f->ops, store);
@@ -948,6 +938,8 @@ load_func(sql_trans *tr, sql_schema *s, 
        t->s = s;
        t->fix_scale = SCALE_EQ;
        t->sa = tr->sa;
+       if (!t->instantiated)
+               MT_lock_init(&t->function_lock, "function_lock");
        if (t->lang != FUNC_LANG_INT) {
                t->query = t->imp;
                t->imp = NULL;
@@ -2102,8 +2094,6 @@ store_init(int debug, store_type store_t
        MT_lock_init(&store->lock, "sqlstore_lock");
        MT_lock_init(&store->commit, "sqlstore_commit");
        MT_lock_init(&store->flush, "sqlstore_flush");
-       for(int i = 0; i<NR_FUNCTION_LOCKS; i++)
-               MT_lock_init(&store->function_locks[i], "sqlstore_function");
        for(int i = 0; i<NR_TABLE_LOCKS; i++)
                MT_lock_init(&store->table_locks[i], "sqlstore_table");
        for(int i = 0; i<NR_COLUMN_LOCKS; i++)
@@ -3225,6 +3215,7 @@ func_dup(sql_trans *tr, sql_func *of, sq
        f->query = (of->query)?SA_STRDUP(sa, of->query):NULL;
        f->s = s;
        f->sa = sa;
+       MT_lock_init(&f->function_lock, "function_lock");
 
        f->ops = SA_LIST(sa, (fdestroy) &arg_destroy);
        for (node *n=of->ops->h; n; n = n->next)
@@ -4848,6 +4839,8 @@ create_sql_func(sqlstore *store, sql_all
        t->fix_scale = SCALE_EQ;
        t->s = NULL;
        t->system = system;
+       if (!t->instantiated)
+               MT_lock_init(&t->function_lock, "function_lock");
        return t;
 }
 
@@ -4885,6 +4878,8 @@ sql_trans_create_func(sql_func **fres, s
        }
        t->query = (query)?SA_STRDUP(tr->sa, query):NULL;
        t->s = s;
+       if (!t->instantiated)
+               MT_lock_init(&t->function_lock, "function_lock");
 
        if ((res = os_add(s->funcs, tr, t->base.name, &t->base)))
                return res;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to