sxstate sx_commit(sx *t) { assert(t->s == SXPREPARE); if (t->complete) goto complete; ssiter i; ss_iterinit(ss_bufiter, &i); ss_iteropen(ss_bufiter, &i, &t->log.buf, sizeof(svlogv)); for (; ss_iterhas(ss_bufiter, &i); ss_iternext(ss_bufiter, &i)) { svlogv *lv = ss_iterof(ss_bufiter, &i); sxv *v = lv->v.v; /* mark waiters as aborted */ sx_vabortwaiters(v); /* remove from concurrent index and replace * head with a first waiter */ sxindex *i = v->index; if (v->next == NULL) ss_rbremove(&i->i, &v->node); else ss_rbreplace(&i->i, &v->node, &v->next->node); /* unlink version */ sx_vunlink(v); /* translate log version from sxv to svv */ sv_init(&lv->v, &sv_vif, v->v, NULL); lv->vgc = v; } complete: t->s = SXCOMMIT; sx_end(t); return SXCOMMIT; }
static inline void sx_rollback_index(sx *t, int translate) { ssiter i; ss_iterinit(ss_bufiter, &i); ss_iteropen(ss_bufiter, &i, &t->log.buf, sizeof(svlogv)); for (; ss_iterhas(ss_bufiter, &i); ss_iternext(ss_bufiter, &i)) { svlogv *lv = ss_iterof(ss_bufiter, &i); sxv *v = lv->v.v; /* remove from index and replace head with * a first waiter */ if (v->prev) goto unlink; sxindex *i = v->index; if (v->next == NULL) ss_rbremove(&i->i, &v->node); else ss_rbreplace(&i->i, &v->node, &v->next->node); unlink: sx_vunlink(v); /* translate log version from sxv to svv */ if (translate) { sv_init(&lv->v, &sv_vif, v->v, NULL); lv->vgc = v; } } }
static inline void sx_end(sx *t) { sxmanager *m = t->manager; ss_spinlock(&m->lock); ss_rbremove(&m->i, &t->node); m->count--; ss_spinunlock(&m->lock); }
static inline void sx_end(sx *x) { sxmanager *m = x->manager; ss_spinlock(&m->lock); ss_rbremove(&m->i, &x->node); if (x->type == SXRO) m->count_rd--; else m->count_rw--; ss_spinunlock(&m->lock); }
static inline void sx_untrack(sxv *v) { if (v->prev == NULL) { sxindex *i = v->index; if (v->next == NULL) ss_rbremove(&i->i, &v->node); else ss_rbreplace(&i->i, &v->node, &v->next->node); } sx_vunlink(v); }