Do you have a planned use for it? I'm more interested in infrastructure improvements when there's a use case.
On Wed, Oct 12, 2016 at 04:33:21PM +0300, Ilya Maximets wrote: > Hi, Ben. > > So, what about this patch? It's still not in mail-list, I guess, > and still applicable. > > Best regards, Ilya Maximets. > > On 15.07.2016 15:44, Ilya Maximets wrote: > > New functions 'fat_rwlock_{up,down}grade()' introduced to allow > > upgrading read-lock to write-lock and downgrading it back. > > > > Signed-off-by: Ilya Maximets <i.maxim...@samsung.com> > > --- > > Version 4: > > * Added detailed describtion of rwlock states and possible > > operations in each state. > > > > Version 3: > > * First version of this patch. > > > > lib/fat-rwlock.c | 56 > > ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- > > lib/fat-rwlock.h | 33 +++++++++++++++++++++++++++++++++ > > 2 files changed, 87 insertions(+), 2 deletions(-) > > > > diff --git a/lib/fat-rwlock.c b/lib/fat-rwlock.c > > index 2f42b05..86a4693 100644 > > --- a/lib/fat-rwlock.c > > +++ b/lib/fat-rwlock.c > > @@ -53,10 +53,13 @@ struct fat_rwlock_slot { > > * > > * - UINT_MAX: This thread has the write-lock on 'rwlock' and holds > > * 'mutex' (plus the 'mutex' of all of 'rwlock''s other slots). > > + * 'upgrade_depth' means the depth of read-lock on which it was > > + * upgraded to write-lock. > > * > > * Accessed only by the slot's own thread, so no synchronization is > > * needed. */ > > unsigned int depth; > > + unsigned int upgrade_depth; > > }; > > > > static void > > @@ -127,6 +130,7 @@ fat_rwlock_get_slot__(struct fat_rwlock *rwlock) > > slot->rwlock = rwlock; > > ovs_mutex_init(&slot->mutex); > > slot->depth = 0; > > + slot->upgrade_depth = 0; > > > > ovs_mutex_lock(&rwlock->mutex); > > ovs_list_push_back(&rwlock->threads, &slot->list_node); > > @@ -236,6 +240,7 @@ fat_rwlock_wrlock(const struct fat_rwlock *rwlock_) > > > > ovs_assert(!this->depth); > > this->depth = UINT_MAX; > > + this->upgrade_depth = 1; > > > > ovs_mutex_lock(&rwlock->mutex); > > LIST_FOR_EACH (slot, list_node, &rwlock->threads) { > > @@ -257,11 +262,13 @@ fat_rwlock_unlock(const struct fat_rwlock *rwlock_) > > > > switch (this->depth) { > > case UINT_MAX: > > + this->depth = this->upgrade_depth - 1; > > LIST_FOR_EACH (slot, list_node, &rwlock->threads) { > > - ovs_mutex_unlock(&slot->mutex); > > + if (slot != this || this->depth == 0) { > > + ovs_mutex_unlock(&slot->mutex); > > + } > > } > > ovs_mutex_unlock(&rwlock->mutex); > > - this->depth = 0; > > break; > > > > case 0: > > @@ -275,3 +282,48 @@ fat_rwlock_unlock(const struct fat_rwlock *rwlock_) > > break; > > } > > } > > + > > +/* Upgrades last taken read-lock to write-lock. > > + * Not thread-safe with 'fat_rwlock_wrlock' and concurrent upgrades. */ > > +void > > +fat_rwlock_upgrade(const struct fat_rwlock *rwlock_) > > + OVS_NO_THREAD_SAFETY_ANALYSIS > > +{ > > + struct fat_rwlock *rwlock = CONST_CAST(struct fat_rwlock *, rwlock_); > > + struct fat_rwlock_slot *this = fat_rwlock_get_slot__(rwlock); > > + struct fat_rwlock_slot *slot; > > + > > + ovs_assert(this->depth && this->depth != UINT_MAX); > > + > > + this->upgrade_depth = this->depth; > > + this->depth = UINT_MAX; > > + > > + ovs_mutex_lock(&rwlock->mutex); > > + LIST_FOR_EACH (slot, list_node, &rwlock->threads) { > > + if (slot != this) { > > + ovs_mutex_lock(&slot->mutex); > > + } > > + } > > +} > > + > > +/* Downgrades write-lock to read-lock. */ > > +void > > +fat_rwlock_downgrade(const struct fat_rwlock *rwlock_) > > + OVS_NO_THREAD_SAFETY_ANALYSIS > > +{ > > + struct fat_rwlock *rwlock = CONST_CAST(struct fat_rwlock *, rwlock_); > > + struct fat_rwlock_slot *this = fat_rwlock_get_slot__(rwlock); > > + struct fat_rwlock_slot *slot; > > + > > + ovs_assert(this->depth == UINT_MAX); > > + > > + this->depth = this->upgrade_depth; > > + this->upgrade_depth = 0; > > + > > + LIST_FOR_EACH (slot, list_node, &rwlock->threads) { > > + if (slot != this) { > > + ovs_mutex_unlock(&slot->mutex); > > + } > > + } > > + ovs_mutex_unlock(&rwlock->mutex); > > +} > > diff --git a/lib/fat-rwlock.h b/lib/fat-rwlock.h > > index 181fa92..15514fc 100644 > > --- a/lib/fat-rwlock.h > > +++ b/lib/fat-rwlock.h > > @@ -46,4 +46,37 @@ int fat_rwlock_tryrdlock(const struct fat_rwlock *rwlock) > > void fat_rwlock_wrlock(const struct fat_rwlock *rwlock) > > OVS_ACQ_WRLOCK(rwlock); > > void fat_rwlock_unlock(const struct fat_rwlock *rwlock) > > OVS_RELEASES(rwlock); > > > > +/* > > + * Following functions used to upgrade last taken read-lock to write-lock > > and > > + * downgrade it back to read-lock. Upgrading/downgrading doesn't change > > depth > > + * of recursive locking. > > + * > > + * Detailed description: > > + * > > ----------------------------------------------------------------------------- > > + * STATE | POSSIBLE OPERATION | RESULTED STATE > > + * > > ----------------------------------------------------------------------------- > > + * unlocked fat_rwlock_rdlock read-locked with depth > > = 1 > > + * fat_rwlock_wrlock write-locked with > > depth = 1 > > + * > > + * read-locked with depth = 1 fat_rwlock_rdlock read-locked with depth > > = 2 > > + * fat_rwlock_unlock unlocked > > + * fat_rwlock_upgrade write-locked with > > depth = 1 > > + * > > + * read-locked with depth = N fat_rwlock_rdlock read-locked with depth > > = N+1 > > + * fat_rwlock_unlock read-locked with depth > > = N-1 > > + * fat_rwlock_upgrade write-locked with > > depth = N > > + * > > + * write-locked with depth = 1 fat_rwlock_unlock unlocked > > + * fat_rwlock_downgrade read-locked with depth > > = 1 > > + * > > + * write-locked with depth = N fat_rwlock_unlock read-locked with depth > > = N-1 > > + * fat_rwlock_downgrade read-locked with depth > > = N > > + * > > ----------------------------------------------------------------------------- > > + * > > + * Upgrading is NOT thread-safe operation, so, the caller must be sure that > > + * it is the only thread that wants to acquire write-lock. > > + */ > > +void fat_rwlock_upgrade(const struct fat_rwlock *rwlock); > > +void fat_rwlock_downgrade(const struct fat_rwlock *rwlock); > > + > > #endif /* fat-rwlock.h */ > > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev