1 // Copyright 2018 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 <lib/fdio/util.h>
6 #include <lib/zxio/null.h>
7 #include <lib/zxio/ops.h>
8 #include <string.h>
9 #include <zircon/compiler.h>
10 #include <zircon/syscalls.h>
11
12 typedef struct fdio_waitable {
13 zxio_t io;
14
15 // arbitrary handle
16 zx_handle_t handle;
17
18 // signals that cause ZXIO_READABLE
19 zx_signals_t readable;
20
21 // signals that cause ZXIO_WRITABLE
22 zx_signals_t writable;
23
24 // if true, don't close handle on close() op
25 bool shared_handle;
26 } fdio_waitable_t;
27
28 static_assert(sizeof(fdio_waitable_t) <= sizeof(zxio_storage_t),
29 "fdio_waitable_t must fit inside zxio_storage_t.");
30
fdio_waitable_close(zxio_t * io)31 static zx_status_t fdio_waitable_close(zxio_t* io) {
32 fdio_waitable_t* waitable = reinterpret_cast<fdio_waitable_t*>(io);
33 if (!waitable->shared_handle) {
34 zx_handle_t handle = waitable->handle;
35 waitable->handle = ZX_HANDLE_INVALID;
36 zx_handle_close(handle);
37 }
38 return ZX_OK;
39 }
40
fdio_waitable_wait_begin(zxio_t * io,zxio_signals_t zxio_signals,zx_handle_t * out_handle,zx_signals_t * out_zx_signals)41 static void fdio_waitable_wait_begin(zxio_t* io, zxio_signals_t zxio_signals,
42 zx_handle_t* out_handle,
43 zx_signals_t* out_zx_signals) {
44 fdio_waitable_t* waitable = reinterpret_cast<fdio_waitable_t*>(io);
45 zx_signals_t zx_signals = ZX_SIGNAL_NONE;
46 if (zxio_signals & ZXIO_READABLE) {
47 zx_signals |= waitable->readable;
48 }
49 if (zxio_signals & ZXIO_WRITABLE) {
50 zx_signals |= waitable->writable;
51 }
52 *out_handle = waitable->handle;
53 *out_zx_signals = zx_signals;
54 }
55
fdio_waitable_wait_end(zxio_t * io,zx_signals_t zx_signals,zxio_signals_t * out_zxio_signals)56 static void fdio_waitable_wait_end(zxio_t* io, zx_signals_t zx_signals,
57 zxio_signals_t* out_zxio_signals) {
58 fdio_waitable_t* waitable = reinterpret_cast<fdio_waitable_t*>(io);
59 zxio_signals_t zxio_signals = ZXIO_SIGNAL_NONE;
60 if (zx_signals & waitable->readable) {
61 zxio_signals |= ZXIO_READABLE;
62 }
63 if (zx_signals & waitable->writable) {
64 zxio_signals |= ZXIO_WRITABLE;
65 }
66 *out_zxio_signals = zxio_signals;
67 }
68
__anon8cb3e9c50102() 69 static constexpr zxio_ops_t fdio_waitable_ops = []() {
70 zxio_ops_t ops = zxio_default_ops;
71 ops.close = fdio_waitable_close;
72 ops.wait_begin = fdio_waitable_wait_begin;
73 ops.wait_end = fdio_waitable_wait_end;
74 return ops;
75 }();
76
fdio_waitable_init(zxio_storage_t * storage,zx_handle_t handle,zx_signals_t readable,zx_signals_t writable,bool shared_handle)77 static void fdio_waitable_init(zxio_storage_t* storage,
78 zx_handle_t handle,
79 zx_signals_t readable,
80 zx_signals_t writable,
81 bool shared_handle) {
82 fdio_waitable_t* waitable = reinterpret_cast<fdio_waitable_t*>(storage);
83 zxio_init(&waitable->io, &fdio_waitable_ops);
84 waitable->handle = handle;
85 waitable->readable = readable;
86 waitable->writable = writable;
87 waitable->shared_handle = shared_handle;
88 }
89
90 __BEGIN_CDECLS
91
fdio_waitable_create(zx_handle_t handle,zx_signals_t readable,zx_signals_t writable,bool shared_handle)92 fdio_t* fdio_waitable_create(zx_handle_t handle, zx_signals_t readable,
93 zx_signals_t writable, bool shared_handle) {
94 zxio_storage_t* storage = nullptr;
95 fdio_t* io = fdio_zxio_create(&storage);
96 if (io == nullptr) {
97 if (!shared_handle) {
98 zx_handle_close(handle);
99 }
100 return nullptr;
101 }
102 fdio_waitable_init(storage, handle, readable, writable, shared_handle);
103 return io;
104 }
105
106 __END_CDECLS
107