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/event_pair_dispatcher.h>
8 
9 #include <assert.h>
10 #include <err.h>
11 
12 #include <zircon/rights.h>
13 #include <fbl/alloc_checker.h>
14 
Create(fbl::RefPtr<Dispatcher> * dispatcher0,fbl::RefPtr<Dispatcher> * dispatcher1,zx_rights_t * rights)15 zx_status_t EventPairDispatcher::Create(fbl::RefPtr<Dispatcher>* dispatcher0,
16                                         fbl::RefPtr<Dispatcher>* dispatcher1,
17                                         zx_rights_t* rights) {
18     fbl::AllocChecker ac;
19     auto holder0 = fbl::AdoptRef(new (&ac) PeerHolder<EventPairDispatcher>());
20     if (!ac.check())
21         return ZX_ERR_NO_MEMORY;
22     auto holder1 = holder0;
23 
24     auto disp0 = fbl::AdoptRef(new (&ac) EventPairDispatcher(ktl::move(holder0)));
25     if (!ac.check())
26         return ZX_ERR_NO_MEMORY;
27 
28     auto disp1 = fbl::AdoptRef(new (&ac) EventPairDispatcher(ktl::move(holder1)));
29     if (!ac.check())
30         return ZX_ERR_NO_MEMORY;
31 
32     disp0->Init(disp1);
33     disp1->Init(disp0);
34 
35     *rights = default_rights();
36     *dispatcher0 = ktl::move(disp0);
37     *dispatcher1 = ktl::move(disp1);
38 
39     return ZX_OK;
40 }
41 
~EventPairDispatcher()42 EventPairDispatcher::~EventPairDispatcher() {}
43 
on_zero_handles_locked()44 void EventPairDispatcher::on_zero_handles_locked() {
45     canary_.Assert();
46 }
47 
OnPeerZeroHandlesLocked()48 void EventPairDispatcher::OnPeerZeroHandlesLocked() {
49     InvalidateCookieLocked(get_cookie_jar());
50     UpdateStateLocked(0u, ZX_EVENTPAIR_PEER_CLOSED);
51 }
52 
EventPairDispatcher(fbl::RefPtr<PeerHolder<EventPairDispatcher>> holder)53 EventPairDispatcher::EventPairDispatcher(fbl::RefPtr<PeerHolder<EventPairDispatcher>> holder)
54     : PeeredDispatcher(ktl::move(holder))
55 {}
56 
57 // This is called before either EventPairDispatcher is accessible from threads other than the one
58 // initializing the event pair, so it does not need locking.
Init(fbl::RefPtr<EventPairDispatcher> other)59 void EventPairDispatcher::Init(fbl::RefPtr<EventPairDispatcher> other) TA_NO_THREAD_SAFETY_ANALYSIS {
60     DEBUG_ASSERT(other);
61     // No need to take |lock_| here.
62     DEBUG_ASSERT(!peer_);
63     peer_koid_ = other->get_koid();
64     peer_ = ktl::move(other);
65 }
66