0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include <stdlib.h>
0038 #include <stdio.h>
0039
0040
0041 #include <sys/mman.h>
0042 #include <sys/types.h>
0043 #include <sys/sem.h>
0044
0045 #include <unistd.h>
0046 #include <fcntl.h>
0047 #include <sys/stat.h>
0048
0049 #include <ndrstandard.h>
0050 #include <ndebug.h>
0051 #include <nstd_shm.h>
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 expublic int ndrx_sem_rwlock(ndrx_sem_t *sem, int sem_num, int typ)
0070 {
0071 int ret;
0072 struct sembuf semops;
0073 semops.sem_num = sem_num;
0074 semops.sem_flg = SEM_UNDO;
0075
0076 if( typ == NDRX_SEM_TYP_WRITE )
0077 {
0078 semops.sem_op = -sem->maxreaders;
0079 }
0080 else
0081 {
0082 semops.sem_op = -1;
0083 }
0084
0085 do
0086 {
0087 ret = semop( sem->semid, &semops, 1 );
0088
0089 } while ( ret == -1 && errno == EINTR );
0090
0091 if (EXFAIL==ret)
0092 {
0093 int err = errno;
0094
0095
0096 userlog("ndrx_sem_rwlock: semop() failed for type %d lock: %s",
0097 typ, strerror(err));
0098 }
0099
0100 return ret;
0101 }
0102
0103
0104
0105
0106
0107
0108
0109
0110 expublic int ndrx_sem_rwunlock(ndrx_sem_t *sem, int sem_num, int typ)
0111 {
0112 int ret;
0113 struct sembuf semops;
0114 semops.sem_num = sem_num;
0115 semops.sem_op = 1;
0116 semops.sem_flg = SEM_UNDO;
0117
0118 if ( typ == NDRX_SEM_TYP_WRITE )
0119 {
0120 semops.sem_op = sem->maxreaders;
0121 }
0122
0123 do
0124 {
0125 ret = semop(sem->semid,&semops,1);
0126
0127 } while ( ret == -1 && errno == EINTR );
0128
0129 if (EXFAIL==ret)
0130 {
0131 int err = errno;
0132
0133 userlog("ndrx_sem_rwunlock: semop() failed for %d type lock: %s",
0134 typ, strerror(err));
0135 }
0136
0137 return ret;
0138 }
0139
0140
0141
0142
0143
0144
0145
0146 expublic int ndrx_sem_lock(ndrx_sem_t *sem, const char *msg, int sem_num)
0147 {
0148 int ret=EXSUCCEED;
0149 int errno_int;
0150 struct sembuf semops;
0151 semops.sem_num = sem_num;
0152 semops.sem_flg = SEM_UNDO;
0153
0154
0155 semops.sem_op = -sem->maxreaders;
0156
0157 #ifdef NDRX_SEM_DEBUG
0158 userlog("ENTER: ndrx_lock: %s", msg);
0159 #endif
0160
0161 while(EXFAIL==(ret=semop(sem->semid, &semops, 1)) && (EINTR==errno || EAGAIN==errno))
0162 {
0163 NDRX_LOG(log_warn, "%s: Interrupted while waiting for semaphore!!", msg);
0164 };
0165 errno_int = errno;
0166
0167 if (EXSUCCEED==ret)
0168 {
0169 NDRX_LOG(log_info, "%s/%d/%d: semaphore locked... ", msg, sem->semid, sem_num);
0170 }
0171 else
0172 {
0173 NDRX_LOG(log_info, "%s/%d/%d: failed to lock (%d): %s", msg, sem->semid,
0174 sem_num, errno_int,
0175 strerror(errno_int));
0176 }
0177
0178 #ifdef NDRX_SEM_DEBUG
0179 userlog("EXIT: ndrx_lock %d: %s", ret, msg);
0180 #endif
0181
0182 return ret;
0183 }
0184
0185
0186
0187
0188
0189
0190
0191 expublic int ndrx_sem_unlock(ndrx_sem_t *sem, const char *msg, int sem_num)
0192 {
0193 struct sembuf semops;
0194 semops.sem_num = sem_num;
0195 semops.sem_flg = SEM_UNDO;
0196
0197 semops.sem_op = sem->maxreaders;
0198
0199 #ifdef NDRX_SEM_DEBUG
0200 userlog("ENTER: ndrx_unlock: %s", msg);
0201 #endif
0202
0203 if (EXSUCCEED!=semop(sem->semid, &semops, 1))
0204 {
0205 NDRX_LOG(log_debug, "%s/%d%/d: failed: %s", msg,
0206 sem->semid, sem_num, strerror(errno));
0207 return EXFAIL;
0208 }
0209
0210 NDRX_LOG(log_debug, "%s/%d/%d semaphore un-locked",
0211 msg, sem->semid, sem_num);
0212
0213 #ifdef NDRX_SEM_DEBUG
0214 userlog("EXIT: ndrx_unlock: %s", msg);
0215 #endif
0216
0217 return EXSUCCEED;
0218 }
0219
0220
0221
0222
0223
0224
0225
0226 expublic int ndrx_sem_open(ndrx_sem_t *sem, int attach_on_exists)
0227 {
0228 int ret=EXSUCCEED;
0229 int err, i;
0230
0231 #ifdef EX_HAVE_SEMUN
0232 union semun arg;
0233 #else
0234 union semun
0235 {
0236 int val;
0237 struct semid_ds *buf;
0238 ushort *array;
0239 } arg;
0240 #endif
0241
0242 ushort arr[sem->nrsems];
0243 memset(&arg, 0, sizeof(arg));
0244
0245
0246 arg.array = arr;
0247
0248
0249
0250
0251 sem->semid = semget(sem->key, sem->nrsems, 0660|IPC_CREAT|IPC_EXCL);
0252
0253 if (EXFAIL==sem->semid)
0254 {
0255 err = errno;
0256
0257 if (EEXIST==err && attach_on_exists)
0258 {
0259 NDRX_LOG_EARLY(log_info, "Semaphore exists [%x] - attaching",
0260 sem->key);
0261 return ndrx_sem_attach(sem);
0262 }
0263
0264 NDRX_LOG_EARLY(log_error, "Failed to create sem, key[%x]: %s",
0265 sem->key, strerror(err));
0266 ret=EXFAIL;
0267 goto out;
0268 }
0269
0270
0271 for (i=0; i< sem->nrsems; i++)
0272 {
0273 arg.array[i]=sem->maxreaders;
0274 }
0275
0276 if (semctl(sem->semid, i, SETALL, arg) == -1)
0277 {
0278 NDRX_LOG_EARLY(log_error, "Failed to reset to %d, key[%x], semid: %d: %s",
0279 i, sem->key, sem->semid, strerror(errno));
0280 ret=EXFAIL;
0281 goto out;
0282 }
0283
0284 sem->attached = EXTRUE;
0285
0286 NDRX_LOG_EARLY(log_warn, "Semaphore for key %x open, id: %d",
0287 sem->key, sem->semid);
0288 out:
0289
0290 NDRX_LOG_EARLY(log_debug, "return %d", ret);
0291
0292 return ret;
0293 }
0294
0295
0296
0297
0298
0299
0300
0301 expublic int ndrx_sem_remove(ndrx_sem_t *sem, int force)
0302 {
0303 int ret = EXSUCCEED;
0304
0305 if ((sem->attached || force) && sem->semid)
0306 {
0307 NDRX_LOG_EARLY(log_error, "Removing semid: %d", sem->semid);
0308 if (EXSUCCEED!= semctl(sem->semid, 0, IPC_RMID))
0309 {
0310 NDRX_LOG_EARLY(log_warn, "semctl DEL failed err: %s",
0311 strerror(errno));
0312 ret=EXFAIL;
0313 }
0314 else
0315 {
0316 sem->semid=0;
0317 }
0318 }
0319 sem->attached=EXFALSE;
0320
0321 return ret;
0322 }
0323
0324
0325
0326
0327
0328
0329 expublic int ndrx_sem_is_attached(ndrx_sem_t *sem)
0330 {
0331 int ret=EXTRUE;
0332
0333 if (!sem->attached)
0334 {
0335 ret=EXFALSE;
0336 }
0337
0338 return ret;
0339 }
0340
0341
0342
0343
0344
0345 expublic int ndrx_sem_attach(ndrx_sem_t *sem)
0346 {
0347 int ret=EXSUCCEED;
0348
0349 NDRX_LOG_EARLY(log_debug, "enter");
0350
0351 if (sem->attached)
0352 {
0353 NDRX_LOG_EARLY(log_debug, "sem, key %x, id: %d already attached",
0354 sem->key, sem->semid);
0355 goto out;
0356 }
0357
0358
0359 sem->semid = semget(sem->key, sem->nrsems, IPC_EXCL);
0360
0361 if (EXFAIL==sem->semid)
0362 {
0363 NDRX_LOG_EARLY(log_error, "Failed to attach sem, key [%d]: %s",
0364 sem->key, strerror(errno));
0365 ret=EXFAIL;
0366 goto out;
0367 }
0368
0369 NDRX_LOG_EARLY(log_debug, "sem: [%d] attached", sem->semid);
0370
0371 out:
0372
0373 NDRX_LOG_EARLY(log_debug, "return %d", ret);
0374 return ret;
0375 }
0376
0377
0378
0379
0380
0381
0382
0383 expublic int ndrx_sem_close(ndrx_sem_t *sem)
0384 {
0385 int ret=EXSUCCEED;
0386
0387 out:
0388 return ret;
0389 }
0390
0391
0392