libspe2 0.9a
Data Structures | Typedefs | Enumerations | Functions
speevent.h File Reference
#include "spebase.h"
Include dependency graph for speevent.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  spe_context_event_priv

Typedefs

typedef struct
spe_context_event_priv 
spe_context_event_priv_t
typedef struct
spe_context_event_priv
spe_context_event_priv_ptr_t

Enumerations

enum  __spe_event_types {
  __SPE_EVENT_OUT_INTR_MBOX, __SPE_EVENT_IN_MBOX, __SPE_EVENT_TAG_GROUP, __SPE_EVENT_SPE_STOPPED,
  __NUM_SPE_EVENT_TYPES
}

Functions

int _event_spe_stop_info_read (spe_context_ptr_t spe, spe_stop_info_t *stopinfo)
spe_event_handler_ptr_t _event_spe_event_handler_create (void)
int _event_spe_event_handler_destroy (spe_event_handler_ptr_t evhandler)
int _event_spe_event_handler_register (spe_event_handler_ptr_t evhandler, spe_event_unit_t *event)
int _event_spe_event_handler_deregister (spe_event_handler_ptr_t evhandler, spe_event_unit_t *event)
int _event_spe_event_wait (spe_event_handler_ptr_t evhandler, spe_event_unit_t *events, int max_events, int timeout)
int _event_spe_context_finalize (spe_context_ptr_t spe)
struct spe_context_event_priv_event_spe_context_initialize (spe_context_ptr_t spe)
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)
void _event_spe_context_lock (spe_context_ptr_t spe)
void _event_spe_context_unlock (spe_context_ptr_t spe)

Typedef Documentation


Enumeration Type Documentation

Enumerator:
__SPE_EVENT_OUT_INTR_MBOX 
__SPE_EVENT_IN_MBOX 
__SPE_EVENT_TAG_GROUP 
__SPE_EVENT_SPE_STOPPED 
__NUM_SPE_EVENT_TYPES 

Definition at line 28 of file speevent.h.


Function Documentation

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

Here is the call graph for this function:

void _event_spe_context_unlock ( spe_context_ptr_t  spe)
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;
}

Here is the call graph for this function:

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

Here is the call graph for this function:

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

Here is the call graph for this function:

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