00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #if !defined(WIN32)
00018
00019 #include <sstream>
00020 #include <string>
00021 #include <iomanip>
00022
00023 #include "assa/Semaphore.h"
00024
00025 using namespace ASSA;
00026
00027
00028
00029 const int ASSA::Semaphore::BIGCOUNT = 10000;
00030
00031 sembuf Semaphore::m_op_lock [2] =
00032 {
00033 {2, 0, 0},
00034 {2, 1, SEM_UNDO}
00035
00036
00037 };
00038
00039 sembuf Semaphore::m_op_endcreate [2] =
00040 {
00041 {1, -1, SEM_UNDO},
00042
00043 {2, -1, SEM_UNDO}
00044 };
00045
00046 sembuf Semaphore::m_op_open [2] =
00047 {
00048 {1, -1, SEM_UNDO},
00049
00050 };
00051
00052 sembuf Semaphore::m_op_close [3] =
00053 {
00054 {2, 0, 0},
00055 {2, 1, SEM_UNDO},
00056 {1, 1, SEM_UNDO}
00057 };
00058
00059 sembuf Semaphore::m_op_unlock [1] =
00060 {
00061 {2, -1, SEM_UNDO}
00062 };
00063
00064 sembuf Semaphore::m_op_op [1] =
00065 {
00066 {0, 99, SEM_UNDO}
00067
00068
00069 };
00070
00071
00072
00073
00074
00075 int
00076 Semaphore::
00077 create (key_t key_, int initval_)
00078 {
00079 trace_with_mask("Semaphore::create", SEM);
00080
00081 register int semval;
00082
00083 union semnum {
00084 int val;
00085 struct semid_ds* buf;
00086 ushort* array;
00087 } semctrl_arg;
00088
00089 if (IPC_PRIVATE == key_) {
00090 EL((ASSAERR,"Not intended for private semaphores\n"));
00091 return (-1);
00092 }
00093 else if (key_ == (key_t) -1) {
00094 EL((ASSAERR,"Probably an ftok() error by caller\n"));
00095 return (-1);
00096 }
00097 m_key = key_;
00098 bool done = false;
00099
00100 while (!done) {
00101 if ( (m_id = semget (m_key, 3, 0666 | IPC_CREAT)) < 0) {
00102 EL((ASSAERR,"Permission problem or kernel tables full\n"));
00103 return (-1);
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 if (semop (m_id, &m_op_lock[0], 2) < 0) {
00124 if (errno == EINVAL) {
00125 continue;
00126 }
00127 EL((ASSAERR,"Can't lock semaphore\n"));
00128 Assure_exit (false);
00129 }
00130 done = true;
00131 }
00132
00133
00134
00135
00136
00137 if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) {
00138 EL((ASSAERR,"Can't GETVAL\n"));
00139 Assure_exit (false);
00140 }
00141
00142 if (semval == 0) {
00143
00144
00145
00146
00147
00148
00149
00150 semctrl_arg.val = initval_;
00151
00152 if (semctl (m_id, 0, SETVAL, semctrl_arg) < 0) {
00153 EL((ASSAERR,"Can't SETVAL[0]\n"));
00154 Assure_exit (false);
00155 }
00156
00157 semctrl_arg.val = BIGCOUNT;
00158
00159 if (semctl (m_id, 1, SETVAL, semctrl_arg) < 0) {
00160 EL((ASSAERR,"Can't SETVAL[1]\n"));
00161 Assure_exit (false);
00162 }
00163 }
00164
00165
00166
00167 if (semop (m_id, &m_op_endcreate[0], 2) < 0) {
00168 EL((ASSAERR,"Error on semop (ndcreate)\n"));
00169 Assure_exit (false);
00170 }
00171 return (m_id);
00172 }
00173
00174 int
00175 Semaphore::
00176 open (key_t key_)
00177 {
00178 trace_with_mask("Semaphore::open", SEM);
00179
00180 if (IPC_PRIVATE == key_) {
00181 EL((ASSAERR,"Not intended for private semaphores\n"));
00182 return (-1);
00183 }
00184 else if (key_ == (key_t) -1) {
00185 EL((ASSAERR,"Probably an ftok() error by caller\n"));
00186 return (-1);
00187 }
00188
00189 m_key = key_;
00190
00191 if ((m_id = semget (m_key, 3, 0)) < 0) {
00192 EL((ASSAERR,"Error on semget(3)"));
00193 return (-1);
00194 }
00195
00196
00197 if (semop (m_id, &m_op_open[0], 1) < 0) {
00198 EL((ASSAERR,"Error on semget(open)\n"));
00199 Assure_exit(false);
00200 }
00201 return (m_id);
00202 }
00203
00204 void
00205 Semaphore::
00206 remove ()
00207 {
00208 trace_with_mask("Semaphore::remove", SEM);
00209
00210 if (m_id < 0 || m_key == ((key_t) -1) ) return;
00211
00212 if (semctl (m_id, 0, IPC_RMID, 0) < 0) {
00213 EL((ASSAERR,"Can't IPC_RMID\n"));
00214 Assure_exit(false);
00215 }
00216 init ();
00217 }
00218
00219 void
00220 Semaphore::
00221 close ()
00222 {
00223 trace_with_mask("Semaphore::close", SEM);
00224
00225 register int semval;
00226
00227 if (m_id < 0) return;
00228
00229
00230
00231
00232 if (semop (m_id, &m_op_close[0], 3) < 0) {
00233 EL((ASSAERR,"Can't semop(2)\n"));
00234 Assure_exit(false);
00235 }
00236
00237
00238
00239
00240
00241 if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) {
00242 EL((ASSAERR,"Can't GETVAL\n"));
00243 Assure_exit(false);
00244 }
00245
00246 if (semval > BIGCOUNT) {
00247 EL((ASSAERR,"sem[1] > BIGCOUNT\n"));
00248 Assure_exit(false);
00249 }
00250 else if (semval == BIGCOUNT) {
00251 remove ();
00252 }
00253 else if (semop (m_id, &m_op_unlock[0], 1) < 0) {
00254 EL((ASSAERR,"Can't unlock\n"));
00255 Assure_exit(false);
00256 }
00257
00258 init ();
00259 }
00260
00261
00262 void
00263 Semaphore::
00264 op (int value_)
00265 {
00266
00267
00268
00269
00270 trace_with_mask("Semaphore::op", SEM);
00271
00272 int semval = 0;
00273 dump ();
00274
00275 if ((semval = semctl (m_id, 1, GETVAL, 0)) < 0) {
00276 EL((ASSAERR,"Can't GETVAL\n"));
00277 Assure_exit (false);
00278 }
00279
00280
00281 if ((m_op_op[0].sem_op = value_) == 0) {
00282 EL((ASSAERR,"Can't have value_ == 0\n"));
00283 Assure_exit(false);
00284 }
00285
00286 if (semop (m_id, &m_op_op[0], 1) < 0) {
00287 EL((ASSAERR,"sem_op error\n"));
00288 Assure_exit(false);
00289 }
00290 }
00291
00292 void
00293 Semaphore::
00294 dump (void) const
00295 {
00296 trace_with_mask("Semaphore::dump", SEM);
00297
00298 std::ostringstream msg;
00299 msg << "\n\n\tKey.....: ";
00300
00301 if (m_key == (key_t) -1) {
00302 msg << m_key;
00303 }
00304 else {
00305 msg << "0x" << std::hex << m_key << std::dec;
00306 }
00307
00308 msg << "\n\tID......: " << m_id << "\n\n";
00309
00310 if (m_id >= 0 && m_key >= (key_t) -1) {
00311 msg << "\tsemval [0]\tproc counter[1]\tlock [2]\n"
00312 << "\t----------\t---------------\t--------\n";
00313
00314
00315 msg << "\t " << semctl (m_id, 0, GETVAL)
00316 << "\t\t " << semctl (m_id, 1, GETVAL)
00317 << "\t\t " << semctl (m_id, 2, GETVAL);
00318 }
00319 else {
00320 msg << "Semaphore id = -1. No info is available.";
00321 }
00322 msg << std::ends;
00323 DL((SEM,"%s\n\n", msg.str ().c_str ()));
00324 }
00325
00326 #endif
00327