11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* $NetBSD: ev_streams.c,v 1.2 2004/05/20 19:52:31 christos Exp $ */ 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1996-1999 by Internet Software Consortium 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this software for any 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * purpose with or without fee is hereby granted, provided that the above 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * copyright notice and this permission notice appear in all copies. 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* ev_streams.c - implement asynch stream file IO for the eventlib 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * vix 04mar96 [initial] 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/cdefs.h> 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if !defined(LINT) && !defined(CODECENTER) && !defined(lint) 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef notdef 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char rcsid[] = "Id: ev_streams.c,v 1.2.206.2 2004/03/17 00:29:51 marka Exp"; 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__RCSID("$NetBSD: ev_streams.c,v 1.2 2004/05/20 19:52:31 christos Exp $"); 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h> 341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/uio.h> 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h> 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <isc/eventlib.h> 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "eventlib_p.h" 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef _LIBC 421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int copyvec(evStream *str, const struct iovec *iov, int iocnt); 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void consume(evStream *str, size_t bytes); 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void done(evContext opaqueCtx, evStream *str); 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void writable(evContext opaqueCtx, void *uap, int fd, int evmask); 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void readable(evContext opaqueCtx, void *uap, int fd, int evmask); 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct iovec 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectevConsIovec(void *buf, size_t cnt) { 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct iovec ret; 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&ret, 0xf5, sizeof ret); 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ret.iov_base = buf; 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ret.iov_len = cnt; 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (ret); 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef _LIBC 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectevWrite(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt, 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evStreamFunc func, void *uap, evStreamID *id) 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evContext_p *ctx = opaqueCtx.opaque; 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evStream *new; 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int save; 671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project OKNEW(new); 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->func = func; 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->uap = uap; 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->fd = fd; 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->flags = 0; 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (evSelectFD(opaqueCtx, fd, EV_WRITE, writable, new, &new->file) < 0) 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (copyvec(new, iov, iocnt) < 0) 761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->prevDone = NULL; 781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->nextDone = NULL; 791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ctx->streams != NULL) 801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ctx->streams->prev = new; 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->prev = NULL; 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->next = ctx->streams; 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ctx->streams = new; 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (id != NULL) 851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project id->opaque = new; 861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free: 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project save = errno; 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project FREE(new); 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = save; 911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectevRead(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt, 961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evStreamFunc func, void *uap, evStreamID *id) 971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evContext_p *ctx = opaqueCtx.opaque; 991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evStream *new; 1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int save; 1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project OKNEW(new); 1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->func = func; 1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->uap = uap; 1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->fd = fd; 1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->flags = 0; 1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (evSelectFD(opaqueCtx, fd, EV_READ, readable, new, &new->file) < 0) 1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (copyvec(new, iov, iocnt) < 0) 1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->prevDone = NULL; 1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->nextDone = NULL; 1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ctx->streams != NULL) 1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ctx->streams->prev = new; 1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->prev = NULL; 1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project new->next = ctx->streams; 1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ctx->streams = new; 1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (id) 1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project id->opaque = new; 1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free: 1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project save = errno; 1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project FREE(new); 1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = save; 1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectevTimeRW(evContext opaqueCtx, evStreamID id, evTimerID timer) /*ARGSUSED*/ { 1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evStream *str = id.opaque; 1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project UNUSED(opaqueCtx); 1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->timer = timer; 1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->flags |= EV_STR_TIMEROK; 1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectevUntimeRW(evContext opaqueCtx, evStreamID id) /*ARGSUSED*/ { 1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evStream *str = id.opaque; 1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project UNUSED(opaqueCtx); 1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->flags &= ~EV_STR_TIMEROK; 1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectevCancelRW(evContext opaqueCtx, evStreamID id) { 1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evContext_p *ctx = opaqueCtx.opaque; 1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evStream *old = id.opaque; 1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The streams list is doubly threaded. First, there's ctx->streams 1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * that's used by evDestroy() to find and cancel all streams. Second, 1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * there's ctx->strDone (head) and ctx->strLast (tail) which thread 1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * through the potentially smaller number of "IO completed" streams, 1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * used in evGetNext() to avoid scanning the entire list. 1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Unlink from ctx->streams. */ 1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (old->prev != NULL) 1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project old->prev->next = old->next; 1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ctx->streams = old->next; 1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (old->next != NULL) 1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project old->next->prev = old->prev; 1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If 'old' is on the ctx->strDone list, remove it. Update 1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ctx->strLast if necessary. 1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (old->prevDone == NULL && old->nextDone == NULL) { 1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Either 'old' is the only item on the done list, or it's 1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * not on the done list. If the former, then we unlink it 1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * from the list. If the latter, we leave the list alone. 1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ctx->strDone == old) { 1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ctx->strDone = NULL; 1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ctx->strLast = NULL; 1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (old->prevDone != NULL) 1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project old->prevDone->nextDone = old->nextDone; 1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ctx->strDone = old->nextDone; 1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (old->nextDone != NULL) 1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project old->nextDone->prevDone = old->prevDone; 1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ctx->strLast = old->prevDone; 1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Deallocate the stream. */ 1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (old->file.opaque) 1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evDeselectFD(opaqueCtx, old->file); 1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memput(old->iovOrig, sizeof (struct iovec) * old->iovOrigCount); 1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project FREE(old); 2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Copy a scatter/gather vector and initialize a stream handler's IO. */ 2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectcopyvec(evStream *str, const struct iovec *iov, int iocnt) { 2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int i; 2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->iovOrig = (struct iovec *)memget(sizeof(struct iovec) * iocnt); 2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (str->iovOrig == NULL) { 2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = ENOMEM; 2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->ioTotal = 0; 2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (i = 0; i < iocnt; i++) { 2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->iovOrig[i] = iov[i]; 2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->ioTotal += iov[i].iov_len; 2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->iovOrigCount = iocnt; 2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->iovCur = str->iovOrig; 2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->iovCurCount = str->iovOrigCount; 2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->ioDone = 0; 2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Pull off or truncate lead iovec(s). */ 2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void 2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectconsume(evStream *str, size_t bytes) { 2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (bytes > 0U) { 2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (bytes < (size_t)str->iovCur->iov_len) { 2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->iovCur->iov_len -= bytes; 2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->iovCur->iov_base = (void *) 2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ((u_char *)str->iovCur->iov_base + bytes); 2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->ioDone += bytes; 2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bytes = 0; 2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bytes -= str->iovCur->iov_len; 2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->ioDone += str->iovCur->iov_len; 2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->iovCur++; 2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->iovCurCount--; 2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Add a stream to Done list and deselect the FD. */ 2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void 2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdone(evContext opaqueCtx, evStream *str) { 2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evContext_p *ctx = opaqueCtx.opaque; 2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ctx->strLast != NULL) { 2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->prevDone = ctx->strLast; 2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ctx->strLast->nextDone = str; 2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ctx->strLast = str; 2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project INSIST(ctx->strDone == NULL); 2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ctx->strDone = ctx->strLast = str; 2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evDeselectFD(opaqueCtx, str->file); 2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->file.opaque = NULL; 2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* evDrop() will call evCancelRW() on us. */ 2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Dribble out some bytes on the stream. (Called by evDispatch().) */ 2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void 2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectwritable(evContext opaqueCtx, void *uap, int fd, int evmask) { 2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evStream *str = uap; 2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int bytes; 2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project UNUSED(evmask); 2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bytes = writev(fd, str->iovCur, str->iovCurCount); 2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (bytes > 0) { 2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((str->flags & EV_STR_TIMEROK) != 0) 2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evTouchIdleTimer(opaqueCtx, str->timer); 2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project consume(str, bytes); 2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (bytes < 0 && errno != EINTR) { 2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->ioDone = -1; 2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->ioErrno = errno; 2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (str->ioDone == -1 || str->ioDone == str->ioTotal) 2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project done(opaqueCtx, str); 2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Scoop up some bytes from the stream. (Called by evDispatch().) */ 2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void 2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectreadable(evContext opaqueCtx, void *uap, int fd, int evmask) { 2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evStream *str = uap; 2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int bytes; 2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project UNUSED(evmask); 2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bytes = readv(fd, str->iovCur, str->iovCurCount); 2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (bytes > 0) { 2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((str->flags & EV_STR_TIMEROK) != 0) 2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project evTouchIdleTimer(opaqueCtx, str->timer); 2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project consume(str, bytes); 2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (bytes == 0) 3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->ioDone = 0; 3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else { 3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (errno != EINTR) { 3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->ioDone = -1; 3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project str->ioErrno = errno; 3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (str->ioDone <= 0 || str->ioDone == str->ioTotal) 3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project done(opaqueCtx, str); 3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 312