1// Copyright 2016 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7#include <object/log_dispatcher.h>
8
9#include <zircon/rights.h>
10#include <zircon/syscalls/log.h>
11
12#include <err.h>
13
14#include <fbl/alloc_checker.h>
15#include <fbl/auto_lock.h>
16
17zx_status_t LogDispatcher::Create(uint32_t flags, fbl::RefPtr<Dispatcher>* dispatcher,
18                                  zx_rights_t* rights) {
19    fbl::AllocChecker ac;
20    auto disp = new (&ac) LogDispatcher(flags);
21    if (!ac.check()) return ZX_ERR_NO_MEMORY;
22
23    if (flags & ZX_LOG_FLAG_READABLE) {
24        dlog_reader_init(&disp->reader_, &LogDispatcher::Notify, disp);
25    }
26
27    *rights = ZX_DEFAULT_LOG_RIGHTS;
28    *dispatcher = fbl::AdoptRef<Dispatcher>(disp);
29    return ZX_OK;
30}
31
32LogDispatcher::LogDispatcher(uint32_t flags)
33    : SoloDispatcher(ZX_LOG_WRITABLE), flags_(flags) {
34}
35
36LogDispatcher::~LogDispatcher() {
37    if (flags_ & ZX_LOG_FLAG_READABLE) {
38        dlog_reader_destroy(&reader_);
39    }
40}
41
42void LogDispatcher::Signal() {
43    canary_.Assert();
44
45    UpdateState(0, ZX_CHANNEL_READABLE);
46}
47
48// static
49void LogDispatcher::Notify(void* cookie) {
50    LogDispatcher* log = static_cast<LogDispatcher*>(cookie);
51    log->Signal();
52}
53
54zx_status_t LogDispatcher::Write(uint32_t flags, const void* ptr, size_t len) {
55    canary_.Assert();
56
57    return dlog_write(flags_ | flags, ptr, len);
58}
59
60zx_status_t LogDispatcher::Read(uint32_t flags, void* ptr, size_t len, size_t* actual) {
61    canary_.Assert();
62
63    if (!(flags_ & ZX_LOG_FLAG_READABLE))
64        return ZX_ERR_BAD_STATE;
65
66    Guard<fbl::Mutex> guard{get_lock()};
67
68    zx_status_t status = dlog_read(&reader_, 0, ptr, len, actual);
69    if (status == ZX_ERR_SHOULD_WAIT) {
70        UpdateStateLocked(ZX_CHANNEL_READABLE, 0);
71    }
72
73    return status;
74}
75