#include <stdio.h>
#include <stdlib.h>
#include <atomic.h>
#include "../util/io.h"
#include "event_solaris.h"
EVHandler* evhandler_create(EventHandlerConfig *cfg) {
EVHandler *ev = malloc(
sizeof(EVHandler));
ev->current =
0;
ev->instances = calloc(cfg->nthreads,
sizeof(
void*));
ev->numins = cfg->nthreads;
for(
int i=
0;i<cfg->nthreads;i++) {
EventHandler *handler = malloc(
sizeof(EventHandler));
ev->instances[i] = handler;
handler->port = port_create();
if(handler->port ==
0) {
return NULL;
}
SYS_THREAD t = systhread_start(
0,
0,
(thrstartfunc)ev_handle_events,
handler);
systhread_detach(t);
}
return ev;
}
void ev_handle_events(EventHandler *ev) {
port_event_t events[
64];
struct timespec timeout;
timeout.tv_nsec =
0;
timeout.tv_sec =
600;
for(;;) {
uint_t nev =
1;
int ret = port_getn(ev->port, events,
64, &nev, &timeout);
if(ret == -
1) {
perror(
"port_getn");
continue;
}
for(
int i=
0;i<nev;i++) {
Event *event = events[i].portev_user;
if(events[i].portev_source ==
PORT_SOURCE_AIO) {
aiocb_t *aiocb = (
aiocb_t*)events[i].portev_object;
if(event) {
aiocb_s *aio = (aiocb_s*)event->object;
aio->result = aiocb->aio_resultp.aio_return;
aio->result_errno = aiocb->aio_resultp.aio_errno;
if(event->fn) {
if(!event->fn(ev, event) && event->finish) {
event->finish(ev, event);
}
}
}
free(aiocb);
}
else {
if(event->fn) {
if(event->fn(ev, event)) {
if(port_associate(
ev->port,
PORT_SOURCE_FD,
(
uintptr_t)event->object,
ev_convert2sys_events(event->events),
event))
{
perror(
"port_associate");
}
}
else if(event->finish) {
event->finish(ev, event);
}
}
}
}
}
}
int ev_convert2sys_events(
int events) {
int e =
0;
if((events &
EVENT_POLLIN) ==
EVENT_POLLIN) {
e |=
POLLIN;
}
if((events &
EVENT_POLLOUT) ==
EVENT_POLLOUT) {
e |=
POLLOUT;
}
return e;
}
int ev_pollin(EventHandler *h,
int fd, Event *event) {
event->object = (
intptr_t)fd;
event->events =
EVENT_POLLIN;
return port_associate(
h->port,
PORT_SOURCE_FD,
(
uintptr_t)fd,
POLLIN,
event);
}
int ev_pollout(EventHandler *h,
int fd, Event *event) {
event->object = (
intptr_t)fd;
event->events =
EVENT_POLLOUT;
return port_associate(
h->port,
PORT_SOURCE_FD,
(
uintptr_t)fd,
POLLOUT,
event);
}
int ev_remove_poll(EventHandler *h,
int fd) {
return port_dissociate(h->port,
PORT_SOURCE_FD, (
uintptr_t)fd);
}
int event_send(EventHandler *h, Event *event) {
event->object =
0;
event->events =
0;
return port_send(h->port,
0, event);
}
static int ev_aio(
int fd, aiocb_s *cb, WSBool read) {
EventHandler *ev = cb->evhandler;
if(!ev) {
return -
1;
}
aiocb_t *aiocb = malloc(
sizeof(
aiocb_t));
if(!aiocb) {
return -
1;
}
ZERO(aiocb,
sizeof(
aiocb_t));
aiocb->aio_fildes = fd;
aiocb->aio_buf = cb->buf;
aiocb->aio_nbytes = cb->nbytes;
aiocb->aio_offset = cb->offset;
port_notify_t *portnotify = malloc(
sizeof(
port_notify_t));
if(!portnotify) {
free(aiocb);
return -
1;
}
portnotify->portnfy_port = ev->port;
portnotify->portnfy_user = cb->event;
aiocb->aio_sigevent.sigev_notify =
SIGEV_PORT;
aiocb->aio_sigevent.sigev_value.sival_ptr = portnotify;
if(read) {
return aio_read(aiocb);
}
else {
return aio_write(aiocb);
}
}
int ev_aioread(
int fd, aiocb_s *cb) {
return ev_aio(fd, cb,
TRUE);
}
int ev_aiowrite(
int fd, aiocb_s *cb) {
return ev_aio(fd, cb,
FALSE);
}
int event_pollin(EventHandler *ev,
SYS_NETFD fd, Event *event) {
return ((IOStream*)fd)->poll(fd, ev,
IO_POLL_IN, event);
}
int event_pollout(EventHandler *ev,
SYS_NETFD fd, Event *event) {
return ((IOStream*)fd)->poll(fd, ev,
IO_POLL_OUT, event);
}
int event_removepoll(EventHandler *ev,
SYS_NETFD fd) {
return ((IOStream*)fd)->poll(fd, ev,
IO_POLL_NONE,
NULL);
}