mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
Convert SharedFileSet->refcnt to an atomic variable.
Currently, this variable is an int protected by a spinlock. By converting it to an atomic variable, we can remove the spinlock. Detaching becomes an atomic subtract, and attaching becomes a compare-and-exchange loop, since it must not resurrect a fileset whose reference count has already reached zero. Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com> Tested-by: solai v <solai.cdac@gmail.com> Discussion: https://postgr.es/m/alAJeRRzehDjLaF1%40nathan
This commit is contained in:
@@ -38,8 +38,7 @@ void
|
||||
SharedFileSetInit(SharedFileSet *fileset, dsm_segment *seg)
|
||||
{
|
||||
/* Initialize the shared fileset specific members. */
|
||||
SpinLockInit(&fileset->mutex);
|
||||
fileset->refcnt = 1;
|
||||
pg_atomic_init_u32(&fileset->refcnt, 1);
|
||||
|
||||
/* Initialize the fileset. */
|
||||
FileSetInit(&fileset->fs);
|
||||
@@ -55,22 +54,20 @@ SharedFileSetInit(SharedFileSet *fileset, dsm_segment *seg)
|
||||
void
|
||||
SharedFileSetAttach(SharedFileSet *fileset, dsm_segment *seg)
|
||||
{
|
||||
bool success;
|
||||
uint32 refcnt;
|
||||
|
||||
SpinLockAcquire(&fileset->mutex);
|
||||
if (fileset->refcnt == 0)
|
||||
success = false;
|
||||
else
|
||||
refcnt = pg_atomic_read_u32(&fileset->refcnt);
|
||||
while (true)
|
||||
{
|
||||
++fileset->refcnt;
|
||||
success = true;
|
||||
}
|
||||
SpinLockRelease(&fileset->mutex);
|
||||
if (refcnt == 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||
errmsg("could not attach to a SharedFileSet that is already destroyed")));
|
||||
|
||||
if (!success)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||
errmsg("could not attach to a SharedFileSet that is already destroyed")));
|
||||
if (pg_atomic_compare_exchange_u32(&fileset->refcnt, &refcnt,
|
||||
refcnt + 1))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Register our cleanup callback. */
|
||||
on_dsm_detach(seg, SharedFileSetOnDetach, PointerGetDatum(fileset));
|
||||
@@ -98,11 +95,9 @@ SharedFileSetOnDetach(dsm_segment *segment, Datum datum)
|
||||
bool unlink_all = false;
|
||||
SharedFileSet *fileset = (SharedFileSet *) DatumGetPointer(datum);
|
||||
|
||||
SpinLockAcquire(&fileset->mutex);
|
||||
Assert(fileset->refcnt > 0);
|
||||
if (--fileset->refcnt == 0)
|
||||
Assert(pg_atomic_read_u32(&fileset->refcnt) > 0);
|
||||
if (pg_atomic_sub_fetch_u32(&fileset->refcnt, 1) == 0)
|
||||
unlink_all = true;
|
||||
SpinLockRelease(&fileset->mutex);
|
||||
|
||||
/*
|
||||
* If we are the last to detach, we delete the directory in all
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
#ifndef SHAREDFILESET_H
|
||||
#define SHAREDFILESET_H
|
||||
|
||||
#include "port/atomics.h"
|
||||
#include "storage/dsm.h"
|
||||
#include "storage/fd.h"
|
||||
#include "storage/fileset.h"
|
||||
#include "storage/spin.h"
|
||||
|
||||
/*
|
||||
* A set of temporary files that can be shared by multiple backends.
|
||||
@@ -26,8 +26,7 @@
|
||||
typedef struct SharedFileSet
|
||||
{
|
||||
FileSet fs;
|
||||
slock_t mutex; /* mutex protecting the reference count */
|
||||
int refcnt; /* number of attached backends */
|
||||
pg_atomic_uint32 refcnt; /* number of attached backends */
|
||||
} SharedFileSet;
|
||||
|
||||
extern void SharedFileSetInit(SharedFileSet *fileset, dsm_segment *seg);
|
||||
|
||||
Reference in New Issue
Block a user