Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "postgres.h"
00019
00020 #include <fcntl.h>
00021 #include <signal.h>
00022 #include <unistd.h>
00023
00024 #include "miscadmin.h"
00025 #include "storage/ipc.h"
00026 #include "storage/pg_sema.h"
00027
00028
00029 #ifdef USE_NAMED_POSIX_SEMAPHORES
00030
00031 #define PG_SEM_REF(x) (*(x))
00032 #else
00033
00034 #define PG_SEM_REF(x) (x)
00035 #endif
00036
00037
00038 #define IPCProtection (0600)
00039
00040 static sem_t **mySemPointers;
00041 static int numSems;
00042 static int maxSems;
00043 static int nextSemKey;
00044
00045
00046 static void ReleaseSemaphores(int status, Datum arg);
00047
00048
00049 #ifdef USE_NAMED_POSIX_SEMAPHORES
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 static sem_t *
00061 PosixSemaphoreCreate(void)
00062 {
00063 int semKey;
00064 char semname[64];
00065 sem_t *mySem;
00066
00067 for (;;)
00068 {
00069 semKey = nextSemKey++;
00070
00071 snprintf(semname, sizeof(semname), "/pgsql-%d", semKey);
00072
00073 mySem = sem_open(semname, O_CREAT | O_EXCL,
00074 (mode_t) IPCProtection, (unsigned) 1);
00075
00076 #ifdef SEM_FAILED
00077 if (mySem != (sem_t *) SEM_FAILED)
00078 break;
00079 #else
00080 if (mySem != (sem_t *) (-1))
00081 break;
00082 #endif
00083
00084
00085 if (errno == EEXIST || errno == EACCES || errno == EINTR)
00086 continue;
00087
00088
00089
00090
00091 elog(FATAL, "sem_open(\"%s\") failed: %m", semname);
00092 }
00093
00094
00095
00096
00097
00098 sem_unlink(semname);
00099
00100 return mySem;
00101 }
00102 #else
00103
00104
00105
00106
00107
00108
00109 static void
00110 PosixSemaphoreCreate(sem_t * sem)
00111 {
00112 if (sem_init(sem, 1, 1) < 0)
00113 elog(FATAL, "sem_init failed: %m");
00114 }
00115 #endif
00116
00117
00118
00119
00120
00121 static void
00122 PosixSemaphoreKill(sem_t * sem)
00123 {
00124 #ifdef USE_NAMED_POSIX_SEMAPHORES
00125
00126 if (sem_close(sem) < 0)
00127 elog(LOG, "sem_close failed: %m");
00128 #else
00129
00130 if (sem_destroy(sem) < 0)
00131 elog(LOG, "sem_destroy failed: %m");
00132 #endif
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 void
00154 PGReserveSemaphores(int maxSemas, int port)
00155 {
00156 mySemPointers = (sem_t **) malloc(maxSemas * sizeof(sem_t *));
00157 if (mySemPointers == NULL)
00158 elog(PANIC, "out of memory");
00159 numSems = 0;
00160 maxSems = maxSemas;
00161 nextSemKey = port * 1000;
00162
00163 on_shmem_exit(ReleaseSemaphores, 0);
00164 }
00165
00166
00167
00168
00169
00170
00171 static void
00172 ReleaseSemaphores(int status, Datum arg)
00173 {
00174 int i;
00175
00176 for (i = 0; i < numSems; i++)
00177 PosixSemaphoreKill(mySemPointers[i]);
00178 free(mySemPointers);
00179 }
00180
00181
00182
00183
00184
00185
00186 void
00187 PGSemaphoreCreate(PGSemaphore sema)
00188 {
00189 sem_t *newsem;
00190
00191
00192 Assert(!IsUnderPostmaster);
00193
00194 if (numSems >= maxSems)
00195 elog(PANIC, "too many semaphores created");
00196
00197 #ifdef USE_NAMED_POSIX_SEMAPHORES
00198 *sema = newsem = PosixSemaphoreCreate();
00199 #else
00200 PosixSemaphoreCreate(sema);
00201 newsem = sema;
00202 #endif
00203
00204
00205 mySemPointers[numSems++] = newsem;
00206 }
00207
00208
00209
00210
00211
00212
00213 void
00214 PGSemaphoreReset(PGSemaphore sema)
00215 {
00216
00217
00218
00219
00220 for (;;)
00221 {
00222 if (sem_trywait(PG_SEM_REF(sema)) < 0)
00223 {
00224 if (errno == EAGAIN || errno == EDEADLK)
00225 break;
00226 if (errno == EINTR)
00227 continue;
00228 elog(FATAL, "sem_trywait failed: %m");
00229 }
00230 }
00231 }
00232
00233
00234
00235
00236
00237
00238 void
00239 PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
00240 {
00241 int errStatus;
00242
00243
00244
00245
00246
00247
00248
00249 do
00250 {
00251 ImmediateInterruptOK = interruptOK;
00252 CHECK_FOR_INTERRUPTS();
00253 errStatus = sem_wait(PG_SEM_REF(sema));
00254 ImmediateInterruptOK = false;
00255 } while (errStatus < 0 && errno == EINTR);
00256
00257 if (errStatus < 0)
00258 elog(FATAL, "sem_wait failed: %m");
00259 }
00260
00261
00262
00263
00264
00265
00266 void
00267 PGSemaphoreUnlock(PGSemaphore sema)
00268 {
00269 int errStatus;
00270
00271
00272
00273
00274
00275
00276
00277 do
00278 {
00279 errStatus = sem_post(PG_SEM_REF(sema));
00280 } while (errStatus < 0 && errno == EINTR);
00281
00282 if (errStatus < 0)
00283 elog(FATAL, "sem_post failed: %m");
00284 }
00285
00286
00287
00288
00289
00290
00291 bool
00292 PGSemaphoreTryLock(PGSemaphore sema)
00293 {
00294 int errStatus;
00295
00296
00297
00298
00299
00300
00301 do
00302 {
00303 errStatus = sem_trywait(PG_SEM_REF(sema));
00304 } while (errStatus < 0 && errno == EINTR);
00305
00306 if (errStatus < 0)
00307 {
00308 if (errno == EAGAIN || errno == EDEADLK)
00309 return false;
00310
00311 elog(FATAL, "sem_trywait failed: %m");
00312 }
00313
00314 return true;
00315 }