00001
00002
00003
00004 #include "ace/Shared_Memory_Pool.h"
00005 #include "ace/OS_NS_sys_shm.h"
00006 #include "ace/Log_Msg.h"
00007
00008 ACE_RCSID(ace, Shared_Memory_Pool, "$Id: Shared_Memory_Pool.cpp 79134 2007-07-31 18:23:50Z johnnyw $")
00009
00010 #if !defined (ACE_LACKS_SYSV_SHMEM)
00011
00012 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00013
00014 ACE_ALLOC_HOOK_DEFINE(ACE_Shared_Memory_Pool)
00015
00016 ACE_Shared_Memory_Pool_Options::ACE_Shared_Memory_Pool_Options (
00017 const char *base_addr,
00018 size_t max_segments,
00019 size_t file_perms,
00020 ACE_OFF_T minimum_bytes,
00021 size_t segment_size)
00022 : base_addr_ (base_addr),
00023 max_segments_ (max_segments),
00024 minimum_bytes_ (minimum_bytes),
00025 file_perms_ (file_perms),
00026 segment_size_ (segment_size)
00027 {
00028 ACE_TRACE ("ACE_Shared_Memory_Pool_Options::ACE_Shared_Memory_Pool_Options");
00029 }
00030
00031 void
00032 ACE_Shared_Memory_Pool::dump (void) const
00033 {
00034 #if defined (ACE_HAS_DUMP)
00035 ACE_TRACE ("ACE_Shared_Memory_Pool::dump");
00036 #endif
00037 }
00038
00039 int
00040 ACE_Shared_Memory_Pool::in_use (ACE_OFF_T &offset,
00041 size_t &counter)
00042 {
00043 offset = 0;
00044 SHM_TABLE *st = reinterpret_cast<SHM_TABLE *> (this->base_addr_);
00045 shmid_ds buf;
00046
00047 for (counter = 0;
00048 counter < this->max_segments_ && st[counter].used_ == 1;
00049 counter++)
00050 {
00051 if (ACE_OS::shmctl (st[counter].shmid_, IPC_STAT, &buf) == -1)
00052 ACE_ERROR_RETURN ((LM_ERROR,
00053 ACE_TEXT ("(%P|%t) %p\n"),
00054 ACE_TEXT ("shmctl")),
00055 -1);
00056 offset += buf.shm_segsz;
00057
00058 }
00059
00060 return 0;
00061 }
00062
00063 int
00064 ACE_Shared_Memory_Pool::find_seg (const void* const searchPtr,
00065 ACE_OFF_T &offset,
00066 size_t &counter)
00067 {
00068 offset = 0;
00069 SHM_TABLE *st = reinterpret_cast<SHM_TABLE *> (this->base_addr_);
00070 shmid_ds buf;
00071
00072 for (counter = 0;
00073 counter < this->max_segments_
00074 && st[counter].used_ == 1;
00075 counter++)
00076 {
00077 if (ACE_OS::shmctl (st[counter].shmid_, IPC_STAT, &buf) == -1)
00078 ACE_ERROR_RETURN ((LM_ERROR,
00079 ACE_TEXT ("(%P|%t) %p\n"),
00080 ACE_TEXT ("shmctl")),
00081 -1);
00082 offset += buf.shm_segsz;
00083
00084
00085
00086
00087 if (((ptrdiff_t) offset + (ptrdiff_t) (this->base_addr_)) > (ptrdiff_t) searchPtr)
00088 {
00089 --counter;
00090 offset -= buf.shm_segsz;
00091 return 0;
00092 }
00093
00094 }
00095
00096 return 0;
00097 }
00098
00099 int
00100 ACE_Shared_Memory_Pool::commit_backing_store_name (size_t rounded_bytes,
00101 ACE_OFF_T &offset)
00102 {
00103 ACE_TRACE ("ACE_Shared_Memory_Pool::commit_backing_store_name");
00104
00105 size_t counter;
00106 SHM_TABLE *st = reinterpret_cast<SHM_TABLE *> (this->base_addr_);
00107
00108 if (this->in_use (offset, counter) == -1)
00109 return -1;
00110
00111 if (counter == this->max_segments_)
00112 ACE_ERROR_RETURN ((LM_ERROR,
00113 "exceeded max number of segments = %d, base = %u, offset = %u\n",
00114 counter,
00115 this->base_addr_,
00116 offset),
00117 -1);
00118 else
00119 {
00120 int shmid = ACE_OS::shmget (st[counter].key_,
00121 rounded_bytes,
00122 this->file_perms_ | IPC_CREAT | IPC_EXCL);
00123 if (shmid == -1)
00124 ACE_ERROR_RETURN ((LM_ERROR,
00125 ACE_TEXT ("(%P|%t) %p\n"),
00126 ACE_TEXT ("shmget")),
00127 -1);
00128 st[counter].shmid_ = shmid;
00129 st[counter].used_ = 1;
00130
00131 void *address = (void *) (((char *) this->base_addr_) + offset);
00132 void *shmem = ACE_OS::shmat (st[counter].shmid_,
00133 (char *) address,
00134 0);
00135
00136 if (shmem != address)
00137 ACE_ERROR_RETURN ((LM_ERROR,
00138 "(%P|%t) %p, shmem = %u, address = %u\n",
00139 "shmat",
00140 shmem,
00141 address),
00142 -1);
00143 }
00144 return 0;
00145 }
00146
00147
00148
00149 int
00150 ACE_Shared_Memory_Pool::handle_signal (int , siginfo_t *siginfo, ucontext_t *)
00151 {
00152 ACE_TRACE ("ACE_Shared_Memory_Pool::handle_signal");
00153
00154
00155
00156
00157 #if defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR) && \
00158 (defined (SEGV_MAPERR) || defined (SEGV_MEMERR))
00159 ACE_OFF_T offset;
00160
00161
00162
00163 if (siginfo != 0)
00164 {
00165
00166 size_t counter;
00167 if (this->in_use (offset, counter) == -1)
00168 ACE_ERROR ((LM_ERROR,
00169 ACE_TEXT ("(%P|%t) %p\n"),
00170 ACE_TEXT ("in_use")));
00171 #if !defined(_UNICOS)
00172 else if (!(siginfo->si_code == SEGV_MAPERR
00173 && siginfo->si_addr < (((char *) this->base_addr_) + offset)
00174 && siginfo->si_addr >= ((char *) this->base_addr_)))
00175 ACE_ERROR_RETURN ((LM_ERROR,
00176 "(%P|%t) address %u out of range\n",
00177 siginfo->si_addr),
00178 -1);
00179 #else
00180 else if (!(siginfo->si_code == SEGV_MEMERR
00181 && siginfo->si_addr < (((unsigned long) this->base_addr_) + offset)
00182 && siginfo->si_addr >= ((unsigned long) this->base_addr_)))
00183 ACE_ERROR_RETURN ((LM_ERROR,
00184 "(%P|%t) address %u out of range\n",
00185 siginfo->si_addr),
00186 -1);
00187 #endif
00188 }
00189
00190
00191
00192
00193
00194
00195 size_t counter;
00196
00197 #if !defined(_UNICOS)
00198 if (this->find_seg (siginfo->si_addr, offset, counter) == -1)
00199 #else
00200 if (this->find_seg ((const void *)siginfo->si_addr, offset, counter) == -1)
00201 #endif
00202 ACE_ERROR_RETURN ((LM_ERROR,
00203 ACE_TEXT ("(%P|%t) %p\n"),
00204 ACE_TEXT ("in_use")),
00205 -1);
00206
00207 void *address = (void *) (((char *) this->base_addr_) + offset);
00208 SHM_TABLE *st = reinterpret_cast<SHM_TABLE *> (this->base_addr_);
00209
00210 void *shmem = ACE_OS::shmat (st[counter].shmid_, (char *) address, 0);
00211
00212 if (shmem != address)
00213 ACE_ERROR_RETURN ((LM_ERROR,
00214 "(%P|%t) %p, shmem = %u, address = %u\n",
00215 "shmat",
00216 shmem,
00217 address),
00218 -1);
00219
00220
00221 #else
00222 ACE_UNUSED_ARG (siginfo);
00223 #endif
00224
00225 return 0;
00226 }
00227
00228 ACE_Shared_Memory_Pool::ACE_Shared_Memory_Pool (
00229 const ACE_TCHAR *backing_store_name,
00230 const OPTIONS *options)
00231 : base_addr_ (0),
00232 file_perms_ (ACE_DEFAULT_FILE_PERMS),
00233 max_segments_ (ACE_DEFAULT_MAX_SEGMENTS),
00234 minimum_bytes_ (0),
00235 segment_size_ (ACE_DEFAULT_SEGMENT_SIZE)
00236 {
00237 ACE_TRACE ("ACE_Shared_Memory_Pool::ACE_Shared_Memory_Pool");
00238
00239
00240 if (options)
00241 {
00242 this->base_addr_ =
00243 reinterpret_cast<void *> (const_cast<char *> (options->base_addr_));
00244 this->max_segments_ = options->max_segments_;
00245 this->file_perms_ = options->file_perms_;
00246 this->minimum_bytes_ = options->minimum_bytes_;
00247 this->segment_size_ = options->segment_size_;
00248 }
00249
00250 if (backing_store_name)
00251 {
00252
00253
00254
00255 int segment_key;
00256 int result = ::sscanf (ACE_TEXT_ALWAYS_CHAR (backing_store_name),
00257 "%d",
00258 &segment_key);
00259
00260 if (result == 0 || result == EOF)
00261
00262
00263 this->base_shm_key_ =
00264 (key_t) ACE::crc32 (ACE_TEXT_ALWAYS_CHAR (backing_store_name));
00265 else
00266 this->base_shm_key_ = segment_key;
00267
00268 if (this->base_shm_key_ == IPC_PRIVATE)
00269
00270
00271 this->base_shm_key_ = ACE_DEFAULT_SHM_KEY;
00272 }
00273 else
00274 this->base_shm_key_ = ACE_DEFAULT_SHM_KEY;
00275
00276 if (this->signal_handler_.register_handler (SIGSEGV, this) == -1)
00277 ACE_ERROR ((LM_ERROR,
00278 ACE_TEXT ("%p\n"),
00279 ACE_TEXT ("ACE_Sig_Handler::register_handler")));
00280 }
00281
00282 ACE_Shared_Memory_Pool::~ACE_Shared_Memory_Pool (void)
00283 {
00284 }
00285
00286
00287
00288 void *
00289 ACE_Shared_Memory_Pool::acquire (size_t nbytes,
00290 size_t &rounded_bytes)
00291 {
00292 ACE_TRACE ("ACE_Shared_Memory_Pool::acquire");
00293
00294 rounded_bytes = this->round_up (nbytes);
00295
00296
00297
00298 ACE_OFF_T offset;
00299
00300 if (this->commit_backing_store_name (rounded_bytes, offset) == -1)
00301 return 0;
00302
00303
00304 return ((char *) this->base_addr_) + offset;
00305 }
00306
00307
00308
00309 void *
00310 ACE_Shared_Memory_Pool::init_acquire (size_t nbytes,
00311 size_t &rounded_bytes,
00312 int &first_time)
00313 {
00314 ACE_TRACE ("ACE_Shared_Memory_Pool::init_acquire");
00315
00316 ACE_OFF_T shm_table_offset = ACE::round_to_pagesize (sizeof (SHM_TABLE));
00317 rounded_bytes = this->round_up (nbytes > (size_t) this->minimum_bytes_
00318 ? nbytes
00319 : (size_t) this->minimum_bytes_);
00320
00321
00322
00323
00324 int shmid = ACE_OS::shmget (this->base_shm_key_,
00325 rounded_bytes + shm_table_offset,
00326 this->file_perms_ | IPC_CREAT | IPC_EXCL);
00327 if (shmid == -1)
00328 {
00329 if (errno != EEXIST)
00330 ACE_ERROR_RETURN ((LM_ERROR,
00331 ACE_TEXT ("(%P|%t) %p\n"),
00332 ACE_TEXT ("shmget")),
00333 0);
00334 first_time = 0;
00335
00336 shmid = ACE_OS::shmget (this->base_shm_key_, 0, 0);
00337
00338 if (shmid == -1)
00339 ACE_ERROR_RETURN ((LM_ERROR,
00340 ACE_TEXT ("(%P|%t) %p\n"),
00341 ACE_TEXT ("shmget")),
00342 0);
00343
00344
00345
00346 this->base_addr_ =
00347 ACE_OS::shmat (shmid,
00348 reinterpret_cast<char *> (this->base_addr_),
00349 0);
00350 if (this->base_addr_ == reinterpret_cast<void *> (-1))
00351 ACE_ERROR_RETURN ((LM_ERROR,
00352 "(%P|%t) %p, base_addr = %u\n",
00353 "shmat",
00354 this->base_addr_),
00355 0);
00356 }
00357 else
00358 {
00359 first_time = 1;
00360
00361
00362
00363 this->base_addr_ =
00364 ACE_OS::shmat (shmid,
00365 reinterpret_cast<char *> (this->base_addr_),
00366 0);
00367 if (this->base_addr_ == reinterpret_cast<char *> (-1))
00368 ACE_ERROR_RETURN ((LM_ERROR,
00369 "(%P|%t) %p, base_addr = %u\n",
00370 "shmat",
00371 this->base_addr_), 0);
00372
00373 SHM_TABLE *st = reinterpret_cast<SHM_TABLE *> (this->base_addr_);
00374 st[0].key_ = this->base_shm_key_;
00375 st[0].shmid_ = shmid;
00376
00377 st[0].used_ = 1;
00378
00379 for (size_t counter = 1;
00380 counter < this->max_segments_;
00381 counter++)
00382 {
00383 st[counter].key_ = this->base_shm_key_ + counter;
00384 st[counter].shmid_ = 0;
00385 st[counter].used_ = 0;
00386 }
00387 }
00388
00389 return (void *) (((char *) this->base_addr_) + shm_table_offset);
00390 }
00391
00392
00393
00394 int
00395 ACE_Shared_Memory_Pool::release (int)
00396 {
00397 ACE_TRACE ("ACE_Shared_Memory_Pool::release");
00398
00399 int result = 0;
00400 SHM_TABLE *st = reinterpret_cast<SHM_TABLE *> (this->base_addr_);
00401
00402 for (size_t counter = 0;
00403 counter < this->max_segments_ && st[counter].used_ == 1;
00404 counter++)
00405 if (ACE_OS::shmctl (st[counter].shmid_, IPC_RMID, 0) == -1)
00406 result = -1;
00407
00408 return result;
00409 }
00410
00411 int
00412 ACE_Shared_Memory_Pool::sync (ssize_t, int)
00413 {
00414 ACE_TRACE ("ACE_Shared_Memory_Pool::sync");
00415 return 0;
00416 }
00417
00418 int
00419 ACE_Shared_Memory_Pool::sync (void *, size_t, int)
00420 {
00421 ACE_TRACE ("ACE_Shared_Memory_Pool::sync");
00422 return 0;
00423 }
00424
00425 int
00426 ACE_Shared_Memory_Pool::protect (ssize_t, int)
00427 {
00428 ACE_TRACE ("ACE_Shared_Memory_Pool::protect");
00429 return 0;
00430 }
00431
00432 int
00433 ACE_Shared_Memory_Pool::protect (void *, size_t, int)
00434 {
00435 ACE_TRACE ("ACE_Shared_Memory_Pool::protect");
00436 return 0;
00437 }
00438
00439 void *
00440 ACE_Shared_Memory_Pool::base_addr (void) const
00441 {
00442 ACE_TRACE ("ACE_Shared_Memory_Pool::base_addr");
00443 return this->base_addr_;
00444 }
00445
00446
00447
00448
00449 size_t
00450 ACE_Shared_Memory_Pool::round_up (size_t nbytes)
00451 {
00452 ACE_TRACE ("ACE_Shared_Memory_Pool::round_up");
00453 if (nbytes < this->segment_size_)
00454 nbytes = this->segment_size_;
00455
00456 return ACE::round_to_pagesize (nbytes);
00457 }
00458
00459 ACE_END_VERSIONED_NAMESPACE_DECL
00460
00461 #endif