Module: xenomai-3 Branch: next Commit: 383e8ed5659076771c393a0f1aabb6da8c6b959b URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=383e8ed5659076771c393a0f1aabb6da8c6b959b
Author: Philippe Gerum <r...@xenomai.org> Date: Sun Mar 15 13:02:55 2015 +0100 copperplate: fix synchronization with shared clusters The inter-process synchronization can only work if the syncobj is shared between processes. Add a dictionary object type with an embedded syncobj for implementing shared clusters. --- include/copperplate/cluster.h | 9 ++++- lib/copperplate/cluster.c | 87 ++++++++++++++++++++++++++--------------- 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/include/copperplate/cluster.h b/include/copperplate/cluster.h index 0f75690..9c76cbc 100644 --- a/include/copperplate/cluster.h +++ b/include/copperplate/cluster.h @@ -39,9 +39,14 @@ struct cluster { struct dictionary *d; }; +struct syndictionary { + struct hash_table table; + struct syncobj sobj; + struct hashobj hobj; +}; + struct syncluster { - struct cluster c; - struct syncobj *sobj; + struct syndictionary *d; }; struct pvclusterobj { diff --git a/lib/copperplate/cluster.c b/lib/copperplate/cluster.c index 0dda986..7353aa8 100644 --- a/lib/copperplate/cluster.c +++ b/lib/copperplate/cluster.c @@ -139,20 +139,18 @@ redo: } d = xnmalloc(sizeof(*d)); - if (d == NULL) { - ret = -ENOMEM; - goto out; - } + if (d == NULL) + return __bt(-ENOMEM); hash_init(&d->table); ret = hash_enter(&main_catalog, name, strlen(name), &d->hobj, &hash_operations); + /* + * If someone managed to slip in, creating the cluster between + * the table look up and indexing the new cluster, retry the + * whole process. + */ if (ret == -EEXIST) { - /* - * Someone seems to have slipped in, creating the - * cluster right after we failed retrieving it: retry - * the whole process. - */ hash_destroy(&d->table); xnfree(d); goto redo; @@ -249,17 +247,40 @@ int cluster_walk(struct cluster *c, int syncluster_init(struct syncluster *sc, const char *name) { + struct syndictionary *d; + struct hashobj *hobj; int ret; - ret = __bt(cluster_init(&sc->c, name)); - if (ret) - return ret; +redo: + hobj = hash_search(&main_catalog, name, strlen(name), + &hash_operations); + if (hobj) { + d = container_of(hobj, struct syndictionary, hobj); + ret = 0; + goto out; + } - sc->sobj = xnmalloc(sizeof(*sc->sobj)); - if (sc->sobj == NULL) + d = xnmalloc(sizeof(*d)); + if (d == NULL) return -ENOMEM; - return syncobj_init(sc->sobj, CLOCK_COPPERPLATE, + hash_init(&d->table); + + ret = hash_enter(&main_catalog, name, strlen(name), &d->hobj, + &hash_operations); + /* + * Same as cluster_init(), redo if someone slipped in, + * creating the cluster. + */ + if (ret == -EEXIST) { + hash_destroy(&d->table); + xnfree(d); + goto redo; + } +out: + sc->d = d; + + return syncobj_init(&d->sobj, CLOCK_COPPERPLATE, SYNCOBJ_FIFO, fnref_null); } @@ -271,26 +292,29 @@ int syncluster_addobj(struct syncluster *sc, const char *name, struct syncstate syns; int ret; - if (syncobj_lock(sc->sobj, &syns)) + if (syncobj_lock(&sc->d->sobj, &syns)) return __bt(-EINVAL); - ret = cluster_addobj(&sc->c, name, cobj); + cobj->cnode = __node_id; + + ret = hash_enter_probe(&sc->d->table, name, strlen(name), + &cobj->hobj, &hash_operations); if (ret) goto out; - if (!syncobj_grant_wait_p(sc->sobj)) + if (!syncobj_grant_wait_p(&sc->d->sobj)) goto out; /* * Wake up all threads waiting for this key to appear in the * dictionary. */ - syncobj_for_each_grant_waiter_safe(sc->sobj, thobj, tmp) { + syncobj_for_each_grant_waiter_safe(&sc->d->sobj, thobj, tmp) { wait = threadobj_get_wait(thobj); if (*wait->name == *name && strcmp(wait->name, name) == 0) - syncobj_grant_to(sc->sobj, thobj); + syncobj_grant_to(&sc->d->sobj, thobj); } out: - syncobj_unlock(sc->sobj, &syns); + syncobj_unlock(&sc->d->sobj, &syns); return ret; } @@ -301,12 +325,12 @@ int syncluster_delobj(struct syncluster *sc, struct syncstate syns; int ret; - if (syncobj_lock(sc->sobj, &syns)) + if (syncobj_lock(&sc->d->sobj, &syns)) return __bt(-EINVAL); - ret = __bt(cluster_delobj(&sc->c, cobj)); + ret = __bt(hash_remove(&sc->d->table, &cobj->hobj, &hash_operations)); - syncobj_unlock(sc->sobj, &syns); + syncobj_unlock(&sc->d->sobj, &syns); return ret; } @@ -317,17 +341,18 @@ int syncluster_findobj(struct syncluster *sc, struct clusterobj **cobjp) { struct syncluster_wait_struct *wait = NULL; - struct clusterobj *cobj; struct syncstate syns; + struct hashobj *hobj; int ret = 0; - if (syncobj_lock(sc->sobj, &syns)) + if (syncobj_lock(&sc->d->sobj, &syns)) return -EINVAL; for (;;) { - cobj = cluster_findobj(&sc->c, name); - if (cobj) { - *cobjp = cobj; + hobj = hash_search_probe(&sc->d->table, name, strlen(name), + &hash_operations); + if (hobj) { + *cobjp = container_of(hobj, struct clusterobj, hobj); break; } if (timeout && @@ -343,7 +368,7 @@ int syncluster_findobj(struct syncluster *sc, wait = threadobj_prepare_wait(struct syncluster_wait_struct); wait->name = name; } - ret = syncobj_wait_grant(sc->sobj, timeout, &syns); + ret = syncobj_wait_grant(&sc->d->sobj, timeout, &syns); if (ret) { if (ret == -EIDRM) goto out; @@ -351,7 +376,7 @@ int syncluster_findobj(struct syncluster *sc, } } - syncobj_unlock(sc->sobj, &syns); + syncobj_unlock(&sc->d->sobj, &syns); out: if (wait) threadobj_finish_wait(); _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git