bool SpinIsLocked(SPINLOCK lock) { int semval; semval = IpcSemaphoreGetValue(SpinLockId, lock); return(semval < IpcSemaphoreDefaultStartValue); }
/* * Create a semaphore set with the given number of useful semaphores * (an additional sema is actually allocated to serve as identifier). * Dead Postgres sema sets are recycled if found, but we do not fail * upon collision with non-Postgres sema sets. * * The idea here is to detect and re-use keys that may have been assigned * by a crashed postmaster or backend. */ static IpcSemaphoreId IpcSemaphoreCreate(int numSems) { IpcSemaphoreId semId; union semun semun; PGSemaphoreData mysema; /* Loop till we find a free IPC key */ for (nextSemaKey++;; nextSemaKey++) { pid_t creatorPID; /* Try to create new semaphore set */ semId = InternalIpcSemaphoreCreate(nextSemaKey, numSems + 1); if (semId >= 0) break; /* successful create */ /* See if it looks to be leftover from a dead Postgres process */ semId = semget(nextSemaKey, numSems + 1, 0); if (semId < 0) continue; /* failed: must be some other app's */ if (IpcSemaphoreGetValue(semId, numSems) != PGSemaMagic) continue; /* sema belongs to a non-Postgres app */ /* * If the creator PID is my own PID or does not belong to any extant * process, it's safe to zap it. */ creatorPID = IpcSemaphoreGetLastPID(semId, numSems); if (creatorPID <= 0) continue; /* oops, GETPID failed */ if (creatorPID != getpid()) { if (kill(creatorPID, 0) == 0 || errno != ESRCH) continue; /* sema belongs to a live process */ } /* * The sema set appears to be from a dead Postgres process, or from a * previous cycle of life in this same process. Zap it, if possible. * This probably shouldn't fail, but if it does, assume the sema set * belongs to someone else after all, and continue quietly. */ semun.val = 0; /* unused, but keep compiler quiet */ if (semctl(semId, 0, IPC_RMID, semun) < 0) continue; /* * Now try again to create the sema set. */ semId = InternalIpcSemaphoreCreate(nextSemaKey, numSems + 1); if (semId >= 0) break; /* successful create */ /* * Can only get here if some other process managed to create the same * sema key before we did. Let him have that one, loop around to try * next key. */ } /* * OK, we created a new sema set. Mark it as created by this process. We * do this by setting the spare semaphore to PGSemaMagic-1 and then * incrementing it with semop(). That leaves it with value PGSemaMagic * and sempid referencing this process. */ IpcSemaphoreInitialize(semId, numSems, PGSemaMagic - 1); mysema.semId = semId; mysema.semNum = numSems; PGSemaphoreUnlock(&mysema); return semId; }