1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <trace/observer.h> 6 7#include <zircon/assert.h> 8 9namespace trace { 10 11TraceObserver::TraceObserver() { 12} 13 14TraceObserver::~TraceObserver() { 15 Stop(); 16} 17 18void TraceObserver::Start(async_dispatcher_t* dispatcher, fbl::Closure callback) { 19 ZX_DEBUG_ASSERT(dispatcher); 20 ZX_DEBUG_ASSERT(callback); 21 22 Stop(); 23 callback_ = fbl::move(callback); 24 25 zx_status_t status = zx::event::create(0u, &event_); 26 ZX_ASSERT(status == ZX_OK); 27 trace_register_observer(event_.get()); 28 29 wait_.set_object(event_.get()); 30 wait_.set_trigger(ZX_EVENT_SIGNALED); 31 BeginWait(dispatcher); 32} 33 34void TraceObserver::Stop() { 35 wait_.Cancel(); 36 callback_ = nullptr; 37 38 if (event_) { 39 trace_unregister_observer(event_.get()); 40 event_.reset(); 41 } 42} 43 44void TraceObserver::Handle(async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status, 45 const zx_packet_signal_t* signal) { 46 if (status != ZX_OK) { 47 Stop(); 48 return; 49 } 50 51 ZX_DEBUG_ASSERT(status == ZX_OK); 52 ZX_DEBUG_ASSERT(signal->observed & ZX_EVENT_SIGNALED); 53 54 // Clear the signal otherwise we'll keep getting called. 55 // Clear the signal *before* invoking the callback because there's no 56 // synchronization between the engine and the observers, thus it's possible 57 // that an observer could get back to back notifications. 58 event_.signal(ZX_EVENT_SIGNALED, 0u); 59 60 // Invoke the callback. 61 callback_(); 62 63 // Tell engine we're done. 64 trace_notify_observer_updated(event_.get()); 65 66 // Wait again! 67 BeginWait(dispatcher); 68} 69 70void TraceObserver::BeginWait(async_dispatcher_t* dispatcher) { 71 zx_status_t status = wait_.Begin(dispatcher); 72 if (status != ZX_OK) 73 Stop(); 74} 75 76} // namespace trace 77