libspe2  0.9a
Macros | Functions
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.

Macros

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

Macro Definition 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
Value:
#define SPE_EVENT_IN_MBOX
#define SPE_EVENT_TAG_GROUP
#define SPE_EVENT_SPE_STOPPED
#define SPE_EVENT_OUT_INTR_MBOX

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

417 {
419 
420  if (!spe) {
421  errno = ESRCH;
422  return -1;
423  }
424 
425  evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe);
426  __SPE_EVENT_CONTEXT_PRIV_SET(spe, NULL);
427 
428  close(evctx->stop_event_pipe[0]);
429  close(evctx->stop_event_pipe[1]);
430 
431  pthread_mutex_destroy(&evctx->lock);
432  pthread_mutex_destroy(&evctx->stop_event_read_lock);
433 
434  free(evctx);
435 
436  return 0;
437 }
pthread_mutex_t lock
Definition: speevent.h:37
#define __SPE_EVENT_CONTEXT_PRIV_SET(spe, evctx)
Definition: spe_event.c:42
pthread_mutex_t stop_event_read_lock
Definition: speevent.h:38
#define __SPE_EVENT_CONTEXT_PRIV_GET(spe)
Definition: spe_event.c:40
struct spe_context_event_priv* _event_spe_context_initialize ( spe_context_ptr_t  spe)

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.

440 {
442  int rc;
443  int i;
444 
445  evctx = calloc(1, sizeof(*evctx));
446  if (!evctx) {
447  return NULL;
448  }
449 
450  rc = pipe(evctx->stop_event_pipe);
451  if (rc == -1) {
452  free(evctx);
453  return NULL;
454  }
455  rc = fcntl(evctx->stop_event_pipe[0], F_GETFL);
456  if (rc != -1) {
457  rc = fcntl(evctx->stop_event_pipe[0], F_SETFL, rc | O_NONBLOCK);
458  }
459  if (rc == -1) {
460  close(evctx->stop_event_pipe[0]);
461  close(evctx->stop_event_pipe[1]);
462  free(evctx);
463  errno = EIO;
464  return NULL;
465  }
466 
467  for (i = 0; i < sizeof(evctx->events) / sizeof(evctx->events[0]); i++) {
468  evctx->events[i].spe = spe;
469  }
470 
471  pthread_mutex_init(&evctx->lock, NULL);
472  pthread_mutex_init(&evctx->stop_event_read_lock, NULL);
473 
474  return evctx;
475 }
pthread_mutex_t lock
Definition: speevent.h:37
spe_event_unit_t events[__NUM_SPE_EVENT_TYPES]
Definition: speevent.h:40
spe_context_ptr_t spe
pthread_mutex_t stop_event_read_lock
Definition: speevent.h:38
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().

50 {
51  pthread_mutex_lock(&__SPE_EVENT_CONTEXT_PRIV_GET(spe)->lock);
52 }
#define __SPE_EVENT_CONTEXT_PRIV_GET(spe)
Definition: spe_event.c:40
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.

478 {
480  spe_stop_info_t stopinfo_buf;
481  int rc;
482 
483  if (!stopinfo) {
484  stopinfo = &stopinfo_buf;
485  }
486  rc = _base_spe_context_run(spe, entry, runflags, argp, envp, stopinfo);
487 
488  evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe);
489  if (write(evctx->stop_event_pipe[1], stopinfo, sizeof(*stopinfo)) != sizeof(*stopinfo)) {
490  /* error check. */
491  }
492 
493  return rc;
494 }
int _base_spe_context_run(spe_context_ptr_t spe, unsigned int *entry, unsigned int runflags, void *argp, void *envp, spe_stop_info_t *stopinfo)
Definition: run.c:99
#define __SPE_EVENT_CONTEXT_PRIV_GET(spe)
Definition: spe_event.c:40

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

55 {
56  pthread_mutex_unlock(&__SPE_EVENT_CONTEXT_PRIV_GET(spe)->lock);
57 }
#define __SPE_EVENT_CONTEXT_PRIV_GET(spe)
Definition: spe_event.c:40
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.

111 {
112  int epfd;
113  spe_event_handler_t *evhandler;
114 
115  evhandler = calloc(1, sizeof(*evhandler));
116  if (!evhandler) {
117  return NULL;
118  }
119 
120  epfd = epoll_create(__SPE_EPOLL_SIZE);
121  if (epfd == -1) {
122  free(evhandler);
123  return NULL;
124  }
125 
126  __SPE_EPOLL_FD_SET(evhandler, epfd);
127 
128  return evhandler;
129 }
#define __SPE_EPOLL_SIZE
Definition: spe_event.c:35
int spe_event_handler_t
#define __SPE_EPOLL_FD_SET(handler, fd)
Definition: spe_event.c:38
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.

274 {
275  int epfd;
276  const int ep_op = EPOLL_CTL_DEL;
278  int fd;
279 
280  if (!evhandler) {
281  errno = ESRCH;
282  return -1;
283  }
284  if (!event || !event->spe) {
285  errno = EINVAL;
286  return -1;
287  }
288  if (!__SPE_EVENTS_ENABLED(event->spe)) {
289  errno = ENOTSUP;
290  return -1;
291  }
292 
293  epfd = __SPE_EPOLL_FD_GET(evhandler);
294  evctx = __SPE_EVENT_CONTEXT_PRIV_GET(event->spe);
295 
296  if (event->events & ~__SPE_EVENT_ALL) {
297  errno = ENOTSUP;
298  return -1;
299  }
300 
301  _event_spe_context_lock(event->spe); /* for spe->event_private->events */
302 
303  if (event->events & SPE_EVENT_OUT_INTR_MBOX) {
305  if (fd == -1) {
307  return -1;
308  }
309  if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) {
311  return -1;
312  }
314  }
315 
316  if (event->events & SPE_EVENT_IN_MBOX) {
318  if (fd == -1) {
320  return -1;
321  }
322  if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) {
324  return -1;
325  }
326  evctx->events[__SPE_EVENT_IN_MBOX].events = 0;
327  }
328 
329  if (event->events & SPE_EVENT_TAG_GROUP) {
331  if (fd == -1) {
333  return -1;
334  }
335  if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) {
337  return -1;
338  }
339  evctx->events[__SPE_EVENT_TAG_GROUP].events = 0;
340  }
341 
342  if (event->events & SPE_EVENT_SPE_STOPPED) {
343  fd = evctx->stop_event_pipe[0];
344  if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) {
346  return -1;
347  }
349  }
350 
352 
353  return 0;
354 }
unsigned int events
#define SPE_EVENT_IN_MBOX
spe_event_unit_t events[__NUM_SPE_EVENT_TYPES]
Definition: speevent.h:40
#define __SPE_EVENTS_ENABLED(spe)
Definition: spe_event.c:45
Definition: spebase.h:53
#define __SPE_EPOLL_FD_GET(handler)
Definition: spe_event.c:37
void _event_spe_context_unlock(spe_context_ptr_t spe)
Definition: spe_event.c:54
spe_context_ptr_t spe
#define SPE_EVENT_TAG_GROUP
void _event_spe_context_lock(spe_context_ptr_t spe)
Definition: spe_event.c:49
#define SPE_EVENT_SPE_STOPPED
int __base_spe_event_source_acquire(spe_context_ptr_t spe, enum fd_name fdesc)
Definition: accessors.c:74
#define __SPE_EVENT_ALL
Definition: spe_event.c:31
#define __SPE_EVENT_CONTEXT_PRIV_GET(spe)
Definition: spe_event.c:40
#define SPE_EVENT_OUT_INTR_MBOX

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.

136 {
137  int epfd;
138 
139  if (!evhandler) {
140  errno = ESRCH;
141  return -1;
142  }
143 
144  epfd = __SPE_EPOLL_FD_GET(evhandler);
145  close(epfd);
146 
147  free(evhandler);
148  return 0;
149 }
#define __SPE_EPOLL_FD_GET(handler)
Definition: spe_event.c:37
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.

156 {
157  int epfd;
158  const int ep_op = EPOLL_CTL_ADD;
160  spe_event_unit_t *ev_buf;
161  struct epoll_event ep_event;
162  int fd;
163 
164  if (!evhandler) {
165  errno = ESRCH;
166  return -1;
167  }
168  if (!event || !event->spe) {
169  errno = EINVAL;
170  return -1;
171  }
172  if (!__SPE_EVENTS_ENABLED(event->spe)) {
173  errno = ENOTSUP;
174  return -1;
175  }
176 
177  epfd = __SPE_EPOLL_FD_GET(evhandler);
178  evctx = __SPE_EVENT_CONTEXT_PRIV_GET(event->spe);
179 
180  if (event->events & ~__SPE_EVENT_ALL) {
181  errno = ENOTSUP;
182  return -1;
183  }
184 
185  _event_spe_context_lock(event->spe); /* for spe->event_private->events */
186 
187  if (event->events & SPE_EVENT_OUT_INTR_MBOX) {
189  if (fd == -1) {
191  return -1;
192  }
193 
194  ev_buf = &evctx->events[__SPE_EVENT_OUT_INTR_MBOX];
196  ev_buf->data = event->data;
197 
198  ep_event.events = EPOLLIN;
199  ep_event.data.ptr = ev_buf;
200  if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) {
202  return -1;
203  }
204  }
205 
206  if (event->events & SPE_EVENT_IN_MBOX) {
208  if (fd == -1) {
210  return -1;
211  }
212 
213  ev_buf = &evctx->events[__SPE_EVENT_IN_MBOX];
214  ev_buf->events = SPE_EVENT_IN_MBOX;
215  ev_buf->data = event->data;
216 
217  ep_event.events = EPOLLOUT;
218  ep_event.data.ptr = ev_buf;
219  if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) {
221  return -1;
222  }
223  }
224 
225  if (event->events & SPE_EVENT_TAG_GROUP) {
227  if (fd == -1) {
229  return -1;
230  }
231 
232  if (event->spe->base_private->flags & SPE_MAP_PS) {
234  errno = ENOTSUP;
235  return -1;
236  }
237 
238  ev_buf = &evctx->events[__SPE_EVENT_TAG_GROUP];
239  ev_buf->events = SPE_EVENT_TAG_GROUP;
240  ev_buf->data = event->data;
241 
242  ep_event.events = EPOLLIN;
243  ep_event.data.ptr = ev_buf;
244  if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) {
246  return -1;
247  }
248  }
249 
250  if (event->events & SPE_EVENT_SPE_STOPPED) {
251  fd = evctx->stop_event_pipe[0];
252 
253  ev_buf = &evctx->events[__SPE_EVENT_SPE_STOPPED];
254  ev_buf->events = SPE_EVENT_SPE_STOPPED;
255  ev_buf->data = event->data;
256 
257  ep_event.events = EPOLLIN;
258  ep_event.data.ptr = ev_buf;
259  if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) {
261  return -1;
262  }
263  }
264 
266 
267  return 0;
268 }
unsigned int events
#define SPE_EVENT_IN_MBOX
spe_event_unit_t events[__NUM_SPE_EVENT_TYPES]
Definition: speevent.h:40
#define __SPE_EVENTS_ENABLED(spe)
Definition: spe_event.c:45
spe_event_data_t data
#define SPE_MAP_PS
Definition: spebase.h:53
#define __SPE_EPOLL_FD_GET(handler)
Definition: spe_event.c:37
void _event_spe_context_unlock(spe_context_ptr_t spe)
Definition: spe_event.c:54
spe_context_ptr_t spe
#define SPE_EVENT_TAG_GROUP
struct spe_context_base_priv * base_private
Definition: libspe2-types.h:76
void _event_spe_context_lock(spe_context_ptr_t spe)
Definition: spe_event.c:49
#define SPE_EVENT_SPE_STOPPED
unsigned int flags
Definition: spebase.h:74
int __base_spe_event_source_acquire(spe_context_ptr_t spe, enum fd_name fdesc)
Definition: accessors.c:74
#define __SPE_EVENT_ALL
Definition: spe_event.c:31
#define __SPE_EVENT_CONTEXT_PRIV_GET(spe)
Definition: spe_event.c:40
#define SPE_EVENT_OUT_INTR_MBOX

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.

361 {
362  int epfd;
363  struct epoll_event *ep_events;
364  int rc;
365 
366  if (!evhandler) {
367  errno = ESRCH;
368  return -1;
369  }
370  if (!events || max_events <= 0) {
371  errno = EINVAL;
372  return -1;
373  }
374 
375  epfd = __SPE_EPOLL_FD_GET(evhandler);
376 
377  ep_events = malloc(sizeof(*ep_events) * max_events);
378  if (!ep_events) {
379  return -1;
380  }
381 
382  for ( ; ; ) {
383  rc = epoll_wait(epfd, ep_events, max_events, timeout);
384  if (rc == -1) { /* error */
385  if (errno == EINTR) {
386  if (timeout >= 0) { /* behave as timeout */
387  rc = 0;
388  break;
389  }
390  /* else retry */
391  }
392  else {
393  break;
394  }
395  }
396  else if (rc > 0) {
397  int i;
398  for (i = 0; i < rc; i++) {
399  spe_event_unit_t *ev = (spe_event_unit_t *)(ep_events[i].data.ptr);
400  _event_spe_context_lock(ev->spe); /* lock ev itself */
401  events[i] = *ev;
403  }
404  break;
405  }
406  else { /* timeout */
407  break;
408  }
409  }
410 
411  free(ep_events);
412 
413  return rc;
414 }
#define __SPE_EPOLL_FD_GET(handler)
Definition: spe_event.c:37
void _event_spe_context_unlock(spe_context_ptr_t spe)
Definition: spe_event.c:54
spe_context_ptr_t spe
void _event_spe_context_lock(spe_context_ptr_t spe)
Definition: spe_event.c:49

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.

60 {
62  int rc;
63  int fd;
64  size_t total;
65 
66  evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe);
67  fd = evctx->stop_event_pipe[0];
68 
69  pthread_mutex_lock(&evctx->stop_event_read_lock); /* for atomic read */
70 
71  rc = read(fd, stopinfo, sizeof(*stopinfo));
72  if (rc == -1) {
73  pthread_mutex_unlock(&evctx->stop_event_read_lock);
74  return -1;
75  }
76 
77  total = rc;
78  while (total < sizeof(*stopinfo)) { /* this loop will be executed in few cases */
79  struct pollfd fds;
80  fds.fd = fd;
81  fds.events = POLLIN;
82  rc = poll(&fds, 1, -1);
83  if (rc == -1) {
84  if (errno != EINTR) {
85  break;
86  }
87  }
88  else if (rc == 1) {
89  rc = read(fd, (char *)stopinfo + total, sizeof(*stopinfo) - total);
90  if (rc == -1) {
91  if (errno != EAGAIN) {
92  break;
93  }
94  }
95  else {
96  total += rc;
97  }
98  }
99  }
100 
101  pthread_mutex_unlock(&evctx->stop_event_read_lock);
102 
103  return rc == -1 ? -1 : 0;
104 }
pthread_mutex_t stop_event_read_lock
Definition: speevent.h:38
#define __SPE_EVENT_CONTEXT_PRIV_GET(spe)
Definition: spe_event.c:40