|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
310c69 |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
310c69 |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
310c69 |
* of the License, or (at your option) any later version.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
310c69 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
310c69 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
310c69 |
* GNU General Public License for more details.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
310c69 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
310c69 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
310c69 |
* 02110-1301, USA.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/lockCounter.c#3 $
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "lockCounter.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "atomic.h"
|
|
Packit Service |
310c69 |
#include "memoryAlloc.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* LockCounter is intended to keep all of the locks for the blocks in the
|
|
Packit Service |
310c69 |
* recovery journal. The per-zone counters are all kept in a single array which
|
|
Packit Service |
310c69 |
* is arranged by zone (i.e. zone 0's lock 0 is at index 0, zone 0's lock 1 is
|
|
Packit Service |
310c69 |
* at index 1, and zone 1's lock 0 is at index 'locks'. This arrangement is
|
|
Packit Service |
310c69 |
* intended to minimize cache-line contention for counters from different
|
|
Packit Service |
310c69 |
* zones.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* The locks are implemented as a single object instead of as a lock counter
|
|
Packit Service |
310c69 |
* per lock both to afford this opportunity to reduce cache line contention and
|
|
Packit Service |
310c69 |
* also to eliminate the need to have a completion per lock.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* Lock sets are laid out with the set for recovery journal first, followed by
|
|
Packit Service |
310c69 |
* the logical zones, and then the physical zones.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
typedef enum lockCounterState {
|
|
Packit Service |
310c69 |
LOCK_COUNTER_STATE_NOT_NOTIFYING = 0,
|
|
Packit Service |
310c69 |
LOCK_COUNTER_STATE_NOTIFYING,
|
|
Packit Service |
310c69 |
LOCK_COUNTER_STATE_SUSPENDED,
|
|
Packit Service |
310c69 |
} LockCounterState;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
struct lockCounter {
|
|
Packit Service |
310c69 |
/** The completion for notifying the owner of a lock release */
|
|
Packit Service |
310c69 |
VDOCompletion completion;
|
|
Packit Service |
310c69 |
/** The number of logical zones which may hold locks */
|
|
Packit Service |
310c69 |
ZoneCount logicalZones;
|
|
Packit Service |
310c69 |
/** The number of physical zones which may hold locks */
|
|
Packit Service |
310c69 |
ZoneCount physicalZones;
|
|
Packit Service |
310c69 |
/** The number of locks */
|
|
Packit Service |
310c69 |
BlockCount locks;
|
|
Packit Service |
310c69 |
/** Whether the lock release notification is in flight */
|
|
Packit Service |
310c69 |
Atomic32 state;
|
|
Packit Service |
310c69 |
/** The number of logical zones which hold each lock */
|
|
Packit Service |
310c69 |
Atomic32 *logicalZoneCounts;
|
|
Packit Service |
310c69 |
/** The number of physical zones which hold each lock */
|
|
Packit Service |
310c69 |
Atomic32 *physicalZoneCounts;
|
|
Packit Service |
310c69 |
/** The per-zone, per-lock counts for the journal zone */
|
|
Packit Service |
310c69 |
uint16_t *journalCounters;
|
|
Packit Service |
310c69 |
/** The per-zone, per-lock decrement counts for the journal zone */
|
|
Packit Service |
310c69 |
Atomic32 *journalDecrementCounts;
|
|
Packit Service |
310c69 |
/** The per-zone, per-lock reference counts for logical zones */
|
|
Packit Service |
310c69 |
uint16_t *logicalCounters;
|
|
Packit Service |
310c69 |
/** The per-zone, per-lock reference counts for physical zones */
|
|
Packit Service |
310c69 |
uint16_t *physicalCounters;
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int makeLockCounter(PhysicalLayer *layer,
|
|
Packit Service |
310c69 |
void *parent,
|
|
Packit Service |
310c69 |
VDOAction callback,
|
|
Packit Service |
310c69 |
ThreadID threadID,
|
|
Packit Service |
310c69 |
ZoneCount logicalZones,
|
|
Packit Service |
310c69 |
ZoneCount physicalZones,
|
|
Packit Service |
310c69 |
BlockCount locks,
|
|
Packit Service |
310c69 |
LockCounter **lockCounterPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
LockCounter *lockCounter;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
int result = ALLOCATE(1, LockCounter, __func__, &lockCounter);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = ALLOCATE(locks, uint16_t, __func__, &lockCounter->journalCounters);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
freeLockCounter(&lockCounter);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = ALLOCATE(locks, Atomic32, __func__,
|
|
Packit Service |
310c69 |
&lockCounter->journalDecrementCounts);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
freeLockCounter(&lockCounter);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = ALLOCATE(locks * logicalZones, uint16_t, __func__,
|
|
Packit Service |
310c69 |
&lockCounter->logicalCounters);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
freeLockCounter(&lockCounter);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = ALLOCATE(locks, Atomic32, __func__,
|
|
Packit Service |
310c69 |
&lockCounter->logicalZoneCounts);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
freeLockCounter(&lockCounter);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = ALLOCATE(locks * physicalZones, uint16_t, __func__,
|
|
Packit Service |
310c69 |
&lockCounter->physicalCounters);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
freeLockCounter(&lockCounter);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = ALLOCATE(locks, Atomic32, __func__,
|
|
Packit Service |
310c69 |
&lockCounter->physicalZoneCounts);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
freeLockCounter(&lockCounter);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = initializeEnqueueableCompletion(&lockCounter->completion,
|
|
Packit Service |
310c69 |
LOCK_COUNTER_COMPLETION, layer);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
freeLockCounter(&lockCounter);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
setCallbackWithParent(&lockCounter->completion, callback, threadID, parent);
|
|
Packit Service |
310c69 |
lockCounter->logicalZones = logicalZones;
|
|
Packit Service |
310c69 |
lockCounter->physicalZones = physicalZones;
|
|
Packit Service |
310c69 |
lockCounter->locks = locks;
|
|
Packit Service |
310c69 |
*lockCounterPtr = lockCounter;
|
|
Packit Service |
310c69 |
return VDO_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void freeLockCounter(LockCounter **lockCounterPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (*lockCounterPtr == NULL) {
|
|
Packit Service |
310c69 |
return;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
LockCounter *lockCounter = *lockCounterPtr;
|
|
Packit Service |
310c69 |
destroyEnqueueable(&lockCounter->completion);
|
|
Packit Service |
310c69 |
freeVolatile(lockCounter->physicalZoneCounts);
|
|
Packit Service |
310c69 |
freeVolatile(lockCounter->logicalZoneCounts);
|
|
Packit Service |
310c69 |
freeVolatile(lockCounter->journalDecrementCounts);
|
|
Packit Service |
310c69 |
FREE(lockCounter->journalCounters);
|
|
Packit Service |
310c69 |
FREE(lockCounter->logicalCounters);
|
|
Packit Service |
310c69 |
FREE(lockCounter->physicalCounters);
|
|
Packit Service |
310c69 |
FREE(lockCounter);
|
|
Packit Service |
310c69 |
*lockCounterPtr = NULL;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Get a pointer to the zone count for a given lock on a given zone.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param counter The lock counter
|
|
Packit Service |
310c69 |
* @param lockNumber The lock to get
|
|
Packit Service |
310c69 |
* @param zoneType The zone type whose count is desired
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return A pointer to the zone count for the given lock and zone
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static inline Atomic32 *getZoneCountPtr(LockCounter *counter,
|
|
Packit Service |
310c69 |
BlockCount lockNumber,
|
|
Packit Service |
310c69 |
ZoneType zoneType)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return ((zoneType == ZONE_TYPE_LOGICAL)
|
|
Packit Service |
310c69 |
? &counter->logicalZoneCounts[lockNumber]
|
|
Packit Service |
310c69 |
: &counter->physicalZoneCounts[lockNumber]);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Get the zone counter for a given lock on a given zone.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param counter The lock counter
|
|
Packit Service |
310c69 |
* @param lockNumber The lock to get
|
|
Packit Service |
310c69 |
* @param zoneType The zone type whose count is desired
|
|
Packit Service |
310c69 |
* @param zoneID The zone index whose count is desired
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return The counter for the given lock and zone
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static inline uint16_t *getCounter(LockCounter *counter,
|
|
Packit Service |
310c69 |
BlockCount lockNumber,
|
|
Packit Service |
310c69 |
ZoneType zoneType,
|
|
Packit Service |
310c69 |
ZoneCount zoneID)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
BlockCount zoneCounter = (counter->locks * zoneID) + lockNumber;
|
|
Packit Service |
310c69 |
if (zoneType == ZONE_TYPE_JOURNAL) {
|
|
Packit Service |
310c69 |
return &counter->journalCounters[zoneCounter];
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (zoneType == ZONE_TYPE_LOGICAL) {
|
|
Packit Service |
310c69 |
return &counter->logicalCounters[zoneCounter];
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return &counter->physicalCounters[zoneCounter];
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Check whether the journal zone is locked for a given lock.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param counter The LockCounter
|
|
Packit Service |
310c69 |
* @param lockNumber The lock to check
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return true if the journal zone is locked
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static bool isJournalZoneLocked(LockCounter *counter, BlockCount lockNumber)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
uint16_t journalValue
|
|
Packit Service |
310c69 |
= *(getCounter(counter, lockNumber, ZONE_TYPE_JOURNAL, 0));
|
|
Packit Service |
310c69 |
uint32_t decrements
|
|
Packit Service |
310c69 |
= atomicLoad32(&(counter->journalDecrementCounts[lockNumber]));
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY((decrements <= journalValue),
|
|
Packit Service |
310c69 |
"journal zone lock counter must not underflow");
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return (journalValue != decrements);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
bool isLocked(LockCounter *lockCounter,
|
|
Packit Service |
310c69 |
BlockCount lockNumber,
|
|
Packit Service |
310c69 |
ZoneType zoneType)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY((zoneType != ZONE_TYPE_JOURNAL),
|
|
Packit Service |
310c69 |
"isLocked() called for non-journal zone");
|
|
Packit Service |
310c69 |
return (isJournalZoneLocked(lockCounter, lockNumber)
|
|
Packit Service |
310c69 |
|| (atomicLoad32(getZoneCountPtr(lockCounter, lockNumber, zoneType))
|
|
Packit Service |
310c69 |
!= 0));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Check that we are on the journal thread.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param counter The LockCounter
|
|
Packit Service |
310c69 |
* @param caller The name of the caller (for logging)
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static void assertOnJournalThread(LockCounter *counter, const char *caller)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY((getCallbackThreadID()
|
|
Packit Service |
310c69 |
== counter->completion.callbackThreadID),
|
|
Packit Service |
310c69 |
"%s() called from journal zone", caller);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void initializeLockCount(LockCounter *counter,
|
|
Packit Service |
310c69 |
BlockCount lockNumber,
|
|
Packit Service |
310c69 |
uint16_t value)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
assertOnJournalThread(counter, __func__);
|
|
Packit Service |
310c69 |
uint16_t *journalValue = getCounter(counter, lockNumber, ZONE_TYPE_JOURNAL,
|
|
Packit Service |
310c69 |
0);
|
|
Packit Service |
310c69 |
Atomic32 *decrementCount = &(counter->journalDecrementCounts[lockNumber]);
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY((*journalValue == atomicLoad32(decrementCount)),
|
|
Packit Service |
310c69 |
"count to be initialized not in use");
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*journalValue = value;
|
|
Packit Service |
310c69 |
atomicStore32(decrementCount, 0);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void acquireLockCountReference(LockCounter *counter,
|
|
Packit Service |
310c69 |
BlockCount lockNumber,
|
|
Packit Service |
310c69 |
ZoneType zoneType,
|
|
Packit Service |
310c69 |
ZoneCount zoneID)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY((zoneType != ZONE_TYPE_JOURNAL),
|
|
Packit Service |
310c69 |
"invalid lock count increment from journal zone");
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
uint16_t *currentValue = getCounter(counter, lockNumber, zoneType, zoneID);
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY(*currentValue < UINT16_MAX,
|
|
Packit Service |
310c69 |
"increment of lock counter must not overflow");
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (*currentValue == 0) {
|
|
Packit Service |
310c69 |
// This zone is acquiring this lock for the first time.
|
|
Packit Service |
310c69 |
atomicAdd32(getZoneCountPtr(counter, lockNumber, zoneType), 1);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
*currentValue += 1;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Decrement a non-atomic counter.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param counter The LockCounter
|
|
Packit Service |
310c69 |
* @param lockNumber Which lock to decrement
|
|
Packit Service |
310c69 |
* @param zoneType The type of the zone releasing the reference
|
|
Packit Service |
310c69 |
* @param zoneID The ID of the zone releasing the reference
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return The new value of the counter
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static uint16_t releaseReference(LockCounter *counter,
|
|
Packit Service |
310c69 |
BlockCount lockNumber,
|
|
Packit Service |
310c69 |
ZoneType zoneType,
|
|
Packit Service |
310c69 |
ZoneCount zoneID)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
uint16_t *currentValue = getCounter(counter, lockNumber, zoneType, zoneID);
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY((*currentValue >= 1),
|
|
Packit Service |
310c69 |
"decrement of lock counter must not underflow");
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*currentValue -= 1;
|
|
Packit Service |
310c69 |
return *currentValue;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Attempt to notify the owner of this LockCounter that some lock has been
|
|
Packit Service |
310c69 |
* released for some zone type. Will do nothing if another notification is
|
|
Packit Service |
310c69 |
* already in progress.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param counter The LockCounter
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static void attemptNotification(LockCounter *counter)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (compareAndSwap32(&counter->state,
|
|
Packit Service |
310c69 |
LOCK_COUNTER_STATE_NOT_NOTIFYING,
|
|
Packit Service |
310c69 |
LOCK_COUNTER_STATE_NOTIFYING)) {
|
|
Packit Service |
310c69 |
resetCompletion(&counter->completion);
|
|
Packit Service |
310c69 |
invokeCallback(&counter->completion);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void releaseLockCountReference(LockCounter *counter,
|
|
Packit Service |
310c69 |
BlockCount lockNumber,
|
|
Packit Service |
310c69 |
ZoneType zoneType,
|
|
Packit Service |
310c69 |
ZoneCount zoneID)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY((zoneType != ZONE_TYPE_JOURNAL),
|
|
Packit Service |
310c69 |
"invalid lock count decrement from journal zone");
|
|
Packit Service |
310c69 |
if (releaseReference(counter, lockNumber, zoneType, zoneID) != 0) {
|
|
Packit Service |
310c69 |
return;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (atomicAdd32(getZoneCountPtr(counter, lockNumber, zoneType), -1) == 0) {
|
|
Packit Service |
310c69 |
// This zone was the last lock holder of its type, so try to notify the
|
|
Packit Service |
310c69 |
// owner.
|
|
Packit Service |
310c69 |
attemptNotification(counter);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void releaseJournalZoneReference(LockCounter *counter, BlockCount lockNumber)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
assertOnJournalThread(counter, __func__);
|
|
Packit Service |
310c69 |
releaseReference(counter, lockNumber, ZONE_TYPE_JOURNAL, 0);
|
|
Packit Service |
310c69 |
if (!isJournalZoneLocked(counter, lockNumber)) {
|
|
Packit Service |
310c69 |
// The journal zone is not locked, so try to notify the owner.
|
|
Packit Service |
310c69 |
attemptNotification(counter);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void releaseJournalZoneReferenceFromOtherZone(LockCounter *counter,
|
|
Packit Service |
310c69 |
BlockCount lockNumber)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
atomicAdd32(&(counter->journalDecrementCounts[lockNumber]), 1);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void acknowledgeUnlock(LockCounter *counter)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
atomicStore32(&counter->state, LOCK_COUNTER_STATE_NOT_NOTIFYING);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
bool suspendLockCounter(LockCounter *counter)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
assertOnJournalThread(counter, __func__);
|
|
Packit Service |
310c69 |
return ((atomicLoad32(&counter->state) == LOCK_COUNTER_STATE_SUSPENDED)
|
|
Packit Service |
310c69 |
|| compareAndSwap32(&counter->state,
|
|
Packit Service |
310c69 |
LOCK_COUNTER_STATE_NOT_NOTIFYING,
|
|
Packit Service |
310c69 |
LOCK_COUNTER_STATE_SUSPENDED));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
bool resumeLockCounter(LockCounter *counter)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
assertOnJournalThread(counter, __func__);
|
|
Packit Service |
310c69 |
return compareAndSwap32(&counter->state,
|
|
Packit Service |
310c69 |
LOCK_COUNTER_STATE_SUSPENDED,
|
|
Packit Service |
310c69 |
LOCK_COUNTER_STATE_NOT_NOTIFYING);
|
|
Packit Service |
310c69 |
}
|