1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
/*-------------------------------------------------------------------------
*
* proc.h
* per-process shared memory data structures
*
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: proc.h,v 1.41 2001/03/22 04:01:08 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef _PROC_H_
#define _PROC_H_
#include "access/xlog.h"
#include "storage/lock.h"
/* configurable option */
extern int DeadlockTimeout;
typedef struct
{
IpcSemaphoreId semId; /* SysV semaphore set ID */
int semNum; /* semaphore number within set */
} SEMA;
/*
* 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.
*
* 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
{
/* proc->links MUST BE FIRST IN STRUCT (see ProcSleep,ProcWakeup,etc) */
SHM_QUEUE links; /* list link if process is in a list */
SEMA sem; /* ONE semaphore to sleep on */
int errType; /* STATUS_OK or STATUS_ERROR after wakeup */
TransactionId xid; /* transaction currently being executed by
* this proc */
TransactionId xmin; /* minimal running XID as it was when we
* were starting our xact: vacuum must not
* remove tuples deleted by xid >= xmin ! */
/*
* XLOG location of first XLOG record written by this backend's
* current transaction. If backend is not in a transaction or hasn't
* yet modified anything, logRec.xrecoff is zero.
*/
XLogRecPtr logRec;
/* Info about lock the process is currently waiting for, if any. */
/* waitLock and waitHolder are NULL if not currently waiting. */
LOCK *waitLock; /* Lock object we're sleeping on ... */
HOLDER *waitHolder; /* Per-holder info for awaited lock */
LOCKMODE waitLockMode; /* type of lock we're waiting for */
LOCKMASK heldLocks; /* bitmask for lock types already held on
* this lock object by this backend */
int pid; /* This backend's process id */
Oid databaseId; /* OID of database this backend is using */
short sLocks[MAX_SPINS]; /* Spin lock stats */
SHM_QUEUE procHolders; /* list of HOLDER objects for locks held
* or awaited by this backend */
};
/* NOTE: "typedef struct proc PROC" appears in storage/lock.h. */
extern PROC *MyProc;
extern SPINLOCK ProcStructLock;
#define PROC_INCR_SLOCK(lock) \
do { \
if (MyProc) (MyProc->sLocks[(lock)])++; \
} while (0)
#define PROC_DECR_SLOCK(lock) \
do { \
if (MyProc) (MyProc->sLocks[(lock)])--; \
} while (0)
/*
* There is one ProcGlobal struct for the whole installation.
*
* PROC_NSEMS_PER_SET is the number of semaphores in each sys-V semaphore set
* we allocate. It must be no more than 32 (or however many bits in an int
* on your machine), or our free-semaphores bitmap won't work. It also must
* be *less than* your kernel's SEMMSL (max semaphores per set) parameter,
* which is often around 25. (Less than, because we allocate one extra sema
* in each set for identification purposes.)
*
* PROC_SEM_MAP_ENTRIES is the number of semaphore sets we need to allocate
* to keep track of up to MAXBACKENDS backends.
*/
#define PROC_NSEMS_PER_SET 16
#define PROC_SEM_MAP_ENTRIES ((MAXBACKENDS-1)/PROC_NSEMS_PER_SET+1)
typedef struct procglobal
{
/* Head of list of free PROC structures */
SHMEM_OFFSET freeProcs;
/* Info about semaphore sets used for per-process semaphores */
IpcSemaphoreId procSemIds[PROC_SEM_MAP_ENTRIES];
int32 freeSemMap[PROC_SEM_MAP_ENTRIES];
/*
* In each freeSemMap entry, bit i is set if the i'th semaphore of the
* set is allocated to a process. (i counts from 0 at the LSB)
*/
} PROC_HDR;
/*
* Function Prototypes
*/
extern void InitProcGlobal(int maxBackends);
extern void InitProcess(void);
extern void ProcReleaseLocks(bool isCommit);
extern bool ProcRemove(int pid);
extern void ProcQueueInit(PROC_QUEUE *queue);
extern int ProcSleep(LOCKMETHODTABLE *lockMethodTable, LOCKMODE lockmode,
LOCK *lock, HOLDER *holder);
extern PROC *ProcWakeup(PROC *proc, int errType);
extern void ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock);
extern void ProcReleaseSpins(PROC *proc);
extern bool LockWaitCancel(void);
extern void HandleDeadLock(SIGNAL_ARGS);
#endif /* PROC_H */
|