lock.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:55k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * lock.c
  4.  *   simple lock acquisition
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.55 1999/05/29 06:14:42 vadim Exp $
  11.  *
  12.  * NOTES
  13.  *   Outside modules can create a lock table and acquire/release
  14.  *   locks.  A lock table is a shared memory hash table.  When
  15.  *   a process tries to acquire a lock of a type that conflictRs
  16.  *   with existing locks, it is put to sleep using the routines
  17.  *   in storage/lmgr/proc.c.
  18.  *
  19.  * Interface:
  20.  *
  21.  * LockAcquire(), LockRelease(), LockMethodTableInit(),
  22.  * LockMethodTableRename(), LockReleaseAll, LockOwners()
  23.  * LockResolveConflicts(), GrantLock()
  24.  *
  25.  * NOTE: This module is used to define new lock tables.  The
  26.  * multi-level lock table (multi.c) used by the heap
  27.  * access methods calls these routines.  See multi.c for
  28.  * examples showing how to use this interface.
  29.  *
  30.  *-------------------------------------------------------------------------
  31.  */
  32. #include <stdio.h> /* for sprintf() */
  33. #include <string.h>
  34. #include <sys/types.h>
  35. #include <unistd.h>
  36. #include <signal.h>
  37. #include "postgres.h"
  38. #include "miscadmin.h"
  39. #include "storage/shmem.h"
  40. #include "storage/sinvaladt.h"
  41. #include "storage/spin.h"
  42. #include "storage/proc.h"
  43. #include "storage/lock.h"
  44. #include "utils/hsearch.h"
  45. #include "utils/memutils.h"
  46. #include "utils/palloc.h"
  47. #include "access/xact.h"
  48. #include "access/transam.h"
  49. #include "utils/trace.h"
  50. #include "utils/ps_status.h"
  51. static int WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode);
  52. /*
  53.  * lockDebugRelation can be used to trace unconditionally a single relation,
  54.  * for example pg_listener, if you suspect there are locking problems.
  55.  *
  56.  * lockDebugOidMin is is used to avoid tracing postgres relations, which
  57.  * would produce a lot of output. Unfortunately most system relations are
  58.  * created after bootstrap and have oid greater than BootstrapObjectIdData.
  59.  * If you are using tprintf you should specify a value greater than the max
  60.  * oid of system relations, which can be found with the following query:
  61.  *
  62.  *  select max(int4in(int4out(oid))) from pg_class where relname ~ '^pg_';
  63.  *
  64.  * To get a useful lock trace you can use the following pg_options:
  65.  *
  66.  *  -T "verbose,query,locks,userlocks,lock_debug_oidmin=17500"
  67.  */
  68. #define LOCKDEBUG(lockmethod) (pg_options[TRACE_SHORTLOCKS+lockmethod])
  69. #define lockDebugRelation (pg_options[TRACE_LOCKRELATION])
  70. #define lockDebugOidMin (pg_options[TRACE_LOCKOIDMIN])
  71. #define lockReadPriority (pg_options[OPT_LOCKREADPRIORITY])
  72. #ifdef LOCK_MGR_DEBUG
  73. #define LOCK_PRINT(where,lock,type) 
  74. if (((LOCKDEBUG(LOCK_LOCKMETHOD(*(lock))) >= 1) 
  75.  && (lock->tag.relId >= lockDebugOidMin)) 
  76. || 
  77. (lockDebugRelation && (lock->tag.relId == lockDebugRelation))) 
  78. LOCK_PRINT_AUX(where,lock,type)
  79. #define LOCK_PRINT_AUX(where,lock,type) 
  80. TPRINTF(TRACE_ALL, 
  81.  "%s: lock(%x) tbl(%d) rel(%u) db(%u) obj(%u) mask(%x) " 
  82.  "hold(%d,%d,%d,%d,%d,%d,%d)=%d " 
  83.  "act(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)", 
  84.  where, 
  85.  MAKE_OFFSET(lock), 
  86.  lock->tag.lockmethod, 
  87.  lock->tag.relId, 
  88.  lock->tag.dbId, 
  89.  lock->tag.objId.blkno, 
  90.  lock->mask, 
  91.  lock->holders[1], 
  92.  lock->holders[2], 
  93.  lock->holders[3], 
  94.  lock->holders[4], 
  95.  lock->holders[5], 
  96.  lock->holders[6], 
  97.  lock->holders[7], 
  98.  lock->nHolding, 
  99.  lock->activeHolders[1], 
  100.  lock->activeHolders[2], 
  101.  lock->activeHolders[3], 
  102.  lock->activeHolders[4], 
  103.  lock->activeHolders[5], 
  104.  lock->activeHolders[6], 
  105.  lock->activeHolders[7], 
  106.  lock->nActive, 
  107.  lock->waitProcs.size, 
  108.  lock_types[type])
  109. #define XID_PRINT(where,xidentP) 
  110. if (((LOCKDEBUG(XIDENT_LOCKMETHOD(*(xidentP))) >= 1) 
  111.  && (((LOCK *)MAKE_PTR(xidentP->tag.lock))->tag.relId 
  112.  >= lockDebugOidMin)) 
  113. || (lockDebugRelation && 
  114. (((LOCK *)MAKE_PTR(xidentP->tag.lock))->tag.relId 
  115.  == lockDebugRelation))) 
  116. XID_PRINT_AUX(where,xidentP)
  117. #define XID_PRINT_AUX(where,xidentP) 
  118. TPRINTF(TRACE_ALL, 
  119.  "%s: xid(%x) lock(%x) tbl(%d) pid(%d) xid(%u) " 
  120.  "hold(%d,%d,%d,%d,%d,%d,%d)=%d", 
  121.  where, 
  122.  MAKE_OFFSET(xidentP), 
  123.  xidentP->tag.lock, 
  124.  XIDENT_LOCKMETHOD(*(xidentP)), 
  125.  xidentP->tag.pid, 
  126.  xidentP->tag.xid, 
  127.  xidentP->holders[1], 
  128.  xidentP->holders[2], 
  129.  xidentP->holders[3], 
  130.  xidentP->holders[4], 
  131.  xidentP->holders[5], 
  132.  xidentP->holders[6], 
  133.  xidentP->holders[7], 
  134.  xidentP->nHolding)
  135. #else /* !LOCK_MGR_DEBUG */
  136. #define LOCK_PRINT(where,lock,type)
  137. #define LOCK_PRINT_AUX(where,lock,type)
  138. #define XID_PRINT(where,xidentP)
  139. #define XID_PRINT_AUX(where,xidentP)
  140. #endif  /* !LOCK_MGR_DEBUG */
  141. static char *lock_types[] = {
  142. "INVALID",
  143. "AccessShareLock",
  144. "RowShareLock",
  145. "RowExclusiveLock",
  146. "ShareLock",
  147. "ShareRowExclusiveLock",
  148. "ExclusiveLock",
  149. "AccessExclusiveLock"
  150. };
  151. SPINLOCK LockMgrLock; /* in Shmem or created in
  152.  * CreateSpinlocks() */
  153. /* This is to simplify/speed up some bit arithmetic */
  154. static MASK BITS_OFF[MAX_LOCKMODES];
  155. static MASK BITS_ON[MAX_LOCKMODES];
  156. /* -----------------
  157.  * XXX Want to move this to this file
  158.  * -----------------
  159.  */
  160. static bool LockingIsDisabled;
  161. /* -------------------
  162.  * map from lockmethod to the lock table structure
  163.  * -------------------
  164.  */
  165. static LOCKMETHODTABLE *LockMethodTable[MAX_LOCK_METHODS];
  166. static int NumLockMethods;
  167. /* -------------------
  168.  * InitLocks -- Init the lock module.  Create a private data
  169.  * structure for constructing conflict masks.
  170.  * -------------------
  171.  */
  172. void
  173. InitLocks()
  174. {
  175. int i;
  176. int bit;
  177. bit = 1;
  178. /* -------------------
  179.  * remember 0th lockmode is invalid
  180.  * -------------------
  181.  */
  182. for (i = 0; i < MAX_LOCKMODES; i++, bit <<= 1)
  183. {
  184. BITS_ON[i] = bit;
  185. BITS_OFF[i] = ~bit;
  186. }
  187. #ifdef LOCK_MGR_DEBUG
  188. /*
  189.  * If lockDebugOidMin value has not been specified in pg_options set a
  190.  * default value.
  191.  */
  192. if (!lockDebugOidMin)
  193. lockDebugOidMin = BootstrapObjectIdData;
  194. #endif
  195. }
  196. /* -------------------
  197.  * LockDisable -- sets LockingIsDisabled flag to TRUE or FALSE.
  198.  * ------------------
  199.  */
  200. void
  201. LockDisable(int status)
  202. {
  203. LockingIsDisabled = status;
  204. }
  205. /*
  206.  * LockMethodInit -- initialize the lock table's lock type
  207.  * structures
  208.  *
  209.  * Notes: just copying.  Should only be called once.
  210.  */
  211. static void
  212. LockMethodInit(LOCKMETHODTABLE *lockMethodTable,
  213.    MASK *conflictsP,
  214.    int *prioP,
  215.    int numModes)
  216. {
  217. int i;
  218. lockMethodTable->ctl->numLockModes = numModes;
  219. numModes++;
  220. for (i = 0; i < numModes; i++, prioP++, conflictsP++)
  221. {
  222. lockMethodTable->ctl->conflictTab[i] = *conflictsP;
  223. lockMethodTable->ctl->prio[i] = *prioP;
  224. }
  225. }
  226. /*
  227.  * LockMethodTableInit -- initialize a lock table structure
  228.  *
  229.  * Notes:
  230.  * (a) a lock table has four separate entries in the shmem index
  231.  * table. This is because every shared hash table and spinlock
  232.  * has its name stored in the shmem index at its creation.  It
  233.  * is wasteful, in this case, but not much space is involved.
  234.  *
  235.  */
  236. LOCKMETHOD
  237. LockMethodTableInit(char *tabName,
  238. MASK *conflictsP,
  239. int *prioP,
  240. int numModes)
  241. {
  242. LOCKMETHODTABLE *lockMethodTable;
  243. char    *shmemName;
  244. HASHCTL info;
  245. int hash_flags;
  246. bool found;
  247. int status = TRUE;
  248. if (numModes > MAX_LOCKMODES)
  249. {
  250. elog(NOTICE, "LockMethodTableInit: too many lock types %d greater than %d",
  251.  numModes, MAX_LOCKMODES);
  252. return INVALID_LOCKMETHOD;
  253. }
  254. /* allocate a string for the shmem index table lookup */
  255. shmemName = (char *) palloc((unsigned) (strlen(tabName) + 32));
  256. if (!shmemName)
  257. {
  258. elog(NOTICE, "LockMethodTableInit: couldn't malloc string %s n", tabName);
  259. return INVALID_LOCKMETHOD;
  260. }
  261. /* each lock table has a non-shared header */
  262. lockMethodTable = (LOCKMETHODTABLE *) palloc((unsigned) sizeof(LOCKMETHODTABLE));
  263. if (!lockMethodTable)
  264. {
  265. elog(NOTICE, "LockMethodTableInit: couldn't malloc lock table %sn", tabName);
  266. pfree(shmemName);
  267. return INVALID_LOCKMETHOD;
  268. }
  269. /* ------------------------
  270.  * find/acquire the spinlock for the table
  271.  * ------------------------
  272.  */
  273. SpinAcquire(LockMgrLock);
  274. /* -----------------------
  275.  * allocate a control structure from shared memory or attach to it
  276.  * if it already exists.
  277.  * -----------------------
  278.  */
  279. sprintf(shmemName, "%s (ctl)", tabName);
  280. lockMethodTable->ctl = (LOCKMETHODCTL *)
  281. ShmemInitStruct(shmemName, (unsigned) sizeof(LOCKMETHODCTL), &found);
  282. if (!lockMethodTable->ctl)
  283. {
  284. elog(FATAL, "LockMethodTableInit: couldn't initialize %s", tabName);
  285. status = FALSE;
  286. }
  287. /* -------------------
  288.  * no zero-th table
  289.  * -------------------
  290.  */
  291. NumLockMethods = 1;
  292. /* ----------------
  293.  * we're first - initialize
  294.  * ----------------
  295.  */
  296. if (!found)
  297. {
  298. MemSet(lockMethodTable->ctl, 0, sizeof(LOCKMETHODCTL));
  299. lockMethodTable->ctl->masterLock = LockMgrLock;
  300. lockMethodTable->ctl->lockmethod = NumLockMethods;
  301. }
  302. /* --------------------
  303.  * other modules refer to the lock table by a lockmethod
  304.  * --------------------
  305.  */
  306. LockMethodTable[NumLockMethods] = lockMethodTable;
  307. NumLockMethods++;
  308. Assert(NumLockMethods <= MAX_LOCK_METHODS);
  309. /* ----------------------
  310.  * allocate a hash table for the lock tags.  This is used
  311.  * to find the different locks.
  312.  * ----------------------
  313.  */
  314. info.keysize = SHMEM_LOCKTAB_KEYSIZE;
  315. info.datasize = SHMEM_LOCKTAB_DATASIZE;
  316. info.hash = tag_hash;
  317. hash_flags = (HASH_ELEM | HASH_FUNCTION);
  318. sprintf(shmemName, "%s (lock hash)", tabName);
  319. lockMethodTable->lockHash = (HTAB *) ShmemInitHash(shmemName,
  320.  INIT_TABLE_SIZE, MAX_TABLE_SIZE,
  321.    &info, hash_flags);
  322. Assert(lockMethodTable->lockHash->hash == tag_hash);
  323. if (!lockMethodTable->lockHash)
  324. {
  325. elog(FATAL, "LockMethodTableInit: couldn't initialize %s", tabName);
  326. status = FALSE;
  327. }
  328. /* -------------------------
  329.  * allocate an xid table.  When different transactions hold
  330.  * the same lock, additional information must be saved (locks per tx).
  331.  * -------------------------
  332.  */
  333. info.keysize = SHMEM_XIDTAB_KEYSIZE;
  334. info.datasize = SHMEM_XIDTAB_DATASIZE;
  335. info.hash = tag_hash;
  336. hash_flags = (HASH_ELEM | HASH_FUNCTION);
  337. sprintf(shmemName, "%s (xid hash)", tabName);
  338. lockMethodTable->xidHash = (HTAB *) ShmemInitHash(shmemName,
  339.  INIT_TABLE_SIZE, MAX_TABLE_SIZE,
  340.   &info, hash_flags);
  341. if (!lockMethodTable->xidHash)
  342. {
  343. elog(FATAL, "LockMethodTableInit: couldn't initialize %s", tabName);
  344. status = FALSE;
  345. }
  346. /* init ctl data structures */
  347. LockMethodInit(lockMethodTable, conflictsP, prioP, numModes);
  348. SpinRelease(LockMgrLock);
  349. pfree(shmemName);
  350. if (status)
  351. return lockMethodTable->ctl->lockmethod;
  352. else
  353. return INVALID_LOCKMETHOD;
  354. }
  355. /*
  356.  * LockMethodTableRename -- allocate another lockmethod to the same
  357.  * lock table.
  358.  *
  359.  * NOTES: Both the lock module and the lock chain (lchain.c)
  360.  * module use table id's to distinguish between different
  361.  * kinds of locks.  Short term and long term locks look
  362.  * the same to the lock table, but are handled differently
  363.  * by the lock chain manager. This function allows the
  364.  * client to use different lockmethods when acquiring/releasing
  365.  * short term and long term locks.
  366.  */
  367. LOCKMETHOD
  368. LockMethodTableRename(LOCKMETHOD lockmethod)
  369. {
  370. LOCKMETHOD newLockMethod;
  371. if (NumLockMethods >= MAX_LOCK_METHODS)
  372. return INVALID_LOCKMETHOD;
  373. if (LockMethodTable[lockmethod] == INVALID_LOCKMETHOD)
  374. return INVALID_LOCKMETHOD;
  375. /* other modules refer to the lock table by a lockmethod */
  376. newLockMethod = NumLockMethods;
  377. NumLockMethods++;
  378. LockMethodTable[newLockMethod] = LockMethodTable[lockmethod];
  379. return newLockMethod;
  380. }
  381. /*
  382.  * LockAcquire -- Check for lock conflicts, sleep if conflict found,
  383.  * set lock if/when no conflicts.
  384.  *
  385.  * Returns: TRUE if parameters are correct, FALSE otherwise.
  386.  *
  387.  * Side Effects: The lock is always acquired.  No way to abort
  388.  * a lock acquisition other than aborting the transaction.
  389.  * Lock is recorded in the lkchain.
  390.  *
  391. #ifdef USER_LOCKS
  392.  *
  393.  * Note on User Locks:
  394.  *
  395.  * User locks are handled totally on the application side as
  396.  * long term cooperative locks which extend beyond the normal
  397.  * transaction boundaries.  Their purpose is to indicate to an
  398.  * application that someone is `working' on an item.  So it is
  399.  * possible to put an user lock on a tuple's oid, retrieve the
  400.  * tuple, work on it for an hour and then update it and remove
  401.  * the lock.  While the lock is active other clients can still
  402.  * read and write the tuple but they can be aware that it has
  403.  * been locked at the application level by someone.
  404.  * User locks use lock tags made of an uint16 and an uint32, for
  405.  * example 0 and a tuple oid, or any other arbitrary pair of
  406.  * numbers following a convention established by the application.
  407.  * In this sense tags don't refer to tuples or database entities.
  408.  * User locks and normal locks are completely orthogonal and
  409.  * they don't interfere with each other, so it is possible
  410.  * to acquire a normal lock on an user-locked tuple or user-lock
  411.  * a tuple for which a normal write lock already exists.
  412.  * User locks are always non blocking, therefore they are never
  413.  * acquired if already held by another process.  They must be
  414.  * released explicitly by the application but they are released
  415.  * automatically when a backend terminates.
  416.  * They are indicated by a lockmethod 2 which is an alias for the
  417.  * normal lock table, and are distinguished from normal locks
  418.  * for the following differences:
  419.  *
  420.  * normal lock user lock
  421.  *
  422.  * lockmethod 1 2
  423.  * tag.relId rel oid 0
  424.  * tag.ItemPointerData.ip_blkid block id lock id2
  425.  * tag.ItemPointerData.ip_posid tuple offset lock id1
  426.  * xid.pid 0 backend pid
  427.  * xid.xid xid or 0 0
  428.  * persistence transaction user or backend
  429.  *
  430.  * The lockmode parameter can have the same values for normal locks
  431.  * although probably only WRITE_LOCK can have some practical use.
  432.  *
  433.  * DZ - 22 Nov 1997
  434. #endif
  435.  */
  436. bool
  437. LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
  438. {
  439. XIDLookupEnt *result,
  440. item;
  441. HTAB    *xidTable;
  442. bool found;
  443. LOCK    *lock = NULL;
  444. SPINLOCK masterLock;
  445. LOCKMETHODTABLE *lockMethodTable;
  446. int status;
  447. TransactionId xid;
  448. #ifdef USER_LOCKS
  449. int is_user_lock;
  450. is_user_lock = (lockmethod == USER_LOCKMETHOD);
  451. if (is_user_lock)
  452. {
  453. #ifdef USER_LOCKS_DEBUG
  454. TPRINTF(TRACE_USERLOCKS, "LockAcquire: user lock [%u] %s",
  455. locktag->objId.blkno,
  456. lock_types[lockmode]);
  457. #endif
  458. }
  459. #endif
  460. /* ???????? This must be changed when short term locks will be used */
  461. locktag->lockmethod = lockmethod;
  462. Assert(lockmethod < NumLockMethods);
  463. lockMethodTable = LockMethodTable[lockmethod];
  464. if (!lockMethodTable)
  465. {
  466. elog(NOTICE, "LockAcquire: bad lock table %d", lockmethod);
  467. return FALSE;
  468. }
  469. if (LockingIsDisabled)
  470. return TRUE;
  471. masterLock = lockMethodTable->ctl->masterLock;
  472. SpinAcquire(masterLock);
  473. /*
  474.  * Find or create a lock with this tag
  475.  */
  476. Assert(lockMethodTable->lockHash->hash == tag_hash);
  477. lock = (LOCK *) hash_search(lockMethodTable->lockHash, (Pointer) locktag,
  478. HASH_ENTER, &found);
  479. if (!lock)
  480. {
  481. SpinRelease(masterLock);
  482. elog(FATAL, "LockAcquire: lock table %d is corrupted", lockmethod);
  483. return FALSE;
  484. }
  485. /* --------------------
  486.  * if there was nothing else there, complete initialization
  487.  * --------------------
  488.  */
  489. if (!found)
  490. {
  491. lock->mask = 0;
  492. lock->nHolding = 0;
  493. lock->nActive = 0;
  494. MemSet((char *) lock->holders, 0, sizeof(int) * MAX_LOCKMODES);
  495. MemSet((char *) lock->activeHolders, 0, sizeof(int) * MAX_LOCKMODES);
  496. ProcQueueInit(&(lock->waitProcs));
  497. Assert(lock->tag.objId.blkno == locktag->objId.blkno);
  498. LOCK_PRINT("LockAcquire: new", lock, lockmode);
  499. }
  500. else
  501. {
  502. LOCK_PRINT("LockAcquire: found", lock, lockmode);
  503. Assert((lock->nHolding > 0) && (lock->holders[lockmode] >= 0));
  504. Assert((lock->nActive > 0) && (lock->activeHolders[lockmode] >= 0));
  505. Assert(lock->nActive <= lock->nHolding);
  506. }
  507. /* ------------------
  508.  * add an element to the lock queue so that we can clear the
  509.  * locks at end of transaction.
  510.  * ------------------
  511.  */
  512. xidTable = lockMethodTable->xidHash;
  513. /* ------------------
  514.  * Zero out all of the tag bytes (this clears the padding bytes for long
  515.  * word alignment and ensures hashing consistency).
  516.  * ------------------
  517.  */
  518. MemSet(&item, 0, XID_TAGSIZE); /* must clear padding, needed */
  519. item.tag.lock = MAKE_OFFSET(lock);
  520. #ifdef USE_XIDTAG_LOCKMETHOD
  521. item.tag.lockmethod = lockmethod;
  522. #endif
  523. #ifdef USER_LOCKS
  524. if (is_user_lock)
  525. {
  526. item.tag.pid = MyProcPid;
  527. item.tag.xid = xid = 0;
  528. }
  529. else
  530. {
  531. xid = GetCurrentTransactionId();
  532. TransactionIdStore(xid, &item.tag.xid);
  533. }
  534. #else
  535. xid = GetCurrentTransactionId();
  536. TransactionIdStore(xid, &item.tag.xid);
  537. #endif
  538. /*
  539.  * Find or create an xid entry with this tag
  540.  */
  541. result = (XIDLookupEnt *) hash_search(xidTable, (Pointer) &item,
  542.   HASH_ENTER, &found);
  543. if (!result)
  544. {
  545. elog(NOTICE, "LockAcquire: xid table corrupted");
  546. return STATUS_ERROR;
  547. }
  548. /*
  549.  * If not found initialize the new entry
  550.  */
  551. if (!found)
  552. {
  553. result->nHolding = 0;
  554. MemSet((char *) result->holders, 0, sizeof(int) * MAX_LOCKMODES);
  555. ProcAddLock(&result->queue);
  556. XID_PRINT("LockAcquire: new", result);
  557. }
  558. else
  559. {
  560. XID_PRINT("LockAcquire: found", result);
  561. Assert((result->nHolding > 0) && (result->holders[lockmode] >= 0));
  562. Assert(result->nHolding <= lock->nActive);
  563. }
  564. /* ----------------
  565.  * lock->nholding tells us how many processes have _tried_ to
  566.  * acquire this lock,  Regardless of whether they succeeded or
  567.  * failed in doing so.
  568.  * ----------------
  569.  */
  570. lock->nHolding++;
  571. lock->holders[lockmode]++;
  572. Assert((lock->nHolding > 0) && (lock->holders[lockmode] > 0));
  573. /* --------------------
  574.  * If I'm the only one holding a lock, then there
  575.  * cannot be a conflict. The same is true if we already
  576.  * hold this lock.
  577.  * --------------------
  578.  */
  579. if (result->nHolding == lock->nActive || result->holders[lockmode] != 0)
  580. {
  581. result->holders[lockmode]++;
  582. result->nHolding++;
  583. XID_PRINT("LockAcquire: owning", result);
  584. Assert((result->nHolding > 0) && (result->holders[lockmode] > 0));
  585. GrantLock(lock, lockmode);
  586. SpinRelease(masterLock);
  587. return TRUE;
  588. }
  589. /*
  590.  * If lock requested conflicts with locks requested by waiters...
  591.  */
  592. if (lockMethodTable->ctl->conflictTab[lockmode] & lock->waitMask)
  593. {
  594. int i = 1;
  595. /*
  596.  * If I don't hold locks or my locks don't conflict with waiters
  597.  * then force to sleep.
  598.  */
  599. if (result->nHolding > 0)
  600. {
  601. for (; i <= lockMethodTable->ctl->numLockModes; i++)
  602. {
  603. if (result->holders[i] > 0 &&
  604. lockMethodTable->ctl->conflictTab[i] & lock->waitMask)
  605. break; /* conflict */
  606. }
  607. }
  608. if (result->nHolding == 0 || i > lockMethodTable->ctl->numLockModes)
  609. {
  610. XID_PRINT("LockAcquire: higher priority proc waiting",
  611.   result);
  612. status = STATUS_FOUND;
  613. }
  614. else
  615. status = LockResolveConflicts(lockmethod, lock, lockmode, xid, result);
  616. }
  617. else
  618. status = LockResolveConflicts(lockmethod, lock, lockmode, xid, result);
  619. if (status == STATUS_OK)
  620. GrantLock(lock, lockmode);
  621. else if (status == STATUS_FOUND)
  622. {
  623. #ifdef USER_LOCKS
  624. /*
  625.  * User locks are non blocking. If we can't acquire a lock we must
  626.  * remove the xid entry and return FALSE without waiting.
  627.  */
  628. if (is_user_lock)
  629. {
  630. if (!result->nHolding)
  631. {
  632. SHMQueueDelete(&result->queue);
  633. result = (XIDLookupEnt *) hash_search(xidTable,
  634.   (Pointer) result,
  635. HASH_REMOVE, &found);
  636. if (!result || !found)
  637. elog(NOTICE, "LockAcquire: remove xid, table corrupted");
  638. }
  639. else
  640. XID_PRINT_AUX("LockAcquire: NHOLDING", result);
  641. lock->nHolding--;
  642. lock->holders[lockmode]--;
  643. LOCK_PRINT("LockAcquire: user lock failed", lock, lockmode);
  644. Assert((lock->nHolding > 0) && (lock->holders[lockmode] >= 0));
  645. Assert(lock->nActive <= lock->nHolding);
  646. SpinRelease(masterLock);
  647. return FALSE;
  648. }
  649. #endif
  650. /*
  651.  * Construct bitmask of locks we hold before going to sleep.
  652.  */
  653. MyProc->holdLock = 0;
  654. if (result->nHolding > 0)
  655. {
  656. int i,
  657. tmpMask = 2;
  658. for (i = 1; i <= lockMethodTable->ctl->numLockModes;
  659.  i++, tmpMask <<= 1)
  660. {
  661. if (result->holders[i] > 0)
  662. MyProc->holdLock |= tmpMask;
  663. }
  664. Assert(MyProc->holdLock != 0);
  665. }
  666. status = WaitOnLock(lockmethod, lock, lockmode);
  667. /*
  668.  * Check the xid entry status, in case something in the ipc
  669.  * communication doesn't work correctly.
  670.  */
  671. if (!((result->nHolding > 0) && (result->holders[lockmode] > 0)))
  672. {
  673. XID_PRINT_AUX("LockAcquire: INCONSISTENT ", result);
  674. LOCK_PRINT_AUX("LockAcquire: INCONSISTENT ", lock, lockmode);
  675. /* Should we retry ? */
  676. return FALSE;
  677. }
  678. XID_PRINT("LockAcquire: granted", result);
  679. LOCK_PRINT("LockAcquire: granted", lock, lockmode);
  680. }
  681. SpinRelease(masterLock);
  682. return status == STATUS_OK;
  683. }
  684. /* ----------------------------
  685.  * LockResolveConflicts -- test for lock conflicts
  686.  *
  687.  * NOTES:
  688.  * Here's what makes this complicated: one transaction's
  689.  * locks don't conflict with one another.  When many processes
  690.  * hold locks, each has to subtract off the other's locks when
  691.  * determining whether or not any new lock acquired conflicts with
  692.  * the old ones.
  693.  *
  694.  * ----------------------------
  695.  */
  696. int
  697. LockResolveConflicts(LOCKMETHOD lockmethod,
  698.  LOCK *lock,
  699.  LOCKMODE lockmode,
  700.  TransactionId xid,
  701.  XIDLookupEnt *xidentP) /* xident ptr or NULL */
  702. {
  703. XIDLookupEnt *result,
  704. item;
  705. int    *myHolders;
  706. int numLockModes;
  707. HTAB    *xidTable;
  708. bool found;
  709. int bitmask;
  710. int i,
  711. tmpMask;
  712. #ifdef USER_LOCKS
  713. int is_user_lock;
  714. #endif
  715. numLockModes = LockMethodTable[lockmethod]->ctl->numLockModes;
  716. xidTable = LockMethodTable[lockmethod]->xidHash;
  717. if (xidentP)
  718. {
  719. /*
  720.  * A pointer to the xid entry was supplied from the caller.
  721.  * Actually only LockAcquire can do it.
  722.  */
  723. result = xidentP;
  724. }
  725. else
  726. {
  727. /* ---------------------
  728.  * read my own statistics from the xid table.  If there
  729.  * isn't an entry, then we'll just add one.
  730.  *
  731.  * Zero out the tag, this clears the padding bytes for long
  732.  * word alignment and ensures hashing consistency.
  733.  * ------------------
  734.  */
  735. MemSet(&item, 0, XID_TAGSIZE);
  736. item.tag.lock = MAKE_OFFSET(lock);
  737. #ifdef USE_XIDTAG_LOCKMETHOD
  738. item.tag.lockmethod = lockmethod;
  739. #endif
  740. #ifdef USER_LOCKS
  741. is_user_lock = (lockmethod == 2);
  742. if (is_user_lock)
  743. {
  744. item.tag.pid = MyProcPid;
  745. item.tag.xid = 0;
  746. }
  747. else
  748. TransactionIdStore(xid, &item.tag.xid);
  749. #else
  750. TransactionIdStore(xid, &item.tag.xid);
  751. #endif
  752. /*
  753.  * Find or create an xid entry with this tag
  754.  */
  755. result = (XIDLookupEnt *) hash_search(xidTable, (Pointer) &item,
  756.   HASH_ENTER, &found);
  757. if (!result)
  758. {
  759. elog(NOTICE, "LockResolveConflicts: xid table corrupted");
  760. return STATUS_ERROR;
  761. }
  762. /*
  763.  * If not found initialize the new entry. THIS SHOULD NEVER
  764.  * HAPPEN, if we are trying to resolve a conflict we must already
  765.  * have allocated an xid entry for this lock.  dz 21-11-1997
  766.  */
  767. if (!found)
  768. {
  769. /* ---------------
  770.  * we're not holding any type of lock yet.  Clear
  771.  * the lock stats.
  772.  * ---------------
  773.  */
  774. MemSet(result->holders, 0, numLockModes * sizeof(*(lock->holders)));
  775. result->nHolding = 0;
  776. XID_PRINT_AUX("LockResolveConflicts: NOT FOUND", result);
  777. }
  778. else
  779. XID_PRINT("LockResolveConflicts: found", result);
  780. }
  781. Assert((result->nHolding >= 0) && (result->holders[lockmode] >= 0));
  782. /* ----------------------------
  783.  * first check for global conflicts: If no locks conflict
  784.  * with mine, then I get the lock.
  785.  *
  786.  * Checking for conflict: lock->mask represents the types of
  787.  * currently held locks.  conflictTable[lockmode] has a bit
  788.  * set for each type of lock that conflicts with mine. Bitwise
  789.  * compare tells if there is a conflict.
  790.  * ----------------------------
  791.  */
  792. if (!(LockMethodTable[lockmethod]->ctl->conflictTab[lockmode] & lock->mask))
  793. {
  794. result->holders[lockmode]++;
  795. result->nHolding++;
  796. XID_PRINT("LockResolveConflicts: no conflict", result);
  797. Assert((result->nHolding > 0) && (result->holders[lockmode] > 0));
  798. return STATUS_OK;
  799. }
  800. /* ------------------------
  801.  * Rats.  Something conflicts. But it could still be my own
  802.  * lock.  We have to construct a conflict mask
  803.  * that does not reflect our own locks.
  804.  * ------------------------
  805.  */
  806. myHolders = result->holders;
  807. bitmask = 0;
  808. tmpMask = 2;
  809. for (i = 1; i <= numLockModes; i++, tmpMask <<= 1)
  810. {
  811. if (lock->activeHolders[i] != myHolders[i])
  812. bitmask |= tmpMask;
  813. }
  814. /* ------------------------
  815.  * now check again for conflicts.  'bitmask' describes the types
  816.  * of locks held by other processes.  If one of these
  817.  * conflicts with the kind of lock that I want, there is a
  818.  * conflict and I have to sleep.
  819.  * ------------------------
  820.  */
  821. if (!(LockMethodTable[lockmethod]->ctl->conflictTab[lockmode] & bitmask))
  822. {
  823. /* no conflict. Get the lock and go on */
  824. result->holders[lockmode]++;
  825. result->nHolding++;
  826. XID_PRINT("LockResolveConflicts: resolved", result);
  827. Assert((result->nHolding > 0) && (result->holders[lockmode] > 0));
  828. return STATUS_OK;
  829. }
  830. XID_PRINT("LockResolveConflicts: conflicting", result);
  831. return STATUS_FOUND;
  832. }
  833. /*
  834.  * GrantLock -- update the lock data structure to show
  835.  * the new lock holder.
  836.  */
  837. void
  838. GrantLock(LOCK *lock, LOCKMODE lockmode)
  839. {
  840. lock->nActive++;
  841. lock->activeHolders[lockmode]++;
  842. lock->mask |= BITS_ON[lockmode];
  843. LOCK_PRINT("GrantLock", lock, lockmode);
  844. Assert((lock->nActive > 0) && (lock->activeHolders[lockmode] > 0));
  845. Assert(lock->nActive <= lock->nHolding);
  846. }
  847. static int
  848. WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode)
  849. {
  850. PROC_QUEUE *waitQueue = &(lock->waitProcs);
  851. LOCKMETHODTABLE *lockMethodTable = LockMethodTable[lockmethod];
  852. char old_status[64],
  853. new_status[64];
  854. Assert(lockmethod < NumLockMethods);
  855. /*
  856.  * the waitqueue is ordered by priority. I insert myself according to
  857.  * the priority of the lock I am acquiring.
  858.  *
  859.  * SYNC NOTE: I am assuming that the lock table spinlock is sufficient
  860.  * synchronization for this queue. That will not be true if/when
  861.  * people can be deleted from the queue by a SIGINT or something.
  862.  */
  863. LOCK_PRINT_AUX("WaitOnLock: sleeping on lock", lock, lockmode);
  864. strcpy(old_status, PS_STATUS);
  865. strcpy(new_status, PS_STATUS);
  866. strcat(new_status, " waiting");
  867. PS_SET_STATUS(new_status);
  868. if (ProcSleep(waitQueue,
  869.   lockMethodTable->ctl,
  870.   lockmode,
  871.   lock) != NO_ERROR)
  872. {
  873. /* -------------------
  874.  * This could have happend as a result of a deadlock,
  875.  * see HandleDeadLock().
  876.  * Decrement the lock nHolding and holders fields as
  877.  * we are no longer waiting on this lock.
  878.  * -------------------
  879.  */
  880. lock->nHolding--;
  881. lock->holders[lockmode]--;
  882. LOCK_PRINT_AUX("WaitOnLock: aborting on lock", lock, lockmode);
  883. Assert((lock->nHolding >= 0) && (lock->holders[lockmode] >= 0));
  884. Assert(lock->nActive <= lock->nHolding);
  885. if (lock->activeHolders[lockmode] == lock->holders[lockmode])
  886. lock->waitMask &= BITS_OFF[lockmode];
  887. SpinRelease(lockMethodTable->ctl->masterLock);
  888. elog(ERROR, "WaitOnLock: error on wakeup - Aborting this transaction");
  889. /* not reached */
  890. }
  891. if (lock->activeHolders[lockmode] == lock->holders[lockmode])
  892. lock->waitMask &= BITS_OFF[lockmode];
  893. PS_SET_STATUS(old_status);
  894. LOCK_PRINT_AUX("WaitOnLock: wakeup on lock", lock, lockmode);
  895. return STATUS_OK;
  896. }
  897. /*
  898.  * LockRelease -- look up 'locktag' in lock table 'lockmethod' and
  899.  * release it.
  900.  *
  901.  * Side Effects: if the lock no longer conflicts with the highest
  902.  * priority waiting process, that process is granted the lock
  903.  * and awoken. (We have to grant the lock here to avoid a
  904.  * race between the waking process and any new process to
  905.  * come along and request the lock).
  906.  */
  907. bool
  908. LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
  909. {
  910. LOCK    *lock = NULL;
  911. SPINLOCK masterLock;
  912. bool found;
  913. LOCKMETHODTABLE *lockMethodTable;
  914. XIDLookupEnt *result,
  915. item;
  916. HTAB    *xidTable;
  917. TransactionId xid;
  918. bool wakeupNeeded = true;
  919. int trace_flag;
  920. #ifdef USER_LOCKS
  921. int is_user_lock;
  922. is_user_lock = (lockmethod == USER_LOCKMETHOD);
  923. if (is_user_lock)
  924. {
  925. TPRINTF(TRACE_USERLOCKS, "LockRelease: user lock tag [%u] %d",
  926. locktag->objId.blkno,
  927. lockmode);
  928. }
  929. #endif
  930. /* ???????? This must be changed when short term locks will be used */
  931. locktag->lockmethod = lockmethod;
  932. #ifdef USER_LOCKS
  933. trace_flag = 
  934. (lockmethod == USER_LOCKMETHOD) ? TRACE_USERLOCKS : TRACE_LOCKS;
  935. #else
  936. trace_flag = TRACE_LOCKS;
  937. #endif
  938. Assert(lockmethod < NumLockMethods);
  939. lockMethodTable = LockMethodTable[lockmethod];
  940. if (!lockMethodTable)
  941. {
  942. elog(NOTICE, "lockMethodTable is null in LockRelease");
  943. return FALSE;
  944. }
  945. if (LockingIsDisabled)
  946. return TRUE;
  947. masterLock = lockMethodTable->ctl->masterLock;
  948. SpinAcquire(masterLock);
  949. /*
  950.  * Find a lock with this tag
  951.  */
  952. Assert(lockMethodTable->lockHash->hash == tag_hash);
  953. lock = (LOCK *) hash_search(lockMethodTable->lockHash, (Pointer) locktag,
  954. HASH_FIND, &found);
  955. /*
  956.  * let the caller print its own error message, too. Do not
  957.  * elog(ERROR).
  958.  */
  959. if (!lock)
  960. {
  961. SpinRelease(masterLock);
  962. elog(NOTICE, "LockRelease: locktable corrupted");
  963. return FALSE;
  964. }
  965. if (!found)
  966. {
  967. SpinRelease(masterLock);
  968. #ifdef USER_LOCKS
  969. if (is_user_lock)
  970. {
  971. TPRINTF(TRACE_USERLOCKS, "LockRelease: no lock with this tag");
  972. return FALSE;
  973. }
  974. #endif
  975. elog(NOTICE, "LockRelease: locktable lookup failed, no lock");
  976. return FALSE;
  977. }
  978. LOCK_PRINT("LockRelease: found", lock, lockmode);
  979. Assert((lock->nHolding > 0) && (lock->holders[lockmode] >= 0));
  980. Assert((lock->nActive > 0) && (lock->activeHolders[lockmode] >= 0));
  981. Assert(lock->nActive <= lock->nHolding);
  982. /* ------------------
  983.  * Zero out all of the tag bytes (this clears the padding bytes for long
  984.  * word alignment and ensures hashing consistency).
  985.  * ------------------
  986.  */
  987. MemSet(&item, 0, XID_TAGSIZE);
  988. item.tag.lock = MAKE_OFFSET(lock);
  989. #ifdef USE_XIDTAG_LOCKMETHOD
  990. item.tag.lockmethod = lockmethod;
  991. #endif
  992. #ifdef USER_LOCKS
  993. if (is_user_lock)
  994. {
  995. item.tag.pid = MyProcPid;
  996. item.tag.xid = xid = 0;
  997. }
  998. else
  999. {
  1000. xid = GetCurrentTransactionId();
  1001. TransactionIdStore(xid, &item.tag.xid);
  1002. }
  1003. #else
  1004. xid = GetCurrentTransactionId();
  1005. TransactionIdStore(xid, &item.tag.xid);
  1006. #endif
  1007. /*
  1008.  * Find an xid entry with this tag
  1009.  */
  1010. xidTable = lockMethodTable->xidHash;
  1011. result = (XIDLookupEnt *) hash_search(xidTable, (Pointer) &item,
  1012.   HASH_FIND_SAVE, &found);
  1013. if (!result || !found)
  1014. {
  1015. SpinRelease(masterLock);
  1016. #ifdef USER_LOCKS
  1017. if (!found && is_user_lock)
  1018. TPRINTF(TRACE_USERLOCKS, "LockRelease: no lock with this tag");
  1019. else
  1020. #endif
  1021. elog(NOTICE, "LockReplace: xid table corrupted");
  1022. return FALSE;
  1023. }
  1024. XID_PRINT("LockRelease: found", result);
  1025. Assert(result->tag.lock == MAKE_OFFSET(lock));
  1026. /*
  1027.  * Check that we are actually holding a lock of the type we want to
  1028.  * release.
  1029.  */
  1030. if (!(result->holders[lockmode] > 0))
  1031. {
  1032. SpinRelease(masterLock);
  1033. XID_PRINT_AUX("LockAcquire: WRONGTYPE", result);
  1034. elog(NOTICE, "LockRelease: you don't own a lock of type %s",
  1035.  lock_types[lockmode]);
  1036. Assert(result->holders[lockmode] >= 0);
  1037. return FALSE;
  1038. }
  1039. Assert(result->nHolding > 0);
  1040. /*
  1041.  * fix the general lock stats
  1042.  */
  1043. lock->nHolding--;
  1044. lock->holders[lockmode]--;
  1045. lock->nActive--;
  1046. lock->activeHolders[lockmode]--;
  1047. #ifdef NOT_USED
  1048. /* --------------------------
  1049.  * If there are still active locks of the type I just released, no one
  1050.  * should be woken up. Whoever is asleep will still conflict
  1051.  * with the remaining locks.
  1052.  * --------------------------
  1053.  */
  1054. if (lock->activeHolders[lockmode])
  1055. wakeupNeeded = false;
  1056. else
  1057. #endif
  1058. /*
  1059.  * Above is not valid any more (due to MVCC lock modes). Actually
  1060.  * we should compare activeHolders[lockmode] with number of
  1061.  * waiters holding lock of this type and try to wakeup only if
  1062.  * these numbers are equal (and lock released conflicts with locks
  1063.  * requested by waiters). For the moment we only check the last
  1064.  * condition.
  1065.  */
  1066. if (lockMethodTable->ctl->conflictTab[lockmode] & lock->waitMask)
  1067. wakeupNeeded = true;
  1068. if (!(lock->activeHolders[lockmode]))
  1069. {
  1070. /* change the conflict mask.  No more of this lock type. */
  1071. lock->mask &= BITS_OFF[lockmode];
  1072. }
  1073. LOCK_PRINT("LockRelease: updated", lock, lockmode);
  1074. Assert((lock->nHolding >= 0) && (lock->holders[lockmode] >= 0));
  1075. Assert((lock->nActive >= 0) && (lock->activeHolders[lockmode] >= 0));
  1076. Assert(lock->nActive <= lock->nHolding);
  1077. if (!lock->nHolding)
  1078. {
  1079. /* ------------------
  1080.  * if there's no one waiting in the queue,
  1081.  * we just released the last lock.
  1082.  * Delete it from the lock table.
  1083.  * ------------------
  1084.  */
  1085. Assert(lockMethodTable->lockHash->hash == tag_hash);
  1086. lock = (LOCK *) hash_search(lockMethodTable->lockHash,
  1087. (Pointer) &(lock->tag),
  1088. HASH_REMOVE,
  1089. &found);
  1090. Assert(lock && found);
  1091. wakeupNeeded = false;
  1092. }
  1093. /*
  1094.  * now check to see if I have any private locks.  If I do, decrement
  1095.  * the counts associated with them.
  1096.  */
  1097. result->holders[lockmode]--;
  1098. result->nHolding--;
  1099. XID_PRINT("LockRelease: updated", result);
  1100. Assert((result->nHolding >= 0) && (result->holders[lockmode] >= 0));
  1101. /*
  1102.  * If this was my last hold on this lock, delete my entry in the XID
  1103.  * table.
  1104.  */
  1105. if (!result->nHolding)
  1106. {
  1107. if (result->queue.prev == INVALID_OFFSET)
  1108. elog(NOTICE, "LockRelease: xid.prev == INVALID_OFFSET");
  1109. if (result->queue.next == INVALID_OFFSET)
  1110. elog(NOTICE, "LockRelease: xid.next == INVALID_OFFSET");
  1111. if (result->queue.next != INVALID_OFFSET)
  1112. SHMQueueDelete(&result->queue);
  1113. XID_PRINT("LockRelease: deleting", result);
  1114. result = (XIDLookupEnt *) hash_search(xidTable, (Pointer) &result,
  1115.   HASH_REMOVE_SAVED, &found);
  1116. if (!result || !found)
  1117. {
  1118. SpinRelease(masterLock);
  1119. elog(NOTICE, "LockRelease: remove xid, table corrupted");
  1120. return FALSE;
  1121. }
  1122. }
  1123. if (wakeupNeeded)
  1124. ProcLockWakeup(&(lock->waitProcs), lockmethod, lock);
  1125. else
  1126. {
  1127. if (((LOCKDEBUG(LOCK_LOCKMETHOD(*(lock))) >= 1) 
  1128.  &&(lock->tag.relId >= lockDebugOidMin)) 
  1129. ||
  1130. (lockDebugRelation && (lock->tag.relId == lockDebugRelation)))
  1131. TPRINTF(TRACE_ALL, "LockRelease: no wakeup needed");
  1132. }
  1133. SpinRelease(masterLock);
  1134. return TRUE;
  1135. }
  1136. /*
  1137.  * LockReleaseAll -- Release all locks in a process lock queue.
  1138.  */
  1139. bool
  1140. LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
  1141. {
  1142. PROC_QUEUE *waitQueue;
  1143. int done;
  1144. XIDLookupEnt *xidLook = NULL;
  1145. XIDLookupEnt *tmp = NULL;
  1146. XIDLookupEnt *result;
  1147. SHMEM_OFFSET end = MAKE_OFFSET(lockQueue);
  1148. SPINLOCK masterLock;
  1149. LOCKMETHODTABLE *lockMethodTable;
  1150. int i,
  1151. numLockModes;
  1152. LOCK    *lock;
  1153. bool found;
  1154. int trace_flag;
  1155. int xidtag_lockmethod;
  1156. #ifdef USER_LOCKS
  1157. int is_user_lock_table,
  1158. count,
  1159. nleft;
  1160. count = nleft = 0;
  1161. is_user_lock_table = (lockmethod == USER_LOCKMETHOD);
  1162. trace_flag = (lockmethod == 2) ? TRACE_USERLOCKS : TRACE_LOCKS;
  1163. #else
  1164. trace_flag = TRACE_LOCKS;
  1165. #endif
  1166. TPRINTF(trace_flag, "LockReleaseAll: lockmethod=%d, pid=%d",
  1167. lockmethod, MyProcPid);
  1168. Assert(lockmethod < NumLockMethods);
  1169. lockMethodTable = LockMethodTable[lockmethod];
  1170. if (!lockMethodTable)
  1171. {
  1172. elog(NOTICE, "LockAcquire: bad lockmethod %d", lockmethod);
  1173. return FALSE;
  1174. }
  1175. if (SHMQueueEmpty(lockQueue))
  1176. return TRUE;
  1177. numLockModes = lockMethodTable->ctl->numLockModes;
  1178. masterLock = lockMethodTable->ctl->masterLock;
  1179. SpinAcquire(masterLock);
  1180. SHMQueueFirst(lockQueue, (Pointer *) &xidLook, &xidLook->queue);
  1181. for (;;)
  1182. {
  1183. bool wakeupNeeded = false;
  1184. /*
  1185.  * Sometimes the queue appears to be messed up.
  1186.  */
  1187. if (count++ > 1000)
  1188. {
  1189. elog(NOTICE, "LockReleaseAll: xid loop detected, giving up");
  1190. nleft = 0;
  1191. break;
  1192. }
  1193. /* ---------------------------
  1194.  * XXX Here we assume the shared memory queue is circular and
  1195.  * that we know its internal structure.  Should have some sort of
  1196.  * macros to allow one to walk it. mer 20 July 1991
  1197.  * ---------------------------
  1198.  */
  1199. done = (xidLook->queue.next == end);
  1200. lock = (LOCK *) MAKE_PTR(xidLook->tag.lock);
  1201. xidtag_lockmethod = XIDENT_LOCKMETHOD(*xidLook);
  1202. if ((xidtag_lockmethod == lockmethod) && pg_options[trace_flag])
  1203. {
  1204. XID_PRINT("LockReleaseAll", xidLook);
  1205. LOCK_PRINT("LockReleaseAll", lock, 0);
  1206. }
  1207. #ifdef USE_XIDTAG_LOCKMETHOD
  1208. if (xidtag_lockmethod != LOCK_LOCKMETHOD(*lock))
  1209. elog(NOTICE, "LockReleaseAll: xid/lock method mismatch: %d != %d",
  1210.  xidtag_lockmethod, lock->tag.lockmethod);
  1211. #endif
  1212. if ((xidtag_lockmethod != lockmethod) && (trace_flag >= 2))
  1213. {
  1214. TPRINTF(trace_flag, "LockReleaseAll: skipping other table");
  1215. nleft++;
  1216. goto next_item;
  1217. }
  1218. Assert(lock->nHolding > 0);
  1219. Assert(lock->nActive > 0);
  1220. Assert(lock->nActive <= lock->nHolding);
  1221. Assert(xidLook->nHolding >= 0);
  1222. Assert(xidLook->nHolding <= lock->nHolding);
  1223. #ifdef USER_LOCKS
  1224. if (is_user_lock_table)
  1225. {
  1226. if ((xidLook->tag.pid == 0) || (xidLook->tag.xid != 0))
  1227. {
  1228. TPRINTF(TRACE_USERLOCKS,
  1229. "LockReleaseAll: skiping normal lock [%d,%d,%d]",
  1230.   xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
  1231. nleft++;
  1232. goto next_item;
  1233. }
  1234. if (xidLook->tag.pid != MyProcPid)
  1235. {
  1236. /* Should never happen */
  1237. elog(NOTICE,
  1238.  "LockReleaseAll: INVALID PID: [%u] [%d,%d,%d]",
  1239.  lock->tag.objId.blkno,
  1240.   xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
  1241. nleft++;
  1242. goto next_item;
  1243. }
  1244. TPRINTF(TRACE_USERLOCKS,
  1245. "LockReleaseAll: releasing user lock [%u] [%d,%d,%d]",
  1246. lock->tag.objId.blkno,
  1247.   xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
  1248. }
  1249. else
  1250. {
  1251. /*
  1252.  * Can't check xidLook->tag.xid, can be 0 also for normal
  1253.  * locks
  1254.  */
  1255. if (xidLook->tag.pid != 0)
  1256. {
  1257. TPRINTF(TRACE_LOCKS,
  1258.  "LockReleaseAll: skiping user lock [%u] [%d,%d,%d]",
  1259. lock->tag.objId.blkno,
  1260.   xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
  1261. nleft++;
  1262. goto next_item;
  1263. }
  1264. }
  1265. #endif
  1266. /* ------------------
  1267.  * fix the general lock stats
  1268.  * ------------------
  1269.  */
  1270. if (lock->nHolding != xidLook->nHolding)
  1271. {
  1272. for (i = 1; i <= numLockModes; i++)
  1273. {
  1274. Assert(xidLook->holders[i] >= 0);
  1275. lock->holders[i] -= xidLook->holders[i];
  1276. lock->activeHolders[i] -= xidLook->holders[i];
  1277. Assert((lock->holders[i] >= 0) 
  1278.    &&(lock->activeHolders[i] >= 0));
  1279. if (!lock->activeHolders[i])
  1280. lock->mask &= BITS_OFF[i];
  1281. /*
  1282.  * Read comments in LockRelease
  1283.  */
  1284. if (!wakeupNeeded && xidLook->holders[i] > 0 &&
  1285. lockMethodTable->ctl->conflictTab[i] & lock->waitMask)
  1286. wakeupNeeded = true;
  1287. }
  1288. lock->nHolding -= xidLook->nHolding;
  1289. lock->nActive -= xidLook->nHolding;
  1290. Assert((lock->nHolding >= 0) && (lock->nActive >= 0));
  1291. Assert(lock->nActive <= lock->nHolding);
  1292. }
  1293. else
  1294. {
  1295. /* --------------
  1296.  * set nHolding to zero so that we can garbage collect the lock
  1297.  * down below...
  1298.  * --------------
  1299.  */
  1300. lock->nHolding = 0;
  1301. /* Fix the lock status, just for next LOCK_PRINT message. */
  1302. for (i = 1; i <= numLockModes; i++)
  1303. {
  1304. Assert(lock->holders[i] == lock->activeHolders[i]);
  1305. lock->holders[i] = lock->activeHolders[i] = 0;
  1306. }
  1307. }
  1308. LOCK_PRINT("LockReleaseAll: updated", lock, 0);
  1309. /*
  1310.  * Remove the xid from the process lock queue
  1311.  */
  1312. SHMQueueDelete(&xidLook->queue);
  1313. /* ----------------
  1314.  * always remove the xidLookup entry, we're done with it now
  1315.  * ----------------
  1316.  */
  1317. XID_PRINT("LockReleaseAll: deleting", xidLook);
  1318. result = (XIDLookupEnt *) hash_search(lockMethodTable->xidHash,
  1319.   (Pointer) xidLook,
  1320.   HASH_REMOVE,
  1321.   &found);
  1322. if (!result || !found)
  1323. {
  1324. SpinRelease(masterLock);
  1325. elog(NOTICE, "LockReleaseAll: xid table corrupted");
  1326. return FALSE;
  1327. }
  1328. if (!lock->nHolding)
  1329. {
  1330. /* --------------------
  1331.  * if there's no one waiting in the queue, we've just released
  1332.  * the last lock.
  1333.  * --------------------
  1334.  */
  1335. LOCK_PRINT("LockReleaseAll: deleting", lock, 0);
  1336. Assert(lockMethodTable->lockHash->hash == tag_hash);
  1337. lock = (LOCK *) hash_search(lockMethodTable->lockHash,
  1338. (Pointer) &(lock->tag),
  1339. HASH_REMOVE, &found);
  1340. if ((!lock) || (!found))
  1341. {
  1342. SpinRelease(masterLock);
  1343. elog(NOTICE, "LockReleaseAll: cannot remove lock from HTAB");
  1344. return FALSE;
  1345. }
  1346. }
  1347. else if (wakeupNeeded)
  1348. {
  1349. waitQueue = &(lock->waitProcs);
  1350. ProcLockWakeup(waitQueue, lockmethod, lock);
  1351. }
  1352. #ifdef USER_LOCKS
  1353. next_item:
  1354. #endif
  1355. if (done)
  1356. break;
  1357. SHMQueueFirst(&xidLook->queue, (Pointer *) &tmp, &tmp->queue);
  1358. xidLook = tmp;
  1359. }
  1360. /*
  1361.  * Reinitialize the queue only if nothing has been left in.
  1362.  */
  1363. if (nleft == 0)
  1364. {
  1365. TPRINTF(trace_flag, "LockReleaseAll: reinitializing lockQueue");
  1366. SHMQueueInit(lockQueue);
  1367. }
  1368. SpinRelease(masterLock);
  1369. TPRINTF(trace_flag, "LockReleaseAll: done");
  1370. return TRUE;
  1371. }
  1372. int
  1373. LockShmemSize(int maxBackends)
  1374. {
  1375. int size = 0;
  1376. size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */
  1377. size += MAXALIGN(maxBackends * sizeof(PROC)); /* each MyProc */
  1378. size += MAXALIGN(maxBackends * sizeof(LOCKMETHODCTL)); /* each
  1379.  * lockMethodTable->ctl */
  1380. /* lockHash table */
  1381. size += hash_estimate_size(NLOCKENTS(maxBackends),
  1382.    SHMEM_LOCKTAB_KEYSIZE,
  1383.    SHMEM_LOCKTAB_DATASIZE);
  1384. /* xidHash table */
  1385. size += hash_estimate_size(NLOCKENTS(maxBackends),
  1386.    SHMEM_XIDTAB_KEYSIZE,
  1387.    SHMEM_XIDTAB_DATASIZE);
  1388. /*
  1389.  * Since the lockHash entry count above is only an estimate, add 10%
  1390.  * safety margin.
  1391.  */
  1392. size += size / 10;
  1393. return size;
  1394. }
  1395. /* -----------------
  1396.  * Boolean function to determine current locking status
  1397.  * -----------------
  1398.  */
  1399. bool
  1400. LockingDisabled()
  1401. {
  1402. return LockingIsDisabled;
  1403. }
  1404. /*
  1405.  * DeadlockCheck -- Checks for deadlocks for a given process
  1406.  *
  1407.  * We can't block on user locks, so no sense testing for deadlock
  1408.  * because there is no blocking, and no timer for the block.
  1409.  *
  1410.  * This code takes a list of locks a process holds, and the lock that
  1411.  * the process is sleeping on, and tries to find if any of the processes
  1412.  * waiting on its locks hold the lock it is waiting for.  If no deadlock
  1413.  * is found, it goes on to look at all the processes waiting on their locks.
  1414.  *
  1415.  * We have already locked the master lock before being called.
  1416.  */
  1417. bool
  1418. DeadLockCheck(void *proc, LOCK *findlock)
  1419. {
  1420. XIDLookupEnt *xidLook = NULL;
  1421. XIDLookupEnt *tmp = NULL;
  1422. PROC    *thisProc = (PROC *) proc,
  1423.    *waitProc;
  1424. SHM_QUEUE  *lockQueue = &(thisProc->lockQueue);
  1425. SHMEM_OFFSET end = MAKE_OFFSET(lockQueue);
  1426. LOCK    *lock;
  1427. PROC_QUEUE *waitQueue;
  1428. int i,
  1429. j;
  1430. bool first_run = (thisProc == MyProc),
  1431. done;
  1432. static PROC *checked_procs[MAXBACKENDS];
  1433. static int nprocs;
  1434. /* initialize at start of recursion */
  1435. if (first_run)
  1436. {
  1437. checked_procs[0] = MyProc;
  1438. nprocs = 1;
  1439. }
  1440. if (SHMQueueEmpty(lockQueue))
  1441. return false;
  1442. SHMQueueFirst(lockQueue, (Pointer *) &xidLook, &xidLook->queue);
  1443. XID_PRINT("DeadLockCheck", xidLook);
  1444. for (;;)
  1445. {
  1446. done = (xidLook->queue.next == end);
  1447. lock = (LOCK *) MAKE_PTR(xidLook->tag.lock);
  1448. LOCK_PRINT("DeadLockCheck", lock, 0);
  1449. if (lock->tag.relId == 0) /* user' lock */
  1450. goto nxtl;
  1451. /*
  1452.  * waitLock is always in lockQueue of waiting proc, if !first_run
  1453.  * then upper caller will handle waitProcs queue of waitLock.
  1454.  */
  1455. if (thisProc->waitLock == lock && !first_run)
  1456. goto nxtl;
  1457. /*
  1458.  * If we found proc holding findlock and sleeping on some my other
  1459.  * lock then we have to check does it block me or another waiters.
  1460.  */
  1461. if (lock == findlock && !first_run)
  1462. {
  1463. LOCKMETHODCTL *lockctl =
  1464. LockMethodTable[DEFAULT_LOCKMETHOD]->ctl;
  1465. int lm;
  1466. Assert(xidLook->nHolding > 0);
  1467. for (lm = 1; lm <= lockctl->numLockModes; lm++)
  1468. {
  1469. if (xidLook->holders[lm] > 0 &&
  1470. lockctl->conflictTab[lm] & findlock->waitMask)
  1471. return true;
  1472. }
  1473. /*
  1474.  * Else - get the next lock from thisProc's lockQueue
  1475.  */
  1476. goto nxtl;
  1477. }
  1478. waitQueue = &(lock->waitProcs);
  1479. waitProc = (PROC *) MAKE_PTR(waitQueue->links.prev);
  1480. for (i = 0; i < waitQueue->size; i++)
  1481. {
  1482. if (waitProc == thisProc)
  1483. {
  1484. Assert(waitProc->waitLock == lock);
  1485. Assert(waitProc == MyProc);
  1486. waitProc = (PROC *) MAKE_PTR(waitProc->links.prev);
  1487. continue;
  1488. }
  1489. if (lock == findlock) /* first_run also true */
  1490. {
  1491. LOCKMETHODCTL *lockctl =
  1492. LockMethodTable[DEFAULT_LOCKMETHOD]->ctl;
  1493. /*
  1494.  * If me blocked by his holdlock...
  1495.  */
  1496. if (lockctl->conflictTab[MyProc->token] & waitProc->holdLock)
  1497. {
  1498. /* and he blocked by me -> deadlock */
  1499. if (lockctl->conflictTab[waitProc->token] & MyProc->holdLock)
  1500. return true;
  1501. /* we shouldn't look at lockQueue of our blockers */
  1502. waitProc = (PROC *) MAKE_PTR(waitProc->links.prev);
  1503. continue;
  1504. }
  1505. /*
  1506.  * If he isn't blocked by me and we request
  1507.  * non-conflicting lock modes - no deadlock here because
  1508.  * of he isn't blocked by me in any sence (explicitle or
  1509.  * implicitly). Note that we don't do like test if
  1510.  * !first_run (when thisProc is holder and non-waiter on
  1511.  * lock) and so we call DeadLockCheck below for every
  1512.  * waitProc in thisProc->lockQueue, even for waitProc-s
  1513.  * un-blocked by thisProc. Should we? This could save us
  1514.  * some time...
  1515.  */
  1516. if (!(lockctl->conflictTab[waitProc->token] & MyProc->holdLock) &&
  1517. !(lockctl->conflictTab[waitProc->token] & (1 << MyProc->token)))
  1518. {
  1519. waitProc = (PROC *) MAKE_PTR(waitProc->links.prev);
  1520. continue;
  1521. }
  1522. }
  1523. /*
  1524.  * Look in lockQueue of this waitProc, if didn't do this
  1525.  * before.
  1526.  */
  1527. for (j = 0; j < nprocs; j++)
  1528. {
  1529. if (checked_procs[j] == waitProc)
  1530. break;
  1531. }
  1532. if (j >= nprocs)
  1533. {
  1534. Assert(nprocs < MAXBACKENDS);
  1535. checked_procs[nprocs++] = waitProc;
  1536. if (DeadLockCheck(waitProc, findlock))
  1537. {
  1538. LOCKMETHODCTL *lockctl =
  1539. LockMethodTable[DEFAULT_LOCKMETHOD]->ctl;
  1540. int holdLock;
  1541. /*
  1542.  * Ok, but is waitProc waiting for me (thisProc) ?
  1543.  */
  1544. if (thisProc->waitLock == lock)
  1545. {
  1546. Assert(first_run);
  1547. holdLock = thisProc->holdLock;
  1548. }
  1549. else
  1550. /* should we cache holdLock ? */
  1551. {
  1552. int lm,
  1553. tmpMask = 2;
  1554. Assert(xidLook->nHolding > 0);
  1555. for (holdLock = 0, lm = 1;
  1556.  lm <= lockctl->numLockModes;
  1557.  lm++, tmpMask <<= 1)
  1558. {
  1559. if (xidLook->holders[lm] > 0)
  1560. holdLock |= tmpMask;
  1561. }
  1562. Assert(holdLock != 0);
  1563. }
  1564. if (lockctl->conflictTab[waitProc->token] & holdLock)
  1565. {
  1566. /*
  1567.  * Last attempt to avoid deadlock - try to wakeup
  1568.  * myself.
  1569.  */
  1570. if (first_run)
  1571. {
  1572. if (LockResolveConflicts(DEFAULT_LOCKMETHOD,
  1573.  MyProc->waitLock,
  1574.  MyProc->token,
  1575.  MyProc->xid,
  1576.  NULL) == STATUS_OK)
  1577. {
  1578. GrantLock(MyProc->waitLock, MyProc->token);
  1579. (MyProc->waitLock->waitProcs.size)--;
  1580. ProcWakeup(MyProc, NO_ERROR);
  1581. return false;
  1582. }
  1583. }
  1584. return true;
  1585. }
  1586. /*
  1587.  * Hell! Is he blocked by any (other) holder ?
  1588.  */
  1589. if (LockResolveConflicts(DEFAULT_LOCKMETHOD,
  1590.  lock,
  1591.  waitProc->token,
  1592.  waitProc->xid,
  1593.  NULL) != STATUS_OK)
  1594. {
  1595. /*
  1596.  * Blocked by others - no deadlock...
  1597.  */
  1598. #ifdef DEADLOCK_DEBUG
  1599. LOCK_PRINT("DeadLockCheck: blocked by others",
  1600.    lock, waitProc->token);
  1601. #endif
  1602. waitProc = (PROC *) MAKE_PTR(waitProc->links.prev);
  1603. continue;
  1604. }
  1605. /*
  1606.  * Well - wakeup this guy! This is the case of
  1607.  * implicit blocking: thisProc blocked someone who
  1608.  * blocked waitProc by the fact that he/someone is
  1609.  * already waiting for lock.  We do this for
  1610.  * anti-starving.
  1611.  */
  1612. GrantLock(lock, waitProc->token);
  1613. waitQueue->size--;
  1614. waitProc = ProcWakeup(waitProc, NO_ERROR);
  1615. continue;
  1616. }
  1617. }
  1618. waitProc = (PROC *) MAKE_PTR(waitProc->links.prev);
  1619. }
  1620. nxtl: ;
  1621. if (done)
  1622. break;
  1623. SHMQueueFirst(&xidLook->queue, (Pointer *) &tmp, &tmp->queue);
  1624. xidLook = tmp;
  1625. }
  1626. /* if we got here, no deadlock */
  1627. return false;
  1628. }
  1629. #ifdef NOT_USED
  1630. /*
  1631.  * Return an array with the pids of all processes owning a lock.
  1632.  * This works only for user locks because normal locks have no
  1633.  * pid information in the corresponding XIDLookupEnt.
  1634.  */
  1635. ArrayType  *
  1636. LockOwners(LOCKMETHOD lockmethod, LOCKTAG *locktag)
  1637. {
  1638. XIDLookupEnt *xidLook = NULL;
  1639. SPINLOCK masterLock;
  1640. LOCK    *lock;
  1641. SHMEM_OFFSET lock_offset;
  1642. int count = 0;
  1643. LOCKMETHODTABLE *lockMethodTable;
  1644. HTAB    *xidTable;
  1645. bool found;
  1646. int ndims,
  1647. nitems,
  1648. hdrlen,
  1649. size;
  1650. int lbounds[1],
  1651. hbounds[1];
  1652. ArrayType  *array;
  1653. int    *data_ptr;
  1654. /* Assume that no one will modify the result */
  1655. static int empty_array[] = {20, 1, 0, 0, 0};
  1656. #ifdef USER_LOCKS
  1657. int is_user_lock;
  1658. is_user_lock = (lockmethod == USER_LOCKMETHOD);
  1659. if (is_user_lock)
  1660. {
  1661. TPRINTF(TRACE_USERLOCKS, "LockOwners: user lock tag [%u]",
  1662. locktag->objId.blkno);
  1663. }
  1664. #endif
  1665. /* This must be changed when short term locks will be used */
  1666. locktag->lockmethod = lockmethod;
  1667. Assert((lockmethod >= MIN_LOCKMETHOD) && (lockmethod < NumLockMethods));
  1668. lockMethodTable = LockMethodTable[lockmethod];
  1669. if (!lockMethodTable)
  1670. {
  1671. elog(NOTICE, "lockMethodTable is null in LockOwners");
  1672. return (ArrayType *) &empty_array;
  1673. }
  1674. if (LockingIsDisabled)
  1675. return (ArrayType *) &empty_array;
  1676. masterLock = lockMethodTable->ctl->masterLock;
  1677. SpinAcquire(masterLock);
  1678. /*
  1679.  * Find a lock with this tag
  1680.  */
  1681. Assert(lockMethodTable->lockHash->hash == tag_hash);
  1682. lock = (LOCK *) hash_search(lockMethodTable->lockHash, (Pointer) locktag,
  1683. HASH_FIND, &found);
  1684. /*
  1685.  * let the caller print its own error message, too. Do not elog(WARN).
  1686.  */
  1687. if (!lock)
  1688. {
  1689. SpinRelease(masterLock);
  1690. elog(NOTICE, "LockOwners: locktable corrupted");
  1691. return (ArrayType *) &empty_array;
  1692. }
  1693. if (!found)
  1694. {
  1695. SpinRelease(masterLock);
  1696. #ifdef USER_LOCKS
  1697. if (is_user_lock)
  1698. {
  1699. TPRINTF(TRACE_USERLOCKS, "LockOwners: no lock with this tag");
  1700. return (ArrayType *) &empty_array;
  1701. }
  1702. #endif
  1703. elog(NOTICE, "LockOwners: locktable lookup failed, no lock");
  1704. return (ArrayType *) &empty_array;
  1705. }
  1706. LOCK_PRINT("LockOwners: found", lock, 0);
  1707. Assert((lock->nHolding > 0) && (lock->nActive > 0));
  1708. Assert(lock->nActive <= lock->nHolding);
  1709. lock_offset = MAKE_OFFSET(lock);
  1710. /* Construct a 1-dimensional array */
  1711. ndims = 1;
  1712. hdrlen = ARR_OVERHEAD(ndims);
  1713. lbounds[0] = 0;
  1714. hbounds[0] = lock->nActive;
  1715. size = hdrlen + sizeof(int) * hbounds[0];
  1716. array = (ArrayType *) palloc(size);
  1717. MemSet(array, 0, size);
  1718. memmove((char *) array, (char *) &size, sizeof(int));
  1719. memmove((char *) ARR_NDIM_PTR(array), (char *) &ndims, sizeof(int));
  1720. memmove((char *) ARR_DIMS(array), (char *) hbounds, ndims * sizeof(int));
  1721. memmove((char *) ARR_LBOUND(array), (char *) lbounds, ndims * sizeof(int));
  1722. SET_LO_FLAG(false, array);
  1723. data_ptr = (int *) ARR_DATA_PTR(array);
  1724. xidTable = lockMethodTable->xidHash;
  1725. hash_seq(NULL);
  1726. nitems = 0;
  1727. while ((xidLook = (XIDLookupEnt *) hash_seq(xidTable)) &&
  1728.    (xidLook != (XIDLookupEnt *) TRUE))
  1729. {
  1730. if (count++ > 1000)
  1731. {
  1732. elog(NOTICE, "LockOwners: possible loop, giving up");
  1733. break;
  1734. }
  1735. if (xidLook->tag.pid == 0)
  1736. {
  1737. XID_PRINT("LockOwners: no pid", xidLook);
  1738. continue;
  1739. }
  1740. if (!xidLook->tag.lock)
  1741. {
  1742. XID_PRINT("LockOwners: NULL LOCK", xidLook);
  1743. continue;
  1744. }
  1745. if (xidLook->tag.lock != lock_offset)
  1746. {
  1747. XID_PRINT("LockOwners: different lock", xidLook);
  1748. continue;
  1749. }
  1750. if (LOCK_LOCKMETHOD(*lock) != lockmethod)
  1751. {
  1752. XID_PRINT("LockOwners: other table", xidLook);
  1753. continue;
  1754. }
  1755. if (xidLook->nHolding <= 0)
  1756. {
  1757. XID_PRINT("LockOwners: not holding", xidLook);
  1758. continue;
  1759. }
  1760. if (nitems >= hbounds[0])
  1761. {
  1762. elog(NOTICE, "LockOwners: array size exceeded");
  1763. break;
  1764. }
  1765. /*
  1766.  * Check that the holding process is still alive by sending him an
  1767.  * unused (ignored) signal. If the kill fails the process is not
  1768.  * alive.
  1769.  */
  1770. if ((xidLook->tag.pid != MyProcPid) 
  1771. &&(kill(xidLook->tag.pid, SIGCHLD)) != 0)
  1772. {
  1773. /* Return a negative pid to signal that process is dead */
  1774. data_ptr[nitems++] = -(xidLook->tag.pid);
  1775. XID_PRINT("LockOwners: not alive", xidLook);
  1776. /* XXX - TODO: remove this entry and update lock stats */
  1777. continue;
  1778. }
  1779. /* Found a process holding the lock */
  1780. XID_PRINT("LockOwners: holding", xidLook);
  1781. data_ptr[nitems++] = xidLook->tag.pid;
  1782. }
  1783. SpinRelease(masterLock);
  1784. /* Adjust the actual size of the array */
  1785. hbounds[0] = nitems;
  1786. size = hdrlen + sizeof(int) * hbounds[0];
  1787. memmove((char *) array, (char *) &size, sizeof(int));
  1788. memmove((char *) ARR_DIMS(array), (char *) hbounds, ndims * sizeof(int));
  1789. return array;
  1790. }
  1791. #endif
  1792. #ifdef DEADLOCK_DEBUG
  1793. /*
  1794.  * Dump all locks in the proc->lockQueue. Must have already acquired
  1795.  * the masterLock.
  1796.  */
  1797. void
  1798. DumpLocks()
  1799. {
  1800. SHMEM_OFFSET location;
  1801. PROC    *proc;
  1802. SHM_QUEUE  *lockQueue;
  1803. int done;
  1804. XIDLookupEnt *xidLook = NULL;
  1805. XIDLookupEnt *tmp = NULL;
  1806. SHMEM_OFFSET end;
  1807. SPINLOCK masterLock;
  1808. int numLockModes;
  1809. LOCK    *lock;
  1810. int count = 0;
  1811. int lockmethod = DEFAULT_LOCKMETHOD;
  1812. LOCKMETHODTABLE *lockMethodTable;
  1813. ShmemPIDLookup(MyProcPid, &location);
  1814. if (location == INVALID_OFFSET)
  1815. return;
  1816. proc = (PROC *) MAKE_PTR(location);
  1817. if (proc != MyProc)
  1818. return;
  1819. lockQueue = &proc->lockQueue;
  1820. Assert(lockmethod < NumLockMethods);
  1821. lockMethodTable = LockMethodTable[lockmethod];
  1822. if (!lockMethodTable)
  1823. return;
  1824. numLockModes = lockMethodTable->ctl->numLockModes;
  1825. masterLock = lockMethodTable->ctl->masterLock;
  1826. if (SHMQueueEmpty(lockQueue))
  1827. return;
  1828. SHMQueueFirst(lockQueue, (Pointer *) &xidLook, &xidLook->queue);
  1829. end = MAKE_OFFSET(lockQueue);
  1830. if (MyProc->waitLock)
  1831. LOCK_PRINT_AUX("DumpLocks: waiting on", MyProc->waitLock, 0);
  1832. for (;;)
  1833. {
  1834. if (count++ > 2000)
  1835. {
  1836. elog(NOTICE, "DumpLocks: xid loop detected, giving up");
  1837. break;
  1838. }
  1839. /* ---------------------------
  1840.  * XXX Here we assume the shared memory queue is circular and
  1841.  * that we know its internal structure.  Should have some sort of
  1842.  * macros to allow one to walk it. mer 20 July 1991
  1843.  * ---------------------------
  1844.  */
  1845. done = (xidLook->queue.next == end);
  1846. lock = (LOCK *) MAKE_PTR(xidLook->tag.lock);
  1847. XID_PRINT_AUX("DumpLocks", xidLook);
  1848. LOCK_PRINT_AUX("DumpLocks", lock, 0);
  1849. if (done)
  1850. break;
  1851. SHMQueueFirst(&xidLook->queue, (Pointer *) &tmp, &tmp->queue);
  1852. xidLook = tmp;
  1853. }
  1854. }
  1855. /*
  1856.  * Dump all postgres locks. Must have already acquired the masterLock.
  1857.  */
  1858. void
  1859. DumpAllLocks()
  1860. {
  1861. SHMEM_OFFSET location;
  1862. PROC    *proc;
  1863. XIDLookupEnt *xidLook = NULL;
  1864. LOCK    *lock;
  1865. int pid;
  1866. int count = 0;
  1867. int lockmethod = DEFAULT_LOCKMETHOD;
  1868. LOCKMETHODTABLE *lockMethodTable;
  1869. HTAB    *xidTable;
  1870. pid = getpid();
  1871. ShmemPIDLookup(pid, &location);
  1872. if (location == INVALID_OFFSET)
  1873. return;
  1874. proc = (PROC *) MAKE_PTR(location);
  1875. if (proc != MyProc)
  1876. return;
  1877. Assert(lockmethod < NumLockMethods);
  1878. lockMethodTable = LockMethodTable[lockmethod];
  1879. if (!lockMethodTable)
  1880. return;
  1881. xidTable = lockMethodTable->xidHash;
  1882. if (MyProc->waitLock)
  1883. LOCK_PRINT_AUX("DumpAllLocks: waiting on", MyProc->waitLock, 0);
  1884. hash_seq(NULL);
  1885. while ((xidLook = (XIDLookupEnt *) hash_seq(xidTable)) &&
  1886.    (xidLook != (XIDLookupEnt *) TRUE))
  1887. {
  1888. XID_PRINT_AUX("DumpAllLocks", xidLook);
  1889. if (xidLook->tag.lock)
  1890. {
  1891. lock = (LOCK *) MAKE_PTR(xidLook->tag.lock);
  1892. LOCK_PRINT_AUX("DumpAllLocks", lock, 0);
  1893. }
  1894. else
  1895. elog(DEBUG, "DumpAllLocks: xidLook->tag.lock = NULL");
  1896. if (count++ > 2000)
  1897. {
  1898. elog(NOTICE, "DumpAllLocks: possible loop, giving up");
  1899. break;
  1900. }
  1901. }
  1902. }
  1903. #endif