24 #include <utils/ipc/shm.h> 25 #include <utils/ipc/shm_exceptions.h> 26 #include <utils/ipc/shm_lister.h> 27 #include <utils/ipc/semset.h> 28 #include <utils/ipc/shm_registry.h> 224 #define WRITE_MUTEX_SEM 0 244 bool destroy_on_delete,
245 const char *registry_name)
265 __shared_mem_upper_bound = NULL;
267 __write_lock_aquired =
false;
269 __registry_name = NULL;
272 __registry_name = strdup(registry_name);
302 __shared_mem_upper_bound = NULL;
304 __write_lock_aquired =
false;
305 if (s.__registry_name) {
306 __registry_name = strdup(s.__registry_name);
308 __registry_name = NULL;
314 e.
append(
"SharedMemory public copy constructor");
355 const char *registry_name)
375 __shared_mem_upper_bound = NULL;
377 __write_lock_aquired =
false;
379 __registry_name = NULL;
381 __registry_name = strdup(__registry_name);
387 e.
append(
"SharedMemory public constructor");
402 if ( __semset != NULL ) {
413 delete __shm_registry;
414 if (__registry_name)
::free(__registry_name);
430 shmctl(__shared_mem_id, IPC_RMID, NULL);
432 __shared_mem_id = -1;
434 if (__shared_mem != NULL) {
458 if ((
_memptr != NULL) && (__shared_mem_id != -1)) {
463 std::list<SharedMemoryRegistry::SharedMemID> segments =
467 std::list<SharedMemoryRegistry::SharedMemID>::iterator s;
471 struct shmid_ds shm_segment;
473 for (s = segments.begin(); (
_memptr == NULL) && (s != segments.end()); ++s) {
475 if (shmctl(s->shmid, IPC_STAT, &shm_segment) < 0)
continue;
478 shm_buf = shmat(s->shmid, NULL,
_is_read_only ? SHM_RDONLY : 0);
479 if (shm_buf != (
void *)-1) {
494 if (
_mem_size != (
unsigned int) shm_segment.shm_segsz) {
496 (
unsigned int)shm_segment.shm_segsz);
499 __shared_mem_id = s->shmid;
500 __shared_mem = shm_buf;
501 __shared_mem_upper_bound = (
void *)((
size_t)__shared_mem +
_mem_size);
525 while ((
_memptr == NULL) && (key < INT_MAX)) {
527 __shared_mem_id = shmget(key,
_mem_size, IPC_CREAT | IPC_EXCL | 0666);
528 if (__shared_mem_id != -1) {
529 __shared_mem = shmat(__shared_mem_id, NULL, 0);
530 if (__shared_mem != (
void *)-1) {
550 shmctl(__shared_mem_id, IPC_RMID, NULL);
554 if (errno == EEXIST) {
559 }
else if (errno == EINVAL) {
609 if ( addr == NULL)
return NULL;
610 if ( (addr < _shm_header->shm_addr) ||
640 if ( ptr == NULL)
return NULL;
641 if ( (ptr < __shared_mem) ||
642 (ptr >= __shared_mem_upper_bound) ) {
706 return __shared_mem_id;
785 return (__semset != NULL);
812 if (__semset != NULL)
return;
813 if (
_memptr == NULL)
throw Exception(
"Cannot add semaphore if not attached");
828 __semset->
unlock(WRITE_MUTEX_SEM);
833 throw Exception(
"Cannot create semaphore for read-only shmem segment");
851 shmctl(__shared_mem_id, SHM_UNLOCK, NULL);
853 shmctl(__shared_mem_id, SHM_LOCK, NULL);
869 if ( __semset == NULL ) {
873 __semset->
lock(READ_SEM);
874 __lock_aquired =
true;
899 if ( __semset == NULL )
return false;
901 if ( __semset->
try_lock(READ_SEM) ) {
902 __lock_aquired =
true;
920 if ( __semset == NULL ) {
924 __semset->
lock(WRITE_MUTEX_SEM);
926 __semset->
lock(READ_SEM);
928 __write_lock_aquired =
true;
929 __lock_aquired =
true;
930 __semset->
unlock(WRITE_MUTEX_SEM);
955 if ( __semset == NULL )
return false;
957 if ( __semset->
try_lock(WRITE_MUTEX_SEM) ) {
959 if ( ! __semset->
try_lock(READ_SEM) ) {
961 for (
short j = 0; j < i - 1; ++j) {
962 __semset->
unlock(READ_SEM);
964 __semset->
unlock(WRITE_MUTEX_SEM);
968 __lock_aquired =
true;
969 __write_lock_aquired =
true;
970 __semset->
unlock(WRITE_MUTEX_SEM);
987 if ( __semset == NULL || ! __lock_aquired )
return;
989 if ( __write_lock_aquired ) {
991 __semset->
unlock(READ_SEM);
993 __write_lock_aquired =
false;
995 __semset->
unlock(READ_SEM);
1013 struct shmid_ds shm_segment;
1015 if (shmctl(shm_id, IPC_STAT, &shm_segment ) == -1) {
1019 struct ipc_perm *perm = &shm_segment.shm_perm;
1020 return (perm->mode & SHM_DEST);
1037 struct shmid_ds shm_segment;
1038 struct ipc_perm *perm = &shm_segment.shm_perm;
1040 if (shmctl(shm_id, IPC_STAT, &shm_segment ) < 0) {
1043 return ! (perm->mode & SHM_LOCKED);
1058 struct shmid_ds shm_segment;
1060 if (shmctl(shm_id, IPC_STAT, &shm_segment ) < 0) {
1063 return shm_segment.shm_nattch;
1081 const char *registry_name)
1093 while ( i != endi ) {
1117 const char *registry_name)
1125 if ( (i == endi) && (lister != NULL)) {
1129 while ( i != endi ) {
1136 shmctl(i.
shmid(), IPC_RMID, NULL);
1138 if ( lister != NULL) {
1166 const char *registry_name)
1174 if ( (i == endi) && (lister != NULL)) {
1178 unsigned int num_segments = 0;
1180 while ( i != endi ) {
1190 shmctl(i.
shmid(), IPC_RMID, NULL);
1192 if ( lister != NULL) {
1202 if ( (num_segments == 0) && (lister != NULL) ) {
1223 const char *registry_name)
1225 return (
find(magic_token, header, registry_name) !=
end());
1238 const char *registry_name)
1272 __id_it = __ids.end();
1278 __initialized =
true;
1287 __header = shmit.__header->
clone();
1288 __cur_shmid = shmit.__cur_shmid;
1292 __ids = shmit.__ids;
1293 __initialized =
true;
1295 if (shmit.__id_it == shmit.__ids.end()) {
1296 __id_it = __ids.end();
1298 std::list<SharedMemoryRegistry::SharedMemID>::iterator s;
1299 for (s = __ids.begin(); s != __ids.end(); ++s) {
1300 if (s->shmid == shmit.__id_it->shmid)
break;
1304 if ( shmit.__shm_buf != (
void *)-1 ) {
1320 std::list<SharedMemoryRegistry::SharedMemID> ids,
1323 __header = header->
clone();
1325 __shm_buf = (
void *)-1;
1329 __initialized =
false;
1340 if ( __shm_buf != (
void *)-1 ) {
1342 __shm_buf = (
void *)-1;
1349 SharedMemory::SharedMemoryIterator::attach()
1351 struct shmid_ds shm_segment;
1354 __cur_shmid = __id_it->shmid;
1355 if ( __cur_shmid < 0 ) {
1367 __shm_buf = shmat(__cur_shmid, NULL, SHM_RDONLY);
1368 if (__shm_buf == (
void *)-1) {
1373 if (shmctl( __cur_shmid, IPC_STAT, &shm_segment) < 0 ) {
1378 __segmsize = shm_segment.shm_segsz;
1379 __segmnattch = shm_segment.shm_nattch;
1385 SharedMemory::SharedMemoryIterator::reset()
1387 if ( __header) __header->reset();
1388 if ( __shm_buf != (
void *)-1) {
1390 __shm_buf = (
void *)-1;
1408 if (! __initialized) {
1409 __id_it = __ids.begin();
1412 if (__id_it == __ids.end())
return *
this;
1414 if (__initialized) ++__id_it;
1415 else __initialized =
true;
1417 for (; __id_it != __ids.end(); ++__id_it) {
1421 if (!__header || __header->matches((
char *)__shm_buf +
MagicTokenSize 1432 + (__header ? __header->size() : 0);
1472 for (
unsigned int j = 0; j < i; ++j) {
1486 for (
unsigned int j = 0; j < i; ++j) {
1500 return (__cur_shmid == s.__cur_shmid);
1511 return ! (*
this == s);
1532 if ( __shm_buf != (
void *)-1 ) {
1534 __shm_buf = (
void *)-1;
1538 __header = shmit.__header->
clone();
1539 __ids = shmit.__ids;
1540 __cur_shmid = shmit.__cur_shmid;
1543 if (shmit.__id_it != shmit.__ids.end()) {
1544 for (__id_it = __ids.begin(); __id_it != __ids.end(); ++__id_it) {
1545 if (__id_it->shmid == shmit.__id_it->shmid)
break;
1549 if ( shmit.__shm_buf != (
void *)-1 ) {
1564 if (__id_it == __ids.end()) {
1567 return __id_it->magic_token;
1608 return __segmnattch;
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.
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.