Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb25b6c9

Browse files
committed
Once again allow LWLocks to be used within DSM segments.
Prior to commit7882c3b, it waspossible to use LWLocks within DSM segments, but that commit brokethis use case by switching from a doubly linked list to a circularlinked list. Switch back, using a new bit of general infrastructurefor maintaining lists of PGPROCs.Thomas Munro, reviewed by me.
1 parent2bf06f7 commitb25b6c9

File tree

6 files changed

+240
-35
lines changed

6 files changed

+240
-35
lines changed

‎src/backend/storage/lmgr/lwlock.c

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
#include"storage/ipc.h"
8585
#include"storage/predicate.h"
8686
#include"storage/proc.h"
87+
#include"storage/proclist.h"
8788
#include"storage/spin.h"
8889
#include"utils/memutils.h"
8990

@@ -717,7 +718,7 @@ LWLockInitialize(LWLock *lock, int tranche_id)
717718
pg_atomic_init_u32(&lock->nwaiters,0);
718719
#endif
719720
lock->tranche=tranche_id;
720-
dlist_init(&lock->waiters);
721+
proclist_init(&lock->waiters);
721722
}
722723

723724
/*
@@ -920,25 +921,25 @@ LWLockWakeup(LWLock *lock)
920921
{
921922
boolnew_release_ok;
922923
boolwokeup_somebody= false;
923-
dlist_headwakeup;
924-
dlist_mutable_iteriter;
924+
proclist_headwakeup;
925+
proclist_mutable_iteriter;
925926

926-
dlist_init(&wakeup);
927+
proclist_init(&wakeup);
927928

928929
new_release_ok= true;
929930

930931
/* lock wait list while collecting backends to wake up */
931932
LWLockWaitListLock(lock);
932933

933-
dlist_foreach_modify(iter,&lock->waiters)
934+
proclist_foreach_modify(iter,&lock->waiters,lwWaitLink)
934935
{
935-
PGPROC*waiter=dlist_container(PGPROC,lwWaitLink,iter.cur);
936+
PGPROC*waiter=GetPGProcByNumber(iter.cur);
936937

937938
if (wokeup_somebody&&waiter->lwWaitMode==LW_EXCLUSIVE)
938939
continue;
939940

940-
dlist_delete(&waiter->lwWaitLink);
941-
dlist_push_tail(&wakeup,&waiter->lwWaitLink);
941+
proclist_delete(&lock->waiters,iter.cur,lwWaitLink);
942+
proclist_push_tail(&wakeup,iter.cur,lwWaitLink);
942943

943944
if (waiter->lwWaitMode!=LW_WAIT_UNTIL_FREE)
944945
{
@@ -963,7 +964,7 @@ LWLockWakeup(LWLock *lock)
963964
break;
964965
}
965966

966-
Assert(dlist_is_empty(&wakeup)||pg_atomic_read_u32(&lock->state)&LW_FLAG_HAS_WAITERS);
967+
Assert(proclist_is_empty(&wakeup)||pg_atomic_read_u32(&lock->state)&LW_FLAG_HAS_WAITERS);
967968

968969
/* unset required flags, and release lock, in one fell swoop */
969970
{
@@ -982,7 +983,7 @@ LWLockWakeup(LWLock *lock)
982983
else
983984
desired_state &= ~LW_FLAG_RELEASE_OK;
984985

985-
if (dlist_is_empty(&wakeup))
986+
if (proclist_is_empty(&wakeup))
986987
desired_state &= ~LW_FLAG_HAS_WAITERS;
987988

988989
desired_state &= ~LW_FLAG_LOCKED;/* release lock */
@@ -994,12 +995,12 @@ LWLockWakeup(LWLock *lock)
994995
}
995996

996997
/* Awaken any waiters I removed from the queue. */
997-
dlist_foreach_modify(iter,&wakeup)
998+
proclist_foreach_modify(iter,&wakeup,lwWaitLink)
998999
{
999-
PGPROC*waiter=dlist_container(PGPROC,lwWaitLink,iter.cur);
1000+
PGPROC*waiter=GetPGProcByNumber(iter.cur);
10001001

10011002
LOG_LWDEBUG("LWLockRelease",lock,"release waiter");
1002-
dlist_delete(&waiter->lwWaitLink);
1003+
proclist_delete(&wakeup,iter.cur,lwWaitLink);
10031004

10041005
/*
10051006
* Guarantee that lwWaiting being unset only becomes visible once the
@@ -1046,9 +1047,9 @@ LWLockQueueSelf(LWLock *lock, LWLockMode mode)
10461047

10471048
/* LW_WAIT_UNTIL_FREE waiters are always at the front of the queue */
10481049
if (mode==LW_WAIT_UNTIL_FREE)
1049-
dlist_push_head(&lock->waiters,&MyProc->lwWaitLink);
1050+
proclist_push_head(&lock->waiters,MyProc->pgprocno,lwWaitLink);
10501051
else
1051-
dlist_push_tail(&lock->waiters,&MyProc->lwWaitLink);
1052+
proclist_push_tail(&lock->waiters,MyProc->pgprocno,lwWaitLink);
10521053

10531054
/* Can release the mutex now */
10541055
LWLockWaitListUnlock(lock);
@@ -1070,7 +1071,7 @@ static void
10701071
LWLockDequeueSelf(LWLock*lock)
10711072
{
10721073
boolfound= false;
1073-
dlist_mutable_iteriter;
1074+
proclist_mutable_iteriter;
10741075

10751076
#ifdefLWLOCK_STATS
10761077
lwlock_stats*lwstats;
@@ -1086,19 +1087,17 @@ LWLockDequeueSelf(LWLock *lock)
10861087
* Can't just remove ourselves from the list, but we need to iterate over
10871088
* all entries as somebody else could have unqueued us.
10881089
*/
1089-
dlist_foreach_modify(iter,&lock->waiters)
1090+
proclist_foreach_modify(iter,&lock->waiters,lwWaitLink)
10901091
{
1091-
PGPROC*proc=dlist_container(PGPROC,lwWaitLink,iter.cur);
1092-
1093-
if (proc==MyProc)
1092+
if (iter.cur==MyProc->pgprocno)
10941093
{
10951094
found= true;
1096-
dlist_delete(&proc->lwWaitLink);
1095+
proclist_delete(&lock->waiters,iter.cur,lwWaitLink);
10971096
break;
10981097
}
10991098
}
11001099

1101-
if (dlist_is_empty(&lock->waiters)&&
1100+
if (proclist_is_empty(&lock->waiters)&&
11021101
(pg_atomic_read_u32(&lock->state)&LW_FLAG_HAS_WAITERS)!=0)
11031102
{
11041103
pg_atomic_fetch_and_u32(&lock->state, ~LW_FLAG_HAS_WAITERS);
@@ -1719,12 +1718,12 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
17191718
void
17201719
LWLockUpdateVar(LWLock*lock,uint64*valptr,uint64val)
17211720
{
1722-
dlist_headwakeup;
1723-
dlist_mutable_iteriter;
1721+
proclist_headwakeup;
1722+
proclist_mutable_iteriter;
17241723

17251724
PRINT_LWDEBUG("LWLockUpdateVar",lock,LW_EXCLUSIVE);
17261725

1727-
dlist_init(&wakeup);
1726+
proclist_init(&wakeup);
17281727

17291728
LWLockWaitListLock(lock);
17301729

@@ -1737,15 +1736,15 @@ LWLockUpdateVar(LWLock *lock, uint64 *valptr, uint64 val)
17371736
* See if there are any LW_WAIT_UNTIL_FREE waiters that need to be woken
17381737
* up. They are always in the front of the queue.
17391738
*/
1740-
dlist_foreach_modify(iter,&lock->waiters)
1739+
proclist_foreach_modify(iter,&lock->waiters,lwWaitLink)
17411740
{
1742-
PGPROC*waiter=dlist_container(PGPROC,lwWaitLink,iter.cur);
1741+
PGPROC*waiter=GetPGProcByNumber(iter.cur);
17431742

17441743
if (waiter->lwWaitMode!=LW_WAIT_UNTIL_FREE)
17451744
break;
17461745

1747-
dlist_delete(&waiter->lwWaitLink);
1748-
dlist_push_tail(&wakeup,&waiter->lwWaitLink);
1746+
proclist_delete(&lock->waiters,iter.cur,lwWaitLink);
1747+
proclist_push_tail(&wakeup,iter.cur,lwWaitLink);
17491748
}
17501749

17511750
/* We are done updating shared state of the lock itself. */
@@ -1754,11 +1753,11 @@ LWLockUpdateVar(LWLock *lock, uint64 *valptr, uint64 val)
17541753
/*
17551754
* Awaken any waiters I removed from the queue.
17561755
*/
1757-
dlist_foreach_modify(iter,&wakeup)
1756+
proclist_foreach_modify(iter,&wakeup,lwWaitLink)
17581757
{
1759-
PGPROC*waiter=dlist_container(PGPROC,lwWaitLink,iter.cur);
1758+
PGPROC*waiter=GetPGProcByNumber(iter.cur);
17601759

1761-
dlist_delete(&waiter->lwWaitLink);
1760+
proclist_delete(&wakeup,iter.cur,lwWaitLink);
17621761
/* check comment in LWLockWakeup() about this barrier */
17631762
pg_write_barrier();
17641763
waiter->lwWaiting= false;

‎src/include/storage/lwlock.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#error "lwlock.h may not be included from frontend code"
1919
#endif
2020

21-
#include"lib/ilist.h"
21+
#include"storage/proclist_types.h"
2222
#include"storage/s_lock.h"
2323
#include"port/atomics.h"
2424

@@ -59,7 +59,7 @@ typedef struct LWLock
5959
{
6060
uint16tranche;/* tranche ID */
6161
pg_atomic_uint32state;/* state of exclusive/nonexclusive lockers */
62-
dlist_headwaiters;/* list of waiting PGPROCs */
62+
proclist_headwaiters;/* list of waiting PGPROCs */
6363
#ifdefLOCK_DEBUG
6464
pg_atomic_uint32nwaiters;/* number of waiters */
6565
structPGPROC*owner;/* last exclusive owner of the lock */

‎src/include/storage/proc.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include"storage/latch.h"
2020
#include"storage/lock.h"
2121
#include"storage/pg_sema.h"
22+
#include"storage/proclist_types.h"
2223

2324
/*
2425
* Each backend advertises up to PGPROC_MAX_CACHED_SUBXIDS TransactionIds
@@ -112,7 +113,7 @@ struct PGPROC
112113
/* Info about LWLock the process is currently waiting for, if any. */
113114
boollwWaiting;/* true if waiting for an LW lock */
114115
uint8lwWaitMode;/* lwlock mode being waited for */
115-
dlist_nodelwWaitLink;/* position in LW lock wait list */
116+
proclist_nodelwWaitLink;/* position in LW lock wait list */
116117

117118
/* Info about lock the process is currently waiting for, if any. */
118119
/* waitLock and waitProcLock are NULL if not currently waiting. */
@@ -243,6 +244,9 @@ extern PROC_HDR *ProcGlobal;
243244

244245
externPGPROC*PreparedXactProcs;
245246

247+
/* Accessor for PGPROC given a pgprocno. */
248+
#defineGetPGProcByNumber(n) (&ProcGlobal->allProcs[(n)])
249+
246250
/*
247251
* We set aside some extra PGPROC structures for auxiliary processes,
248252
* ie things that aren't full-fledged backends but need shmem access.

‎src/include/storage/proclist.h

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* proclist.h
4+
*operations on doubly-linked lists of pgprocnos
5+
*
6+
* The interface is similar to dlist from ilist.h, but uses pgprocno instead
7+
* of pointers. This allows proclist_head to be mapped at different addresses
8+
* in different backends.
9+
*
10+
* See proclist_types.h for the structs that these functions operate on. They
11+
* are separated to break a header dependency cycle with proc.h.
12+
*
13+
* Portions Copyright (c) 2016, PostgreSQL Global Development Group
14+
*
15+
* IDENTIFICATION
16+
*src/include/storage/proclist.h
17+
*-------------------------------------------------------------------------
18+
*/
19+
#ifndefPROCLIST_H
20+
#definePROCLIST_H
21+
22+
#include"storage/proc.h"
23+
#include"storage/proclist_types.h"
24+
25+
/*
26+
* Initialize a proclist.
27+
*/
28+
staticinlinevoid
29+
proclist_init(proclist_head*list)
30+
{
31+
list->head=list->tail=INVALID_PGPROCNO;
32+
}
33+
34+
/*
35+
* Is the list empty?
36+
*/
37+
staticinlinebool
38+
proclist_is_empty(proclist_head*list)
39+
{
40+
returnlist->head==INVALID_PGPROCNO;
41+
}
42+
43+
/*
44+
* Get a pointer to a proclist_node inside a given PGPROC, given a procno and
45+
* an offset.
46+
*/
47+
staticinlineproclist_node*
48+
proclist_node_get(intprocno,size_tnode_offset)
49+
{
50+
char*entry= (char*)GetPGProcByNumber(procno);
51+
52+
return (proclist_node*) (entry+node_offset);
53+
}
54+
55+
/*
56+
* Insert a node at the beginning of a list.
57+
*/
58+
staticinlinevoid
59+
proclist_push_head_offset(proclist_head*list,intprocno,size_tnode_offset)
60+
{
61+
proclist_node*node=proclist_node_get(procno,node_offset);
62+
63+
if (list->head==INVALID_PGPROCNO)
64+
{
65+
Assert(list->tail==INVALID_PGPROCNO);
66+
node->next=node->prev=INVALID_PGPROCNO;
67+
list->head=list->tail=procno;
68+
}
69+
else
70+
{
71+
Assert(list->tail!=INVALID_PGPROCNO);
72+
node->next=list->head;
73+
proclist_node_get(node->next,node_offset)->prev=procno;
74+
node->prev=INVALID_PGPROCNO;
75+
list->head=procno;
76+
}
77+
}
78+
79+
/*
80+
* Insert a node a the end of a list.
81+
*/
82+
staticinlinevoid
83+
proclist_push_tail_offset(proclist_head*list,intprocno,size_tnode_offset)
84+
{
85+
proclist_node*node=proclist_node_get(procno,node_offset);
86+
87+
if (list->tail==INVALID_PGPROCNO)
88+
{
89+
Assert(list->head==INVALID_PGPROCNO);
90+
node->next=node->prev=INVALID_PGPROCNO;
91+
list->head=list->tail=procno;
92+
}
93+
else
94+
{
95+
Assert(list->head!=INVALID_PGPROCNO);
96+
node->prev=list->tail;
97+
proclist_node_get(node->prev,node_offset)->next=procno;
98+
node->next=INVALID_PGPROCNO;
99+
list->tail=procno;
100+
}
101+
}
102+
103+
/*
104+
* Delete a node. The node must be in the list.
105+
*/
106+
staticinlinevoid
107+
proclist_delete_offset(proclist_head*list,intprocno,size_tnode_offset)
108+
{
109+
proclist_node*node=proclist_node_get(procno,node_offset);
110+
111+
if (node->prev==INVALID_PGPROCNO)
112+
list->head=node->next;
113+
else
114+
proclist_node_get(node->prev,node_offset)->next=node->next;
115+
116+
if (node->next==INVALID_PGPROCNO)
117+
list->tail=node->prev;
118+
else
119+
proclist_node_get(node->next,node_offset)->prev=node->prev;
120+
}
121+
122+
/*
123+
* Helper macros to avoid repetition of offsetof(PGPROC, <member>).
124+
* 'link_member' is the name of a proclist_node member in PGPROC.
125+
*/
126+
#defineproclist_delete(list,procno,link_member) \
127+
proclist_delete_offset((list), (procno), offsetof(PGPROC, link_member))
128+
#defineproclist_push_head(list,procno,link_member) \
129+
proclist_push_head_offset((list), (procno), offsetof(PGPROC, link_member))
130+
#defineproclist_push_tail(list,procno,link_member) \
131+
proclist_push_tail_offset((list), (procno), offsetof(PGPROC, link_member))
132+
133+
/*
134+
* Iterate through the list pointed at by 'lhead', storing the current
135+
* position in 'iter'. 'link_member' is the name of a proclist_node member in
136+
* PGPROC. Access the current position with iter.cur.
137+
*
138+
* The only list modification allowed while iterating is deleting the current
139+
* node with proclist_delete(list, iter.cur, node_offset).
140+
*/
141+
#defineproclist_foreach_modify(iter,lhead,link_member)\
142+
for (AssertVariableIsOfTypeMacro(iter, proclist_mutable_iter),\
143+
AssertVariableIsOfTypeMacro(lhead, proclist_head *),\
144+
(iter).cur = (lhead)->head,\
145+
(iter).next = (iter).cur == INVALID_PGPROCNO ? INVALID_PGPROCNO :\
146+
proclist_node_get((iter).cur,\
147+
offsetof(PGPROC, link_member))->next;\
148+
(iter).cur != INVALID_PGPROCNO;\
149+
(iter).cur = (iter).next,\
150+
(iter).next = (iter).cur == INVALID_PGPROCNO ? INVALID_PGPROCNO :\
151+
proclist_node_get((iter).cur,\
152+
offsetof(PGPROC, link_member))->next)
153+
154+
#endif

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp