spe_event.c File Reference

#include <stdlib.h>
#include "speevent.h"
#include <errno.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <poll.h>
#include <fcntl.h>

Include dependency graph for spe_event.c:

Go to the source code of this file.

Defines

#define __SPE_EVENT_ALL
#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) )
#define __SPE_EVENTS_ENABLED(spe)   ((spe)->base_private->flags & SPE_EVENTS_ENABLE)

Functions

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


Define Documentation

#define __SPE_EPOLL_FD_GET ( handler   )     (*(int*)(handler))

#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

#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) )

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)


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.

00417 {
00418   spe_context_event_priv_ptr_t evctx;
00419 
00420   if (!spe) {
00421     errno = ESRCH;
00422     return -1;
00423   }
00424 
00425   evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe);
00426   __SPE_EVENT_CONTEXT_PRIV_SET(spe, NULL);
00427   
00428   close(evctx->stop_event_pipe[0]);
00429   close(evctx->stop_event_pipe[1]);
00430 
00431   pthread_mutex_destroy(&evctx->lock);
00432   pthread_mutex_destroy(&evctx->stop_event_read_lock);
00433 
00434   free(evctx);
00435 
00436   return 0;
00437 }

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.

00440 {
00441   spe_context_event_priv_ptr_t evctx;
00442   int rc;
00443   int i;
00444 
00445   evctx = calloc(1, sizeof(*evctx));
00446   if (!evctx) {
00447     return NULL;
00448   }
00449 
00450   rc = pipe(evctx->stop_event_pipe);
00451   if (rc == -1) {
00452     free(evctx);
00453     return NULL;
00454   }
00455   rc = fcntl(evctx->stop_event_pipe[0], F_GETFL);
00456   if (rc != -1) {
00457     rc = fcntl(evctx->stop_event_pipe[0], F_SETFL, rc | O_NONBLOCK);
00458   }
00459   if (rc == -1) {
00460     close(evctx->stop_event_pipe[0]);
00461     close(evctx->stop_event_pipe[1]);
00462     free(evctx);
00463     errno = EIO;
00464     return NULL;
00465   }
00466 
00467   for (i = 0; i < sizeof(evctx->events) / sizeof(evctx->events[0]); i++) {
00468     evctx->events[i].spe = spe;
00469   }
00470 
00471   pthread_mutex_init(&evctx->lock, NULL);
00472   pthread_mutex_init(&evctx->stop_event_read_lock, NULL);
00473 
00474   return evctx;
00475 }

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().

00050 {
00051   pthread_mutex_lock(&__SPE_EVENT_CONTEXT_PRIV_GET(spe)->lock);
00052 }

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.

00478 {
00479   spe_context_event_priv_ptr_t evctx;
00480   spe_stop_info_t stopinfo_buf;
00481   int rc;
00482 
00483   if (!stopinfo) {
00484     stopinfo = &stopinfo_buf;
00485   }
00486   rc = _base_spe_context_run(spe, entry, runflags, argp, envp, stopinfo);
00487 
00488   evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe);
00489   if (write(evctx->stop_event_pipe[1], stopinfo, sizeof(*stopinfo)) != sizeof(*stopinfo)) {
00490     /* error check. */
00491   }
00492 
00493   return rc;
00494 }

Here is the call graph for this function:

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().

00055 {
00056   pthread_mutex_unlock(&__SPE_EVENT_CONTEXT_PRIV_GET(spe)->lock);
00057 }

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.

00111 {
00112   int epfd;
00113   spe_event_handler_t *evhandler;
00114 
00115   evhandler = calloc(1, sizeof(*evhandler));
00116   if (!evhandler) {
00117     return NULL;
00118   }
00119 
00120   epfd = epoll_create(__SPE_EPOLL_SIZE);
00121   if (epfd == -1) {
00122     free(evhandler);
00123     return NULL;
00124   }
00125 
00126   __SPE_EPOLL_FD_SET(evhandler, epfd);
00127 
00128   return evhandler;
00129 }

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.

00274 {
00275   int epfd;
00276   const int ep_op = EPOLL_CTL_DEL;
00277   spe_context_event_priv_ptr_t evctx;
00278   int fd;
00279 
00280   if (!evhandler) {
00281     errno = ESRCH;
00282     return -1;
00283   }
00284   if (!event || !event->spe) {
00285     errno = EINVAL;
00286     return -1;
00287   }
00288   if (!__SPE_EVENTS_ENABLED(event->spe)) {
00289     errno = ENOTSUP;
00290     return -1;
00291   }
00292 
00293   epfd = __SPE_EPOLL_FD_GET(evhandler);
00294   evctx = __SPE_EVENT_CONTEXT_PRIV_GET(event->spe);
00295 
00296   if (event->events & ~__SPE_EVENT_ALL) {
00297     errno = ENOTSUP;
00298     return -1;
00299   }
00300 
00301   _event_spe_context_lock(event->spe); /* for spe->event_private->events */
00302   
00303   if (event->events & SPE_EVENT_OUT_INTR_MBOX) {
00304     fd = __base_spe_event_source_acquire(event->spe, FD_IBOX);
00305     if (fd == -1) {
00306       _event_spe_context_unlock(event->spe);
00307       return -1;
00308     }
00309     if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) {
00310       _event_spe_context_unlock(event->spe);
00311       return -1;
00312     }
00313     evctx->events[__SPE_EVENT_OUT_INTR_MBOX].events = 0;
00314   }
00315   
00316   if (event->events & SPE_EVENT_IN_MBOX) {
00317     fd = __base_spe_event_source_acquire(event->spe, FD_WBOX);
00318     if (fd == -1) {
00319       _event_spe_context_unlock(event->spe);
00320       return -1;
00321     }
00322     if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) {
00323       _event_spe_context_unlock(event->spe);
00324       return -1;
00325     }
00326     evctx->events[__SPE_EVENT_IN_MBOX].events = 0;
00327   }
00328   
00329   if (event->events & SPE_EVENT_TAG_GROUP) {
00330     fd = __base_spe_event_source_acquire(event->spe, FD_MFC);
00331     if (fd == -1) {
00332       _event_spe_context_unlock(event->spe);
00333       return -1;
00334     }
00335     if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) {
00336       _event_spe_context_unlock(event->spe);
00337       return -1;
00338     }
00339     evctx->events[__SPE_EVENT_TAG_GROUP].events = 0;
00340   }
00341   
00342   if (event->events & SPE_EVENT_SPE_STOPPED) {
00343     fd = evctx->stop_event_pipe[0];
00344     if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) {
00345       _event_spe_context_unlock(event->spe);
00346       return -1;
00347     }
00348     evctx->events[__SPE_EVENT_SPE_STOPPED].events = 0;
00349   }
00350 
00351   _event_spe_context_unlock(event->spe);
00352 
00353   return 0;
00354 }

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.

00136 {
00137   int epfd;
00138   
00139   if (!evhandler) {
00140     errno = ESRCH;
00141     return -1;
00142   }
00143 
00144   epfd = __SPE_EPOLL_FD_GET(evhandler);
00145   close(epfd);
00146 
00147   free(evhandler);
00148   return 0;
00149 }

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.

00156 {
00157   int epfd;
00158   const int ep_op = EPOLL_CTL_ADD;
00159   spe_context_event_priv_ptr_t evctx;
00160   spe_event_unit_t *ev_buf;
00161   struct epoll_event ep_event;
00162   int fd;
00163 
00164   if (!evhandler) {
00165     errno = ESRCH;
00166     return -1;
00167   }
00168   if (!event || !event->spe) {
00169     errno = EINVAL;
00170     return -1;
00171   }
00172   if (!__SPE_EVENTS_ENABLED(event->spe)) {
00173     errno = ENOTSUP;
00174     return -1;
00175   }
00176 
00177   epfd = __SPE_EPOLL_FD_GET(evhandler);
00178   evctx = __SPE_EVENT_CONTEXT_PRIV_GET(event->spe);
00179 
00180   if (event->events & ~__SPE_EVENT_ALL) {
00181     errno = ENOTSUP;
00182     return -1;
00183   }
00184 
00185   _event_spe_context_lock(event->spe); /* for spe->event_private->events */
00186 
00187   if (event->events & SPE_EVENT_OUT_INTR_MBOX) {
00188     fd = __base_spe_event_source_acquire(event->spe, FD_IBOX);
00189     if (fd == -1) {
00190       _event_spe_context_unlock(event->spe);
00191       return -1;
00192     }
00193     
00194     ev_buf = &evctx->events[__SPE_EVENT_OUT_INTR_MBOX];
00195     ev_buf->events = SPE_EVENT_OUT_INTR_MBOX;
00196     ev_buf->data = event->data;
00197     
00198     ep_event.events = EPOLLIN;
00199     ep_event.data.ptr = ev_buf;
00200     if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) {
00201       _event_spe_context_unlock(event->spe);
00202       return -1;
00203     }
00204   }
00205   
00206   if (event->events & SPE_EVENT_IN_MBOX) {
00207     fd = __base_spe_event_source_acquire(event->spe, FD_WBOX);
00208     if (fd == -1) {
00209       _event_spe_context_unlock(event->spe);
00210       return -1;
00211     }
00212     
00213     ev_buf = &evctx->events[__SPE_EVENT_IN_MBOX];
00214     ev_buf->events = SPE_EVENT_IN_MBOX;
00215     ev_buf->data = event->data;
00216     
00217     ep_event.events = EPOLLOUT;
00218     ep_event.data.ptr = ev_buf;
00219     if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) {
00220       _event_spe_context_unlock(event->spe);
00221       return -1;
00222     }
00223   }
00224 
00225   if (event->events & SPE_EVENT_TAG_GROUP) {
00226     fd = __base_spe_event_source_acquire(event->spe, FD_MFC);
00227     if (fd == -1) {
00228       _event_spe_context_unlock(event->spe);
00229       return -1;
00230     }
00231 
00232     if (event->spe->base_private->flags & SPE_MAP_PS) {
00233             _event_spe_context_unlock(event->spe);
00234             errno = ENOTSUP;
00235             return -1;
00236     }
00237     
00238     ev_buf = &evctx->events[__SPE_EVENT_TAG_GROUP];
00239     ev_buf->events = SPE_EVENT_TAG_GROUP;
00240     ev_buf->data = event->data;
00241     
00242     ep_event.events = EPOLLIN;
00243     ep_event.data.ptr = ev_buf;
00244     if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) {
00245       _event_spe_context_unlock(event->spe);
00246       return -1;
00247     }
00248   }
00249 
00250   if (event->events & SPE_EVENT_SPE_STOPPED) {
00251     fd = evctx->stop_event_pipe[0];
00252     
00253     ev_buf = &evctx->events[__SPE_EVENT_SPE_STOPPED];
00254     ev_buf->events = SPE_EVENT_SPE_STOPPED;
00255     ev_buf->data = event->data;
00256     
00257     ep_event.events = EPOLLIN;
00258     ep_event.data.ptr = ev_buf;
00259     if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) {
00260       _event_spe_context_unlock(event->spe);
00261       return -1;
00262     }
00263   }
00264 
00265   _event_spe_context_unlock(event->spe);
00266 
00267   return 0;
00268 }

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.

00361 {
00362   int epfd;
00363   struct epoll_event *ep_events;
00364   int rc;
00365   
00366   if (!evhandler) {
00367     errno = ESRCH;
00368     return -1;
00369   }
00370   if (!events || max_events <= 0) {
00371     errno = EINVAL;
00372     return -1;
00373   }
00374   
00375   epfd = __SPE_EPOLL_FD_GET(evhandler);
00376 
00377   ep_events = malloc(sizeof(*ep_events) * max_events);
00378   if (!ep_events) {
00379     return -1;
00380   }
00381 
00382   for ( ; ; ) {
00383     rc = epoll_wait(epfd, ep_events, max_events, timeout);
00384     if (rc == -1) { /* error */
00385       if (errno == EINTR) {
00386         if (timeout >= 0) { /* behave as timeout */
00387           rc = 0;
00388           break;
00389         }
00390         /* else retry */
00391       }
00392       else {
00393         break;
00394       }
00395     }
00396     else if (rc > 0) {
00397       int i;
00398       for (i = 0; i < rc; i++) {
00399         spe_event_unit_t *ev = (spe_event_unit_t *)(ep_events[i].data.ptr);
00400         _event_spe_context_lock(ev->spe); /* lock ev itself */
00401         events[i] = *ev;
00402         _event_spe_context_unlock(ev->spe);
00403       }
00404       break;
00405     }
00406     else { /* timeout */
00407       break;
00408     }
00409   }
00410 
00411   free(ep_events);
00412 
00413   return rc;
00414 }

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.

00060 {
00061   spe_context_event_priv_ptr_t evctx;
00062   int rc;
00063   int fd;
00064   size_t total;
00065   
00066   evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe);
00067   fd = evctx->stop_event_pipe[0];
00068 
00069   pthread_mutex_lock(&evctx->stop_event_read_lock); /* for atomic read */
00070 
00071   rc = read(fd, stopinfo, sizeof(*stopinfo));
00072   if (rc == -1) {
00073     pthread_mutex_unlock(&evctx->stop_event_read_lock);
00074     return -1;
00075   }
00076 
00077   total = rc;
00078   while (total < sizeof(*stopinfo)) { /* this loop will be executed in few cases */
00079     struct pollfd fds;
00080     fds.fd = fd;
00081     fds.events = POLLIN;
00082     rc = poll(&fds, 1, -1);
00083     if (rc == -1) {
00084       if (errno != EINTR) {
00085         break;
00086       }
00087     }
00088     else if (rc == 1) {
00089       rc = read(fd, (char *)stopinfo + total, sizeof(*stopinfo) - total);
00090       if (rc == -1) {
00091         if (errno != EAGAIN) {
00092           break;
00093         }
00094       }
00095       else {
00096         total += rc;
00097       }
00098     }
00099   }
00100 
00101   pthread_mutex_unlock(&evctx->stop_event_read_lock);
00102 
00103   return rc == -1 ? -1 : 0;
00104 }


Generated on Tue Dec 16 10:15:37 2008 for libspe2 by  doxygen 1.5.7.1