PostgreSQL Source Code: src/backend/port/posix_sema.c Source File (original) (raw)

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

27

28#include <fcntl.h>

29#include <semaphore.h>

30#include <signal.h>

32#include <sys/stat.h>

33

38

39

40

41#if defined(USE_NAMED_POSIX_SEMAPHORES) && defined(EXEC_BACKEND)

42#error cannot use named POSIX semaphores with EXEC_BACKEND

43#endif

44

46{

50

51

53{

56

57#define PG_SEM_REF(x) (&(x)->sem_padded.pgsem)

58

59#define IPCProtection (0600)

60

61#ifdef USE_NAMED_POSIX_SEMAPHORES

62static sem_t **mySemPointers;

63#else

65#endif

66static int numSems;

67static int maxSems;

69

70

72

73

74#ifdef USE_NAMED_POSIX_SEMAPHORES

75

76

77

78

79

80

81

82

83

84

85static sem_t *

87{

88 int semKey;

89 char semname[64];

90 sem_t *mySem;

91

92 for (;;)

93 {

95

96 snprintf(semname, sizeof(semname), "/pgsql-%d", semKey);

97

98 mySem = sem_open(semname, O_CREAT | O_EXCL,

100

101#ifdef SEM_FAILED

102 if (mySem != (sem_t *) SEM_FAILED)

103 break;

104#else

105 if (mySem != (sem_t *) (-1))

106 break;

107#endif

108

109

110 if (errno == EEXIST || errno == EACCES || errno == EINTR)

111 continue;

112

113

114

115

116 elog(FATAL, "sem_open(\"%s\") failed: %m", semname);

117 }

118

119

120

121

122

123 sem_unlink(semname);

124

125 return mySem;

126}

127#else

128

129

130

131

132

133

134static void

136{

137 if (sem_init(sem, 1, 1) < 0)

138 elog(FATAL, "sem_init failed: %m");

139}

140#endif

141

142

143

144

145

146static void

148{

149#ifdef USE_NAMED_POSIX_SEMAPHORES

150

151 if (sem_close(sem) < 0)

152 elog(LOG, "sem_close failed: %m");

153#else

154

155 if (sem_destroy(sem) < 0)

156 elog(LOG, "sem_destroy failed: %m");

157#endif

158}

159

160

161

162

163

166{

167#ifdef USE_NAMED_POSIX_SEMAPHORES

168

169 return 0;

170#else

171

173#endif

174}

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195void

197{

198 struct stat statbuf;

199

200

201

202

203

204

205

209 errmsg("could not stat data directory \"%s\": %m",

211

212#ifdef USE_NAMED_POSIX_SEMAPHORES

213 mySemPointers = (sem_t **) malloc(maxSemas * sizeof(sem_t *));

214 if (mySemPointers == NULL)

216#else

217

218

219

220

221

224#endif

225

229

231}

232

233

234

235

236

237

238static void

240{

241 int i;

242

243#ifdef USE_NAMED_POSIX_SEMAPHORES

246 free(mySemPointers);

247#endif

248

249#ifdef USE_UNNAMED_POSIX_SEMAPHORES

252#endif

253}

254

255

256

257

258

259

262{

264 sem_t *newsem;

265

266

268

270 elog(PANIC, "too many semaphores created");

271

272#ifdef USE_NAMED_POSIX_SEMAPHORES

274

275 mySemPointers[numSems] = newsem;

277#else

281#endif

282

284

285 return sema;

286}

287

288

289

290

291

292

293void

295{

296

297

298

299

300 for (;;)

301 {

302 if (sem_trywait(PG_SEM_REF(sema)) < 0)

303 {

304 if (errno == EAGAIN || errno == EDEADLK)

305 break;

306 if (errno == EINTR)

307 continue;

308 elog(FATAL, "sem_trywait failed: %m");

309 }

310 }

311}

312

313

314

315

316

317

318void

320{

321 int errStatus;

322

323

324 do

325 {

326 errStatus = sem_wait(PG_SEM_REF(sema));

327 } while (errStatus < 0 && errno == EINTR);

328

329 if (errStatus < 0)

330 elog(FATAL, "sem_wait failed: %m");

331}

332

333

334

335

336

337

338void

340{

341 int errStatus;

342

343

344

345

346

347

348

349 do

350 {

351 errStatus = sem_post(PG_SEM_REF(sema));

352 } while (errStatus < 0 && errno == EINTR);

353

354 if (errStatus < 0)

355 elog(FATAL, "sem_post failed: %m");

356}

357

358

359

360

361

362

363bool

365{

366 int errStatus;

367

368

369

370

371

372

373 do

374 {

375 errStatus = sem_trywait(PG_SEM_REF(sema));

376 } while (errStatus < 0 && errno == EINTR);

377

378 if (errStatus < 0)

379 {

380 if (errno == EAGAIN || errno == EDEADLK)

381 return false;

382

383 elog(FATAL, "sem_trywait failed: %m");

384 }

385

386 return true;

387}

int errcode_for_file_access(void)

int errmsg(const char *fmt,...)

#define ereport(elevel,...)

Assert(PointerIsAligned(start, uint64))

void on_shmem_exit(pg_on_exit_callback function, Datum arg)

#define PG_CACHE_LINE_SIZE

struct PGSemaphoreData * PGSemaphore

Size PGSemaphoreShmemSize(int maxSemas)

void PGSemaphoreUnlock(PGSemaphore sema)

union SemTPadded SemTPadded

static void PosixSemaphoreKill(sem_t *sem)

struct PGSemaphoreData PGSemaphoreData

void PGReserveSemaphores(int maxSemas)

void PGSemaphoreReset(PGSemaphore sema)

void PGSemaphoreLock(PGSemaphore sema)

bool PGSemaphoreTryLock(PGSemaphore sema)

static PGSemaphore sharedSemas

PGSemaphore PGSemaphoreCreate(void)

static void ReleaseSemaphores(int status, Datum arg)

static void PosixSemaphoreCreate(sem_t *sem)

void * ShmemAllocUnlocked(Size size)

Size mul_size(Size s1, Size s2)

char pad[PG_CACHE_LINE_SIZE]