|
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;
}
1.7.4