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);
1548 if (shm_buf_ != (
void *)-1) {
1550 shm_buf_ = (
void *)-1;
1554 header_ = shmit.header_->
clone();
1556 cur_shmid_ = shmit.cur_shmid_;
1559 if (shmit.id_it_ != shmit.ids_.end()) {
1560 for (id_it_ = ids_.begin(); id_it_ != ids_.end(); ++id_it_) {
1561 if (id_it_->shmid == shmit.id_it_->shmid)
1566 if (shmit.shm_buf_ != (
void *)-1) {
1580 if (id_it_ == ids_.end()) {
1583 return id_it_->magic_token;
Base class for exceptions in Fawkes.
void append(const char *format,...) noexcept
Append messages to the message list.
void set_destroy_on_delete(bool destroy)
Set if semaphore set should be destroyed on delete.
void unlock(unsigned short sem_num=0, short num=-1)
Unlock resources on the semaphore set.
bool try_lock(unsigned short sem_num=0, short num=1)
Try to lock resources on the semaphore set.
void lock(unsigned short sem_num=0, short num=1)
Lock resources on the semaphore set.
int key()
Get key of semaphore.
static void destroy(int key)
Destroy a semaphore set.
void set_value(int sem_num, int val)
Set the semaphore value.
Format list output for shared memory segments.
virtual void print_header()=0
Print header of the table.
virtual void print_info(const SharedMemoryHeader *header, int shm_id, int semaphore, unsigned int mem_size, const void *memptr)=0
Print info about segment.
virtual void print_no_segments()=0
Print this if no matching segment was found.
virtual void print_footer()=0
Print footer of the table.
virtual void print_no_orphaned_segments()=0
Print this if no matching orphaned segment was found.
void add_segment(int shmid, const char *magic_token)
Register a segment.
void remove_segment(int shmid)
Remove segment.
std::list< SharedMemoryRegistry::SharedMemID > find_segments(const char *magic_token) const
Find segments with particular magic token.
bool operator==(const SharedMemoryIterator &s) const
Check iterators for equality.
SharedMemoryIterator & operator+(unsigned int i)
Advance by i steps.
const char * magic_token() const
Get magic token.
~SharedMemoryIterator()
Destructor.
SharedMemoryIterator & operator=(const SharedMemoryIterator &shmit)
Make this instance point to the same segment as shmit.
SharedMemoryIterator()
Constructor.
int semaphore() const
Get semaphore.
void * databuf() const
Get pointer to data buffer.
SharedMemoryIterator & operator++()
Prefix increment.
const SharedMemoryHeader * operator*() const
Get SharedMemoryHeader.
SharedMemoryIterator & operator+=(unsigned int i)
Advance by i steps.
size_t segmsize() const
Get segment size.
int shmid() const
Get shared memory ID.
bool operator!=(const SharedMemoryIterator &s) const
Check iterators for inequality.
size_t segmnattch() const
Get number of attached parties.
bool try_lock_for_read()
Try to aquire lock on shared memory segment for reading.
bool is_read_only() const
Check for read-only mode.
void free()
Detach from and maybe destroy the shared memory segment.
static SharedMemoryIterator find(const char *magic_token, SharedMemoryHeader *header, const char *registry_name=0)
Find SharedMemory segments.
int shmem_id() const
Get shared memory ID.
static void list(const char *magic_token, SharedMemoryHeader *header, SharedMemoryLister *lister, const char *registry_name=0)
List shared memory segments of a given type.
void * addr(void *ptr) const
Get an address from a real pointer.
bool is_valid() const
Check validity of shared memory segment.
void add_semaphore()
Add semaphore to shared memory segment.
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.
virtual ~SharedMemory()
Destructor.
bool _is_read_only
Read-only.
char * _magic_token
Magic token.
bool is_destroyed() const
Check if segment has been destroyed This can be used if the segment has been destroyed.
void * _shm_upper_bound
Upper bound of memory.
size_t data_size() const
Get the size of the data-segment.
bool is_swapable() const
Check if memory can be swapped out.
bool is_protected() const
Check if memory segment is protected.
void lock_for_write()
Lock shared memory segment for writing.
SharedMemory_header_t * _shm_header
general header as stored in the shared memory segment
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 set(void *memptr)
Copies data from the memptr to shared memory.
unsigned int num_attached() const
Get number of attached processes.
void * memptr() const
Get a pointer to the shared memory This method returns a pointer to the data-segment of the shared me...
size_t _data_size
Size of the data segment only.
SharedMemoryHeader * _header
Data-specific header.
SharedMemory & operator=(const SharedMemory &s)
Assignment operator.
void * _memptr
Pointer to the data segment.
void * ptr(void *addr) const
Get the real pointer to the data based on an address.
void unlock()
Unlock memory.
char * _shm_magic_token
Magic token as stored in the shared memory segment.
long unsigned int _shm_offset
Offset to the master's base addr.
static const short MaxNumConcurrentReaders
Maximum number of concurrent readers.
static const unsigned int MagicTokenSize
The magic token size.
bool try_lock_for_write()
Try to aquire lock on shared memory segment for writing.
void set_destroy_on_delete(bool destroy)
Set deletion behaviour.
void set_swapable(bool swapable)
Set shared memory swapable.
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.
bool is_creator() const
Determine if the shared memory segment has been created by this instance.
static bool exists(const char *magic_token, SharedMemoryHeader *header, const char *registry_name=0)
Check if a specific shared memory segment exists.
static SharedMemoryIterator end()
Get invalid iterator.
void attach()
Attach to the shared memory segment.
size_t _mem_size
Total size of the segment, including headers.
bool _destroy_on_delete
destroy on delete.
void lock_for_read()
Lock shared memory segment for reading.
bool _should_create
Create shared memory segment.
The address points out of the shared memory.
Could not attach to shared memory segment.
Memory size does not match.
The pointer does not point inside the shared memory.
Fawkes library namespace.