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 
Create(uint32_t flags,fbl::RefPtr<Dispatcher> * dispatcher,zx_rights_t * rights)17 zx_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 = default_rights();
28     *dispatcher = fbl::AdoptRef<Dispatcher>(disp);
29     return ZX_OK;
30 }
31 
LogDispatcher(uint32_t flags)32 LogDispatcher::LogDispatcher(uint32_t flags)
33     : SoloDispatcher(ZX_LOG_WRITABLE), flags_(flags) {
34 }
35 
~LogDispatcher()36 LogDispatcher::~LogDispatcher() {
37     if (flags_ & ZX_LOG_FLAG_READABLE) {
38         dlog_reader_destroy(&reader_);
39     }
40 }
41 
Signal()42 void LogDispatcher::Signal() {
43     canary_.Assert();
44 
45     UpdateState(0, ZX_CHANNEL_READABLE);
46 }
47 
48 // static
Notify(void * cookie)49 void LogDispatcher::Notify(void* cookie) {
50     LogDispatcher* log = static_cast<LogDispatcher*>(cookie);
51     log->Signal();
52 }
53 
Write(uint32_t flags,const void * ptr,size_t len)54 zx_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 
Read(uint32_t flags,void * ptr,size_t len,size_t * actual)60 zx_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