// Copyright 2017 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include #include #include #include #include #include #include #if TRACE_PORT_API #define zprintf(fmt...) printf(fmt) #else #define zprintf(fmt...) do {} while (0) #endif zx_status_t port_init(port_t* port) { zx_status_t r = zx_port_create(0, &port->handle); zprintf("port_init(%p) port=%x\n", port, port->handle); return r; } zx_status_t port_wait(port_t* port, port_handler_t* ph) { zprintf("port_wait(%p, %p) obj=%x port=%x\n", port, ph, ph->handle, port->handle); return zx_object_wait_async(ph->handle, port->handle, (uint64_t)(uintptr_t)ph, ph->waitfor, ZX_WAIT_ASYNC_ONCE); } zx_status_t port_wait_repeating(port_t* port, port_handler_t* ph) { zprintf("port_wait_repeating(%p, %p) obj=%x port=%x\n", port, ph, ph->handle, port->handle); return zx_object_wait_async(ph->handle, port->handle, (uint64_t)(uintptr_t)ph, ph->waitfor, ZX_WAIT_ASYNC_REPEATING); } zx_status_t port_cancel(port_t* port, port_handler_t* ph) { zx_status_t r = zx_port_cancel(port->handle, ph->handle, (uint64_t)(uintptr_t)ph); zprintf("port_cancel(%p, %p) obj=%x port=%x: r = %d\n", port, ph, ph->handle, port->handle, r); return r; } zx_status_t port_queue(port_t* port, port_handler_t* ph, uint32_t evt) { zx_port_packet_t pkt; pkt.key = (uintptr_t)ph; pkt.user.u32[0] = evt; zx_status_t r = zx_port_queue(port->handle, &pkt); zprintf("port_queue(%p, %p) obj=%x port=%x evt=%x: r=%d\n", port, ph, ph->handle, port->handle, r, evt); return r; } zx_status_t port_dispatch(port_t* port, zx_time_t deadline, bool once) { for (;;) { zx_port_packet_t pkt; zx_status_t r; if ((r = zx_port_wait(port->handle, deadline, &pkt)) != ZX_OK) { if (r != ZX_ERR_TIMED_OUT) { printf("port_dispatch: port wait failed %d\n", r); } return r; } port_handler_t* ph = (void*) (uintptr_t) pkt.key; if (pkt.type == ZX_PKT_TYPE_USER) { zprintf("port_dispatch(%p) port=%x ph=%p func=%p: evt=%x\n", port, port->handle, ph, ph->func, pkt.user.u32[0]); ph->func(ph, 0, pkt.user.u32[0]); } else { zprintf("port_dispatch(%p) port=%x ph=%p func=%p: signals=%x\n", port, port->handle, ph, ph->func, pkt.signal.observed); if (ph->func(ph, pkt.signal.observed, 0) == ZX_OK) { port_wait(port, ph); } } if (once) { return ZX_OK; } } } static zx_status_t port_fd_handler_func(port_handler_t* ph, zx_signals_t signals, uint32_t evt) { port_fd_handler_t* fh = (void*) ph; if (evt) { return fh->func(fh, 0, evt); } else { uint32_t pollevt; __fdio_wait_end(fh->fdio_context, signals, &pollevt); return fh->func(fh, pollevt, 0); } } zx_status_t port_fd_handler_init(port_fd_handler_t* fh, int fd, unsigned pollevt) { fdio_t* io = __fdio_fd_to_io(fd); if (io == NULL) { return ZX_ERR_INVALID_ARGS; } __fdio_wait_begin(io, pollevt, &fh->ph.handle, &fh->ph.waitfor); fh->ph.func = port_fd_handler_func; fh->fdio_context = io; return ZX_OK; } void port_fd_handler_done(port_fd_handler_t* fh) { __fdio_release(fh->fdio_context); fh->fdio_context = NULL; fh->ph.handle = ZX_HANDLE_INVALID; fh->ph.waitfor = 0; }