libspe2 0.9a
|
#include <stdlib.h>
#include "speevent.h"
#include <errno.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <poll.h>
#include <fcntl.h>
Go to the source code of this file.
#define __SPE_EPOLL_FD_GET | ( | handler | ) | (*(int*)(handler)) |
Definition at line 37 of file spe_event.c.
Referenced by _event_spe_event_handler_deregister(), _event_spe_event_handler_destroy(), _event_spe_event_handler_register(), and _event_spe_event_wait().
#define __SPE_EPOLL_FD_SET | ( | handler, | |
fd | |||
) | (*(int*)(handler) = (fd)) |
Definition at line 38 of file spe_event.c.
Referenced by _event_spe_event_handler_create().
#define __SPE_EPOLL_SIZE 10 |
Definition at line 35 of file spe_event.c.
Referenced by _event_spe_event_handler_create().
#define __SPE_EVENT_ALL |
Definition at line 31 of file spe_event.c.
Referenced by _event_spe_event_handler_deregister(), and _event_spe_event_handler_register().
#define __SPE_EVENT_CONTEXT_PRIV_GET | ( | spe | ) | ( (spe_context_event_priv_ptr_t)(spe)->event_private) |
Definition at line 40 of file spe_event.c.
Referenced by _event_spe_context_finalize(), _event_spe_context_lock(), _event_spe_context_run(), _event_spe_context_unlock(), _event_spe_event_handler_deregister(), _event_spe_event_handler_register(), and _event_spe_stop_info_read().
#define __SPE_EVENT_CONTEXT_PRIV_SET | ( | spe, | |
evctx | |||
) | ( (spe)->event_private = (evctx) ) |
Definition at line 42 of file spe_event.c.
Referenced by _event_spe_context_finalize().
#define __SPE_EVENTS_ENABLED | ( | spe | ) | ((spe)->base_private->flags & SPE_EVENTS_ENABLE) |
Definition at line 45 of file spe_event.c.
Referenced by _event_spe_event_handler_deregister(), and _event_spe_event_handler_register().
int _event_spe_context_finalize | ( | spe_context_ptr_t | spe | ) |
Definition at line 416 of file spe_event.c.
References __SPE_EVENT_CONTEXT_PRIV_GET, __SPE_EVENT_CONTEXT_PRIV_SET, spe_context_event_priv::lock, spe_context_event_priv::stop_event_pipe, and spe_context_event_priv::stop_event_read_lock.
{ spe_context_event_priv_ptr_t evctx; if (!spe) { errno = ESRCH; return -1; } evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe); __SPE_EVENT_CONTEXT_PRIV_SET(spe, NULL); close(evctx->stop_event_pipe[0]); close(evctx->stop_event_pipe[1]); pthread_mutex_destroy(&evctx->lock); pthread_mutex_destroy(&evctx->stop_event_read_lock); free(evctx); return 0; }
struct spe_context_event_priv* _event_spe_context_initialize | ( | spe_context_ptr_t | spe | ) | [read] |
Definition at line 439 of file spe_event.c.
References spe_context_event_priv::events, spe_context_event_priv::lock, spe_event_unit::spe, spe_context_event_priv::stop_event_pipe, and spe_context_event_priv::stop_event_read_lock.
{ spe_context_event_priv_ptr_t evctx; int rc; int i; evctx = calloc(1, sizeof(*evctx)); if (!evctx) { return NULL; } rc = pipe(evctx->stop_event_pipe); if (rc == -1) { free(evctx); return NULL; } rc = fcntl(evctx->stop_event_pipe[0], F_GETFL); if (rc != -1) { rc = fcntl(evctx->stop_event_pipe[0], F_SETFL, rc | O_NONBLOCK); } if (rc == -1) { close(evctx->stop_event_pipe[0]); close(evctx->stop_event_pipe[1]); free(evctx); errno = EIO; return NULL; } for (i = 0; i < sizeof(evctx->events) / sizeof(evctx->events[0]); i++) { evctx->events[i].spe = spe; } pthread_mutex_init(&evctx->lock, NULL); pthread_mutex_init(&evctx->stop_event_read_lock, NULL); return evctx; }
void _event_spe_context_lock | ( | spe_context_ptr_t | spe | ) |
Definition at line 49 of file spe_event.c.
References __SPE_EVENT_CONTEXT_PRIV_GET.
Referenced by _event_spe_event_handler_deregister(), _event_spe_event_handler_register(), and _event_spe_event_wait().
{ pthread_mutex_lock(&__SPE_EVENT_CONTEXT_PRIV_GET(spe)->lock); }
int _event_spe_context_run | ( | spe_context_ptr_t | spe, |
unsigned int * | entry, | ||
unsigned int | runflags, | ||
void * | argp, | ||
void * | envp, | ||
spe_stop_info_t * | stopinfo | ||
) |
Definition at line 477 of file spe_event.c.
References __SPE_EVENT_CONTEXT_PRIV_GET, _base_spe_context_run(), and spe_context_event_priv::stop_event_pipe.
{ spe_context_event_priv_ptr_t evctx; spe_stop_info_t stopinfo_buf; int rc; if (!stopinfo) { stopinfo = &stopinfo_buf; } rc = _base_spe_context_run(spe, entry, runflags, argp, envp, stopinfo); evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe); if (write(evctx->stop_event_pipe[1], stopinfo, sizeof(*stopinfo)) != sizeof(*stopinfo)) { /* error check. */ } return rc; }
void _event_spe_context_unlock | ( | spe_context_ptr_t | spe | ) |
Definition at line 54 of file spe_event.c.
References __SPE_EVENT_CONTEXT_PRIV_GET.
Referenced by _event_spe_event_handler_deregister(), _event_spe_event_handler_register(), and _event_spe_event_wait().
{ pthread_mutex_unlock(&__SPE_EVENT_CONTEXT_PRIV_GET(spe)->lock); }
spe_event_handler_ptr_t _event_spe_event_handler_create | ( | void | ) |
Definition at line 110 of file spe_event.c.
References __SPE_EPOLL_FD_SET, and __SPE_EPOLL_SIZE.
{ int epfd; spe_event_handler_t *evhandler; evhandler = calloc(1, sizeof(*evhandler)); if (!evhandler) { return NULL; } epfd = epoll_create(__SPE_EPOLL_SIZE); if (epfd == -1) { free(evhandler); return NULL; } __SPE_EPOLL_FD_SET(evhandler, epfd); return evhandler; }
int _event_spe_event_handler_deregister | ( | spe_event_handler_ptr_t | evhandler, |
spe_event_unit_t * | event | ||
) |
Definition at line 273 of file spe_event.c.
References __base_spe_event_source_acquire(), __SPE_EPOLL_FD_GET, __SPE_EVENT_ALL, __SPE_EVENT_CONTEXT_PRIV_GET, __SPE_EVENT_IN_MBOX, __SPE_EVENT_OUT_INTR_MBOX, __SPE_EVENT_SPE_STOPPED, __SPE_EVENT_TAG_GROUP, __SPE_EVENTS_ENABLED, _event_spe_context_lock(), _event_spe_context_unlock(), spe_context_event_priv::events, spe_event_unit::events, FD_IBOX, FD_MFC, FD_WBOX, spe_event_unit::spe, SPE_EVENT_IN_MBOX, SPE_EVENT_OUT_INTR_MBOX, SPE_EVENT_SPE_STOPPED, SPE_EVENT_TAG_GROUP, and spe_context_event_priv::stop_event_pipe.
{ int epfd; const int ep_op = EPOLL_CTL_DEL; spe_context_event_priv_ptr_t evctx; int fd; if (!evhandler) { errno = ESRCH; return -1; } if (!event || !event->spe) { errno = EINVAL; return -1; } if (!__SPE_EVENTS_ENABLED(event->spe)) { errno = ENOTSUP; return -1; } epfd = __SPE_EPOLL_FD_GET(evhandler); evctx = __SPE_EVENT_CONTEXT_PRIV_GET(event->spe); if (event->events & ~__SPE_EVENT_ALL) { errno = ENOTSUP; return -1; } _event_spe_context_lock(event->spe); /* for spe->event_private->events */ if (event->events & SPE_EVENT_OUT_INTR_MBOX) { fd = __base_spe_event_source_acquire(event->spe, FD_IBOX); if (fd == -1) { _event_spe_context_unlock(event->spe); return -1; } if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) { _event_spe_context_unlock(event->spe); return -1; } evctx->events[__SPE_EVENT_OUT_INTR_MBOX].events = 0; } if (event->events & SPE_EVENT_IN_MBOX) { fd = __base_spe_event_source_acquire(event->spe, FD_WBOX); if (fd == -1) { _event_spe_context_unlock(event->spe); return -1; } if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) { _event_spe_context_unlock(event->spe); return -1; } evctx->events[__SPE_EVENT_IN_MBOX].events = 0; } if (event->events & SPE_EVENT_TAG_GROUP) { fd = __base_spe_event_source_acquire(event->spe, FD_MFC); if (fd == -1) { _event_spe_context_unlock(event->spe); return -1; } if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) { _event_spe_context_unlock(event->spe); return -1; } evctx->events[__SPE_EVENT_TAG_GROUP].events = 0; } if (event->events & SPE_EVENT_SPE_STOPPED) { fd = evctx->stop_event_pipe[0]; if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) { _event_spe_context_unlock(event->spe); return -1; } evctx->events[__SPE_EVENT_SPE_STOPPED].events = 0; } _event_spe_context_unlock(event->spe); return 0; }
int _event_spe_event_handler_destroy | ( | spe_event_handler_ptr_t | evhandler | ) |
Definition at line 135 of file spe_event.c.
References __SPE_EPOLL_FD_GET.
{ int epfd; if (!evhandler) { errno = ESRCH; return -1; } epfd = __SPE_EPOLL_FD_GET(evhandler); close(epfd); free(evhandler); return 0; }
int _event_spe_event_handler_register | ( | spe_event_handler_ptr_t | evhandler, |
spe_event_unit_t * | event | ||
) |
Definition at line 155 of file spe_event.c.
References __base_spe_event_source_acquire(), __SPE_EPOLL_FD_GET, __SPE_EVENT_ALL, __SPE_EVENT_CONTEXT_PRIV_GET, __SPE_EVENT_IN_MBOX, __SPE_EVENT_OUT_INTR_MBOX, __SPE_EVENT_SPE_STOPPED, __SPE_EVENT_TAG_GROUP, __SPE_EVENTS_ENABLED, _event_spe_context_lock(), _event_spe_context_unlock(), spe_context::base_private, spe_event_unit::data, spe_context_event_priv::events, spe_event_unit::events, FD_IBOX, FD_MFC, FD_WBOX, spe_context_base_priv::flags, spe_event_data::ptr, spe_event_unit::spe, SPE_EVENT_IN_MBOX, SPE_EVENT_OUT_INTR_MBOX, SPE_EVENT_SPE_STOPPED, SPE_EVENT_TAG_GROUP, SPE_MAP_PS, and spe_context_event_priv::stop_event_pipe.
{ int epfd; const int ep_op = EPOLL_CTL_ADD; spe_context_event_priv_ptr_t evctx; spe_event_unit_t *ev_buf; struct epoll_event ep_event; int fd; if (!evhandler) { errno = ESRCH; return -1; } if (!event || !event->spe) { errno = EINVAL; return -1; } if (!__SPE_EVENTS_ENABLED(event->spe)) { errno = ENOTSUP; return -1; } epfd = __SPE_EPOLL_FD_GET(evhandler); evctx = __SPE_EVENT_CONTEXT_PRIV_GET(event->spe); if (event->events & ~__SPE_EVENT_ALL) { errno = ENOTSUP; return -1; } _event_spe_context_lock(event->spe); /* for spe->event_private->events */ if (event->events & SPE_EVENT_OUT_INTR_MBOX) { fd = __base_spe_event_source_acquire(event->spe, FD_IBOX); if (fd == -1) { _event_spe_context_unlock(event->spe); return -1; } ev_buf = &evctx->events[__SPE_EVENT_OUT_INTR_MBOX]; ev_buf->events = SPE_EVENT_OUT_INTR_MBOX; ev_buf->data = event->data; ep_event.events = EPOLLIN; ep_event.data.ptr = ev_buf; if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) { _event_spe_context_unlock(event->spe); return -1; } } if (event->events & SPE_EVENT_IN_MBOX) { fd = __base_spe_event_source_acquire(event->spe, FD_WBOX); if (fd == -1) { _event_spe_context_unlock(event->spe); return -1; } ev_buf = &evctx->events[__SPE_EVENT_IN_MBOX]; ev_buf->events = SPE_EVENT_IN_MBOX; ev_buf->data = event->data; ep_event.events = EPOLLOUT; ep_event.data.ptr = ev_buf; if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) { _event_spe_context_unlock(event->spe); return -1; } } if (event->events & SPE_EVENT_TAG_GROUP) { fd = __base_spe_event_source_acquire(event->spe, FD_MFC); if (fd == -1) { _event_spe_context_unlock(event->spe); return -1; } if (event->spe->base_private->flags & SPE_MAP_PS) { _event_spe_context_unlock(event->spe); errno = ENOTSUP; return -1; } ev_buf = &evctx->events[__SPE_EVENT_TAG_GROUP]; ev_buf->events = SPE_EVENT_TAG_GROUP; ev_buf->data = event->data; ep_event.events = EPOLLIN; ep_event.data.ptr = ev_buf; if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) { _event_spe_context_unlock(event->spe); return -1; } } if (event->events & SPE_EVENT_SPE_STOPPED) { fd = evctx->stop_event_pipe[0]; ev_buf = &evctx->events[__SPE_EVENT_SPE_STOPPED]; ev_buf->events = SPE_EVENT_SPE_STOPPED; ev_buf->data = event->data; ep_event.events = EPOLLIN; ep_event.data.ptr = ev_buf; if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) { _event_spe_context_unlock(event->spe); return -1; } } _event_spe_context_unlock(event->spe); return 0; }
int _event_spe_event_wait | ( | spe_event_handler_ptr_t | evhandler, |
spe_event_unit_t * | events, | ||
int | max_events, | ||
int | timeout | ||
) |
Definition at line 360 of file spe_event.c.
References __SPE_EPOLL_FD_GET, _event_spe_context_lock(), _event_spe_context_unlock(), and spe_event_unit::spe.
{ int epfd; struct epoll_event *ep_events; int rc; if (!evhandler) { errno = ESRCH; return -1; } if (!events || max_events <= 0) { errno = EINVAL; return -1; } epfd = __SPE_EPOLL_FD_GET(evhandler); ep_events = malloc(sizeof(*ep_events) * max_events); if (!ep_events) { return -1; } for ( ; ; ) { rc = epoll_wait(epfd, ep_events, max_events, timeout); if (rc == -1) { /* error */ if (errno == EINTR) { if (timeout >= 0) { /* behave as timeout */ rc = 0; break; } /* else retry */ } else { break; } } else if (rc > 0) { int i; for (i = 0; i < rc; i++) { spe_event_unit_t *ev = (spe_event_unit_t *)(ep_events[i].data.ptr); _event_spe_context_lock(ev->spe); /* lock ev itself */ events[i] = *ev; _event_spe_context_unlock(ev->spe); } break; } else { /* timeout */ break; } } free(ep_events); return rc; }
int _event_spe_stop_info_read | ( | spe_context_ptr_t | spe, |
spe_stop_info_t * | stopinfo | ||
) |
Definition at line 59 of file spe_event.c.
References __SPE_EVENT_CONTEXT_PRIV_GET, spe_context_event_priv::stop_event_pipe, and spe_context_event_priv::stop_event_read_lock.
{ spe_context_event_priv_ptr_t evctx; int rc; int fd; size_t total; evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe); fd = evctx->stop_event_pipe[0]; pthread_mutex_lock(&evctx->stop_event_read_lock); /* for atomic read */ rc = read(fd, stopinfo, sizeof(*stopinfo)); if (rc == -1) { pthread_mutex_unlock(&evctx->stop_event_read_lock); return -1; } total = rc; while (total < sizeof(*stopinfo)) { /* this loop will be executed in few cases */ struct pollfd fds; fds.fd = fd; fds.events = POLLIN; rc = poll(&fds, 1, -1); if (rc == -1) { if (errno != EINTR) { break; } } else if (rc == 1) { rc = read(fd, (char *)stopinfo + total, sizeof(*stopinfo) - total); if (rc == -1) { if (errno != EAGAIN) { break; } } else { total += rc; } } } pthread_mutex_unlock(&evctx->stop_event_read_lock); return rc == -1 ? -1 : 0; }