Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
64e6c608
Commit
64e6c608
authored
Jan 16, 2001
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rename fields of lock and lockholder structures to something a tad less
confusing, and clean up documentation.
parent
2dbc457e
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
299 additions
and
271 deletions
+299
-271
src/backend/storage/lmgr/README
src/backend/storage/lmgr/README
+32
-33
src/backend/storage/lmgr/lock.c
src/backend/storage/lmgr/lock.c
+187
-178
src/backend/storage/lmgr/proc.c
src/backend/storage/lmgr/proc.c
+37
-33
src/include/storage/lock.h
src/include/storage/lock.h
+28
-20
src/include/storage/proc.h
src/include/storage/proc.h
+15
-7
No files found.
src/backend/storage/lmgr/README
View file @
64e6c608
$Header: /cvsroot/pgsql/src/backend/storage/lmgr/README,v 1.
4 2000/12/22 00:51:5
4 tgl Exp $
$Header: /cvsroot/pgsql/src/backend/storage/lmgr/README,v 1.
5 2001/01/16 06:11:3
4 tgl Exp $
There are two fundamental lock structures: the per-lockable-object LOCK
There are two fundamental lock structures: the per-lockable-object LOCK
struct, and the per-lock-holder HOLDER struct. A LOCK object exists
struct, and the per-lock-holder HOLDER struct. A LOCK object exists
...
@@ -44,51 +44,52 @@ tag -
...
@@ -44,51 +44,52 @@ tag -
only a single table (see Gray's paper on 2 phase locking if
only a single table (see Gray's paper on 2 phase locking if
you are puzzled about how multi-level lock tables work).
you are puzzled about how multi-level lock tables work).
m
ask -
grantM
ask -
This
field
indicates what types of locks are currently held on the
This
bitmask
indicates what types of locks are currently held on the
given lockable object. It is used (against the lock table's conflict
given lockable object. It is used (against the lock table's conflict
table) to determine if
the
new lock request will conflict with existing
table) to determine if
a
new lock request will conflict with existing
lock types held. Conficts are determined by bitwise AND operations
lock types held. Conficts are determined by bitwise AND operations
between the mask and the conflict table entry for the given lock type
between the grantMask and the conflict table entry for the requested
to be set. The current representation is that each bit (1 through 5)
lock type. Bit i of grantMask is 1 if and only if granted[i] > 0.
is set when that lock type (WRITE, READ, WRITE INTENT, READ INTENT, EXTEND)
has been acquired for the lock.
waitMask -
This bitmask shows the types of locks being waited for. Bit i of waitMask
is 1 if and only if requested[i] > granted[i].
waitProcs -
waitProcs -
This is a shared memory queue of all process structures corresponding to
This is a shared memory queue of all process structures corresponding to
a backend that is waiting (sleeping) until another backend releases this
a backend that is waiting (sleeping) until another backend releases this
lock. The process structure holds the information needed to determine
lock. The process structure holds the information needed to determine
if it should be woken up when this lock is released. If, for example,
if it should be woken up when this lock is released.
we are releasing a read lock and the process is sleeping trying to acquire
a read lock then there is no point in waking it since the lock being
released isn't what caused it to sleep in the first place. There will
be more on this below (when I get to releasing locks and waking sleeping
process routines).
n
Holding
-
n
Requested
-
Keeps a count of how many times this lock has been attempted to be
Keeps a count of how many times this lock has been attempted to be
acquired. The count includes attempts by processes which were put
acquired. The count includes attempts by processes which were put
to sleep due to conflicts. It also counts the same backend twice
to sleep due to conflicts. It also counts the same backend twice
if, for example, a backend process first acquires a read and then
if, for example, a backend process first acquires a read and then
acquires a write.
acquires a write
, or acquires a read lock twice
.
holders
-
requested
-
Keeps a count of how many locks of each type have been attempted. Only
Keeps a count of how many locks of each type have been attempted. Only
elements 1 through MAX_LOCK
_TYPES
are used as they correspond to the lock
elements 1 through MAX_LOCK
MODES-1
are used as they correspond to the lock
type defined constants
(WRITE through EXTEND). Summing the values of
type defined constants
. Summing the values of requested[] should come out
holders should come out equal to nHolding
.
equal to nRequested
.
n
Active
-
n
Granted
-
Keeps
a count of how many times this lock has been succe
sfully acquired.
Keeps
count of how many times this lock has been succes
sfully acquired.
This count does not include attempts that are waiting due to conflicts,
This count does not include attempts that are waiting due to conflicts,
but can count the same backend twice (e.g. a read then a write -- since
but can count the same backend twice (e.g. a read then a write -- since
its the same transaction this won't cause a conflict)
its the same transaction this won't cause a conflict).
granted -
Keeps count of how many locks of each type are currently held. Once again
only elements 1 through MAX_LOCKMODES-1 are used (0 is not). Also, like
requested, summing the values of granted should total to the value
of nGranted.
activeHolders -
We should always have 0 <= nGranted <= nRequested, and
Keeps a count of how locks of each type are currently held. Once again
0 <= granted[i] <= requested[i] for each i. If the request counts go to
only elements 1 through MAX_LOCK_TYPES are used (0 is not). Also, like
zero, the lock object is no longer needed and can be freed.
holders, summing the values of activeHolders should total to the value
of nActive.
---------------------------------------------------------------------------
---------------------------------------------------------------------------
...
@@ -116,14 +117,12 @@ tag -
...
@@ -116,14 +117,12 @@ tag -
are always session locks, and we also use session locks for multi-
are always session locks, and we also use session locks for multi-
transaction operations like VACUUM.
transaction operations like VACUUM.
hold
ers
-
hold
ing
-
The number of successfully acquired locks of each type for this holder.
The number of successfully acquired locks of each type for this holder.
(CAUTION: the semantics are not the same as the LOCK's holder[], which
This should be <= the corresponding granted[] value of the lock object!
counts both acquired and pending requests. Probably a different name
should be used...)
nHolding -
nHolding -
Sum of the hold
ers
[] array.
Sum of the hold
ing
[] array.
queue -
queue -
List link for shared memory queue of all the HOLDER objects for the
List link for shared memory queue of all the HOLDER objects for the
...
...
src/backend/storage/lmgr/lock.c
View file @
64e6c608
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.7
7 2001/01/14 05:08:15
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.7
8 2001/01/16 06:11:34
tgl Exp $
*
*
* NOTES
* NOTES
* Outside modules can create a lock table and acquire/release
* Outside modules can create a lock table and acquire/release
...
@@ -43,8 +43,8 @@
...
@@ -43,8 +43,8 @@
static
int
WaitOnLock
(
LOCKMETHOD
lockmethod
,
LOCKMODE
lockmode
,
static
int
WaitOnLock
(
LOCKMETHOD
lockmethod
,
LOCKMODE
lockmode
,
LOCK
*
lock
,
HOLDER
*
holder
);
LOCK
*
lock
,
HOLDER
*
holder
);
static
void
LockCountMyLocks
(
SHMEM_OFFSET
lockOffset
,
PROC
*
proc
,
static
void
LockCountMyLocks
(
SHMEM_OFFSET
lockOffset
,
PROC
*
proc
,
int
*
myHold
ers
);
int
*
myHold
ing
);
static
int
LockGetMyH
o
ldLocks
(
SHMEM_OFFSET
lockOffset
,
PROC
*
proc
);
static
int
LockGetMyH
e
ldLocks
(
SHMEM_OFFSET
lockOffset
,
PROC
*
proc
);
static
char
*
lock_types
[]
=
static
char
*
lock_types
[]
=
{
{
...
@@ -91,7 +91,7 @@ LOCK_DEBUG_ENABLED(const LOCK * lock)
...
@@ -91,7 +91,7 @@ LOCK_DEBUG_ENABLED(const LOCK * lock)
return
return
(((
LOCK_LOCKMETHOD
(
*
lock
)
==
DEFAULT_LOCKMETHOD
&&
Trace_locks
)
(((
LOCK_LOCKMETHOD
(
*
lock
)
==
DEFAULT_LOCKMETHOD
&&
Trace_locks
)
||
(
LOCK_LOCKMETHOD
(
*
lock
)
==
USER_LOCKMETHOD
&&
Trace_userlocks
))
||
(
LOCK_LOCKMETHOD
(
*
lock
)
==
USER_LOCKMETHOD
&&
Trace_userlocks
))
&&
(
lock
->
tag
.
relId
>=
Trace_lock_oidmin
))
&&
(
lock
->
tag
.
relId
>=
(
Oid
)
Trace_lock_oidmin
))
||
(
Trace_lock_table
&&
(
lock
->
tag
.
relId
==
Trace_lock_table
));
||
(
Trace_lock_table
&&
(
lock
->
tag
.
relId
==
Trace_lock_table
));
}
}
...
@@ -101,17 +101,18 @@ LOCK_PRINT(const char * where, const LOCK * lock, LOCKMODE type)
...
@@ -101,17 +101,18 @@ LOCK_PRINT(const char * where, const LOCK * lock, LOCKMODE type)
{
{
if
(
LOCK_DEBUG_ENABLED
(
lock
))
if
(
LOCK_DEBUG_ENABLED
(
lock
))
elog
(
DEBUG
,
elog
(
DEBUG
,
"%s: lock(%lx) tbl(%d) rel(%u) db(%u) obj(%u)
m
ask(%x) "
"%s: lock(%lx) tbl(%d) rel(%u) db(%u) obj(%u)
grantM
ask(%x) "
"
hold
(%d,%d,%d,%d,%d,%d,%d)=%d "
"
req
(%d,%d,%d,%d,%d,%d,%d)=%d "
"
ac
t(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)"
,
"
gran
t(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)"
,
where
,
MAKE_OFFSET
(
lock
),
where
,
MAKE_OFFSET
(
lock
),
lock
->
tag
.
lockmethod
,
lock
->
tag
.
relId
,
lock
->
tag
.
dbId
,
lock
->
tag
.
lockmethod
,
lock
->
tag
.
relId
,
lock
->
tag
.
dbId
,
lock
->
tag
.
objId
.
blkno
,
lock
->
mask
,
lock
->
tag
.
objId
.
blkno
,
lock
->
grantMask
,
lock
->
holders
[
1
],
lock
->
holders
[
2
],
lock
->
holders
[
3
],
lock
->
holders
[
4
],
lock
->
requested
[
1
],
lock
->
requested
[
2
],
lock
->
requested
[
3
],
lock
->
holders
[
5
],
lock
->
holders
[
6
],
lock
->
holders
[
7
],
lock
->
nHolding
,
lock
->
requested
[
4
],
lock
->
requested
[
5
],
lock
->
requested
[
6
],
lock
->
activeHolders
[
1
],
lock
->
activeHolders
[
2
],
lock
->
activeHolders
[
3
],
lock
->
requested
[
7
],
lock
->
nRequested
,
lock
->
activeHolders
[
4
],
lock
->
activeHolders
[
5
],
lock
->
activeHolders
[
6
],
lock
->
granted
[
1
],
lock
->
granted
[
2
],
lock
->
granted
[
3
],
lock
->
activeHolders
[
7
],
lock
->
nActive
,
lock
->
granted
[
4
],
lock
->
granted
[
5
],
lock
->
granted
[
6
],
lock
->
granted
[
7
],
lock
->
nGranted
,
lock
->
waitProcs
.
size
,
lock_types
[
type
]);
lock
->
waitProcs
.
size
,
lock_types
[
type
]);
}
}
...
@@ -122,7 +123,7 @@ HOLDER_PRINT(const char * where, const HOLDER * holderP)
...
@@ -122,7 +123,7 @@ HOLDER_PRINT(const char * where, const HOLDER * holderP)
if
(
if
(
(((
HOLDER_LOCKMETHOD
(
*
holderP
)
==
DEFAULT_LOCKMETHOD
&&
Trace_locks
)
(((
HOLDER_LOCKMETHOD
(
*
holderP
)
==
DEFAULT_LOCKMETHOD
&&
Trace_locks
)
||
(
HOLDER_LOCKMETHOD
(
*
holderP
)
==
USER_LOCKMETHOD
&&
Trace_userlocks
))
||
(
HOLDER_LOCKMETHOD
(
*
holderP
)
==
USER_LOCKMETHOD
&&
Trace_userlocks
))
&&
(((
LOCK
*
)
MAKE_PTR
(
holderP
->
tag
.
lock
))
->
tag
.
relId
>=
Trace_lock_oidmin
))
&&
(((
LOCK
*
)
MAKE_PTR
(
holderP
->
tag
.
lock
))
->
tag
.
relId
>=
(
Oid
)
Trace_lock_oidmin
))
||
(
Trace_lock_table
&&
(((
LOCK
*
)
MAKE_PTR
(
holderP
->
tag
.
lock
))
->
tag
.
relId
==
Trace_lock_table
))
||
(
Trace_lock_table
&&
(((
LOCK
*
)
MAKE_PTR
(
holderP
->
tag
.
lock
))
->
tag
.
relId
==
Trace_lock_table
))
)
)
elog
(
DEBUG
,
elog
(
DEBUG
,
...
@@ -130,8 +131,9 @@ HOLDER_PRINT(const char * where, const HOLDER * holderP)
...
@@ -130,8 +131,9 @@ HOLDER_PRINT(const char * where, const HOLDER * holderP)
where
,
MAKE_OFFSET
(
holderP
),
holderP
->
tag
.
lock
,
where
,
MAKE_OFFSET
(
holderP
),
holderP
->
tag
.
lock
,
HOLDER_LOCKMETHOD
(
*
(
holderP
)),
HOLDER_LOCKMETHOD
(
*
(
holderP
)),
holderP
->
tag
.
pid
,
holderP
->
tag
.
xid
,
holderP
->
tag
.
pid
,
holderP
->
tag
.
xid
,
holderP
->
holders
[
1
],
holderP
->
holders
[
2
],
holderP
->
holders
[
3
],
holderP
->
holders
[
4
],
holderP
->
holding
[
1
],
holderP
->
holding
[
2
],
holderP
->
holding
[
3
],
holderP
->
holders
[
5
],
holderP
->
holders
[
6
],
holderP
->
holders
[
7
],
holderP
->
nHolding
);
holderP
->
holding
[
4
],
holderP
->
holding
[
5
],
holderP
->
holding
[
6
],
holderP
->
holding
[
7
],
holderP
->
nHolding
);
}
}
#else
/* not LOCK_DEBUG */
#else
/* not LOCK_DEBUG */
...
@@ -146,7 +148,12 @@ HOLDER_PRINT(const char * where, const HOLDER * holderP)
...
@@ -146,7 +148,12 @@ HOLDER_PRINT(const char * where, const HOLDER * holderP)
SPINLOCK
LockMgrLock
;
/* in Shmem or created in
SPINLOCK
LockMgrLock
;
/* in Shmem or created in
* CreateSpinlocks() */
* CreateSpinlocks() */
/* This is to simplify/speed up some bit arithmetic */
/*
* These are to simplify/speed up some bit arithmetic.
*
* XXX is a fetch from a static array really faster than a shift?
* Wouldn't bet on it...
*/
static
LOCKMASK
BITS_OFF
[
MAX_LOCKMODES
];
static
LOCKMASK
BITS_OFF
[
MAX_LOCKMODES
];
static
LOCKMASK
BITS_ON
[
MAX_LOCKMODES
];
static
LOCKMASK
BITS_ON
[
MAX_LOCKMODES
];
...
@@ -471,7 +478,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -471,7 +478,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
SPINLOCK
masterLock
;
SPINLOCK
masterLock
;
LOCKMETHODTABLE
*
lockMethodTable
;
LOCKMETHODTABLE
*
lockMethodTable
;
int
status
;
int
status
;
int
myHold
ers
[
MAX_LOCKMODES
];
int
myHold
ing
[
MAX_LOCKMODES
];
int
i
;
int
i
;
#ifdef LOCK_DEBUG
#ifdef LOCK_DEBUG
...
@@ -517,20 +524,21 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -517,20 +524,21 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
*/
*/
if
(
!
found
)
if
(
!
found
)
{
{
lock
->
mask
=
0
;
lock
->
grantMask
=
0
;
lock
->
nHolding
=
0
;
lock
->
waitMask
=
0
;
lock
->
nActive
=
0
;
lock
->
nRequested
=
0
;
MemSet
((
char
*
)
lock
->
holders
,
0
,
sizeof
(
int
)
*
MAX_LOCKMODES
);
lock
->
nGranted
=
0
;
MemSet
((
char
*
)
lock
->
activeHolders
,
0
,
sizeof
(
int
)
*
MAX_LOCKMODES
);
MemSet
((
char
*
)
lock
->
requested
,
0
,
sizeof
(
int
)
*
MAX_LOCKMODES
);
MemSet
((
char
*
)
lock
->
granted
,
0
,
sizeof
(
int
)
*
MAX_LOCKMODES
);
ProcQueueInit
(
&
(
lock
->
waitProcs
));
ProcQueueInit
(
&
(
lock
->
waitProcs
));
LOCK_PRINT
(
"LockAcquire: new"
,
lock
,
lockmode
);
LOCK_PRINT
(
"LockAcquire: new"
,
lock
,
lockmode
);
}
}
else
else
{
{
LOCK_PRINT
(
"LockAcquire: found"
,
lock
,
lockmode
);
LOCK_PRINT
(
"LockAcquire: found"
,
lock
,
lockmode
);
Assert
((
lock
->
n
Holding
>
0
)
&&
(
lock
->
holders
[
lockmode
]
>=
0
));
Assert
((
lock
->
n
Requested
>=
0
)
&&
(
lock
->
requested
[
lockmode
]
>=
0
));
Assert
((
lock
->
n
Active
>
0
)
&&
(
lock
->
activeHolders
[
lockmode
]
>=
0
));
Assert
((
lock
->
n
Granted
>=
0
)
&&
(
lock
->
granted
[
lockmode
]
>=
0
));
Assert
(
lock
->
n
Active
<=
lock
->
nHolding
);
Assert
(
lock
->
n
Granted
<=
lock
->
nRequested
);
}
}
/* ------------------
/* ------------------
...
@@ -561,15 +569,15 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -561,15 +569,15 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
if
(
!
found
)
if
(
!
found
)
{
{
holder
->
nHolding
=
0
;
holder
->
nHolding
=
0
;
MemSet
((
char
*
)
holder
->
hold
ers
,
0
,
sizeof
(
int
)
*
MAX_LOCKMODES
);
MemSet
((
char
*
)
holder
->
hold
ing
,
0
,
sizeof
(
int
)
*
MAX_LOCKMODES
);
ProcAddLock
(
&
holder
->
queue
);
ProcAddLock
(
&
holder
->
queue
);
HOLDER_PRINT
(
"LockAcquire: new"
,
holder
);
HOLDER_PRINT
(
"LockAcquire: new"
,
holder
);
}
}
else
else
{
{
HOLDER_PRINT
(
"LockAcquire: found"
,
holder
);
HOLDER_PRINT
(
"LockAcquire: found"
,
holder
);
Assert
((
holder
->
nHolding
>
0
)
&&
(
holder
->
holders
[
lockmode
]
>=
0
));
Assert
((
holder
->
nHolding
>
=
0
)
&&
(
holder
->
holding
[
lockmode
]
>=
0
));
Assert
(
holder
->
nHolding
<=
lock
->
n
Active
);
Assert
(
holder
->
nHolding
<=
lock
->
n
Granted
);
#ifdef CHECK_DEADLOCK_RISK
#ifdef CHECK_DEADLOCK_RISK
/*
/*
...
@@ -588,7 +596,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -588,7 +596,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
*/
*/
for
(
i
=
lockMethodTable
->
ctl
->
numLockModes
;
i
>
0
;
i
--
)
for
(
i
=
lockMethodTable
->
ctl
->
numLockModes
;
i
>
0
;
i
--
)
{
{
if
(
holder
->
hold
ers
[
i
]
>
0
)
if
(
holder
->
hold
ing
[
i
]
>
0
)
{
{
if
(
i
>=
(
int
)
lockmode
)
if
(
i
>=
(
int
)
lockmode
)
break
;
/* safe: we have a lock >= req level */
break
;
/* safe: we have a lock >= req level */
...
@@ -603,21 +611,21 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -603,21 +611,21 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
}
}
/* ----------------
/* ----------------
* lock->n
Holding and lock->holders count the total number of holders
* lock->n
Requested and lock->requested[] count the total number of
*
either holding or waiting for the lock
, so increment those immediately.
*
requests, whether granted or waiting
, so increment those immediately.
* The other counts don't increment till we get the lock.
* The other counts don't increment till we get the lock.
* ----------------
* ----------------
*/
*/
lock
->
n
Holding
++
;
lock
->
n
Requested
++
;
lock
->
holders
[
lockmode
]
++
;
lock
->
requested
[
lockmode
]
++
;
Assert
((
lock
->
n
Holding
>
0
)
&&
(
lock
->
holders
[
lockmode
]
>
0
));
Assert
((
lock
->
n
Requested
>
0
)
&&
(
lock
->
requested
[
lockmode
]
>
0
));
/* --------------------
/* --------------------
* If I'm the only one holding any lock on this object, then there
* If I'm the only one holding any lock on this object, then there
* cannot be a conflict. The same is true if I already hold this lock.
* cannot be a conflict. The same is true if I already hold this lock.
* --------------------
* --------------------
*/
*/
if
(
holder
->
nHolding
==
lock
->
n
Active
||
holder
->
holders
[
lockmode
]
!=
0
)
if
(
holder
->
nHolding
==
lock
->
n
Granted
||
holder
->
holding
[
lockmode
]
!=
0
)
{
{
GrantLock
(
lock
,
holder
,
lockmode
);
GrantLock
(
lock
,
holder
,
lockmode
);
HOLDER_PRINT
(
"LockAcquire: owning"
,
holder
);
HOLDER_PRINT
(
"LockAcquire: owning"
,
holder
);
...
@@ -630,8 +638,8 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -630,8 +638,8 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
* then there is no conflict, either.
* then there is no conflict, either.
* --------------------
* --------------------
*/
*/
LockCountMyLocks
(
holder
->
tag
.
lock
,
MyProc
,
myHold
ers
);
LockCountMyLocks
(
holder
->
tag
.
lock
,
MyProc
,
myHold
ing
);
if
(
myHold
ers
[
lockmode
]
!=
0
)
if
(
myHold
ing
[
lockmode
]
!=
0
)
{
{
GrantLock
(
lock
,
holder
,
lockmode
);
GrantLock
(
lock
,
holder
,
lockmode
);
HOLDER_PRINT
(
"LockAcquire: my other XID owning"
,
holder
);
HOLDER_PRINT
(
"LockAcquire: my other XID owning"
,
holder
);
...
@@ -650,7 +658,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -650,7 +658,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
*/
*/
for
(
i
=
1
;
i
<=
lockMethodTable
->
ctl
->
numLockModes
;
i
++
)
for
(
i
=
1
;
i
<=
lockMethodTable
->
ctl
->
numLockModes
;
i
++
)
{
{
if
(
myHold
ers
[
i
]
>
0
&&
if
(
myHold
ing
[
i
]
>
0
&&
lockMethodTable
->
ctl
->
conflictTab
[
i
]
&
lock
->
waitMask
)
lockMethodTable
->
ctl
->
conflictTab
[
i
]
&
lock
->
waitMask
)
break
;
/* yes, there is a conflict */
break
;
/* yes, there is a conflict */
}
}
...
@@ -664,12 +672,12 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -664,12 +672,12 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
else
else
status
=
LockResolveConflicts
(
lockmethod
,
lockmode
,
status
=
LockResolveConflicts
(
lockmethod
,
lockmode
,
lock
,
holder
,
lock
,
holder
,
MyProc
,
myHold
ers
);
MyProc
,
myHold
ing
);
}
}
else
else
status
=
LockResolveConflicts
(
lockmethod
,
lockmode
,
status
=
LockResolveConflicts
(
lockmethod
,
lockmode
,
lock
,
holder
,
lock
,
holder
,
MyProc
,
myHold
ers
);
MyProc
,
myHold
ing
);
if
(
status
==
STATUS_OK
)
if
(
status
==
STATUS_OK
)
GrantLock
(
lock
,
holder
,
lockmode
);
GrantLock
(
lock
,
holder
,
lockmode
);
...
@@ -694,11 +702,11 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -694,11 +702,11 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
}
}
else
else
HOLDER_PRINT
(
"LockAcquire: NHOLDING"
,
holder
);
HOLDER_PRINT
(
"LockAcquire: NHOLDING"
,
holder
);
lock
->
n
Holding
--
;
lock
->
n
Requested
--
;
lock
->
holders
[
lockmode
]
--
;
lock
->
requested
[
lockmode
]
--
;
LOCK_PRINT
(
"LockAcquire: user lock failed"
,
lock
,
lockmode
);
LOCK_PRINT
(
"LockAcquire: user lock failed"
,
lock
,
lockmode
);
Assert
((
lock
->
n
Holding
>
0
)
&&
(
lock
->
holders
[
lockmode
]
>=
0
));
Assert
((
lock
->
n
Requested
>
0
)
&&
(
lock
->
requested
[
lockmode
]
>=
0
));
Assert
(
lock
->
n
Active
<=
lock
->
nHolding
);
Assert
(
lock
->
n
Granted
<=
lock
->
nRequested
);
SpinRelease
(
masterLock
);
SpinRelease
(
masterLock
);
return
FALSE
;
return
FALSE
;
}
}
...
@@ -708,17 +716,17 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -708,17 +716,17 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
* Construct bitmask of locks this process holds on this object.
* Construct bitmask of locks this process holds on this object.
*/
*/
{
{
int
h
oldLock
=
0
;
int
h
eldLocks
=
0
;
int
tmpMask
;
int
tmpMask
;
for
(
i
=
1
,
tmpMask
=
2
;
for
(
i
=
1
,
tmpMask
=
2
;
i
<=
lockMethodTable
->
ctl
->
numLockModes
;
i
<=
lockMethodTable
->
ctl
->
numLockModes
;
i
++
,
tmpMask
<<=
1
)
i
++
,
tmpMask
<<=
1
)
{
{
if
(
myHold
ers
[
i
]
>
0
)
if
(
myHold
ing
[
i
]
>
0
)
h
oldLock
|=
tmpMask
;
h
eldLocks
|=
tmpMask
;
}
}
MyProc
->
h
oldLock
=
holdLock
;
MyProc
->
h
eldLocks
=
heldLocks
;
}
}
/*
/*
...
@@ -736,7 +744,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -736,7 +744,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
* Check the holder entry status, in case something in the ipc
* Check the holder entry status, in case something in the ipc
* communication doesn't work correctly.
* communication doesn't work correctly.
*/
*/
if
(
!
((
holder
->
nHolding
>
0
)
&&
(
holder
->
hold
ers
[
lockmode
]
>
0
)))
if
(
!
((
holder
->
nHolding
>
0
)
&&
(
holder
->
hold
ing
[
lockmode
]
>
0
)))
{
{
HOLDER_PRINT
(
"LockAcquire: INCONSISTENT"
,
holder
);
HOLDER_PRINT
(
"LockAcquire: INCONSISTENT"
,
holder
);
LOCK_PRINT
(
"LockAcquire: INCONSISTENT"
,
lock
,
lockmode
);
LOCK_PRINT
(
"LockAcquire: INCONSISTENT"
,
lock
,
lockmode
);
...
@@ -763,7 +771,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -763,7 +771,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
* determining whether or not any new lock acquired conflicts with
* determining whether or not any new lock acquired conflicts with
* the old ones.
* the old ones.
*
*
* The caller can optionally pass the process's total hold
ers
counts, if
* The caller can optionally pass the process's total hold
ing
counts, if
* known. If NULL is passed then these values will be computed internally.
* known. If NULL is passed then these values will be computed internally.
* ----------------------------
* ----------------------------
*/
*/
...
@@ -773,28 +781,28 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
...
@@ -773,28 +781,28 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
LOCK
*
lock
,
LOCK
*
lock
,
HOLDER
*
holder
,
HOLDER
*
holder
,
PROC
*
proc
,
PROC
*
proc
,
int
*
myHold
ers
)
/* myHolders
[] array or NULL */
int
*
myHold
ing
)
/* myHolding
[] array or NULL */
{
{
LOCKMETHODCTL
*
lockctl
=
LockMethodTable
[
lockmethod
]
->
ctl
;
LOCKMETHODCTL
*
lockctl
=
LockMethodTable
[
lockmethod
]
->
ctl
;
int
numLockModes
=
lockctl
->
numLockModes
;
int
numLockModes
=
lockctl
->
numLockModes
;
int
bitmask
;
int
bitmask
;
int
i
,
int
i
,
tmpMask
;
tmpMask
;
int
localHold
ers
[
MAX_LOCKMODES
];
int
localHold
ing
[
MAX_LOCKMODES
];
Assert
((
holder
->
nHolding
>=
0
)
&&
(
holder
->
hold
ers
[
lockmode
]
>=
0
));
Assert
((
holder
->
nHolding
>=
0
)
&&
(
holder
->
hold
ing
[
lockmode
]
>=
0
));
/* ----------------------------
/* ----------------------------
* first check for global conflicts: If no locks conflict
* first check for global conflicts: If no locks conflict
* with mine, then I get the lock.
* with mine, then I get the lock.
*
*
* Checking for conflict: lock->
m
ask represents the types of
* Checking for conflict: lock->
grantM
ask represents the types of
* currently held locks. conflictTable[lockmode] has a bit
* currently held locks. conflictTable[lockmode] has a bit
* set for each type of lock that conflicts with mine. Bitwise
* set for each type of lock that conflicts with mine. Bitwise
* compare tells if there is a conflict.
* compare tells if there is a conflict.
* ----------------------------
* ----------------------------
*/
*/
if
(
!
(
lockctl
->
conflictTab
[
lockmode
]
&
lock
->
m
ask
))
if
(
!
(
lockctl
->
conflictTab
[
lockmode
]
&
lock
->
grantM
ask
))
{
{
HOLDER_PRINT
(
"LockResolveConflicts: no conflict"
,
holder
);
HOLDER_PRINT
(
"LockResolveConflicts: no conflict"
,
holder
);
return
STATUS_OK
;
return
STATUS_OK
;
...
@@ -807,11 +815,11 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
...
@@ -807,11 +815,11 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
* process under another XID also count as "our own locks".
* process under another XID also count as "our own locks".
* ------------------------
* ------------------------
*/
*/
if
(
myHold
ers
==
NULL
)
if
(
myHold
ing
==
NULL
)
{
{
/* Caller didn't do calculation of total holding for me */
/* Caller didn't do calculation of total holding for me */
LockCountMyLocks
(
holder
->
tag
.
lock
,
proc
,
localHold
ers
);
LockCountMyLocks
(
holder
->
tag
.
lock
,
proc
,
localHold
ing
);
myHold
ers
=
localHolders
;
myHold
ing
=
localHolding
;
}
}
/* Compute mask of lock types held by other processes */
/* Compute mask of lock types held by other processes */
...
@@ -819,7 +827,7 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
...
@@ -819,7 +827,7 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
tmpMask
=
2
;
tmpMask
=
2
;
for
(
i
=
1
;
i
<=
numLockModes
;
i
++
,
tmpMask
<<=
1
)
for
(
i
=
1
;
i
<=
numLockModes
;
i
++
,
tmpMask
<<=
1
)
{
{
if
(
lock
->
activeHolders
[
i
]
!=
myHolders
[
i
])
if
(
lock
->
granted
[
i
]
!=
myHolding
[
i
])
bitmask
|=
tmpMask
;
bitmask
|=
tmpMask
;
}
}
...
@@ -852,20 +860,20 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
...
@@ -852,20 +860,20 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
* be a net slowdown.
* be a net slowdown.
*/
*/
static
void
static
void
LockCountMyLocks
(
SHMEM_OFFSET
lockOffset
,
PROC
*
proc
,
int
*
myHold
ers
)
LockCountMyLocks
(
SHMEM_OFFSET
lockOffset
,
PROC
*
proc
,
int
*
myHold
ing
)
{
{
HOLDER
*
holder
=
NULL
;
HOLDER
*
holder
=
NULL
;
HOLDER
*
nextHolder
=
NULL
;
HOLDER
*
nextHolder
=
NULL
;
SHM_QUEUE
*
lockQueue
=
&
(
proc
->
lock
Queue
);
SHM_QUEUE
*
holderQueue
=
&
(
proc
->
holder
Queue
);
SHMEM_OFFSET
end
=
MAKE_OFFSET
(
lock
Queue
);
SHMEM_OFFSET
end
=
MAKE_OFFSET
(
holder
Queue
);
int
i
;
int
i
;
MemSet
(
myHold
ers
,
0
,
MAX_LOCKMODES
*
sizeof
(
int
));
MemSet
(
myHold
ing
,
0
,
MAX_LOCKMODES
*
sizeof
(
int
));
if
(
SHMQueueEmpty
(
lock
Queue
))
if
(
SHMQueueEmpty
(
holder
Queue
))
return
;
return
;
SHMQueueFirst
(
lock
Queue
,
(
Pointer
*
)
&
holder
,
&
holder
->
queue
);
SHMQueueFirst
(
holder
Queue
,
(
Pointer
*
)
&
holder
,
&
holder
->
queue
);
do
do
{
{
...
@@ -885,7 +893,7 @@ LockCountMyLocks(SHMEM_OFFSET lockOffset, PROC *proc, int *myHolders)
...
@@ -885,7 +893,7 @@ LockCountMyLocks(SHMEM_OFFSET lockOffset, PROC *proc, int *myHolders)
{
{
for
(
i
=
1
;
i
<
MAX_LOCKMODES
;
i
++
)
for
(
i
=
1
;
i
<
MAX_LOCKMODES
;
i
++
)
{
{
myHold
ers
[
i
]
+=
holder
->
holders
[
i
];
myHold
ing
[
i
]
+=
holder
->
holding
[
i
];
}
}
}
}
...
@@ -894,47 +902,47 @@ LockCountMyLocks(SHMEM_OFFSET lockOffset, PROC *proc, int *myHolders)
...
@@ -894,47 +902,47 @@ LockCountMyLocks(SHMEM_OFFSET lockOffset, PROC *proc, int *myHolders)
}
}
/*
/*
* LockGetMyH
o
ldLocks -- compute bitmask of lock types held by a process
* LockGetMyH
e
ldLocks -- compute bitmask of lock types held by a process
* for a given lockable object.
* for a given lockable object.
*/
*/
static
int
static
int
LockGetMyH
o
ldLocks
(
SHMEM_OFFSET
lockOffset
,
PROC
*
proc
)
LockGetMyH
e
ldLocks
(
SHMEM_OFFSET
lockOffset
,
PROC
*
proc
)
{
{
int
myHold
ers
[
MAX_LOCKMODES
];
int
myHold
ing
[
MAX_LOCKMODES
];
int
h
oldLock
=
0
;
int
h
eldLocks
=
0
;
int
i
,
int
i
,
tmpMask
;
tmpMask
;
LockCountMyLocks
(
lockOffset
,
proc
,
myHold
ers
);
LockCountMyLocks
(
lockOffset
,
proc
,
myHold
ing
);
for
(
i
=
1
,
tmpMask
=
2
;
for
(
i
=
1
,
tmpMask
=
2
;
i
<
MAX_LOCKMODES
;
i
<
MAX_LOCKMODES
;
i
++
,
tmpMask
<<=
1
)
i
++
,
tmpMask
<<=
1
)
{
{
if
(
myHold
ers
[
i
]
>
0
)
if
(
myHold
ing
[
i
]
>
0
)
h
oldLock
|=
tmpMask
;
h
eldLocks
|=
tmpMask
;
}
}
return
h
oldLock
;
return
h
eldLocks
;
}
}
/*
/*
* GrantLock -- update the lock and holder data structures to show
* GrantLock -- update the lock and holder data structures to show
* the
new lock
has been granted.
* the
lock request
has been granted.
*/
*/
void
void
GrantLock
(
LOCK
*
lock
,
HOLDER
*
holder
,
LOCKMODE
lockmode
)
GrantLock
(
LOCK
*
lock
,
HOLDER
*
holder
,
LOCKMODE
lockmode
)
{
{
lock
->
n
Active
++
;
lock
->
n
Granted
++
;
lock
->
activeHolders
[
lockmode
]
++
;
lock
->
granted
[
lockmode
]
++
;
lock
->
m
ask
|=
BITS_ON
[
lockmode
];
lock
->
grantM
ask
|=
BITS_ON
[
lockmode
];
if
(
lock
->
activeHolders
[
lockmode
]
==
lock
->
holders
[
lockmode
])
if
(
lock
->
granted
[
lockmode
]
==
lock
->
requested
[
lockmode
])
lock
->
waitMask
&=
BITS_OFF
[
lockmode
];
lock
->
waitMask
&=
BITS_OFF
[
lockmode
];
LOCK_PRINT
(
"GrantLock"
,
lock
,
lockmode
);
LOCK_PRINT
(
"GrantLock"
,
lock
,
lockmode
);
Assert
((
lock
->
n
Active
>
0
)
&&
(
lock
->
activeHolders
[
lockmode
]
>
0
));
Assert
((
lock
->
n
Granted
>
0
)
&&
(
lock
->
granted
[
lockmode
]
>
0
));
Assert
(
lock
->
n
Active
<=
lock
->
nHolding
);
Assert
(
lock
->
n
Granted
<=
lock
->
nRequested
);
holder
->
hold
ers
[
lockmode
]
++
;
holder
->
hold
ing
[
lockmode
]
++
;
holder
->
nHolding
++
;
holder
->
nHolding
++
;
Assert
((
holder
->
nHolding
>
0
)
&&
(
holder
->
hold
ers
[
lockmode
]
>
0
));
Assert
((
holder
->
nHolding
>
0
)
&&
(
holder
->
hold
ing
[
lockmode
]
>
0
));
}
}
/*
/*
...
@@ -952,14 +960,6 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
...
@@ -952,14 +960,6 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
Assert
(
lockmethod
<
NumLockMethods
);
Assert
(
lockmethod
<
NumLockMethods
);
/*
* the waitqueue is ordered by priority. I insert myself according to
* the priority of the lock I am acquiring.
*
* SYNC NOTE: I am assuming that the lock table spinlock is sufficient
* synchronization for this queue. That will not be true if/when
* people can be deleted from the queue by a SIGINT or something.
*/
LOCK_PRINT
(
"WaitOnLock: sleeping on lock"
,
lock
,
lockmode
);
LOCK_PRINT
(
"WaitOnLock: sleeping on lock"
,
lock
,
lockmode
);
old_status
=
pstrdup
(
get_ps_display
());
old_status
=
pstrdup
(
get_ps_display
());
...
@@ -971,7 +971,7 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
...
@@ -971,7 +971,7 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
/*
/*
* NOTE: Think not to put any lock state cleanup after the call to
* NOTE: Think not to put any lock state cleanup after the call to
* ProcSleep, in either the normal or failure path. The lock state
* ProcSleep, in either the normal or failure path. The lock state
* must be fully set by the lock grantor, or by HandleDead
l
ock if we
* must be fully set by the lock grantor, or by HandleDead
L
ock if we
* give up waiting for the lock. This is necessary because of the
* give up waiting for the lock. This is necessary because of the
* possibility that a cancel/die interrupt will interrupt ProcSleep
* possibility that a cancel/die interrupt will interrupt ProcSleep
* after someone else grants us the lock, but before we've noticed it.
* after someone else grants us the lock, but before we've noticed it.
...
@@ -1074,9 +1074,6 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -1074,9 +1074,6 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
return
FALSE
;
return
FALSE
;
}
}
LOCK_PRINT
(
"LockRelease: found"
,
lock
,
lockmode
);
LOCK_PRINT
(
"LockRelease: found"
,
lock
,
lockmode
);
Assert
((
lock
->
nHolding
>
0
)
&&
(
lock
->
holders
[
lockmode
]
>=
0
));
Assert
((
lock
->
nActive
>
0
)
&&
(
lock
->
activeHolders
[
lockmode
]
>=
0
));
Assert
(
lock
->
nActive
<=
lock
->
nHolding
);
/*
/*
* Find the holder entry for this holder.
* Find the holder entry for this holder.
...
@@ -1107,29 +1104,32 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -1107,29 +1104,32 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
* Check that we are actually holding a lock of the type we want to
* Check that we are actually holding a lock of the type we want to
* release.
* release.
*/
*/
if
(
!
(
holder
->
hold
ers
[
lockmode
]
>
0
))
if
(
!
(
holder
->
hold
ing
[
lockmode
]
>
0
))
{
{
SpinRelease
(
masterLock
);
SpinRelease
(
masterLock
);
HOLDER_PRINT
(
"LockRelease: WRONGTYPE"
,
holder
);
HOLDER_PRINT
(
"LockRelease: WRONGTYPE"
,
holder
);
elog
(
NOTICE
,
"LockRelease: you don't own a lock of type %s"
,
elog
(
NOTICE
,
"LockRelease: you don't own a lock of type %s"
,
lock_types
[
lockmode
]);
lock_types
[
lockmode
]);
Assert
(
holder
->
hold
ers
[
lockmode
]
>=
0
);
Assert
(
holder
->
hold
ing
[
lockmode
]
>=
0
);
return
FALSE
;
return
FALSE
;
}
}
Assert
(
holder
->
nHolding
>
0
);
Assert
(
holder
->
nHolding
>
0
);
Assert
((
lock
->
nRequested
>
0
)
&&
(
lock
->
requested
[
lockmode
]
>
0
));
Assert
((
lock
->
nGranted
>
0
)
&&
(
lock
->
granted
[
lockmode
]
>
0
));
Assert
(
lock
->
nGranted
<=
lock
->
nRequested
);
/*
/*
* fix the general lock stats
* fix the general lock stats
*/
*/
lock
->
n
Holding
--
;
lock
->
n
Requested
--
;
lock
->
holders
[
lockmode
]
--
;
lock
->
requested
[
lockmode
]
--
;
lock
->
n
Active
--
;
lock
->
n
Granted
--
;
lock
->
activeHolders
[
lockmode
]
--
;
lock
->
granted
[
lockmode
]
--
;
if
(
!
(
lock
->
activeHolders
[
lockmode
])
)
if
(
lock
->
granted
[
lockmode
]
==
0
)
{
{
/* change the conflict mask. No more of this lock type. */
/* change the conflict mask. No more of this lock type. */
lock
->
m
ask
&=
BITS_OFF
[
lockmode
];
lock
->
grantM
ask
&=
BITS_OFF
[
lockmode
];
}
}
#ifdef NOT_USED
#ifdef NOT_USED
...
@@ -1139,14 +1139,14 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -1139,14 +1139,14 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
* with the remaining locks.
* with the remaining locks.
* --------------------------
* --------------------------
*/
*/
if
(
lock
->
activeHolders
[
lockmode
])
if
(
lock
->
granted
[
lockmode
])
wakeupNeeded
=
false
;
wakeupNeeded
=
false
;
else
else
#endif
#endif
/*
/*
* Above is not valid any more (due to MVCC lock modes). Actually
* Above is not valid any more (due to MVCC lock modes). Actually
* we should compare
activeHolders
[lockmode] with number of
* we should compare
granted
[lockmode] with number of
* waiters holding lock of this type and try to wakeup only if
* waiters holding lock of this type and try to wakeup only if
* these numbers are equal (and lock released conflicts with locks
* these numbers are equal (and lock released conflicts with locks
* requested by waiters). For the moment we only check the last
* requested by waiters). For the moment we only check the last
...
@@ -1156,11 +1156,11 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -1156,11 +1156,11 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
wakeupNeeded
=
true
;
wakeupNeeded
=
true
;
LOCK_PRINT
(
"LockRelease: updated"
,
lock
,
lockmode
);
LOCK_PRINT
(
"LockRelease: updated"
,
lock
,
lockmode
);
Assert
((
lock
->
n
Holding
>=
0
)
&&
(
lock
->
holders
[
lockmode
]
>=
0
));
Assert
((
lock
->
n
Requested
>=
0
)
&&
(
lock
->
requested
[
lockmode
]
>=
0
));
Assert
((
lock
->
n
Active
>=
0
)
&&
(
lock
->
activeHolders
[
lockmode
]
>=
0
));
Assert
((
lock
->
n
Granted
>=
0
)
&&
(
lock
->
granted
[
lockmode
]
>=
0
));
Assert
(
lock
->
n
Active
<=
lock
->
nHolding
);
Assert
(
lock
->
n
Granted
<=
lock
->
nRequested
);
if
(
!
lock
->
n
Holding
)
if
(
!
lock
->
n
Requested
)
{
{
/* ------------------
/* ------------------
* if there's no one waiting in the queue,
* if there's no one waiting in the queue,
...
@@ -1180,10 +1180,10 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
...
@@ -1180,10 +1180,10 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
/*
/*
* Now fix the per-holder lock stats.
* Now fix the per-holder lock stats.
*/
*/
holder
->
hold
ers
[
lockmode
]
--
;
holder
->
hold
ing
[
lockmode
]
--
;
holder
->
nHolding
--
;
holder
->
nHolding
--
;
HOLDER_PRINT
(
"LockRelease: updated"
,
holder
);
HOLDER_PRINT
(
"LockRelease: updated"
,
holder
);
Assert
((
holder
->
nHolding
>=
0
)
&&
(
holder
->
hold
ers
[
lockmode
]
>=
0
));
Assert
((
holder
->
nHolding
>=
0
)
&&
(
holder
->
hold
ing
[
lockmode
]
>=
0
));
/*
/*
* If this was my last hold on this lock, delete my entry in the holder
* If this was my last hold on this lock, delete my entry in the holder
...
@@ -1236,8 +1236,8 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
...
@@ -1236,8 +1236,8 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
{
{
HOLDER
*
holder
=
NULL
;
HOLDER
*
holder
=
NULL
;
HOLDER
*
nextHolder
=
NULL
;
HOLDER
*
nextHolder
=
NULL
;
SHM_QUEUE
*
lockQueue
=
&
(
proc
->
lock
Queue
);
SHM_QUEUE
*
holderQueue
=
&
(
proc
->
holder
Queue
);
SHMEM_OFFSET
end
=
MAKE_OFFSET
(
lock
Queue
);
SHMEM_OFFSET
end
=
MAKE_OFFSET
(
holder
Queue
);
SPINLOCK
masterLock
;
SPINLOCK
masterLock
;
LOCKMETHODTABLE
*
lockMethodTable
;
LOCKMETHODTABLE
*
lockMethodTable
;
int
i
,
int
i
,
...
@@ -1260,7 +1260,7 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
...
@@ -1260,7 +1260,7 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
return
FALSE
;
return
FALSE
;
}
}
if
(
SHMQueueEmpty
(
lock
Queue
))
if
(
SHMQueueEmpty
(
holder
Queue
))
return
TRUE
;
return
TRUE
;
numLockModes
=
lockMethodTable
->
ctl
->
numLockModes
;
numLockModes
=
lockMethodTable
->
ctl
->
numLockModes
;
...
@@ -1268,7 +1268,7 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
...
@@ -1268,7 +1268,7 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
SpinAcquire
(
masterLock
);
SpinAcquire
(
masterLock
);
SHMQueueFirst
(
lock
Queue
,
(
Pointer
*
)
&
holder
,
&
holder
->
queue
);
SHMQueueFirst
(
holder
Queue
,
(
Pointer
*
)
&
holder
,
&
holder
->
queue
);
nleft
=
0
;
nleft
=
0
;
...
@@ -1308,53 +1308,55 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
...
@@ -1308,53 +1308,55 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
HOLDER_PRINT
(
"LockReleaseAll"
,
holder
);
HOLDER_PRINT
(
"LockReleaseAll"
,
holder
);
LOCK_PRINT
(
"LockReleaseAll"
,
lock
,
0
);
LOCK_PRINT
(
"LockReleaseAll"
,
lock
,
0
);
Assert
(
lock
->
n
Holding
>
0
);
Assert
(
lock
->
n
Requested
>=
0
);
Assert
(
lock
->
n
Active
>
0
);
Assert
(
lock
->
n
Granted
>=
0
);
Assert
(
lock
->
n
Active
<=
lock
->
nHolding
);
Assert
(
lock
->
n
Granted
<=
lock
->
nRequested
);
Assert
(
holder
->
nHolding
>=
0
);
Assert
(
holder
->
nHolding
>=
0
);
Assert
(
holder
->
nHolding
<=
lock
->
n
Holding
);
Assert
(
holder
->
nHolding
<=
lock
->
n
Requested
);
/* ------------------
/* ------------------
* fix the general lock stats
* fix the general lock stats
* ------------------
* ------------------
*/
*/
if
(
lock
->
n
Holding
!=
holder
->
nHolding
)
if
(
lock
->
n
Requested
!=
holder
->
nHolding
)
{
{
for
(
i
=
1
;
i
<=
numLockModes
;
i
++
)
for
(
i
=
1
;
i
<=
numLockModes
;
i
++
)
{
{
Assert
(
holder
->
hold
ers
[
i
]
>=
0
);
Assert
(
holder
->
hold
ing
[
i
]
>=
0
);
lock
->
holders
[
i
]
-=
holder
->
holders
[
i
];
if
(
holder
->
holding
[
i
]
>
0
)
lock
->
activeHolders
[
i
]
-=
holder
->
holders
[
i
];
{
Assert
((
lock
->
holders
[
i
]
>=
0
)
\
lock
->
requested
[
i
]
-=
holder
->
holding
[
i
];
&&
(
lock
->
activeHolders
[
i
]
>=
0
))
;
lock
->
granted
[
i
]
-=
holder
->
holding
[
i
]
;
if
(
!
lock
->
activeHolders
[
i
])
Assert
(
lock
->
requested
[
i
]
>=
0
&&
lock
->
granted
[
i
]
>=
0
);
lock
->
mask
&=
BITS_OFF
[
i
];
if
(
lock
->
granted
[
i
]
==
0
)
lock
->
grantMask
&=
BITS_OFF
[
i
];
/*
/*
* Read comments in LockRelease
* Read comments in LockRelease
*/
*/
if
(
!
wakeupNeeded
&&
holder
->
holders
[
i
]
>
0
&&
if
(
!
wakeupNeeded
&&
lockMethodTable
->
ctl
->
conflictTab
[
i
]
&
lock
->
waitMask
)
lockMethodTable
->
ctl
->
conflictTab
[
i
]
&
lock
->
waitMask
)
wakeupNeeded
=
true
;
wakeupNeeded
=
true
;
}
}
lock
->
nHolding
-=
holder
->
nHolding
;
}
lock
->
nActive
-=
holder
->
nHolding
;
lock
->
nRequested
-=
holder
->
nHolding
;
Assert
((
lock
->
nHolding
>=
0
)
&&
(
lock
->
nActive
>=
0
));
lock
->
nGranted
-=
holder
->
nHolding
;
Assert
(
lock
->
nActive
<=
lock
->
nHolding
);
Assert
((
lock
->
nRequested
>=
0
)
&&
(
lock
->
nGranted
>=
0
));
Assert
(
lock
->
nGranted
<=
lock
->
nRequested
);
}
}
else
else
{
{
/* --------------
/* --------------
* set n
Holding
to zero so that we can garbage collect the lock
* set n
Requested
to zero so that we can garbage collect the lock
* down below...
* down below...
* --------------
* --------------
*/
*/
lock
->
nHolding
=
0
;
lock
->
nRequested
=
0
;
lock
->
nGranted
=
0
;
/* Fix the lock status, just for next LOCK_PRINT message. */
/* Fix the lock status, just for next LOCK_PRINT message. */
for
(
i
=
1
;
i
<=
numLockModes
;
i
++
)
for
(
i
=
1
;
i
<=
numLockModes
;
i
++
)
{
{
Assert
(
lock
->
holders
[
i
]
==
lock
->
activeHolders
[
i
]);
Assert
(
lock
->
requested
[
i
]
==
lock
->
granted
[
i
]);
lock
->
holders
[
i
]
=
lock
->
activeHolders
[
i
]
=
0
;
lock
->
requested
[
i
]
=
lock
->
granted
[
i
]
=
0
;
}
}
}
}
LOCK_PRINT
(
"LockReleaseAll: updated"
,
lock
,
0
);
LOCK_PRINT
(
"LockReleaseAll: updated"
,
lock
,
0
);
...
@@ -1380,11 +1382,11 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
...
@@ -1380,11 +1382,11 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
return
FALSE
;
return
FALSE
;
}
}
if
(
!
lock
->
n
Holding
)
if
(
!
lock
->
n
Requested
)
{
{
/* --------------------
/* --------------------
*
if there's no one waiting in the queue, we've just released
*
We've just released the last lock, so garbage-collect the
*
the last lock
.
*
lock object
.
* --------------------
* --------------------
*/
*/
LOCK_PRINT
(
"LockReleaseAll: deleting"
,
lock
,
0
);
LOCK_PRINT
(
"LockReleaseAll: deleting"
,
lock
,
0
);
...
@@ -1413,12 +1415,13 @@ next_item:
...
@@ -1413,12 +1415,13 @@ next_item:
{
{
#ifdef LOCK_DEBUG
#ifdef LOCK_DEBUG
if
(
lockmethod
==
USER_LOCKMETHOD
?
Trace_userlocks
:
Trace_locks
)
if
(
lockmethod
==
USER_LOCKMETHOD
?
Trace_userlocks
:
Trace_locks
)
elog
(
DEBUG
,
"LockReleaseAll: reinitializing
lock
Queue"
);
elog
(
DEBUG
,
"LockReleaseAll: reinitializing
holder
Queue"
);
#endif
#endif
SHMQueueInit
(
lock
Queue
);
SHMQueueInit
(
holder
Queue
);
}
}
SpinRelease
(
masterLock
);
SpinRelease
(
masterLock
);
#ifdef LOCK_DEBUG
#ifdef LOCK_DEBUG
if
(
lockmethod
==
USER_LOCKMETHOD
?
Trace_userlocks
:
Trace_locks
)
if
(
lockmethod
==
USER_LOCKMETHOD
?
Trace_userlocks
:
Trace_locks
)
elog
(
DEBUG
,
"LockReleaseAll: done"
);
elog
(
DEBUG
,
"LockReleaseAll: done"
);
...
@@ -1457,16 +1460,17 @@ LockShmemSize(int maxBackends)
...
@@ -1457,16 +1460,17 @@ LockShmemSize(int maxBackends)
}
}
/*
/*
* DeadlockCheck -- Checks for deadlocks for a given process
* DeadLockCheck -- Checks for deadlocks for a given process
*
* We can't block on user locks, so no sense testing for deadlock
* because there is no blocking, and no timer for the block.
*
*
* This code takes a list of locks a process holds, and the lock that
* This code takes a list of locks a process holds, and the lock that
* the process is sleeping on, and tries to find if any of the processes
* the process is sleeping on, and tries to find if any of the processes
* waiting on its locks hold the lock it is waiting for. If no deadlock
* waiting on its locks hold the lock it is waiting for. If no deadlock
* is found, it goes on to look at all the processes waiting on their locks.
* is found, it goes on to look at all the processes waiting on their locks.
*
*
* We can't block on user locks, so no sense testing for deadlock
* because there is no blocking, and no timer for the block. So,
* only look at regular locks.
*
* We have already locked the master lock before being called.
* We have already locked the master lock before being called.
*/
*/
bool
bool
...
@@ -1476,8 +1480,8 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
...
@@ -1476,8 +1480,8 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
HOLDER
*
nextHolder
=
NULL
;
HOLDER
*
nextHolder
=
NULL
;
PROC
*
waitProc
;
PROC
*
waitProc
;
PROC_QUEUE
*
waitQueue
;
PROC_QUEUE
*
waitQueue
;
SHM_QUEUE
*
lockQueue
=
&
(
thisProc
->
lock
Queue
);
SHM_QUEUE
*
holderQueue
=
&
(
thisProc
->
holder
Queue
);
SHMEM_OFFSET
end
=
MAKE_OFFSET
(
lock
Queue
);
SHMEM_OFFSET
end
=
MAKE_OFFSET
(
holder
Queue
);
LOCKMETHODCTL
*
lockctl
=
LockMethodTable
[
DEFAULT_LOCKMETHOD
]
->
ctl
;
LOCKMETHODCTL
*
lockctl
=
LockMethodTable
[
DEFAULT_LOCKMETHOD
]
->
ctl
;
LOCK
*
lock
;
LOCK
*
lock
;
int
i
,
int
i
,
...
@@ -1494,10 +1498,13 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
...
@@ -1494,10 +1498,13 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
nprocs
=
1
;
nprocs
=
1
;
}
}
if
(
SHMQueueEmpty
(
lockQueue
))
/*
* Scan over all the locks held/awaited by thisProc.
*/
if
(
SHMQueueEmpty
(
holderQueue
))
return
false
;
return
false
;
SHMQueueFirst
(
lock
Queue
,
(
Pointer
*
)
&
holder
,
&
holder
->
queue
);
SHMQueueFirst
(
holder
Queue
,
(
Pointer
*
)
&
holder
,
&
holder
->
queue
);
do
do
{
{
...
@@ -1525,7 +1532,7 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
...
@@ -1525,7 +1532,7 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
LOCK_PRINT
(
"DeadLockCheck"
,
lock
,
0
);
LOCK_PRINT
(
"DeadLockCheck"
,
lock
,
0
);
/*
/*
* waitLock is always in
lock
Queue of waiting proc, if !first_run
* waitLock is always in
holder
Queue of waiting proc, if !first_run
* then upper caller will handle waitProcs queue of waitLock.
* then upper caller will handle waitProcs queue of waitLock.
*/
*/
if
(
thisProc
->
waitLock
==
lock
&&
!
first_run
)
if
(
thisProc
->
waitLock
==
lock
&&
!
first_run
)
...
@@ -1542,13 +1549,13 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
...
@@ -1542,13 +1549,13 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
Assert
(
holder
->
nHolding
>
0
);
Assert
(
holder
->
nHolding
>
0
);
for
(
lm
=
1
;
lm
<=
lockctl
->
numLockModes
;
lm
++
)
for
(
lm
=
1
;
lm
<=
lockctl
->
numLockModes
;
lm
++
)
{
{
if
(
holder
->
hold
ers
[
lm
]
>
0
&&
if
(
holder
->
hold
ing
[
lm
]
>
0
&&
lockctl
->
conflictTab
[
lm
]
&
findlock
->
waitMask
)
lockctl
->
conflictTab
[
lm
]
&
findlock
->
waitMask
)
return
true
;
return
true
;
}
}
/*
/*
* Else - get the next lock from thisProc's
lock
Queue
* Else - get the next lock from thisProc's
holder
Queue
*/
*/
goto
nxtl
;
goto
nxtl
;
}
}
...
@@ -1557,6 +1564,8 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
...
@@ -1557,6 +1564,8 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
waitProc
=
(
PROC
*
)
MAKE_PTR
(
waitQueue
->
links
.
prev
);
waitProc
=
(
PROC
*
)
MAKE_PTR
(
waitQueue
->
links
.
prev
);
/*
/*
* Inner loop scans over all processes waiting for this lock.
*
* NOTE: loop must count down because we want to examine each item
* NOTE: loop must count down because we want to examine each item
* in the queue even if waitQueue->size decreases due to waking up
* in the queue even if waitQueue->size decreases due to waking up
* some of the processes.
* some of the processes.
...
@@ -1573,14 +1582,14 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
...
@@ -1573,14 +1582,14 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
if
(
lock
==
findlock
)
/* first_run also true */
if
(
lock
==
findlock
)
/* first_run also true */
{
{
/*
/*
* If
me blocked by his holdlock
...
* If
I'm blocked by his heldLocks
...
*/
*/
if
(
lockctl
->
conflictTab
[
MyProc
->
waitLockMode
]
&
waitProc
->
h
oldLock
)
if
(
lockctl
->
conflictTab
[
MyProc
->
waitLockMode
]
&
waitProc
->
h
eldLocks
)
{
{
/* and he blocked by me -> deadlock */
/* and he blocked by me -> deadlock */
if
(
lockctl
->
conflictTab
[
waitProc
->
waitLockMode
]
&
MyProc
->
h
oldLock
)
if
(
lockctl
->
conflictTab
[
waitProc
->
waitLockMode
]
&
MyProc
->
h
eldLocks
)
return
true
;
return
true
;
/* we shouldn't look at
lock
Queue of our blockers */
/* we shouldn't look at
holder
Queue of our blockers */
goto
nextWaitProc
;
goto
nextWaitProc
;
}
}
...
@@ -1591,11 +1600,11 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
...
@@ -1591,11 +1600,11 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
* implicitly). Note that we don't do like test if
* implicitly). Note that we don't do like test if
* !first_run (when thisProc is holder and non-waiter on
* !first_run (when thisProc is holder and non-waiter on
* lock) and so we call DeadLockCheck below for every
* lock) and so we call DeadLockCheck below for every
* waitProc in thisProc->
lock
Queue, even for waitProc-s
* waitProc in thisProc->
holder
Queue, even for waitProc-s
* un-blocked by thisProc. Should we? This could save us
* un-blocked by thisProc. Should we? This could save us
* some time...
* some time...
*/
*/
if
(
!
(
lockctl
->
conflictTab
[
waitProc
->
waitLockMode
]
&
MyProc
->
h
oldLock
)
&&
if
(
!
(
lockctl
->
conflictTab
[
waitProc
->
waitLockMode
]
&
MyProc
->
h
eldLocks
)
&&
!
(
lockctl
->
conflictTab
[
waitProc
->
waitLockMode
]
&
(
1
<<
MyProc
->
waitLockMode
)))
!
(
lockctl
->
conflictTab
[
waitProc
->
waitLockMode
]
&
(
1
<<
MyProc
->
waitLockMode
)))
goto
nextWaitProc
;
goto
nextWaitProc
;
}
}
...
@@ -1609,13 +1618,13 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
...
@@ -1609,13 +1618,13 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
goto
nextWaitProc
;
goto
nextWaitProc
;
}
}
/* Recursively check this process's
lock
Queue. */
/* Recursively check this process's
holder
Queue. */
Assert
(
nprocs
<
MAXBACKENDS
);
Assert
(
nprocs
<
MAXBACKENDS
);
checked_procs
[
nprocs
++
]
=
waitProc
;
checked_procs
[
nprocs
++
]
=
waitProc
;
if
(
DeadLockCheck
(
waitProc
,
findlock
))
if
(
DeadLockCheck
(
waitProc
,
findlock
))
{
{
int
h
oldLock
;
int
h
eldLocks
;
/*
/*
* Ok, but is waitProc waiting for me (thisProc) ?
* Ok, but is waitProc waiting for me (thisProc) ?
...
@@ -1623,15 +1632,15 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
...
@@ -1623,15 +1632,15 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
if
(
thisProc
->
waitLock
==
lock
)
if
(
thisProc
->
waitLock
==
lock
)
{
{
Assert
(
first_run
);
Assert
(
first_run
);
h
oldLock
=
thisProc
->
holdLock
;
h
eldLocks
=
thisProc
->
heldLocks
;
}
}
else
else
{
{
/* should we cache h
oldLock
to speed this up? */
/* should we cache h
eldLocks
to speed this up? */
h
oldLock
=
LockGetMyHo
ldLocks
(
holder
->
tag
.
lock
,
thisProc
);
h
eldLocks
=
LockGetMyHe
ldLocks
(
holder
->
tag
.
lock
,
thisProc
);
Assert
(
h
oldLock
!=
0
);
Assert
(
h
eldLocks
!=
0
);
}
}
if
(
lockctl
->
conflictTab
[
waitProc
->
waitLockMode
]
&
h
oldLock
)
if
(
lockctl
->
conflictTab
[
waitProc
->
waitLockMode
]
&
h
eldLocks
)
{
{
/*
/*
* Last attempt to avoid deadlock: try to wakeup myself.
* Last attempt to avoid deadlock: try to wakeup myself.
...
@@ -1703,7 +1712,7 @@ nxtl:
...
@@ -1703,7 +1712,7 @@ nxtl:
#ifdef LOCK_DEBUG
#ifdef LOCK_DEBUG
/*
/*
* Dump all locks in the proc->
lock
Queue. Must have already acquired
* Dump all locks in the proc->
holder
Queue. Must have already acquired
* the masterLock.
* the masterLock.
*/
*/
void
void
...
@@ -1711,7 +1720,7 @@ DumpLocks(void)
...
@@ -1711,7 +1720,7 @@ DumpLocks(void)
{
{
SHMEM_OFFSET
location
;
SHMEM_OFFSET
location
;
PROC
*
proc
;
PROC
*
proc
;
SHM_QUEUE
*
lock
Queue
;
SHM_QUEUE
*
holder
Queue
;
HOLDER
*
holder
=
NULL
;
HOLDER
*
holder
=
NULL
;
HOLDER
*
nextHolder
=
NULL
;
HOLDER
*
nextHolder
=
NULL
;
SHMEM_OFFSET
end
;
SHMEM_OFFSET
end
;
...
@@ -1725,8 +1734,8 @@ DumpLocks(void)
...
@@ -1725,8 +1734,8 @@ DumpLocks(void)
proc
=
(
PROC
*
)
MAKE_PTR
(
location
);
proc
=
(
PROC
*
)
MAKE_PTR
(
location
);
if
(
proc
!=
MyProc
)
if
(
proc
!=
MyProc
)
return
;
return
;
lockQueue
=
&
proc
->
lock
Queue
;
holderQueue
=
&
proc
->
holder
Queue
;
end
=
MAKE_OFFSET
(
lock
Queue
);
end
=
MAKE_OFFSET
(
holder
Queue
);
Assert
(
lockmethod
<
NumLockMethods
);
Assert
(
lockmethod
<
NumLockMethods
);
lockMethodTable
=
LockMethodTable
[
lockmethod
];
lockMethodTable
=
LockMethodTable
[
lockmethod
];
...
@@ -1736,10 +1745,10 @@ DumpLocks(void)
...
@@ -1736,10 +1745,10 @@ DumpLocks(void)
if
(
proc
->
waitLock
)
if
(
proc
->
waitLock
)
LOCK_PRINT
(
"DumpLocks: waiting on"
,
proc
->
waitLock
,
0
);
LOCK_PRINT
(
"DumpLocks: waiting on"
,
proc
->
waitLock
,
0
);
if
(
SHMQueueEmpty
(
lock
Queue
))
if
(
SHMQueueEmpty
(
holder
Queue
))
return
;
return
;
SHMQueueFirst
(
lock
Queue
,
(
Pointer
*
)
&
holder
,
&
holder
->
queue
);
SHMQueueFirst
(
holder
Queue
,
(
Pointer
*
)
&
holder
,
&
holder
->
queue
);
do
do
{
{
...
...
src/backend/storage/lmgr/proc.c
View file @
64e6c608
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.9
2 2001/01/14 05:08:16
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.9
3 2001/01/16 06:11:34
tgl Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -48,7 +48,7 @@
...
@@ -48,7 +48,7 @@
* This is so that we can support more backends. (system-wide semaphore
* This is so that we can support more backends. (system-wide semaphore
* sets run out pretty fast.) -ay 4/95
* sets run out pretty fast.) -ay 4/95
*
*
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.9
2 2001/01/14 05:08:16
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.9
3 2001/01/16 06:11:34
tgl Exp $
*/
*/
#include "postgres.h"
#include "postgres.h"
...
@@ -230,7 +230,7 @@ InitProcess(void)
...
@@ -230,7 +230,7 @@ InitProcess(void)
}
}
/* this cannot be initialized until after the buffer pool */
/* this cannot be initialized until after the buffer pool */
SHMQueueInit
(
&
(
MyProc
->
lock
Queue
));
SHMQueueInit
(
&
(
MyProc
->
holder
Queue
));
}
}
/*
/*
...
@@ -311,8 +311,8 @@ ZeroProcSemaphore(PROC *proc)
...
@@ -311,8 +311,8 @@ ZeroProcSemaphore(PROC *proc)
* Locktable lock must be held by caller.
* Locktable lock must be held by caller.
*
*
* NB: this does not remove the process' holder object, nor the lock object,
* NB: this does not remove the process' holder object, nor the lock object,
* even though their
holder counts might now have gone to zero. That will
* even though their
counts might now have gone to zero. That will happen
*
happen
during a subsequent LockReleaseAll call, which we expect will happen
* during a subsequent LockReleaseAll call, which we expect will happen
* during transaction cleanup. (Removal of a proc from its wait queue by
* during transaction cleanup. (Removal of a proc from its wait queue by
* this routine can only happen if we are aborting the transaction.)
* this routine can only happen if we are aborting the transaction.)
*/
*/
...
@@ -331,14 +331,14 @@ RemoveFromWaitQueue(PROC *proc)
...
@@ -331,14 +331,14 @@ RemoveFromWaitQueue(PROC *proc)
SHMQueueDelete
(
&
(
proc
->
links
));
SHMQueueDelete
(
&
(
proc
->
links
));
waitLock
->
waitProcs
.
size
--
;
waitLock
->
waitProcs
.
size
--
;
/* Undo increments of
holder
counts by waiting process */
/* Undo increments of
request
counts by waiting process */
Assert
(
waitLock
->
n
Holding
>
0
);
Assert
(
waitLock
->
n
Requested
>
0
);
Assert
(
waitLock
->
n
Holding
>
proc
->
waitLock
->
nActive
);
Assert
(
waitLock
->
n
Requested
>
proc
->
waitLock
->
nGranted
);
waitLock
->
n
Holding
--
;
waitLock
->
n
Requested
--
;
Assert
(
waitLock
->
holders
[
lockmode
]
>
0
);
Assert
(
waitLock
->
requested
[
lockmode
]
>
0
);
waitLock
->
holders
[
lockmode
]
--
;
waitLock
->
requested
[
lockmode
]
--
;
/* don't forget to clear waitMask bit if appropriate */
/* don't forget to clear waitMask bit if appropriate */
if
(
waitLock
->
activeHolders
[
lockmode
]
==
waitLock
->
holders
[
lockmode
])
if
(
waitLock
->
granted
[
lockmode
]
==
waitLock
->
requested
[
lockmode
])
waitLock
->
waitMask
&=
~
(
1
<<
lockmode
);
waitLock
->
waitMask
&=
~
(
1
<<
lockmode
);
/* Clean up the proc's own state */
/* Clean up the proc's own state */
...
@@ -546,7 +546,7 @@ ProcSleep(LOCKMETHODCTL *lockctl,
...
@@ -546,7 +546,7 @@ ProcSleep(LOCKMETHODCTL *lockctl,
int
waitMask
=
lock
->
waitMask
;
int
waitMask
=
lock
->
waitMask
;
PROC
*
proc
;
PROC
*
proc
;
int
i
;
int
i
;
int
ahead
Holders
[
MAX_LOCKMODES
];
int
ahead
Granted
[
MAX_LOCKMODES
];
bool
selfConflict
=
(
lockctl
->
conflictTab
[
lockmode
]
&
myMask
),
bool
selfConflict
=
(
lockctl
->
conflictTab
[
lockmode
]
&
myMask
),
prevSame
=
false
;
prevSame
=
false
;
#ifndef __BEOS__
#ifndef __BEOS__
...
@@ -559,7 +559,7 @@ ProcSleep(LOCKMETHODCTL *lockctl,
...
@@ -559,7 +559,7 @@ ProcSleep(LOCKMETHODCTL *lockctl,
MyProc
->
waitLock
=
lock
;
MyProc
->
waitLock
=
lock
;
MyProc
->
waitHolder
=
holder
;
MyProc
->
waitHolder
=
holder
;
MyProc
->
waitLockMode
=
lockmode
;
MyProc
->
waitLockMode
=
lockmode
;
/* We assume the caller set up MyProc->h
oldLock
*/
/* We assume the caller set up MyProc->h
eldLocks
*/
proc
=
(
PROC
*
)
MAKE_PTR
(
waitQueue
->
links
.
prev
);
proc
=
(
PROC
*
)
MAKE_PTR
(
waitQueue
->
links
.
prev
);
...
@@ -567,57 +567,61 @@ ProcSleep(LOCKMETHODCTL *lockctl,
...
@@ -567,57 +567,61 @@ ProcSleep(LOCKMETHODCTL *lockctl,
if
(
!
(
lockctl
->
conflictTab
[
lockmode
]
&
waitMask
))
if
(
!
(
lockctl
->
conflictTab
[
lockmode
]
&
waitMask
))
goto
ins
;
goto
ins
;
/* otherwise, determine where we should go into the queue */
for
(
i
=
1
;
i
<
MAX_LOCKMODES
;
i
++
)
for
(
i
=
1
;
i
<
MAX_LOCKMODES
;
i
++
)
ahead
Holders
[
i
]
=
lock
->
activeHolders
[
i
];
ahead
Granted
[
i
]
=
lock
->
granted
[
i
];
(
ahead
Holders
[
lockmode
])
++
;
(
ahead
Granted
[
lockmode
])
++
;
for
(
i
=
0
;
i
<
waitQueue
->
size
;
i
++
)
for
(
i
=
0
;
i
<
waitQueue
->
size
;
i
++
)
{
{
/* am I waiting for him ? */
LOCKMODE
procWaitMode
=
proc
->
waitLockMode
;
if
(
lockctl
->
conflictTab
[
lockmode
]
&
proc
->
holdLock
)
/* must I wait for him ? */
if
(
lockctl
->
conflictTab
[
lockmode
]
&
proc
->
heldLocks
)
{
{
/* is he waiting for me ? */
/* is he waiting for me ? */
if
(
lockctl
->
conflictTab
[
proc
->
waitLockMode
]
&
MyProc
->
holdLock
)
if
(
lockctl
->
conflictTab
[
proc
WaitMode
]
&
MyProc
->
heldLocks
)
{
{
/* Yes, report deadlock failure */
/* Yes, report deadlock failure */
MyProc
->
errType
=
STATUS_ERROR
;
MyProc
->
errType
=
STATUS_ERROR
;
goto
rt
;
goto
rt
;
}
}
/*
being waiting for him - go past
*/
/*
I must go after him in queue - so continue loop
*/
}
}
/* if he waits for me */
/* if he waits for me
, go before him in queue
*/
else
if
(
lockctl
->
conflictTab
[
proc
->
waitLockMode
]
&
MyProc
->
holdLock
)
else
if
(
lockctl
->
conflictTab
[
proc
WaitMode
]
&
MyProc
->
heldLocks
)
break
;
break
;
/* if conflicting locks requested */
/* if conflicting locks requested */
else
if
(
lockctl
->
conflictTab
[
proc
->
waitLock
Mode
]
&
myMask
)
else
if
(
lockctl
->
conflictTab
[
proc
Wait
Mode
]
&
myMask
)
{
{
/*
/*
* If I request non self-conflicting lock and there are others
* If I request non self-conflicting lock and there are others
* requesting the same lock just before
me - stay
here.
* requesting the same lock just before
this guy - stop
here.
*/
*/
if
(
!
selfConflict
&&
prevSame
)
if
(
!
selfConflict
&&
prevSame
)
break
;
break
;
}
}
/*
/*
* Last attempt to
don't move any more: if we don't conflict with
* Last attempt to
not move any further to the back of the queue:
*
rest waiters in queu
e.
*
if we don't conflict with remaining waiters, stop her
e.
*/
*/
else
if
(
!
(
lockctl
->
conflictTab
[
lockmode
]
&
waitMask
))
else
if
(
!
(
lockctl
->
conflictTab
[
lockmode
]
&
waitMask
))
break
;
break
;
prevSame
=
(
proc
->
waitLockMode
==
lockmode
);
/* Move past this guy, and update state accordingly */
(
aheadHolders
[
proc
->
waitLockMode
])
++
;
prevSame
=
(
procWaitMode
==
lockmode
);
if
(
aheadHolders
[
proc
->
waitLockMode
]
==
lock
->
holders
[
proc
->
waitLockMode
])
(
aheadGranted
[
procWaitMode
])
++
;
waitMask
&=
~
(
1
<<
proc
->
waitLockMode
);
if
(
aheadGranted
[
procWaitMode
]
==
lock
->
requested
[
procWaitMode
])
waitMask
&=
~
(
1
<<
procWaitMode
);
proc
=
(
PROC
*
)
MAKE_PTR
(
proc
->
links
.
prev
);
proc
=
(
PROC
*
)
MAKE_PTR
(
proc
->
links
.
prev
);
}
}
ins:
;
ins:
;
/* -------------------
/* -------------------
* Insert self into queue
. These operations are atomic (because
* Insert self into queue
, ahead of the given proc.
* of the spinlock).
*
These operations are atomic (because
of the spinlock).
* -------------------
* -------------------
*/
*/
SHMQueueInsertTL
(
&
(
proc
->
links
),
&
(
MyProc
->
links
));
SHMQueueInsertTL
(
&
(
proc
->
links
),
&
(
MyProc
->
links
));
...
@@ -838,7 +842,7 @@ nextProc:
...
@@ -838,7 +842,7 @@ nextProc:
void
void
ProcAddLock
(
SHM_QUEUE
*
elem
)
ProcAddLock
(
SHM_QUEUE
*
elem
)
{
{
SHMQueueInsertTL
(
&
MyProc
->
lock
Queue
,
elem
);
SHMQueueInsertTL
(
&
MyProc
->
holder
Queue
,
elem
);
}
}
/* --------------------
/* --------------------
...
...
src/include/storage/lock.h
View file @
64e6c608
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $Id: lock.h,v 1.4
0 2000/12/22 00:51:5
4 tgl Exp $
* $Id: lock.h,v 1.4
1 2001/01/16 06:11:3
4 tgl Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -150,26 +150,28 @@ typedef struct LOCKTAG
...
@@ -150,26 +150,28 @@ typedef struct LOCKTAG
* Per-locked-object lock information:
* Per-locked-object lock information:
*
*
* tag -- uniquely identifies the object being locked
* tag -- uniquely identifies the object being locked
* mask -- union of the conflict masks of all lock types
* grantMask -- bitmask for all lock types currently granted on this object.
* currently held on this object.
* waitMask -- bitmask for all lock types currently awaited on this object.
* waitProcs -- queue of processes waiting for this lock
* waitProcs -- queue of processes waiting for this lock.
* holders -- count of each lock type currently held on the
* requested -- count of each lock type currently requested on the lock
* lock.
* (includes requests already granted!!).
* nHolding -- total locks of all types.
* nRequested -- total requested locks of all types.
* granted -- count of each lock type currently granted on the lock.
* nGranted -- total granted locks of all types.
*/
*/
typedef
struct
LOCK
typedef
struct
LOCK
{
{
/* hash key */
/* hash key */
LOCKTAG
tag
;
LOCKTAG
tag
;
/* unique identifier of lockable object */
/* data */
/* data */
int
mask
;
int
grantMask
;
/* bitmask for lock types already granted */
int
waitMask
;
int
waitMask
;
/* bitmask for lock types awaited */
PROC_QUEUE
waitProcs
;
PROC_QUEUE
waitProcs
;
/* list of PROC objects waiting on lock */
int
holders
[
MAX_LOCKMODES
];
int
requested
[
MAX_LOCKMODES
];
/* counts of requested locks */
int
n
Holding
;
int
n
Requested
;
/* total of requested[] array */
int
activeHolders
[
MAX_LOCKMODES
];
int
granted
[
MAX_LOCKMODES
];
/* counts of granted locks */
int
n
Active
;
int
n
Granted
;
/* total of granted[] array */
}
LOCK
;
}
LOCK
;
#define SHMEM_LOCKTAB_KEYSIZE sizeof(LOCKTAG)
#define SHMEM_LOCKTAB_KEYSIZE sizeof(LOCKTAG)
...
@@ -193,6 +195,12 @@ typedef struct LOCK
...
@@ -193,6 +195,12 @@ typedef struct LOCK
* Currently, session holders are used for user locks and for cross-xact
* Currently, session holders are used for user locks and for cross-xact
* locks obtained for VACUUM. We assume that a session lock never conflicts
* locks obtained for VACUUM. We assume that a session lock never conflicts
* with per-transaction locks obtained by the same backend.
* with per-transaction locks obtained by the same backend.
*
* The holding[] array counts the granted locks (of each type) represented
* by this holder. Note that there will be a holder object, possibly with
* zero holding[], for any lock that the process is currently waiting on.
* Otherwise, holder objects whose counts have gone to zero are recycled
* as soon as convenient.
*/
*/
typedef
struct
HOLDERTAG
typedef
struct
HOLDERTAG
{
{
...
@@ -204,12 +212,12 @@ typedef struct HOLDERTAG
...
@@ -204,12 +212,12 @@ typedef struct HOLDERTAG
typedef
struct
HOLDER
typedef
struct
HOLDER
{
{
/* tag */
/* tag */
HOLDERTAG
tag
;
HOLDERTAG
tag
;
/* unique identifier of holder object */
/* data */
/* data */
int
hold
ers
[
MAX_LOCKMODES
];
int
hold
ing
[
MAX_LOCKMODES
];
/* count of locks currently held */
int
nHolding
;
int
nHolding
;
/* total of holding[] array */
SHM_QUEUE
queue
;
SHM_QUEUE
queue
;
/* list link for process' list of holders */
}
HOLDER
;
}
HOLDER
;
#define SHMEM_HOLDERTAB_KEYSIZE sizeof(HOLDERTAG)
#define SHMEM_HOLDERTAB_KEYSIZE sizeof(HOLDERTAG)
...
@@ -241,7 +249,7 @@ extern bool LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
...
@@ -241,7 +249,7 @@ extern bool LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
bool
allxids
,
TransactionId
xid
);
bool
allxids
,
TransactionId
xid
);
extern
int
LockResolveConflicts
(
LOCKMETHOD
lockmethod
,
LOCKMODE
lockmode
,
extern
int
LockResolveConflicts
(
LOCKMETHOD
lockmethod
,
LOCKMODE
lockmode
,
LOCK
*
lock
,
HOLDER
*
holder
,
PROC
*
proc
,
LOCK
*
lock
,
HOLDER
*
holder
,
PROC
*
proc
,
int
*
myHold
ers
);
int
*
myHold
ing
);
extern
void
GrantLock
(
LOCK
*
lock
,
HOLDER
*
holder
,
LOCKMODE
lockmode
);
extern
void
GrantLock
(
LOCK
*
lock
,
HOLDER
*
holder
,
LOCKMODE
lockmode
);
extern
int
LockShmemSize
(
int
maxBackends
);
extern
int
LockShmemSize
(
int
maxBackends
);
extern
bool
DeadLockCheck
(
PROC
*
thisProc
,
LOCK
*
findlock
);
extern
bool
DeadLockCheck
(
PROC
*
thisProc
,
LOCK
*
findlock
);
...
...
src/include/storage/proc.h
View file @
64e6c608
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $Id: proc.h,v 1.3
4 2001/01/14 05:08:16
tgl Exp $
* $Id: proc.h,v 1.3
5 2001/01/16 06:11:34
tgl Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -27,13 +27,20 @@ typedef struct
...
@@ -27,13 +27,20 @@ typedef struct
}
SEMA
;
}
SEMA
;
/*
/*
* Each backend has:
* Each backend has a PROC struct in shared memory. There is also a list
* of currently-unused PROC structs that will be reallocated to new backends
* (a fairly pointless optimization, but it's there anyway).
*
* links: list link for any list the PROC is in. When waiting for a lock,
* the PROC is linked into that lock's waitProcs queue. A recycled PROC
* is linked into ProcGlobal's freeProcs list.
*/
*/
struct
proc
struct
proc
{
{
/* proc->links MUST BE THE FIRST ELEMENT OF STRUCT (see ProcWakeup()) */
/* proc->links MUST BE THE FIRST ELEMENT OF STRUCT (see ProcWakeup()) */
SHM_QUEUE
links
;
/* proc can be waiting for one event(lock) */
SHM_QUEUE
links
;
/* list link if process is in a list */
SEMA
sem
;
/* ONE semaphore to sleep on */
SEMA
sem
;
/* ONE semaphore to sleep on */
int
errType
;
/* error code tells why we woke up */
int
errType
;
/* error code tells why we woke up */
...
@@ -48,16 +55,17 @@ struct proc
...
@@ -48,16 +55,17 @@ struct proc
/* Info about lock the process is currently waiting for, if any */
/* Info about lock the process is currently waiting for, if any */
LOCK
*
waitLock
;
/* Lock object we're sleeping on ... */
LOCK
*
waitLock
;
/* Lock object we're sleeping on ... */
HOLDER
*
waitHolder
;
/* Per-holder info for
our
lock */
HOLDER
*
waitHolder
;
/* Per-holder info for
awaited
lock */
LOCKMODE
waitLockMode
;
/* type of lock we're waiting for */
LOCKMODE
waitLockMode
;
/* type of lock we're waiting for */
LOCKMASK
holdLock
;
/* bitmask for lock types already held */
LOCKMASK
heldLocks
;
/* bitmask for lock types already held on
* this lock object by this backend */
int
pid
;
/* This backend's process id */
int
pid
;
/* This backend's process id */
Oid
databaseId
;
/* OID of database this backend is using */
Oid
databaseId
;
/* OID of database this backend is using */
short
sLocks
[
MAX_SPINS
];
/* Spin lock stats */
short
sLocks
[
MAX_SPINS
];
/* Spin lock stats */
SHM_QUEUE
lockQueue
;
/* locks associated with current
SHM_QUEUE
holderQueue
;
/* list of HOLDER objects for locks held or
*
transaction
*/
*
awaited by this backend
*/
};
};
/* NOTE: "typedef struct proc PROC" appears in storage/lock.h. */
/* NOTE: "typedef struct proc PROC" appears in storage/lock.h. */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment