4 * Fault observer that attaches a magic event buffer
5 * (see measurements.h) to each replica and dumps the replicas'
6 * event buffers after the program terminates.
8 * (c) 2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
9 * economic rights: Technische Universität Dresden (Germany)
11 * This file is part of TUD:OS and distributed under the terms of the
12 * GNU General Public License 2.
13 * Please see the COPYING-GPL-2 file for details.
16 #include "observers.h"
17 #include "../configuration"
22 #include <l4/plr/uu.h>
23 #include <l4/plr/measurements.h>
26 extern InstanceManager *_the_instance_manager;
30 void *to_thread(void *arg)
32 Romain::ReplicaLogObserver *o = reinterpret_cast<Romain::ReplicaLogObserver *>(arg);
33 INFO() << "Waiting for " << o->timeout() << " seconds.";
39 l4_debugger_set_object_name(pthread_getl4cap(pthread_self()), "romain::timout");
41 Measurements::GenericEvent* ev = Romain::_the_instance_manager->logbuf()->next();
42 ev->header.tsc = Romain::_the_instance_manager->logbuf()->getTime(Romain::Log::logLocalTSC);
43 ev->header.vcpu = (l4_uint32_t)0xDEADBEEF;
44 ev->header.type = Measurements::Thread_stop;
46 Romain::_the_instance_manager->show_stats();
50 enter_kdebug("abort after logdump");
56 Romain::ReplicaLogObserver::ReplicaLogObserver()
59 _timeout = ConfigIntValue("general:logtimeout");
61 int err = pthread_create(&_to_thread, NULL, to_thread, this);
62 _check(err != 0, "error creating timeout thread");
64 for (unsigned i = 0; i < Romain::MAX_REPLICAS; ++i) {
65 buffers[i].local_addr = 0;
71 Romain::ReplicaLogObserver::map_eventlog(Romain::App_instance *i, int logsizeMB)
73 int size = logsizeMB << 20;
75 l4_addr_t local_map_addr = buffers[i->id()].local_addr;
76 l4_addr_t remote_map_addr = Romain::REPLICA_LOG_ADDRESS;
78 /* 1. map the TSC shared page read-only */
79 INFO() << "shared tsc @ " << Romain::_the_instance_manager->logbuf()->timestamp;
80 i->map_aligned(reinterpret_cast<l4_addr_t>(Romain::_the_instance_manager->logbuf()->timestamp),
81 Romain::REPLICA_TSC_ADDRESS, L4_PAGESHIFT, L4_FPAGE_RO);
83 /* Now initialize the shared event buffer */
84 Measurements::EventBuf* buf = reinterpret_cast<Measurements::EventBuf*>(buffers[i->id()].local_addr);
86 buf->sharedTSC = true;
87 buf->set_buffer((unsigned char*)remote_map_addr + sizeof(Measurements::GenericEvent), (logsizeMB << 20) - sizeof(Measurements::GenericEvent));
88 INFO() << buf->index << " " << buf->size << std::endl;
94 if (size >= (4 << 20)) { // map 4 MB page
95 sz = L4_SUPERPAGESIZE;
96 shift = L4_SUPERPAGESHIFT;
97 } else { // map 4 kB page
102 i->map_aligned(local_map_addr, remote_map_addr, shift, L4_FPAGE_RW);
104 local_map_addr += sz;
105 remote_map_addr += sz;
109 INFO() << "Mapped to replica. Used " << mapops << " map() operations";
113 void Romain::ReplicaLogObserver::startup_notify(Romain::App_instance *i,
114 Romain::App_thread *t,
115 Romain::Thread_group *tg,
116 Romain::App_model *a)
118 static bool logregion_reserved = false;
120 int logMB = ConfigIntValue("general:replicalogsize");
121 if (logMB == -1) { // use general logbuf size if no specific size was set
122 logMB = ConfigIntValue("general:logbuf");
125 INFO() << "Replica log size: " << logMB << " MB";
127 /* Reserve the area at the replicas' RM. We map this buffer without going through
128 the official channels. */
129 if (!logregion_reserved) {
130 a->rm()->attach_area(Romain::REPLICA_LOG_ADDRESS, logMB << 20, 0, L4_SUPERPAGESHIFT);
131 logregion_reserved = true;
134 L4::Cap<L4Re::Dataspace> mem;
135 buffers[i->id()].local_addr = Romain::Region_map::allocate_and_attach(&mem, logMB << 20, 0, L4_SUPERPAGESHIFT);
136 INFO() << "Buffer for instance " << i->id() << " @ " << std::hex << buffers[i->id()].local_addr;
137 l4_touch_rw(reinterpret_cast<void*>(buffers[i->id()].local_addr), logMB << 20);
139 map_eventlog(i, logMB);
141 //enter_kdebug("LogObserver::startup");
145 Romain::Observer::ObserverReturnVal
146 Romain::ReplicaLogObserver::notify(Romain::App_instance *i,
147 Romain::App_thread *t,
148 Romain::Thread_group *tg,
149 Romain::App_model *a)
151 /* We don't handle any events. */
152 return Romain::Observer::Ignored;
157 Romain::ReplicaLogObserver::dump_eventlog(unsigned id) const
159 // prevent a potential timeout thread from dumping in parallel
160 const_cast<Romain::ReplicaLogObserver*>(this)->_cancel = true;
162 INFO() << "Dumping ... " << id;
164 Measurements::EventBuf *buf = reinterpret_cast<Measurements::EventBuf*>(buffers[id].local_addr);
165 INFO() << " event buffer @ " << std::hex << buf;
168 snprintf(filename, 32, "replica%d.log", id);
170 INFO() << "file: " << filename;
172 unsigned oldest = buf->oldest();
174 INFO() << "oldest: " << oldest;
176 l4_umword_t dump_start, dump_size;
179 dump_size = buf->index * sizeof(Measurements::GenericEvent);
181 dump_start = oldest * sizeof(Measurements::GenericEvent);
182 dump_size = buf->size * sizeof(Measurements::GenericEvent);
185 /* buf addr is relocated in replica AS -> need to retransform */
186 char *bufaddr = ((l4_addr_t)buf->buffer - Romain::REPLICA_LOG_ADDRESS) + (char*)buf;
188 INFO() << "file: " << filename << " start " << std::hex << dump_start << " size " << dump_size;
189 uu_dumpz_ringbuffer(filename, bufaddr,
190 buf->size * sizeof(Measurements::GenericEvent),
191 dump_start, dump_size);
196 Romain::ReplicaLogObserver::status() const
198 for (unsigned i = 0; i < Romain::MAX_REPLICAS; ++i) {
199 if (buffers[i].local_addr != 0) {
203 //enter_kdebug("LogObserver::status");