Changeset 04aaf954817d7e85e9daf2feb52c9411d1acb30f
- Timestamp:
- 12/04/08 22:19:49 (5 years ago)
- git-parent:
- Files:
-
- src/eventer/eventer.h (modified) (2 diffs)
- src/eventer/eventer_epoll_impl.c (modified) (4 diffs)
- src/eventer/eventer_kqueue_impl.c (modified) (4 diffs)
- src/eventer/eventer_ports_impl.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
src/eventer/eventer.h
rdf2e1eb r04aaf95 78 78 eventer_t (*remove_fd)(int fd); 79 79 eventer_t (*find_fd)(int fd); 80 void (*trigger)(eventer_t e, int mask); 80 81 int (*loop)(); 81 82 } *eventer_impl_t; … … 99 100 #define eventer_find_fd __eventer->find_fd 100 101 #define eventer_loop __eventer->loop 102 #define eventer_trigger __eventer->trigger 101 103 102 104 extern eventer_impl_t registered_eventers[]; src/eventer/eventer_epoll_impl.c
rdf2e1eb r04aaf95 196 196 static eventer_t eventer_epoll_impl_find_fd(int fd) { 197 197 return master_fds[fd].e; 198 } 199 200 static void eventer_epoll_impl_trigger(eventer_t e, int mask) { 201 struct timeval __now; 202 int fd, oldmask, newmask; 203 const char *cbname; 204 ev_lock_state_t lockstate; 205 206 fd = e->fd; 207 if(e != master_fds[fd].e) return; 208 lockstate = acquire_master_fd(fd); 209 if(lockstate == EV_ALREADY_OWNED) return; 210 assert(lockstate == EV_OWNED); 211 212 gettimeofday(&__now, NULL); 213 oldmask = e->mask; 214 cbname = eventer_name_for_callback(e->callback); 215 noitLT(eventer_deb, &__now, "epoll: fire on %d/%x to %s(%p)\n", 216 fd, mask, cbname?cbname:"???", e->callback); 217 newmask = e->callback(e, mask, e->closure, &__now); 218 219 if(newmask) { 220 struct epoll_event _ev; 221 memset(&_ev, 0, sizeof(_ev)); 222 _ev.data.fd = fd; 223 if(newmask & EVENTER_READ) _ev.events |= (EPOLLIN|EPOLLPRI); 224 if(newmask & EVENTER_WRITE) _ev.events |= (EPOLLOUT); 225 if(newmask & EVENTER_EXCEPTION) _ev.events |= (EPOLLERR|EPOLLHUP); 226 epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &_ev); 227 /* Set our mask */ 228 e->mask = newmask; 229 } 230 else { 231 /* see kqueue implementation for details on the next line */ 232 if(master_fds[fd].e == e) master_fds[fd].e = NULL; 233 eventer_free(e); 234 } 235 release_master_fd(fd, lockstate); 198 236 } 199 237 static int eventer_epoll_impl_loop() { … … 269 307 for(idx = 0; idx < fd_cnt; idx++) { 270 308 struct epoll_event *ev; 271 const char *cbname;272 ev_lock_state_t lockstate;273 309 eventer_t e; 274 int fd, oldmask,mask = 0;310 int fd, mask = 0; 275 311 276 312 ev = &epev[idx]; … … 281 317 282 318 fd = ev->data.fd; 319 283 320 e = master_fds[fd].e; 284 321 /* It's possible that someone removed the event and freed it … … 287 324 if(!e) continue; 288 325 289 290 lockstate = acquire_master_fd(fd); 291 assert(lockstate == EV_OWNED); 292 293 gettimeofday(&__now, NULL); 294 oldmask = e->mask; 295 cbname = eventer_name_for_callback(e->callback); 296 noitLT(eventer_deb, &__now, "epoll: fire on %d/%x to %s(%p)\n", 297 fd, mask, cbname?cbname:"???", e->callback); 298 newmask = e->callback(e, mask, e->closure, &__now); 299 300 if(newmask) { 301 struct epoll_event _ev; 302 memset(&_ev, 0, sizeof(_ev)); 303 _ev.data.fd = fd; 304 if(newmask & EVENTER_READ) _ev.events |= (EPOLLIN|EPOLLPRI); 305 if(newmask & EVENTER_WRITE) _ev.events |= (EPOLLOUT); 306 if(newmask & EVENTER_EXCEPTION) _ev.events |= (EPOLLERR|EPOLLHUP); 307 epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &_ev); 308 /* Set our mask */ 309 e->mask = newmask; 310 } 311 else { 312 /* see kqueue implementation for details on the next line */ 313 if(master_fds[fd].e == e) master_fds[fd].e = NULL; 314 eventer_free(e); 315 } 316 release_master_fd(fd, lockstate); 326 eventer_epoll_impl_trigger(e, mask); 317 327 } 318 328 } src/eventer/eventer_kqueue_impl.c
rdf2e1eb r04aaf95 251 251 static eventer_t eventer_kqueue_impl_find_fd(int fd) { 252 252 return master_fds[fd].e; 253 } 254 static void eventer_kqueue_impl_trigger(eventer_t e, int mask) { 255 ev_lock_state_t lockstate; 256 struct timeval __now; 257 int oldmask, newmask; 258 const char *cbname; 259 int fd; 260 261 fd = e->fd; 262 if(e != master_fds[fd].e) return; 263 lockstate = acquire_master_fd(fd); 264 if(lockstate == EV_ALREADY_OWNED) return; 265 assert(lockstate == EV_OWNED); 266 267 gettimeofday(&__now, NULL); 268 oldmask = e->mask; 269 cbname = eventer_name_for_callback(e->callback); 270 noitLT(eventer_deb, &__now, "kqueue: fire on %d/%x to %s(%p)\n", 271 fd, masks[fd], cbname?cbname:"???", e->callback); 272 newmask = e->callback(e, mask, e->closure, &__now); 273 274 if(newmask) { 275 /* toggle the read bits if needed */ 276 if(newmask & (EVENTER_READ | EVENTER_EXCEPTION)) { 277 if(!(oldmask & (EVENTER_READ | EVENTER_EXCEPTION))) 278 ke_change(fd, EVFILT_READ, EV_ADD | EV_ENABLE, e); 279 } 280 else if(oldmask & (EVENTER_READ | EVENTER_EXCEPTION)) 281 ke_change(fd, EVFILT_READ, EV_DELETE | EV_DISABLE, e); 282 283 /* toggle the write bits if needed */ 284 if(newmask & EVENTER_WRITE) { 285 if(!(oldmask & EVENTER_WRITE)) 286 ke_change(fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, e); 287 } 288 else if(oldmask & EVENTER_WRITE) 289 ke_change(fd, EVFILT_WRITE, EV_DELETE | EV_DISABLE, e); 290 291 /* Set our mask */ 292 e->mask = newmask; 293 } 294 else { 295 /* 296 * Long story long: 297 * When integrating with a few external event systems, we find 298 * it difficult to make their use of remove+add as an update 299 * as it can be recurrent in a single handler call and you cannot 300 * remove completely from the event system if you are going to 301 * just update (otherwise the eventer_t in your call stack could 302 * be stale). What we do is perform a superficial remove, marking 303 * the mask as 0, but not eventer_remove_fd. Then on an add, if 304 * we already have an event, we just update the mask (as we 305 * have not yet returned to the eventer's loop. 306 * This leaves us in a tricky situation when a remove is called 307 * and the add doesn't roll in, we return 0 (mask == 0) and hit 308 * this spot. We have intended to remove the event, but it still 309 * resides at master_fds[fd].e -- even after we free it. 310 * So, in the evnet that we return 0 and the event that 311 * master_fds[fd].e == the event we're about to free... we NULL 312 * it out. 313 */ 314 if(master_fds[fd].e == e) master_fds[fd].e = NULL; 315 eventer_free(e); 316 } 317 release_master_fd(fd, lockstate); 253 318 } 254 319 static int eventer_kqueue_impl_loop() { … … 366 431 /* Loop a last time to process */ 367 432 for(idx = 0; idx < fd_cnt; idx++) { 368 ev_lock_state_t lockstate;369 433 struct kevent *ke; 370 434 eventer_t e; 371 int fd , oldmask;435 int fd; 372 436 373 437 ke = &ke_vec[idx]; 374 438 if(ke->flags & EV_ERROR) { 375 439 if(ke->data != EBADF) 376 noitLT(eventer_err, &__now, "error: %s\n", strerror(ke->data)); 440 noitLT(eventer_err, &__now, "error [%d]: %s\n", 441 (int)ke->ident, strerror(ke->data)); 377 442 continue; 378 443 } … … 384 449 * before we got here. 385 450 */ 386 if(e != master_fds[fd].e) continue; 387 lockstate = acquire_master_fd(fd); 388 assert(lockstate == EV_OWNED); 389 390 gettimeofday(&__now, NULL); 391 oldmask = e->mask; 392 cbname = eventer_name_for_callback(e->callback); 393 noitLT(eventer_deb, &__now, "kqueue: fire on %d/%x to %s(%p)\n", 394 fd, masks[fd], cbname?cbname:"???", e->callback); 395 newmask = e->callback(e, masks[fd], e->closure, &__now); 451 eventer_kqueue_impl_trigger(e, masks[fd]); 396 452 masks[fd] = 0; /* indicates we've processed this fd */ 397 398 if(newmask) {399 /* toggle the read bits if needed */400 if(newmask & (EVENTER_READ | EVENTER_EXCEPTION)) {401 if(!(oldmask & (EVENTER_READ | EVENTER_EXCEPTION)))402 ke_change(fd, EVFILT_READ, EV_ADD | EV_ENABLE, e);403 }404 else if(oldmask & (EVENTER_READ | EVENTER_EXCEPTION))405 ke_change(fd, EVFILT_READ, EV_DELETE | EV_DISABLE, e);406 407 /* toggle the write bits if needed */408 if(newmask & EVENTER_WRITE) {409 if(!(oldmask & EVENTER_WRITE))410 ke_change(fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, e);411 }412 else if(oldmask & EVENTER_WRITE)413 ke_change(fd, EVFILT_WRITE, EV_DELETE | EV_DISABLE, e);414 415 /* Set our mask */416 e->mask = newmask;417 }418 else {419 /*420 * Long story long:421 * When integrating with a few external event systems, we find422 * it difficult to make their use of remove+add as an update423 * as it can be recurrent in a single handler call and you cannot424 * remove completely from the event system if you are going to425 * just update (otherwise the eventer_t in your call stack could426 * be stale). What we do is perform a superficial remove, marking427 * the mask as 0, but not eventer_remove_fd. Then on an add, if428 * we already have an event, we just update the mask (as we429 * have not yet returned to the eventer's loop.430 * This leaves us in a tricky situation when a remove is called431 * and the add doesn't roll in, we return 0 (mask == 0) and hit432 * this spot. We have intended to remove the event, but it still433 * resides at master_fds[fd].e -- even after we free it.434 * So, in the evnet that we return 0 and the event that435 * master_fds[fd].e == the event we're about to free... we NULL436 * it out.437 */438 if(master_fds[fd].e == e) master_fds[fd].e = NULL;439 eventer_free(e);440 }441 release_master_fd(fd, lockstate);442 453 } 443 454 } … … 456 467 eventer_kqueue_impl_remove_fd, 457 468 eventer_kqueue_impl_find_fd, 469 eventer_kqueue_impl_trigger, 458 470 eventer_kqueue_impl_loop 459 471 }; src/eventer/eventer_ports_impl.c
rdf2e1eb r04aaf95 201 201 static eventer_t eventer_ports_impl_find_fd(int fd) { 202 202 return master_fds[fd].e; 203 } 204 static void 205 eventer_ports_impl_trigger(eventer_t e, int mask) { 206 ev_lock_state_t lockstate; 207 const char *cbname; 208 struct timeval __now; 209 int fd, oldmask, newmask; 210 211 fd = e->fd; 212 if(e != master_fds[fd].e) return; 213 lockstate = acquire_master_fd(fd); 214 if(lockstate == EV_ALREADY_OWNED) return; 215 assert(lockstate == EV_OWNED); 216 217 gettimeofday(&__now, NULL); 218 oldmask = e->mask; 219 cbname = eventer_name_for_callback(e->callback); 220 noitLT(eventer_deb, &__now, "ports: fire on %d/%x to %s(%p)\n", 221 fd, mask, cbname?cbname:"???", e->callback); 222 newmask = e->callback(e, mask, e->closure, &__now); 223 224 if(newmask) { 225 alter_fd(e, newmask); 226 /* Set our mask */ 227 e->mask = newmask; 228 } 229 else { 230 /* 231 * Long story long: 232 * When integrating with a few external event systems, we find 233 * it difficult to make their use of remove+add as an update 234 * as it can be recurrent in a single handler call and you cannot 235 * remove completely from the event system if you are going to 236 * just update (otherwise the eventer_t in your call stack could 237 * be stale). What we do is perform a superficial remove, marking 238 * the mask as 0, but not eventer_remove_fd. Then on an add, if 239 * we already have an event, we just update the mask (as we 240 * have not yet returned to the eventer's loop. 241 * This leaves us in a tricky situation when a remove is called 242 * and the add doesn't roll in, we return 0 (mask == 0) and hit 243 * this spot. We have intended to remove the event, but it still 244 * resides at master_fds[fd].e -- even after we free it. 245 * So, in the evnet that we return 0 and the event that 246 * master_fds[fd].e == the event we're about to free... we NULL 247 * it out. 248 */ 249 if(master_fds[fd].e == e) master_fds[fd].e = NULL; 250 eventer_free(e); 251 } 252 release_master_fd(fd, lockstate); 203 253 } 204 254 static int eventer_ports_impl_loop() { … … 285 335 /* Loop a last time to process */ 286 336 for(idx = 0; idx < fd_cnt; idx++) { 287 ev_lock_state_t lockstate;288 337 port_event_t *pe; 289 338 eventer_t e; … … 305 354 * before we got here. 306 355 */ 307 if(e != master_fds[fd].e) continue; 308 lockstate = acquire_master_fd(fd); 309 assert(lockstate == EV_OWNED); 310 311 gettimeofday(&__now, NULL); 312 oldmask = e->mask; 313 cbname = eventer_name_for_callback(e->callback); 314 noitLT(eventer_deb, &__now, "ports: fire on %d/%x to %s(%p)\n", 315 fd, mask, cbname?cbname:"???", e->callback); 316 newmask = e->callback(e, mask, e->closure, &__now); 317 318 if(newmask) { 319 alter_fd(e, newmask); 320 /* Set our mask */ 321 e->mask = newmask; 322 } 323 else { 324 /* 325 * Long story long: 326 * When integrating with a few external event systems, we find 327 * it difficult to make their use of remove+add as an update 328 * as it can be recurrent in a single handler call and you cannot 329 * remove completely from the event system if you are going to 330 * just update (otherwise the eventer_t in your call stack could 331 * be stale). What we do is perform a superficial remove, marking 332 * the mask as 0, but not eventer_remove_fd. Then on an add, if 333 * we already have an event, we just update the mask (as we 334 * have not yet returned to the eventer's loop. 335 * This leaves us in a tricky situation when a remove is called 336 * and the add doesn't roll in, we return 0 (mask == 0) and hit 337 * this spot. We have intended to remove the event, but it still 338 * resides at master_fds[fd].e -- even after we free it. 339 * So, in the evnet that we return 0 and the event that 340 * master_fds[fd].e == the event we're about to free... we NULL 341 * it out. 342 */ 343 if(master_fds[fd].e == e) master_fds[fd].e = NULL; 344 eventer_free(e); 345 } 346 release_master_fd(fd, lockstate); 356 eventer_ports_impl_trigger(e, mask); 347 357 } 348 358 } … … 360 370 eventer_ports_impl_remove_fd, 361 371 eventer_ports_impl_find_fd, 372 eventer_ports_impl_trigger, 362 373 eventer_ports_impl_loop 363 374 };
