ck_spinlock: Adopt RMO semantics for CLH.

ck_pring
Samy Al Bahra 12 years ago
parent 7ebbcf55b1
commit ce4cdd45c8

@ -586,7 +586,7 @@ ck_spinlock_mcs_unlock(struct ck_spinlock_mcs **queue, struct ck_spinlock_mcs *n
struct ck_spinlock_clh { struct ck_spinlock_clh {
unsigned int wait; unsigned int wait;
struct ck_spinlock_clh_thread *previous; struct ck_spinlock_clh *previous;
}; };
typedef struct ck_spinlock_clh ck_spinlock_clh_t; typedef struct ck_spinlock_clh ck_spinlock_clh_t;
@ -606,13 +606,16 @@ ck_spinlock_clh_lock(struct ck_spinlock_clh **queue, struct ck_spinlock_clh *thr
{ {
struct ck_spinlock_clh *previous; struct ck_spinlock_clh *previous;
/* Indicate to the next thread on queue that they will have to block. */
ck_pr_store_uint(&thread->wait, true); ck_pr_store_uint(&thread->wait, true);
ck_pr_fence_store();
/* Mark current request as last request. Save reference to previous request. */ /* Mark current request as last request. Save reference to previous request. */
previous = ck_pr_fas_ptr(queue, thread); previous = ck_pr_fas_ptr(queue, thread);
ck_pr_store_ptr(&thread->previous, previous); thread->previous = previous;
/* Wait until previous thread is done with lock. */ /* Wait until previous thread is done with lock. */
ck_pr_fence_load();
while (ck_pr_load_uint(&previous->wait) == true) while (ck_pr_load_uint(&previous->wait) == true)
ck_pr_stall(); ck_pr_stall();
@ -624,8 +627,6 @@ ck_spinlock_clh_unlock(struct ck_spinlock_clh **thread)
{ {
struct ck_spinlock_clh *previous; struct ck_spinlock_clh *previous;
ck_pr_fence_memory();
/* /*
* If there are waiters, they are spinning on the current node wait * If there are waiters, they are spinning on the current node wait
* flag. The flag is cleared so that the successor may complete an * flag. The flag is cleared so that the successor may complete an
@ -633,7 +634,10 @@ ck_spinlock_clh_unlock(struct ck_spinlock_clh **thread)
* may be updated by a successor's lock operation. In order to avoid * may be updated by a successor's lock operation. In order to avoid
* this, save a copy of the predecessor before setting the flag. * this, save a copy of the predecessor before setting the flag.
*/ */
previous = ck_pr_load_ptr(&(*thread)->previous); previous = thread[0]->previous;
/* We have to pay this cost anyways, use it as a compiler barrier too. */
ck_pr_fence_memory();
ck_pr_store_uint(&(*thread)->wait, false); ck_pr_store_uint(&(*thread)->wait, false);
/* /*
@ -641,7 +645,7 @@ ck_spinlock_clh_unlock(struct ck_spinlock_clh **thread)
* so update caller to use previous structure. This allows successor * so update caller to use previous structure. This allows successor
* all the time in the world to successfully read updated wait flag. * all the time in the world to successfully read updated wait flag.
*/ */
ck_pr_store_ptr(thread, previous); *thread = previous;
return; return;
} }
#endif /* CK_F_SPINLOCK_CLH */ #endif /* CK_F_SPINLOCK_CLH */

Loading…
Cancel
Save