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