Skip to content

Commit

Permalink
Revise DLFTT mutex locking protocol
Browse files Browse the repository at this point in the history
Signed-off-by: Quincey Koziol <[email protected]>
  • Loading branch information
qkoziol committed Dec 6, 2024
1 parent 23398a6 commit e42efba
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 13 deletions.
3 changes: 2 additions & 1 deletion src/H5TSdlftt_mutex.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ H5TS_dlftt_mutex_init(H5TS_dlftt_mutex_t *mutex)

if (H5_UNLIKELY(H5TS_mutex_init(&mutex->mtx, H5TS_MUTEX_TYPE_PLAIN)) < 0)
HGOTO_DONE(FAIL);
mutex->dlftt = 0;
mutex->bypass = false;
mutex->rc = 0;

done:
FUNC_LEAVE_NOAPI_NAMECHECK_ONLY(ret_value)
Expand Down
125 changes: 115 additions & 10 deletions src/H5TSdlftt_mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,78 @@ H5_DLL herr_t H5TS__get_dlftt(unsigned *dlftt);
*
* Purpose: Acquires the lock on a mutex, obeying the "DLFTT" protocol
*
* Note: Algorithm flowchart:
*
* .─────────.
* ( Start )
* `─────────' Acquire DLFTT Mutex
* │ -------------------
* ▼
* Λ
* ╱ ╲
* ╱ ╲
* ╱ ╲
* ╱ ╲
* ╱ ╲ N ┌────────────────┐
* ▕ bypass? ▏───────▶│Get DLFTT value │────────┐
* ╲ ╱ └────────────────┘ │
* ╲ ╱ │
* ╲ ╱ ▼
* ╲ ╱ Λ
* ╲ ╱ ╱ ╲
* V ╱ ╲
* Y │ ╱ ╲
* ▼ ╱ ╲
* ┌────────────┐ ┌───────────────┐ Y ╱ ╲
* │ ++refcount │◀────│ bypass = true │◀─────▕ DLFTT > 0?▏
* └────────────┘ └───────────────┘ ╲ ╱
* │ ╲ ╱
* │ ╲ ╱
* │ ╲ ╱
* │ ╲ ╱
* │ V
* │ N │
* │ ▼
* │ .─. ┌────────────┐
* └────────────────▶( X )◀──────────│ Lock mutex │
* `─' └────────────┘
* │
* ▼
* .─────────.
* ( End )
* `─────────'
*
* Return: Non-negative on success / Negative on failure
*
*--------------------------------------------------------------------------
*/
static inline herr_t
H5TS_dlftt_mutex_acquire(H5TS_dlftt_mutex_t *mtx)
{
/* Query the DLFTT value */
if (H5_UNLIKELY(H5TS__get_dlftt(&mtx->dlftt) < 0))
return FAIL;

/* Don't acquire the mutex if locking is disabled */
if (0 == mtx->dlftt)
/* Acquire the mutex */
if (H5_UNLIKELY(H5TS_mutex_lock(&mtx->mtx) < 0))
/* Check whether we are bypassing locking the mutex */
if (mtx->bypass)
/* Increment refcount */
mtx->rc++;
else {
unsigned dlftt = 0;

/* Query the DLFTT value */
if (H5_UNLIKELY(H5TS__get_dlftt(&dlftt) < 0))
return FAIL;

/* Acquire the mutex if locking is not disabled */
if (0 == dlftt) {
/* Acquire the mutex */
if (H5_UNLIKELY(H5TS_mutex_lock(&mtx->mtx) < 0))
return FAIL;
} /* end if */
else {
/* Indicate that lock should be bypassed */
mtx->bypass = true;
mtx->rc = 1;
} /* end else */
} /* end else */

return SUCCEED;
} /* end H5TS_dlftt_mutex_acquire() */

Expand All @@ -89,18 +144,68 @@ H5TS_dlftt_mutex_acquire(H5TS_dlftt_mutex_t *mtx)
*
* Purpose: Releases the lock on a mutex, obeying the "DLFTT" protocol
*
* Note: Algorithm flowchart:
*
* .─────────.
* ( Start )
* `─────────'
* │ Release DLFTT Mutex
* ▼ -------------------
* Λ
* ╱ ╲
* ╱ ╲
* ╱ ╲
* ╱ ╲
* ╱ ╲ Y ┌────────────┐
* ▕ bypass? ▏──▶│ --refcount │
* ╲ ╱ └────────────┘
* ╲ ╱ │
* ╲ ╱ ▼
* ╲ ╱ Λ
* ╲ ╱ ╱ ╲
* V ╱ ╲
* N │ ╱ ╲
* ▼ ╱ ╲
* ┌────────────┐ ╱refcount ╲ Y ┌───────────────┐
* │Unlock mutex│ ▕ == 0? ▏──▶│bypass = false │
* └────────────┘ ╲ ╱ └───────────────┘
* │ ╲ ╱ │
* │ ╲ ╱ │
* │ ╲ ╱ │
* │ ╲ ╱ │
* │ V │
* │ N │ │
* │ ▼ │
* │ .─. │
* └─────────────▶( X )◀──────────────┘
* `─'
* │
* ▼
* .─────────.
* ( End )
* `─────────'
*
* Return: Non-negative on success / Negative on failure
*
*--------------------------------------------------------------------------
*/
static inline herr_t
H5TS_dlftt_mutex_release(H5TS_dlftt_mutex_t *mtx)
{
/* Don't release the mutex if locking is disabled */
if (0 == mtx->dlftt)
/* Check if we are bypassing the lock currently */
if (mtx->bypass) {
/* Decrement refcount */
mtx->rc--;

/* Check for done bypassing */
if (0 == mtx->rc)
mtx->bypass = false;
} /* end if */
else {
/* Release the mutex */
if (H5_UNLIKELY(H5TS_mutex_unlock(&mtx->mtx) < 0))
return FAIL;
} /* end else */

return SUCCEED;
} /* end H5TS_dlftt_mutex_release() */
5 changes: 3 additions & 2 deletions src/H5TSprivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,9 @@ typedef atomic_flag H5TS_spinlock_t;

/* Mutex that efficiently obeys the "DLFTT" locking protocol */
typedef struct H5TS_dlftt_mutex_t {
H5TS_mutex_t mtx;
unsigned dlftt;
H5TS_mutex_t mtx; /* Underlying mutex */
bool bypass; /* Whether locking is being bypassed (due to DLFTT protocol) */
unsigned rc; /* Refcount of locks bypassed */
} H5TS_dlftt_mutex_t;

/*****************************/
Expand Down

0 comments on commit e42efba

Please sign in to comment.