[Cbe-oss-dev] [PATCH] libspe2: event API implementation

Kazunori Asayama asayama at sm.sony.co.jp
Sat Nov 11 02:10:09 EST 2006


Here is a patch to implement event API of libspe2.

Thanks,
--
(ASAYAMA Kazunori
  (asayama at sm.sony.co.jp))
t
-------------- next part --------------
Index: libspe2-2.0.0/speevent/spe_event.c
===================================================================
--- libspe2-2.0.0.orig/speevent/spe_event.c
+++ libspe2-2.0.0/speevent/spe_event.c
@@ -1,11 +1,74 @@
+/*
+ *  libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS 
+ *
+ *  Copyright (C) 2006 Sony Computer Entertainment Inc.
+ *  Copyright 2006 Sony Corp.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *  
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
 
 #include <stdlib.h>
 #include "speevent.h"
 
+#include <errno.h>
+#include <unistd.h>
+#include <sys/epoll.h>
+#include <sys/poll.h>
+
+#define __SPE_EVENT_ALL \
+  ( SPE_EVENT_OUT_INTR_MBOX | SPE_EVENT_IN_MBOX | \
+    SPE_EVENT_TAG_GROUP | SPE_EVENT_SPE_STOPPED )
+
+#define __SPE_EPOLL_SIZE 10
+
+#define __SPE_EPOLL_FD_GET(handler) (*(int*)(handler))
+#define __SPE_EPOLL_FD_SET(handler, fd) (*(int*)(handler) = (fd))
+
+#define __SPE_EVENT_CONTEXT_PRIV_GET(spe) \
+  ( (spe_context_event_priv_ptr_t)(spe)->event_private)
+#define __SPE_EVENT_CONTEXT_PRIV_SET(spe, evctx) \
+  ( (spe)->event_private = (evctx) )
+
 
 int _event_spe_stop_info_read (spe_context_ptr_t spe, spe_stop_info_t *stopinfo)
 {
-	return 0;
+  spe_context_event_priv_ptr_t evctx;
+  int rc;
+  int fd;
+  struct pollfd pfd;
+  
+  evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe);
+  fd = evctx->stop_event_pipe[0];
+
+  pfd.fd = fd;
+  pfd.events = POLLIN;
+  rc = poll(&pfd, 1, 0);
+  if (rc == -1) {
+    return -1;
+  }
+  else if (rc == 0) {
+    errno = EAGAIN;
+    return -1;
+  }
+  
+  rc = read(fd, stopinfo, sizeof(*stopinfo));
+  if (rc == -1) {
+    return -1;
+  }
+
+  return 0;
 }
 
 /* 
@@ -14,7 +77,23 @@ int _event_spe_stop_info_read (spe_conte
  
 spe_event_handler_ptr_t _event_spe_event_handler_create(void)
 {
-	return NULL;
+  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;
 }
 
 /*
@@ -23,7 +102,18 @@ spe_event_handler_ptr_t _event_spe_event
  
 int _event_spe_event_handler_destroy (spe_event_handler_ptr_t evhandler)
 {
-	return 0;
+  int epfd;
+  
+  if (!evhandler) {
+    errno = ESRCH;
+    return -1;
+  }
+
+  epfd = __SPE_EPOLL_FD_GET(evhandler);
+  close(epfd);
+
+  free(evhandler);
+  return 0;
 }
 
 /*
@@ -32,7 +122,96 @@ int _event_spe_event_handler_destroy (sp
  
 int _event_spe_event_handler_register(spe_event_handler_ptr_t evhandler, spe_event_unit_t *event)
 {
-	return 0;
+  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;
+  }
+
+  epfd = __SPE_EPOLL_FD_GET(evhandler);
+  evctx = __SPE_EVENT_CONTEXT_PRIV_GET(event->spe);
+
+  if (event->events & ~__SPE_EVENT_ALL) {
+    errno = ENOTSUP;
+    return -1;
+  }
+
+  if (event->events & SPE_EVENT_OUT_INTR_MBOX) {
+    fd = __base_spe_event_source_acquire(event->spe, FD_IBOX);
+    if (fd == -1) {
+      return -1;
+    }
+    
+    ev_buf = &evctx->events[__SPE_EVENT_OUT_INTR_MBOX];
+    *ev_buf = *event;
+    ev_buf->events = SPE_EVENT_OUT_INTR_MBOX;
+    
+    ep_event.events = EPOLLIN;
+    ep_event.data.ptr = ev_buf;
+    if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) {
+      return -1;
+    }
+  }
+  
+  if (event->events & SPE_EVENT_IN_MBOX) {
+    fd = __base_spe_event_source_acquire(event->spe, FD_WBOX);
+    if (fd == -1) {
+      return -1;
+    }
+    
+    ev_buf = &evctx->events[__SPE_EVENT_IN_MBOX];
+    *ev_buf = *event;
+    ev_buf->events = SPE_EVENT_IN_MBOX;
+    
+    ep_event.events = EPOLLOUT;
+    ep_event.data.ptr = ev_buf;
+    if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) {
+      return -1;
+    }
+  }
+
+  if (event->events & SPE_EVENT_TAG_GROUP) {
+    fd = __base_spe_event_source_acquire(event->spe, FD_MFC);
+    if (fd == -1) {
+      return -1;
+    }
+    
+    ev_buf = &evctx->events[__SPE_EVENT_TAG_GROUP];
+    *ev_buf = *event;
+    ev_buf->events = SPE_EVENT_TAG_GROUP;
+    
+    ep_event.events = EPOLLIN;
+    ep_event.data.ptr = ev_buf;
+    if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) {
+      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 = *event;
+    ev_buf->events = SPE_EVENT_SPE_STOPPED;
+    
+    ep_event.events = EPOLLIN;
+    ep_event.data.ptr = ev_buf;
+    if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) {
+      return -1;
+    }
+  }
+
+  return 0;
 }
 /*
  * spe_event_handler_deregister
@@ -40,7 +219,70 @@ int _event_spe_event_handler_register(sp
 
 int _event_spe_event_handler_deregister(spe_event_handler_ptr_t evhandler, spe_event_unit_t *event)
 {
-	return 0;
+  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;
+  }
+
+  epfd = __SPE_EPOLL_FD_GET(evhandler);
+  evctx = __SPE_EVENT_CONTEXT_PRIV_GET(event->spe);
+
+  if (event->events & ~__SPE_EVENT_ALL) {
+    errno = ENOTSUP;
+    return -1;
+  }
+  
+  if (event->events & SPE_EVENT_OUT_INTR_MBOX) {
+    fd = __base_spe_event_source_acquire(event->spe, FD_IBOX);
+    if (fd == -1) {
+      return -1;
+    }
+    if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) {
+      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) {
+      return -1;
+    }
+    if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) {
+      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) {
+      return -1;
+    }
+    if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) {
+      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) {
+      return -1;
+    }
+    evctx->events[__SPE_EVENT_SPE_STOPPED].events = 0;
+  }
+
+  return 0;
 }
 
 /*
@@ -49,22 +291,94 @@ int _event_spe_event_handler_deregister(
  
 int _event_spe_event_wait(spe_event_handler_ptr_t evhandler, spe_event_unit_t *events, int max_events, int timeout)
 {
-	return 0;
-}
+  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;
+  }
+
+  rc = epoll_wait(epfd, ep_events, max_events, timeout);
+  if (rc > 0) {
+    int i;
+    for (i = 0; i < rc; i++) {
+      events[i] = *(spe_event_unit_t *)(ep_events[i].data.ptr);
+    }
+  }
 
+  free(ep_events);
+
+  return rc;
+}
 
 int _event_spe_context_finalize(spe_context_ptr_t spe)
 {
-	return 0;
+  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]);
+
+  free(evctx);
+
+  return 0;
 }
 
 struct spe_context_event_priv * _event_spe_context_initialize(spe_context_ptr_t spe)
 {
-	return NULL;
+  spe_context_event_priv_ptr_t evctx;
+  int rc;
+
+  evctx = calloc(1, sizeof(*evctx));
+  if (!evctx) {
+    return NULL;
+  }
+
+  rc = pipe(evctx->stop_event_pipe);
+  if (rc == -1) {
+    free(evctx);
+    return NULL;
+  }
+
+  return evctx;
 }
 
 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)
 {
-	return 0;
+  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;
 }
 
Index: libspe2-2.0.0/speevent/speevent.h
===================================================================
--- libspe2-2.0.0.orig/speevent/speevent.h
+++ libspe2-2.0.0/speevent/speevent.h
@@ -24,6 +24,21 @@
 
 #include "spebase.h"
 
+/* private constants */
+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
+};
+
+/* private types */
+typedef struct spe_context_event_priv
+{
+  int stop_event_pipe[2];
+  spe_event_unit_t events[__NUM_SPE_EVENT_TYPES];
+} spe_context_event_priv_t, *spe_context_event_priv_ptr_t;
+
+
 int _event_spe_stop_info_read (spe_context_ptr_t spe, spe_stop_info_t *stopinfo);
 
 /* 


More information about the cbe-oss-dev mailing list