00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdlib.h>
00023 #include "speevent.h"
00024
00025 #include <errno.h>
00026 #include <unistd.h>
00027 #include <sys/epoll.h>
00028 #include <poll.h>
00029 #include <fcntl.h>
00030
00031 #define __SPE_EVENT_ALL \
00032 ( SPE_EVENT_OUT_INTR_MBOX | SPE_EVENT_IN_MBOX | \
00033 SPE_EVENT_TAG_GROUP | SPE_EVENT_SPE_STOPPED )
00034
00035 #define __SPE_EPOLL_SIZE 10
00036
00037 #define __SPE_EPOLL_FD_GET(handler) (*(int*)(handler))
00038 #define __SPE_EPOLL_FD_SET(handler, fd) (*(int*)(handler) = (fd))
00039
00040 #define __SPE_EVENT_CONTEXT_PRIV_GET(spe) \
00041 ( (spe_context_event_priv_ptr_t)(spe)->event_private)
00042 #define __SPE_EVENT_CONTEXT_PRIV_SET(spe, evctx) \
00043 ( (spe)->event_private = (evctx) )
00044
00045 #define __SPE_EVENTS_ENABLED(spe) \
00046 ((spe)->base_private->flags & SPE_EVENTS_ENABLE)
00047
00048
00049 void _event_spe_context_lock(spe_context_ptr_t spe)
00050 {
00051 pthread_mutex_lock(&__SPE_EVENT_CONTEXT_PRIV_GET(spe)->lock);
00052 }
00053
00054 void _event_spe_context_unlock(spe_context_ptr_t spe)
00055 {
00056 pthread_mutex_unlock(&__SPE_EVENT_CONTEXT_PRIV_GET(spe)->lock);
00057 }
00058
00059 int _event_spe_stop_info_read (spe_context_ptr_t spe, spe_stop_info_t *stopinfo)
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);
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)) {
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 }
00105
00106
00107
00108
00109
00110 spe_event_handler_ptr_t _event_spe_event_handler_create(void)
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 }
00130
00131
00132
00133
00134
00135 int _event_spe_event_handler_destroy (spe_event_handler_ptr_t evhandler)
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 }
00150
00151
00152
00153
00154
00155 int _event_spe_event_handler_register(spe_event_handler_ptr_t evhandler, spe_event_unit_t *event)
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);
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 }
00269
00270
00271
00272
00273 int _event_spe_event_handler_deregister(spe_event_handler_ptr_t evhandler, spe_event_unit_t *event)
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);
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 }
00355
00356
00357
00358
00359
00360 int _event_spe_event_wait(spe_event_handler_ptr_t evhandler, spe_event_unit_t *events, int max_events, int timeout)
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) {
00385 if (errno == EINTR) {
00386 if (timeout >= 0) {
00387 rc = 0;
00388 break;
00389 }
00390
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);
00401 events[i] = *ev;
00402 _event_spe_context_unlock(ev->spe);
00403 }
00404 break;
00405 }
00406 else {
00407 break;
00408 }
00409 }
00410
00411 free(ep_events);
00412
00413 return rc;
00414 }
00415
00416 int _event_spe_context_finalize(spe_context_ptr_t spe)
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 }
00438
00439 struct spe_context_event_priv * _event_spe_context_initialize(spe_context_ptr_t spe)
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 }
00476
00477 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)
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
00491 }
00492
00493 return rc;
00494 }
00495