26 #include <utils/ipc/semset.h> 27 #include <utils/ipc/shm.h> 28 #include <utils/ipc/shm_exceptions.h> 29 #include <utils/ipc/shm_lister.h> 30 #include <utils/ipc/shm_registry.h> 223 #define WRITE_MUTEX_SEM 0 242 bool destroy_on_delete,
243 const char *registry_name)
263 shared_mem_upper_bound_ = NULL;
265 write_lock_aquired_ =
false;
267 registry_name_ = NULL;
270 registry_name_ = strdup(registry_name);
299 shared_mem_upper_bound_ = NULL;
301 write_lock_aquired_ =
false;
302 if (s.registry_name_) {
303 registry_name_ = strdup(s.registry_name_);
305 registry_name_ = NULL;
311 e.
append(
"SharedMemory public copy constructor");
352 bool destroy_on_delete,
353 const char * registry_name)
373 shared_mem_upper_bound_ = NULL;
375 write_lock_aquired_ =
false;
377 registry_name_ = NULL;
379 registry_name_ = strdup(registry_name);
385 e.
append(
"SharedMemory public constructor");
399 if (semset_ != NULL) {
410 delete shm_registry_;
423 if (semset_ != NULL) {
434 delete shm_registry_;
456 shared_mem_upper_bound_ = NULL;
458 write_lock_aquired_ =
false;
459 if (s.registry_name_) {
460 registry_name_ = strdup(s.registry_name_);
462 registry_name_ = NULL;
468 e.
append(
"SharedMemory public copy constructor");
493 shmctl(shared_mem_id_, IPC_RMID, NULL);
497 if (shared_mem_ != NULL) {
519 if ((
_memptr != NULL) && (shared_mem_id_ != -1)) {
524 std::list<SharedMemoryRegistry::SharedMemID> segments =
527 std::list<SharedMemoryRegistry::SharedMemID>::iterator s;
531 struct shmid_ds shm_segment;
533 for (s = segments.begin(); (
_memptr == NULL) && (s != segments.end()); ++s) {
534 if (shmctl(s->shmid, IPC_STAT, &shm_segment) < 0)
537 shm_buf = shmat(s->shmid, NULL,
_is_read_only ? SHM_RDONLY : 0);
538 if (shm_buf != (
void *)-1) {
551 if (
_mem_size != (
unsigned int)shm_segment.shm_segsz) {
555 shared_mem_id_ = s->shmid;
556 shared_mem_ = shm_buf;
557 shared_mem_upper_bound_ = (
void *)((
size_t)shared_mem_ +
_mem_size);
581 while ((
_memptr == NULL) && (key < INT_MAX)) {
583 shared_mem_id_ = shmget(key,
_mem_size, IPC_CREAT | IPC_EXCL | 0666);
584 if (shared_mem_id_ != -1) {
585 shared_mem_ = shmat(shared_mem_id_, NULL, 0);
586 if (shared_mem_ != (
void *)-1) {
604 shmctl(shared_mem_id_, IPC_RMID, NULL);
608 if (errno == EEXIST) {
613 }
else if (errno == EINVAL) {
696 if ((
ptr < shared_mem_) || (
ptr >= shared_mem_upper_bound_)) {
756 return shared_mem_id_;
829 return (semset_ != NULL);
857 throw Exception(
"Cannot add semaphore if not attached");
872 semset_->
unlock(WRITE_MUTEX_SEM);
877 throw Exception(
"Cannot create semaphore for read-only shmem segment");
894 shmctl(shared_mem_id_, SHM_UNLOCK, NULL);
896 shmctl(shared_mem_id_, SHM_LOCK, NULL);
911 if (semset_ == NULL) {
915 semset_->
lock(READ_SEM);
916 lock_aquired_ =
true;
944 lock_aquired_ =
true;
961 if (semset_ == NULL) {
965 semset_->
lock(WRITE_MUTEX_SEM);
967 semset_->
lock(READ_SEM);
969 write_lock_aquired_ =
true;
970 lock_aquired_ =
true;
971 semset_->
unlock(WRITE_MUTEX_SEM);
998 if (semset_->
try_lock(WRITE_MUTEX_SEM)) {
1000 if (!semset_->
try_lock(READ_SEM)) {
1002 for (
short j = 0; j < i - 1; ++j) {
1003 semset_->
unlock(READ_SEM);
1005 semset_->
unlock(WRITE_MUTEX_SEM);
1009 lock_aquired_ =
true;
1010 write_lock_aquired_ =
true;
1011 semset_->
unlock(WRITE_MUTEX_SEM);
1027 if (semset_ == NULL || !lock_aquired_)
1030 if (write_lock_aquired_) {
1032 semset_->
unlock(READ_SEM);
1034 write_lock_aquired_ =
false;
1036 semset_->
unlock(READ_SEM);
1053 struct shmid_ds shm_segment;
1055 if (shmctl(shm_id, IPC_STAT, &shm_segment) == -1) {
1059 struct ipc_perm *perm = &shm_segment.shm_perm;
1060 return (perm->mode & SHM_DEST);
1076 struct shmid_ds shm_segment;
1077 struct ipc_perm *perm = &shm_segment.shm_perm;
1079 if (shmctl(shm_id, IPC_STAT, &shm_segment) < 0) {
1082 return !(perm->mode & SHM_LOCKED);
1096 struct shmid_ds shm_segment;
1098 if (shmctl(shm_id, IPC_STAT, &shm_segment) < 0) {
1101 return shm_segment.shm_nattch;
1119 const char * registry_name)
1154 const char * registry_name)
1162 if ((i == endi) && (lister != NULL)) {
1173 shmctl(i.
shmid(), IPC_RMID, NULL);
1175 if (lister != NULL) {
1202 const char * registry_name)
1210 if ((i == endi) && (lister != NULL)) {
1214 unsigned int num_segments = 0;
1225 shmctl(i.
shmid(), IPC_RMID, NULL);
1227 if (lister != NULL) {
1236 if ((num_segments == 0) && (lister != NULL)) {
1257 return (
find(magic_token, header, registry_name) !=
end());
1300 id_it_ = ids_.end();
1306 initialized_ =
true;
1314 header_ = shmit.header_->
clone();
1315 cur_shmid_ = shmit.cur_shmid_;
1320 initialized_ =
true;
1322 if (shmit.id_it_ == shmit.ids_.end()) {
1323 id_it_ = ids_.end();
1325 std::list<SharedMemoryRegistry::SharedMemID>::iterator s;
1326 for (s = ids_.begin(); s != ids_.end(); ++s) {
1327 if (s->shmid == shmit.id_it_->shmid)
1332 if (shmit.shm_buf_ != (
void *)-1) {
1347 std::list<SharedMemoryRegistry::SharedMemID> ids,
1350 header_ = header->
clone();
1352 shm_buf_ = (
void *)-1;
1356 initialized_ =
false;
1366 if (shm_buf_ != (
void *)-1) {
1368 shm_buf_ = (
void *)-1;
1374 SharedMemory::SharedMemoryIterator::attach()
1376 struct shmid_ds shm_segment;
1379 cur_shmid_ = id_it_->shmid;
1380 if (cur_shmid_ < 0) {
1392 shm_buf_ = shmat(cur_shmid_, NULL, SHM_RDONLY);
1393 if (shm_buf_ == (
void *)-1) {
1398 if (shmctl(cur_shmid_, IPC_STAT, &shm_segment) < 0) {
1400 throw ShmCouldNotAttachException(
"SharedMemoryIterator could not stat (2)");
1403 segmsize_ = shm_segment.shm_segsz;
1404 segmnattch_ = shm_segment.shm_nattch;
1409 SharedMemory::SharedMemoryIterator::reset()
1413 if (shm_buf_ != (
void *)-1) {
1415 shm_buf_ = (
void *)-1;
1427 SharedMemory::SharedMemoryIterator &
1432 if (!initialized_) {
1433 id_it_ = ids_.begin();
1436 if (id_it_ == ids_.end())
1442 initialized_ =
true;
1444 for (; id_it_ != ids_.end(); ++id_it_) {
1456 + (header_ ? header_->size() : 0);
1493 for (
unsigned int j = 0; j < i; ++j) {
1506 for (
unsigned int j = 0; j < i; ++j) {
1519 return (cur_shmid_ == s.cur_shmid_);
1529 return !(*
this == s);
1547 if (shm_buf_ != (
void *)-1) {
1549 shm_buf_ = (
void *)-1;
1553 header_ = shmit.header_->
clone();
1555 cur_shmid_ = shmit.cur_shmid_;
1558 if (shmit.id_it_ != shmit.ids_.end()) {
1559 for (id_it_ = ids_.begin(); id_it_ != ids_.end(); ++id_it_) {
1560 if (id_it_->shmid == shmit.id_it_->shmid)
1565 if (shmit.shm_buf_ != (
void *)-1) {
1579 if (id_it_ == ids_.end()) {
1582 return id_it_->magic_token;
static void erase_orphaned(const char *magic_token, SharedMemoryHeader *header, SharedMemoryLister *lister=0, const char *registry_name=0)
Erase orphaned (attach count = 0) shared memory segments of a given type.
void add_segment(int shmid, const char *magic_token)
Register a segment.
virtual void print_footer()=0
Print footer of the table.
bool is_protected() const
Check if memory segment is protected.
void lock_for_write()
Lock shared memory segment for writing.
SharedMemory(const char *magic_token, SharedMemoryHeader *header, bool is_read_only, bool create, bool destroy_on_delete, const char *registry_name=0)
Create a new shared memory segment.
Fawkes library namespace.
virtual void print_header()=0
Print header of the table.
size_t _mem_size
Total size of the segment, including headers.
bool _should_create
Create shared memory segment.
bool try_lock_for_write()
Try to aquire lock on shared memory segment for writing.
size_t _data_size
Size of the data segment only.
SharedMemory_header_t * _shm_header
general header as stored in the shared memory segment
static void destroy(int key)
Destroy a semaphore set.
void * databuf() const
Get pointer to data buffer.
bool is_swapable() const
Check if memory can be swapped out.
void * _shm_upper_bound
Upper bound of memory.
bool is_creator() const
Determine if the shared memory segment has been created by this instance.
void lock_for_read()
Lock shared memory segment for reading.
bool try_lock_for_read()
Try to aquire lock on shared memory segment for reading.
void * addr(void *ptr) const
Get an address from a real pointer.
size_t segmsize() const
Get segment size.
Memory size does not match.
void lock(unsigned short sem_num=0, short num=1)
Lock resources on the semaphore set.
bool is_valid() const
Check validity of shared memory segment.
char * _magic_token
Magic token.
char * _shm_magic_token
Magic token as stored in the shared memory segment.
The address points out of the shared memory.
static SharedMemoryIterator end()
Get invalid iterator.
bool _destroy_on_delete
destroy on delete.
void set_swapable(bool swapable)
Set shared memory swapable.
static void erase(const char *magic_token, SharedMemoryHeader *header, SharedMemoryLister *lister=0, const char *registry_name=0)
Erase shared memory segments of a given type.
SharedMemory & operator=(const SharedMemory &s)
Assignment operator.
size_t segmnattch() const
Get number of attached parties.
bool is_destroyed() const
Check if segment has been destroyed This can be used if the segment has been destroyed.
bool is_read_only() const
Check for read-only mode.
SharedMemoryIterator & operator++()
Prefix increment.
SharedMemoryIterator()
Constructor.
void free()
Detach from and maybe destroy the shared memory segment.
void set_destroy_on_delete(bool destroy)
Set if semaphore set should be destroyed on delete.
Base class for exceptions in Fawkes.
void attach()
Attach to the shared memory segment.
int key()
Get key of semaphore.
void * ptr(void *addr) const
Get the real pointer to the data based on an address.
static bool exists(const char *magic_token, SharedMemoryHeader *header, const char *registry_name=0)
Check if a specific shared memory segment exists.
void * memptr() const
Get a pointer to the shared memory This method returns a pointer to the data-segment of the shared me...
unsigned int num_attached() const
Get number of attached processes.
void * _memptr
Pointer to the data segment.
void set_destroy_on_delete(bool destroy)
Set deletion behaviour.
Could not attach to shared memory segment.
virtual ~SharedMemory()
Destructor.
Format list output for shared memory segments.
void unlock(unsigned short sem_num=0, short num=-1)
Unlock resources on the semaphore set.
const SharedMemoryHeader * operator*() const
Get SharedMemoryHeader.
int semaphore() const
Get semaphore.
SharedMemoryIterator & operator=(const SharedMemoryIterator &shmit)
Make this instance point to the same segment as shmit.
void add_semaphore()
Add semaphore to shared memory segment.
void set_value(int sem_num, int val)
Set the semaphore value.
static SharedMemoryIterator find(const char *magic_token, SharedMemoryHeader *header, const char *registry_name=0)
Find SharedMemory segments.
std::list< SharedMemoryRegistry::SharedMemID > find_segments(const char *magic_token) const
Find segments with particular magic token.
static const short MaxNumConcurrentReaders
Maximum number of concurrent readers.
bool operator==(const SharedMemoryIterator &s) const
Check iterators for equality.
bool _is_read_only
Read-only.
~SharedMemoryIterator()
Destructor.
bool operator!=(const SharedMemoryIterator &s) const
Check iterators for inequality.
size_t data_size() const
Get the size of the data-segment.
SharedMemoryHeader * _header
Data-specific header.
virtual void print_info(const SharedMemoryHeader *header, int shm_id, int semaphore, unsigned int mem_size, const void *memptr)=0
Print info about segment.
static const unsigned int MagicTokenSize
The magic token size.
int shmid() const
Get shared memory ID.
void remove_segment(int shmid)
Remove segment.
int shmem_id() const
Get shared memory ID.
virtual void print_no_segments()=0
Print this if no matching segment was found.
void set(void *memptr)
Copies data from the memptr to shared memory.
SharedMemoryIterator & operator+(unsigned int i)
Advance by i steps.
long unsigned int _shm_offset
Offset to the master's base addr.
static void list(const char *magic_token, SharedMemoryHeader *header, SharedMemoryLister *lister, const char *registry_name=0)
List shared memory segments of a given type.
SharedMemoryIterator & operator+=(unsigned int i)
Advance by i steps.
bool try_lock(unsigned short sem_num=0, short num=1)
Try to lock resources on the semaphore set.
void unlock()
Unlock memory.
void append(const char *format,...)
Append messages to the message list.
const char * magic_token() const
Get magic token.
virtual void print_no_orphaned_segments()=0
Print this if no matching orphaned segment was found.
The pointer does not point inside the shared memory.