00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
#include "DbjLatch.hpp"
00012
00013
#include <sys/types.h>
00014
#include <sys/ipc.h>
00015
#include <sys/sem.h>
00016
#include <sys/stat.h>
00017
#include <errno.h>
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
#if defined(DBJ_CYGWIN)
00030
#if defined(SEM_UNDO)
00031
#undef SEM_UNDO
00032
#endif
00033
#define SEM_UNDO 0
00034
#endif
00035
00036
00037
00038 static const DbjComponent componentId =
Support;
00039
00040
00041
00042 static const Uint16 DBJ_LATCH_BLOCK_NEW_SHARED = 0;
00043
00044 static const Uint16 DBJ_LATCH_SHARED_COUNTER = 1;
00045
00046 static const Uint16 DBJ_LATCH_EXCLUSIVE = 2;
00047
00048
00049
00050 DbjErrorCode DbjLatch::initialize()
00051 {
00052
Uint16 semValue[3];
00053
int semRc = 0;
00054
00055
DBJ_TRACE_ENTRY();
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
semaphoreId = semget(IPC_PRIVATE, 3,
00068 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
00069
if (
semaphoreId < 0) {
00070
DBJ_SET_ERROR_TOKEN2(
DBJ_LATCH_SEM_CREATE_FAIL,
semaphoreId,
00071 strerror(errno));
00072
goto cleanup;
00073 }
00074
DBJ_TRACE_NUMBER(1,
"semaphore set id",
semaphoreId);
00075
00076
00077 semValue[
DBJ_LATCH_BLOCK_NEW_SHARED] = +1;
00078 semValue[
DBJ_LATCH_SHARED_COUNTER] = 0;
00079 semValue[
DBJ_LATCH_EXCLUSIVE] = 0;
00080 semRc = semctl(
semaphoreId, 0, SETALL, semValue);
00081
if (semRc != 0) {
00082
DBJ_SET_ERROR_TOKEN2(
DBJ_LATCH_SEM_OPERATION_FAIL,
00083 errno, strerror(errno));
00084
destroy(
true);
00085
goto cleanup;
00086 }
00087
00088 cleanup:
00089
return DbjGetErrorCode();
00090 }
00091
00092
00093
00094 DbjErrorCode DbjLatch::destroy(
bool const force)
00095 {
00096
DbjErrorCode rc =
DBJ_SUCCESS;
00097
00098
DBJ_TRACE_ENTRY();
00099
00100
if (
semaphoreId < 0) {
00101
goto cleanup;
00102 }
00103
00104
00105
if (!force) {
00106 rc =
get(
Exclusive);
00107
if (rc !=
DBJ_SUCCESS) {
00108
DBJ_TRACE_ERROR();
00109
goto cleanup;
00110 }
00111 }
00112
00113
00114 {
00115
int semRc = semctl(
semaphoreId, 0, IPC_RMID);
00116
if (semRc == -1) {
00117
DBJ_SET_ERROR_TOKEN2(
DBJ_LATCH_SEM_DESTROY_WARN,
00118 errno, strerror(errno));
00119
goto cleanup;
00120 }
00121 }
00122
00123
semaphoreId = -1;
00124
00125 cleanup:
00126
return DbjGetErrorCode();
00127 }
00128
00129
00130
00131 DbjErrorCode DbjLatch::get(LatchMode
const mode)
00132 {
00133
int semRc = 0;
00134
DbjErrorCode rc =
DBJ_SUCCESS;
00135
struct sembuf semOp[4];
00136
00137
DBJ_TRACE_ENTRY();
00138
00139
switch (mode) {
00140
case Shared:
00141
00142
00143
00144
00145
00146
00147
00148 semOp[0].sem_num =
DBJ_LATCH_BLOCK_NEW_SHARED;
00149 semOp[0].sem_op = -1;
00150 semOp[0].sem_flg = 0;
00151 semOp[1].sem_num =
DBJ_LATCH_SHARED_COUNTER;
00152 semOp[1].sem_op = +1;
00153 semOp[1].sem_flg = SEM_UNDO;
00154 semOp[2].sem_num =
DBJ_LATCH_BLOCK_NEW_SHARED;
00155 semOp[2].sem_op = +1;
00156 semOp[2].sem_flg = 0;
00157 semOp[3].sem_num =
DBJ_LATCH_EXCLUSIVE;
00158 semOp[3].sem_op = 0;
00159 semOp[3].sem_flg = IPC_NOWAIT;
00160 semRc = semop(
semaphoreId, semOp, 4);
00161
if (semRc != 0) {
00162
DBJ_SET_ERROR_TOKEN2(
DBJ_LATCH_SEM_OPERATION_FAIL,
00163 errno, strerror(errno));
00164 rc =
DbjGetErrorCode();
00165
goto cleanup;
00166 }
00167
break;
00168
00169
case Exclusive:
00170
00171
00172 semOp[0].sem_num =
DBJ_LATCH_BLOCK_NEW_SHARED;
00173 semOp[0].sem_op = -1;
00174 semOp[0].sem_flg = SEM_UNDO;
00175 semOp[1].sem_num =
DBJ_LATCH_EXCLUSIVE;
00176 semOp[1].sem_op = 0;
00177 semOp[1].sem_flg = IPC_NOWAIT;
00178 semRc = semop(
semaphoreId, semOp, 2);
00179
if (semRc != 0) {
00180
DBJ_SET_ERROR_TOKEN2(
DBJ_LATCH_SEM_OPERATION_FAIL,
00181 errno, strerror(errno));
00182 rc =
DbjGetErrorCode();
00183
goto cleanup;
00184 }
00185
00186
00187
00188 semOp[0].sem_num =
DBJ_LATCH_SHARED_COUNTER;
00189 semOp[0].sem_op = 0;
00190 semOp[0].sem_flg = 0;
00191 semOp[1].sem_num =
DBJ_LATCH_EXCLUSIVE;
00192 semOp[1].sem_op = +1;
00193 semOp[1].sem_flg = 0;
00194 semRc = semop(
semaphoreId, semOp, 2);
00195
if (semRc != 0) {
00196
if (errno != EIDRM) {
00197
00198
00199
00200 semOp[0].sem_num =
DBJ_LATCH_BLOCK_NEW_SHARED;
00201 semOp[0].sem_op = +1;
00202 semOp[0].sem_flg = SEM_UNDO;
00203 semRc = semop(
semaphoreId, semOp, 1);
00204
00205
00206 }
00207
if (semRc != 0) {
00208
DBJ_SET_ERROR_TOKEN2(
DBJ_LATCH_SEM_OPERATION_FAIL,
00209 errno, strerror(errno));
00210 rc =
DbjGetErrorCode();
00211 }
00212
goto cleanup;
00213 }
00214
break;
00215 }
00216
00217 cleanup:
00218
return rc;
00219 }
00220
00221
00222
00223 DbjErrorCode DbjLatch::release()
00224 {
00225
int semRc = 0;
00226
DbjErrorCode rc =
DBJ_SUCCESS;
00227
struct sembuf semOp[2];
00228
00229
DBJ_TRACE_ENTRY();
00230
00231
00232
00233 semOp[0].sem_num =
DBJ_LATCH_EXCLUSIVE;
00234 semOp[0].sem_op = 0;
00235 semOp[0].sem_flg = IPC_NOWAIT;
00236 semOp[1].sem_num =
DBJ_LATCH_SHARED_COUNTER;
00237 semOp[1].sem_op = -1;
00238 semOp[1].sem_flg = SEM_UNDO;
00239 semRc = semop(
semaphoreId, semOp, 2);
00240
if (semRc != 0) {
00241
if (errno == EAGAIN) {
00242
00243
DBJ_TRACE_STRING(10,
"removing exclusive latch");
00244 semOp[0].sem_num =
DBJ_LATCH_BLOCK_NEW_SHARED;
00245 semOp[0].sem_op = +1;
00246 semOp[0].sem_flg = SEM_UNDO;
00247 semOp[1].sem_num =
DBJ_LATCH_EXCLUSIVE;
00248 semOp[1].sem_op = -1;
00249 semOp[1].sem_flg = 0;
00250 semRc = semop(
semaphoreId, semOp, 2);
00251 }
00252
if (semRc != 0) {
00253
DBJ_SET_ERROR_TOKEN2(
DBJ_LATCH_SEM_OPERATION_FAIL,
00254 errno, strerror(errno));
00255 rc =
DbjGetErrorCode();
00256
goto cleanup;
00257 }
00258 }
00259
00260 cleanup:
00261
return rc;
00262 }
00263
00264
00265
00266 DbjErrorCode DbjLatch::getSharedCount(
Uint32 &sharedCount)
const
00267
{
00268
int semValue = 0;
00269
00270
DBJ_TRACE_ENTRY();
00271
00272 semValue = semctl(
semaphoreId,
DBJ_LATCH_SHARED_COUNTER, GETVAL);
00273
if (semValue < 0) {
00274
DBJ_SET_ERROR_TOKEN2(
DBJ_LATCH_SEM_OPERATION_FAIL,
00275 errno, strerror(errno));
00276
goto cleanup;
00277 }
00278 sharedCount = semValue;
00279
00280 cleanup:
00281
return DbjGetErrorCode();
00282 }
00283
00284
00285
00286 DbjErrorCode DbjLatch::isHeldExclusive(
bool &isHeld)
const
00287
{
00288
int semValue = 0;
00289
00290
DBJ_TRACE_ENTRY();
00291
00292 semValue = semctl(
semaphoreId,
DBJ_LATCH_EXCLUSIVE, GETVAL);
00293
if (semValue < 0) {
00294
DBJ_SET_ERROR_TOKEN2(
DBJ_LATCH_SEM_OPERATION_FAIL,
00295 errno, strerror(errno));
00296
goto cleanup;
00297 }
00298 isHeld = semValue > 0 ?
true :
false;
00299
00300 cleanup:
00301
return DbjGetErrorCode();
00302 }
00303
00304
00305
00306 DbjErrorCode DbjLatch::isLocked(
bool &isLatched)
const
00307
{
00308
DbjErrorCode rc =
DBJ_SUCCESS;
00309
Uint32 sharedCount = 0;
00310
00311
DBJ_TRACE_ENTRY();
00312
00313 rc =
getSharedCount(sharedCount);
00314
if (rc !=
DBJ_SUCCESS) {
00315
DBJ_TRACE_ERROR();
00316
goto cleanup;
00317 }
00318
if (sharedCount > 0) {
00319 isLatched =
true;
00320
goto cleanup;
00321 }
00322 rc =
isHeldExclusive(isLatched);
00323
if (rc !=
DBJ_SUCCESS) {
00324
DBJ_TRACE_ERROR();
00325
goto cleanup;
00326 }
00327
00328 cleanup:
00329
return DbjGetErrorCode();
00330 }
00331