1 /** Aesalon, a tool to visualize program behaviour in real time.
2 Copyright (C) 2009-2011, Aesalon development team.
4 Aesalon is distributed under the terms of the GNU GPLv3. See
5 the included file LICENSE for more information.
7 @file src/monitor/SHMReader.cpp
10 #include <semaphore.h>
18 #include "monitor/SHMReader.h"
19 #include "monitor/Coordinator.h"
20 #include "util/StreamAsString.h"
21 #include "util/MessageSystem.h"
22 #include "util/StringTo.h"
23 #include "shm/ZoneHeader.h"
27 SHMReader::SHMReader() : m_header(NULL
) {
28 m_shmName
= Util::StreamAsString() << "/Aesalon-" << getpid();
30 m_fd
= shm_open(m_shmName
.c_str(), O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
31 if(m_fd
== -1) Message(Fatal
, "Could not open shared memory: " << strerror(errno
));
38 SHMReader::~SHMReader() {
42 uint32_t SHMReader::zoneCount() {
43 return m_header
->zoneCount
;
46 uint8_t *SHMReader::zoneWithData() {
47 for(uint32_t i
= 0; i
< m_header
->zonesAllocated
; i
++) {
48 if(m_zoneUseData
[i
% 8] & (0x01 << (i
% 8))) {
49 uint8_t *zone
= getZone(i
);
52 Message(Warning
, "Could not open zone #" << i
);
56 SHM::ZoneHeader
*zheader
= reinterpret_cast<SHM::ZoneHeader
*>(zone
);
58 if(sem_wait(&zheader
->packetSemaphore
) == -1 && errno
== EAGAIN
) continue;
66 void SHMReader::waitForPacket() {
67 sem_wait(&m_header
->packetSemaphore
);
70 uint8_t *SHMReader::getZone(uint32_t id
) {
71 if(id
< m_zoneList
.size() && m_zoneList
[id
] != NULL
) {
72 return m_zoneList
[id
];
76 static_cast<uint8_t *>(mapRegion(m_header
->zonePageOffset
+ id
*m_header
->zoneSize
, m_header
->zoneSize
));
78 m_zoneList
.resize(id
+1);
79 m_zoneList
[id
] = zone
;
84 void *SHMReader::mapRegion(uint32_t start
, uint32_t size
) {
86 if(fstat(m_fd
, &s
) != 0) {
87 Message(Fatal
, "Could not fstat shared memory to determine size.");
90 if(s
.st_size
> (start
+size
) * AesalonPageSize
) {
91 if(m_header
) sem_wait(&m_header
->resizeSemaphore
);
93 Message(Debug
, "Resizing SHM to " << start
+size
<< " pages.");
94 if(ftruncate(m_fd
, (start
+size
) * AesalonPageSize
) != 0) {
95 Message(Fatal
, "Could not resize shared memory.");
98 if(m_header
) sem_post(&m_header
->resizeSemaphore
);
102 mmap(NULL
, size
* AesalonPageSize
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, m_fd
, start
* AesalonPageSize
);
107 void SHMReader::unmapRegion(void *data
, uint32_t size
) {
108 munmap(data
, size
*AesalonPageSize
);
111 void SHMReader::setupHeader() {
112 m_header
= reinterpret_cast<SHM::Header
*>(mapRegion(0, 1));
114 sem_init(&m_header
->packetSemaphore
, 1, 0);
115 sem_init(&m_header
->resizeSemaphore
, 1, 1);
118 void SHMReader::setupConfiguration() {
119 char *configurationData
= static_cast<char *>(mapRegion(1, 1));
120 m_header
->configDataSize
= 1;
122 std::vector
<Config::Vault::KeyPair
> configItems
;
123 Coordinator::instance()->vault()->match("*", configItems
);
127 for(std::vector
<Config::Vault::KeyPair
>::iterator i
= configItems
.begin(); i
!= configItems
.end(); ++i
) {
128 /* Ignore all internal items. */
129 if(i
->first
.find("::") == 0) continue;
131 while((offset
+ i
->first
.length() + i
->second
.length() + 2) > m_header
->configDataSize
*AesalonPageSize
) {
132 unmapRegion(configurationData
, m_header
->configDataSize
);
133 m_header
->configDataSize
++;
134 configurationData
= static_cast<char *>(mapRegion(1, m_header
->configDataSize
));
136 memcpy(&configurationData
[offset
], i
->first
.c_str(), i
->first
.length()+1);
137 offset
+= i
->first
.length()+1;
138 memcpy(&configurationData
[offset
], i
->second
.c_str(), i
->second
.length()+1);
139 offset
+= i
->second
.length()+1;
143 void SHMReader::setupZones() {
144 m_header
->zoneSize
= Util::StringTo
<uint32_t>(Coordinator::instance()->vault()->get("zoneSize"));
145 m_header
->zoneUsagePages
= Util::StringTo
<uint32_t>(Coordinator::instance()->vault()->get("zoneUsePages"));
146 m_header
->zoneCount
= 0;
149 } // namespace Monitor