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
15zx_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(fbl::move(holder0)));
25    if (!ac.check())
26        return ZX_ERR_NO_MEMORY;
27
28    auto disp1 = fbl::AdoptRef(new (&ac) EventPairDispatcher(fbl::move(holder1)));
29    if (!ac.check())
30        return ZX_ERR_NO_MEMORY;
31
32    disp0->Init(disp1);
33    disp1->Init(disp0);
34
35    *rights = ZX_DEFAULT_EVENTPAIR_RIGHTS;
36    *dispatcher0 = fbl::move(disp0);
37    *dispatcher1 = fbl::move(disp1);
38
39    return ZX_OK;
40}
41
42EventPairDispatcher::~EventPairDispatcher() {}
43
44void EventPairDispatcher::on_zero_handles_locked() {
45    canary_.Assert();
46}
47
48void EventPairDispatcher::OnPeerZeroHandlesLocked() {
49    InvalidateCookieLocked(get_cookie_jar());
50    UpdateStateLocked(0u, ZX_EVENTPAIR_PEER_CLOSED);
51}
52
53EventPairDispatcher::EventPairDispatcher(fbl::RefPtr<PeerHolder<EventPairDispatcher>> holder)
54    : PeeredDispatcher(fbl::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.
59void 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_ = fbl::move(other);
65}
66