00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <utils/ipc/semset.h>
00025 #include <utils/ipc/sem_exceptions.h>
00026 #include <core/exceptions/system.h>
00027
00028 #include <errno.h>
00029
00030 #include <sys/types.h>
00031 #include <sys/ipc.h>
00032 #include <sys/sem.h>
00033 #include <limits.h>
00034
00035 namespace fawkes {
00036
00037
00038
00039 class SemaphoreSetData
00040 {
00041 public:
00042 key_t key;
00043 int semid;
00044 int semflg;
00045 int num_sems;
00046 };
00047
00048 #ifdef _SEM_SEMUN_UNDEFINED
00049 union semun
00050 {
00051 int val;
00052 struct semid_ds *buf;
00053 unsigned short int *array;
00054 struct seminfo *__buf;
00055 };
00056 #endif
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 SemaphoreSet::SemaphoreSet(const char *path, char id,
00103 int num_sems,
00104 bool create, bool destroy_on_delete)
00105 {
00106 data = new SemaphoreSetData();
00107
00108 if ( num_sems < 0 ) {
00109 num_sems = - num_sems;
00110 }
00111
00112 this->destroy_on_delete = destroy_on_delete;
00113 data->num_sems = num_sems;
00114
00115 data->semflg = 0666;
00116 if (create) {
00117 data->semflg |= IPC_CREAT;
00118 }
00119
00120 data->key = ftok(path, id);
00121 data->semid = semget(data->key, num_sems, data->semflg);
00122
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 SemaphoreSet::SemaphoreSet(int key,
00138 int num_sems,
00139 bool create, bool destroy_on_delete)
00140 {
00141 data = new SemaphoreSetData();
00142
00143 if ( num_sems < 0 ) {
00144 num_sems = - num_sems;
00145 }
00146
00147 this->destroy_on_delete = destroy_on_delete;
00148 data->num_sems = num_sems;
00149
00150 data->semflg = 0666;
00151 if (create) {
00152 data->semflg |= IPC_CREAT;
00153 }
00154
00155 data->key = key;
00156 data->semid = semget(data->key, num_sems, data->semflg);
00157
00158 if ( data->semid == -1 ) {
00159 throw Exception(errno, "Creating the semaphore set failed, maybe key does not exist");
00160 }
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 SemaphoreSet::SemaphoreSet(int num_sems,
00174 bool destroy_on_delete)
00175 {
00176 data = new SemaphoreSetData();
00177
00178 if ( num_sems < 0 ) {
00179 num_sems = - num_sems;
00180 }
00181
00182 this->destroy_on_delete = destroy_on_delete;
00183 data->num_sems = num_sems;
00184
00185 data->semflg = 0666;
00186 data->semflg |= IPC_CREAT;
00187 data->semflg |= IPC_EXCL;
00188
00189 for (data->key = 1; data->key < INT_MAX; data->key++) {
00190 data->semid = semget(data->key, num_sems, data->semflg);
00191 if ( data->semid != -1 ) {
00192
00193 break;
00194 }
00195 }
00196 }
00197
00198
00199
00200 SemaphoreSet::~SemaphoreSet()
00201 {
00202 if ((data->semid != -1) && destroy_on_delete) {
00203 semctl(data->semid, 0, IPC_RMID, 0);
00204 }
00205 delete data;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215 bool
00216 SemaphoreSet::valid()
00217 {
00218 if (data->semid == -1) {
00219 data->semid = semget(data->key, data->num_sems, data->semflg);
00220 if (data->semid == -1) {
00221 return false;
00222 } else {
00223 struct semid_ds semds;
00224 union semun s;
00225 s.buf = &semds;
00226 if (semctl(data->semid, 0, IPC_STAT, s) != -1) {
00227 return true;
00228 } else {
00229 data->semid = -1;
00230 return false;
00231 }
00232 }
00233 } else {
00234 struct semid_ds semds;
00235 union semun s;
00236 s.buf = &semds;
00237 if (semctl(data->semid, 0, IPC_STAT, s) != -1) {
00238 return true;
00239 } else {
00240 data->semid = -1;
00241 return false;
00242 }
00243 }
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 void
00255 SemaphoreSet::lock(unsigned short sem_num, short num)
00256 {
00257 if ( data->semid == -1 ) throw SemInvalidException();
00258
00259 struct sembuf sop;
00260 sop.sem_num = sem_num;
00261 sop.sem_op = (short)((num <= 0) ? num : -num);
00262 sop.sem_flg = 0;
00263 if ( semop(data->semid, &sop, 1) != 0 ) {
00264 if ( errno == EINTR ) throw InterruptedException();
00265 else throw SemCannotLockException();
00266 }
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 bool
00279 SemaphoreSet::try_lock(unsigned short sem_num, short num)
00280 {
00281 if ( data->semid == -1 ) throw SemInvalidException();
00282
00283 struct sembuf sop;
00284 sop.sem_num = sem_num;
00285 sop.sem_op = (short)((num <= 0) ? num : -num);
00286 sop.sem_flg = IPC_NOWAIT;
00287 if ( semop(data->semid, &sop, 1) != 0 ) {
00288 if (errno == EAGAIN) {
00289 return false;
00290 } else if ( errno == EINTR ) {
00291 throw InterruptedException();
00292 } else {
00293 throw SemCannotLockException();
00294 }
00295 }
00296 return true;
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 void
00308 SemaphoreSet::unlock(unsigned short sem_num, short num)
00309 {
00310 if ( data->semid == -1 ) throw SemInvalidException();
00311
00312 struct sembuf sop;
00313 sop.sem_num = sem_num;
00314 sop.sem_op = (short)((num >= 0) ? num : -num);
00315 sop.sem_flg = 0;
00316 if ( semop(data->semid, &sop, 1) != 0 ) {
00317 if ( errno == EINTR ) throw InterruptedException();
00318 else throw SemCannotUnlockException();
00319 }
00320 }
00321
00322
00323
00324
00325
00326
00327
00328 void
00329 SemaphoreSet::set_value(int sem_num, int val)
00330 {
00331 if ( data->semid == -1 ) throw SemInvalidException();
00332
00333 union semun s;
00334 s.val = val;
00335
00336 if ( semctl(data->semid, sem_num, SETVAL, s) == -1 ) {
00337 throw SemCannotSetValException();
00338 }
00339 }
00340
00341
00342
00343
00344
00345
00346
00347 int
00348 SemaphoreSet::get_value(int sem_num)
00349 {
00350 if ( data->semid == -1 ) throw SemInvalidException();
00351
00352 return ( semctl(data->semid, sem_num, GETVAL, 0) != 0 );
00353 }
00354
00355
00356
00357
00358
00359 int
00360 SemaphoreSet::key()
00361 {
00362 return data->key;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372 void
00373 SemaphoreSet::set_destroy_on_delete(bool destroy)
00374 {
00375 destroy_on_delete = destroy;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 int
00390 SemaphoreSet::free_key()
00391 {
00392 bool found = false;
00393 int key;
00394 int semid;
00395 for (key = 1; key < INT_MAX; ++key) {
00396 semid = semget(key, 1, IPC_CREAT | IPC_EXCL);
00397 if ( semid != -1 ) {
00398
00399 semctl(semid, 0, IPC_RMID, 0);
00400 found = true;
00401 break;
00402 }
00403 }
00404 return (found ? key : 0);
00405 }
00406
00407
00408
00409
00410
00411
00412
00413 void
00414 SemaphoreSet::destroy(int key)
00415 {
00416 int semid = semget(key, 0, 0);
00417 if ( semid == -1 ) return;
00418 semctl(semid, 0, IPC_RMID, 0);
00419 }
00420
00421
00422 }