UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2013 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <atomic.h> 32 33 #include "../util/io.h" 34 35 #include "event_solaris.h" 36 37 EVHandler* evhandler_create(EventHandlerConfig *cfg) { 38 EVHandler *ev = malloc(sizeof(EVHandler)); 39 ev->current = 0; 40 ev->instances = calloc(cfg->nthreads, sizeof(void*)); 41 ev->numins = cfg->nthreads; 42 43 for(int i=0;i<cfg->nthreads;i++) { 44 EventHandler *handler = malloc(sizeof(EventHandler)); 45 ev->instances[i] = handler; 46 47 handler->port = port_create(); 48 if(handler->port == 0) { 49 // TODO: error 50 return NULL; 51 } 52 53 SYS_THREAD t = systhread_start( 54 0, 55 0, 56 (thrstartfunc)ev_handle_events, 57 handler); 58 systhread_detach(t); 59 } 60 61 return ev; 62 } 63 64 void ev_handle_events(EventHandler *ev) { 65 port_event_t events[64]; 66 struct timespec timeout; 67 timeout.tv_nsec = 0; 68 timeout.tv_sec = 600; 69 70 for(;;) { 71 // wait for events 72 uint_t nev = 1; 73 int ret = port_getn(ev->port, events, 64, &nev, &timeout); 74 if(ret == -1) { 75 // TODO: check for error 76 perror("port_getn"); 77 continue; 78 } 79 80 for(int i=0;i<nev;i++) { 81 Event *event = events[i].portev_user; 82 if(events[i].portev_source == PORT_SOURCE_AIO) { 83 aiocb_t *aiocb = (aiocb_t*)events[i].portev_object; 84 if(event) { 85 aiocb_s *aio = (aiocb_s*)event->object; 86 aio->result = aiocb->aio_resultp.aio_return; 87 aio->result_errno = aiocb->aio_resultp.aio_errno; 88 if(event->fn) { 89 if(!event->fn(ev, event) && event->finish) { 90 event->finish(ev, event); 91 } 92 } 93 } 94 free(aiocb); 95 } else { 96 if(event->fn) { 97 if(event->fn(ev, event)) { 98 /* 99 * on solaris we have to reassociate the fd after 100 * each event 101 * we do this if the event function returns 1 102 */ 103 if(port_associate( 104 ev->port, 105 PORT_SOURCE_FD, 106 (uintptr_t)event->object, 107 ev_convert2sys_events(event->events), 108 event)) 109 { 110 perror("port_associate"); 111 } 112 } else if(event->finish) { 113 event->finish(ev, event); 114 } 115 } 116 } 117 } 118 } 119 } 120 121 int ev_convert2sys_events(int events) { 122 int e = 0; 123 if((events & EVENT_POLLIN) == EVENT_POLLIN) { 124 e |= POLLIN; 125 } 126 if((events & EVENT_POLLOUT) == EVENT_POLLOUT) { 127 e |= POLLOUT; 128 } 129 return e; 130 } 131 132 133 int ev_pollin(EventHandler *h, int fd, Event *event) { 134 event->object = (intptr_t)fd; 135 event->events = EVENT_POLLIN; 136 return port_associate( 137 h->port, 138 PORT_SOURCE_FD, 139 (uintptr_t)fd, 140 POLLIN, 141 event); 142 } 143 144 int ev_pollout(EventHandler *h, int fd, Event *event) { 145 event->object = (intptr_t)fd; 146 event->events = EVENT_POLLOUT; 147 return port_associate( 148 h->port, 149 PORT_SOURCE_FD, 150 (uintptr_t)fd, 151 POLLOUT, 152 event); 153 } 154 155 int ev_remove_poll(EventHandler *h, int fd) { 156 return port_dissociate(h->port, PORT_SOURCE_FD, (uintptr_t)fd); 157 } 158 159 int event_send(EventHandler *h, Event *event) { 160 event->object = 0; 161 event->events = 0; 162 return port_send(h->port, 0, event); 163 } 164 165 static int ev_aio(int fd, aiocb_s *cb, WSBool read) { 166 EventHandler *ev = cb->evhandler; 167 if(!ev) { 168 return -1; 169 } 170 171 aiocb_t *aiocb = malloc(sizeof(aiocb_t)); 172 if(!aiocb) { 173 return -1; 174 } 175 ZERO(aiocb, sizeof(aiocb_t)); 176 177 aiocb->aio_fildes = fd; 178 aiocb->aio_buf = cb->buf; 179 aiocb->aio_nbytes = cb->nbytes; 180 aiocb->aio_offset = cb->offset; 181 182 port_notify_t *portnotify = malloc(sizeof(port_notify_t)); 183 if(!portnotify) { 184 free(aiocb); 185 return -1; 186 } 187 portnotify->portnfy_port = ev->port; 188 portnotify->portnfy_user = cb->event; 189 aiocb->aio_sigevent.sigev_notify = SIGEV_PORT; 190 aiocb->aio_sigevent.sigev_value.sival_ptr = portnotify; 191 192 if(read) { 193 return aio_read(aiocb); 194 } else { 195 return aio_write(aiocb); 196 } 197 } 198 199 int ev_aioread(int fd, aiocb_s *cb) { 200 return ev_aio(fd, cb, TRUE); 201 } 202 203 int ev_aiowrite(int fd, aiocb_s *cb) { 204 return ev_aio(fd, cb, FALSE); 205 } 206 207 208 int event_pollin(EventHandler *ev, SYS_NETFD fd, Event *event) { 209 return ((IOStream*)fd)->poll(fd, ev, IO_POLL_IN, event); 210 } 211 212 int event_pollout(EventHandler *ev, SYS_NETFD fd, Event *event) { 213 return ((IOStream*)fd)->poll(fd, ev, IO_POLL_OUT, event); 214 } 215 216 int event_removepoll(EventHandler *ev, SYS_NETFD fd) { 217 return ((IOStream*)fd)->poll(fd, ev, IO_POLL_NONE, NULL); 218 } 219