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