static void LWLockTryLockWaiting( PGPROC *proc, LWLockId lockid, LWLockMode mode) { volatile LWLock *lock = &(LWLockArray[lockid].lock); int milliseconds = 0; int exclusivePid; while(true) { pg_usleep(5000L); if (PGSemaphoreTryLock(&proc->sem)) { if (milliseconds >= 750) elog(LOG, "Done waiting on lockid %d", lockid); return; } milliseconds += 5; if (milliseconds == 750) { int l; int count = 0; char buffer[200]; SpinLockAcquire(&lock->mutex); if (lock->exclusive > 0) exclusivePid = lock->exclusivePid; else exclusivePid = 0; SpinLockRelease(&lock->mutex); memcpy(buffer, "none", 5); for (l = 0; l < num_held_lwlocks; l++) { if (l == 0) count += sprintf(&buffer[count],"("); else count += sprintf(&buffer[count],", "); count += sprintf(&buffer[count], "lockid %d", held_lwlocks[l]); } if (num_held_lwlocks > 0) count += sprintf(&buffer[count],")"); elog(LOG, "Waited .75 seconds on lockid %d with no success. Exclusive pid %d. Already held: %s", lockid, exclusivePid, buffer); } } }
/* * PGSemaphoreReset * * Reset a previously-initialized PGSemaphore to have count 0 */ void PGSemaphoreReset(PGSemaphore sema) { /* * There's no direct API for this in Win32, so we have to ratchet the * semaphore down to 0 with repeated trylock's. */ while (PGSemaphoreTryLock(sema)); }
int tas_sema(volatile slock_t *lock) { int lockndx = *lock; if (lockndx <= 0 || lockndx > NUM_SPINLOCK_SEMAPHORES) elog(ERROR, "invalid spinlock number: %d", lockndx); /* Note that TAS macros return 0 if *success* */ return !PGSemaphoreTryLock(&SpinlockSemaArray[lockndx - 1]); }
int main(int argc, char **argv) { MyStorage *storage; int cpid; printf("Creating shared memory ... "); fflush(stdout); storage = (MyStorage *) PGSharedMemoryCreate(8192, false, 5433); storage->flag = 1234; printf("OK\n"); printf("Creating semaphores ... "); fflush(stdout); PGReserveSemaphores(2, 5433); PGSemaphoreCreate(&storage->sem); printf("OK\n"); /* sema initial value is 1, so lock should work */ printf("Testing Lock ... "); fflush(stdout); PGSemaphoreLock(&storage->sem, false); printf("OK\n"); /* now sema value is 0, so trylock should fail */ printf("Testing TryLock ... "); fflush(stdout); if (PGSemaphoreTryLock(&storage->sem)) printf("unexpected result!\n"); else printf("OK\n"); /* unlocking twice and then locking twice should work... */ printf("Testing Multiple Lock ... "); fflush(stdout); PGSemaphoreUnlock(&storage->sem); PGSemaphoreUnlock(&storage->sem); PGSemaphoreLock(&storage->sem, false); PGSemaphoreLock(&storage->sem, false); printf("OK\n"); /* check Reset too */ printf("Testing Reset ... "); fflush(stdout); PGSemaphoreUnlock(&storage->sem); PGSemaphoreReset(&storage->sem); if (PGSemaphoreTryLock(&storage->sem)) printf("unexpected result!\n"); else printf("OK\n"); /* Fork a child process and see if it can communicate */ printf("Forking child process ... "); fflush(stdout); cpid = fork(); if (cpid == 0) { /* In child */ on_exit_reset(); sleep(3); storage->flag++; PGSemaphoreUnlock(&storage->sem); proc_exit(0); } if (cpid < 0) { /* Fork failed */ printf("failed: %s\n", strerror(errno)); proc_exit(1); } printf("forked child pid %d OK\n", cpid); if (storage->flag != 1234) printf("Wrong value found in shared memory!\n"); printf("Waiting for child (should wait 3 sec here) ... "); fflush(stdout); PGSemaphoreLock(&storage->sem, false); printf("OK\n"); if (storage->flag != 1235) printf("Wrong value found in shared memory!\n"); /* Test shutdown */ printf("Running shmem_exit processing ... "); fflush(stdout); shmem_exit(0); printf("OK\n"); printf("Tests complete.\n"); proc_exit(0); return 0; /* not reached */ }
int tas_sema(volatile slock_t *lock) { /* Note that TAS macros return 0 if *success* */ return !PGSemaphoreTryLock(&SpinlockSemaArray[*lock]); }
int tas_sema(volatile slock_t *lock) { /* Note that TAS macros return 0 if *success* */ return !PGSemaphoreTryLock((PGSemaphore) lock); }