… | |
… | |
492 | #define ecb_inline static inline |
492 | #define ecb_inline static inline |
493 | #else |
493 | #else |
494 | #define ecb_inline static |
494 | #define ecb_inline static |
495 | #endif |
495 | #endif |
496 | |
496 | |
|
|
497 | #ifndef ECB_MEMORY_FENCE |
|
|
498 | #if ECB_GCC_VERSION(2,5) |
|
|
499 | #if __x86 |
|
|
500 | #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory") |
|
|
501 | #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE |
|
|
502 | #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE /* better be safe than sorry */ |
|
|
503 | #elif __amd64 |
|
|
504 | #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory") |
|
|
505 | #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("lfence" : : : "memory") |
|
|
506 | #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("sfence") |
|
|
507 | #endif |
|
|
508 | #endif |
|
|
509 | #endif |
|
|
510 | |
|
|
511 | #ifndef ECB_MEMORY_FENCE |
|
|
512 | #if ECB_GCC_VERSION(4,4) |
|
|
513 | #define ECB_MEMORY_FENCE __sync_synchronize () |
|
|
514 | #define ECB_MEMORY_FENCE_ACQUIRE ({ char dummy = 0; __sync_lock_test_and_set (&dummy, 1); }) |
|
|
515 | #define ECB_MEMORY_FENCE_RELEASE ({ char dummy = 1; __sync_lock_release (&dummy ); }) |
|
|
516 | #elif _MSC_VER >= 1400 /* VC++ 2005 */ |
|
|
517 | #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier) |
|
|
518 | #define ECB_MEMORY_FENCE _ReadWriteBarrier () |
|
|
519 | #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */ |
|
|
520 | #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier () |
|
|
521 | #elif defined(_WIN32) |
|
|
522 | #include <WinNT.h> |
|
|
523 | #define ECB_MEMORY_FENCE MemoryBarrier () |
|
|
524 | #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE |
|
|
525 | #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE |
|
|
526 | #endif |
|
|
527 | #endif |
|
|
528 | |
|
|
529 | #ifndef ECB_MEMORY_FENCE |
|
|
530 | #include <pthread.h> |
|
|
531 | |
|
|
532 | static pthread_mutex_t ecb_mf_lock = PTHREAD_MUTEX_INITIALIZER; |
|
|
533 | #define ECB_MEMORY_FENCE do { pthread_mutex_lock (&ecb_mf_lock); pthread_mutex_unlock (&ecb_mf_lock); } while (0) |
|
|
534 | #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE |
|
|
535 | #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE |
|
|
536 | #endif |
|
|
537 | |
497 | #if ECB_GCC_VERSION(3,1) |
538 | #if ECB_GCC_VERSION(3,1) |
498 | #define ecb_attribute(attrlist) __attribute__(attrlist) |
539 | #define ecb_attribute(attrlist) __attribute__(attrlist) |
499 | #define ecb_is_constant(expr) __builtin_constant_p (expr) |
540 | #define ecb_is_constant(expr) __builtin_constant_p (expr) |
500 | #define ecb_expect(expr,value) __builtin_expect ((expr),(value)) |
541 | #define ecb_expect(expr,value) __builtin_expect ((expr),(value)) |
501 | #define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality) |
542 | #define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality) |
… | |
… | |
964 | memset ((void *)(base), 0, sizeof (*(base)) * (count)) |
1005 | memset ((void *)(base), 0, sizeof (*(base)) * (count)) |
965 | |
1006 | |
966 | #define array_needsize(type,base,cur,cnt,init) \ |
1007 | #define array_needsize(type,base,cur,cnt,init) \ |
967 | if (expect_false ((cnt) > (cur))) \ |
1008 | if (expect_false ((cnt) > (cur))) \ |
968 | { \ |
1009 | { \ |
969 | int ocur_ = (cur); \ |
1010 | int ecb_unused ocur_ = (cur); \ |
970 | (base) = (type *)array_realloc \ |
1011 | (base) = (type *)array_realloc \ |
971 | (sizeof (type), (base), &(cur), (cnt)); \ |
1012 | (sizeof (type), (base), &(cur), (cnt)); \ |
972 | init ((base) + (ocur_), (cur) - ocur_); \ |
1013 | init ((base) + (ocur_), (cur) - ocur_); \ |
973 | } |
1014 | } |
974 | |
1015 | |
… | |
… | |
1420 | } |
1461 | } |
1421 | |
1462 | |
1422 | inline_speed void |
1463 | inline_speed void |
1423 | evpipe_write (EV_P_ EV_ATOMIC_T *flag) |
1464 | evpipe_write (EV_P_ EV_ATOMIC_T *flag) |
1424 | { |
1465 | { |
1425 | if (!*flag) |
1466 | if (expect_true (*flag)) |
1426 | { |
1467 | return; |
|
|
1468 | |
1427 | *flag = 1; |
1469 | *flag = 1; |
1428 | |
1470 | |
|
|
1471 | ECB_MEMORY_FENCE_RELEASE; /* make sure flag is visible before the wakeup */ |
|
|
1472 | |
1429 | pipe_write_skipped = 1; |
1473 | pipe_write_skipped = 1; |
1430 | |
1474 | |
|
|
1475 | ECB_MEMORY_FENCE; /* make sure pipe_write_skipped is visible before we check pipe_write_wanted */ |
|
|
1476 | |
1431 | if (pipe_write_wanted) |
1477 | if (pipe_write_wanted) |
|
|
1478 | { |
|
|
1479 | int old_errno; |
|
|
1480 | |
|
|
1481 | pipe_write_skipped = 0; /* just an optimsiation, no fence needed */ |
|
|
1482 | |
|
|
1483 | old_errno = errno; /* save errno because write will clobber it */ |
|
|
1484 | |
|
|
1485 | #if EV_USE_EVENTFD |
|
|
1486 | if (evfd >= 0) |
1432 | { |
1487 | { |
1433 | int old_errno; |
|
|
1434 | |
|
|
1435 | pipe_write_skipped = 0; |
|
|
1436 | |
|
|
1437 | old_errno = errno; /* save errno because write will clobber it */ |
|
|
1438 | |
|
|
1439 | #if EV_USE_EVENTFD |
|
|
1440 | if (evfd >= 0) |
|
|
1441 | { |
|
|
1442 | uint64_t counter = 1; |
1488 | uint64_t counter = 1; |
1443 | write (evfd, &counter, sizeof (uint64_t)); |
1489 | write (evfd, &counter, sizeof (uint64_t)); |
1444 | } |
|
|
1445 | else |
|
|
1446 | #endif |
|
|
1447 | { |
|
|
1448 | /* win32 people keep sending patches that change this write() to send() */ |
|
|
1449 | /* and then run away. but send() is wrong, it wants a socket handle on win32 */ |
|
|
1450 | /* so when you think this write should be a send instead, please find out */ |
|
|
1451 | /* where your send() is from - it's definitely not the microsoft send, and */ |
|
|
1452 | /* tell me. thank you. */ |
|
|
1453 | write (evpipe [1], &(evpipe [1]), 1); |
|
|
1454 | } |
|
|
1455 | |
|
|
1456 | errno = old_errno; |
|
|
1457 | } |
1490 | } |
|
|
1491 | else |
|
|
1492 | #endif |
|
|
1493 | { |
|
|
1494 | /* win32 people keep sending patches that change this write() to send() */ |
|
|
1495 | /* and then run away. but send() is wrong, it wants a socket handle on win32 */ |
|
|
1496 | /* so when you think this write should be a send instead, please find out */ |
|
|
1497 | /* where your send() is from - it's definitely not the microsoft send, and */ |
|
|
1498 | /* tell me. thank you. */ |
|
|
1499 | write (evpipe [1], &(evpipe [1]), 1); |
|
|
1500 | } |
|
|
1501 | |
|
|
1502 | errno = old_errno; |
1458 | } |
1503 | } |
1459 | } |
1504 | } |
1460 | |
1505 | |
1461 | /* called whenever the libev signal pipe */ |
1506 | /* called whenever the libev signal pipe */ |
1462 | /* got some events (signal, async) */ |
1507 | /* got some events (signal, async) */ |
… | |
… | |
1520 | |
1565 | |
1521 | if (!EV_A) |
1566 | if (!EV_A) |
1522 | return; |
1567 | return; |
1523 | #endif |
1568 | #endif |
1524 | |
1569 | |
1525 | evpipe_init (EV_A); |
1570 | if (!ev_active (&pipe_w)) |
|
|
1571 | return; |
1526 | |
1572 | |
1527 | signals [signum - 1].pending = 1; |
1573 | signals [signum - 1].pending = 1; |
1528 | evpipe_write (EV_A_ &sig_pending); |
1574 | evpipe_write (EV_A_ &sig_pending); |
1529 | } |
1575 | } |
1530 | |
1576 | |
… | |
… | |
2572 | time_update (EV_A_ 1e100); |
2618 | time_update (EV_A_ 1e100); |
2573 | |
2619 | |
2574 | /* from now on, we want a pipe-wake-up */ |
2620 | /* from now on, we want a pipe-wake-up */ |
2575 | pipe_write_wanted = 1; |
2621 | pipe_write_wanted = 1; |
2576 | |
2622 | |
|
|
2623 | ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */ |
|
|
2624 | |
2577 | if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped))) |
2625 | if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped))) |
2578 | { |
2626 | { |
2579 | waittime = MAX_BLOCKTIME; |
2627 | waittime = MAX_BLOCKTIME; |
2580 | |
2628 | |
2581 | if (timercnt) |
2629 | if (timercnt) |
… | |
… | |
2622 | #endif |
2670 | #endif |
2623 | assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */ |
2671 | assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */ |
2624 | backend_poll (EV_A_ waittime); |
2672 | backend_poll (EV_A_ waittime); |
2625 | assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */ |
2673 | assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */ |
2626 | |
2674 | |
2627 | pipe_write_wanted = 0; |
2675 | pipe_write_wanted = 0; /* just an optimsiation, no fence needed */ |
2628 | |
2676 | |
2629 | if (pipe_write_skipped) |
2677 | if (pipe_write_skipped) |
2630 | { |
2678 | { |
2631 | assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w))); |
2679 | assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w))); |
2632 | ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); |
2680 | ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); |
… | |
… | |
3982 | cb (EV_A_ EV_PERIODIC, ANHE_w (periodics [i])); |
4030 | cb (EV_A_ EV_PERIODIC, ANHE_w (periodics [i])); |
3983 | #endif |
4031 | #endif |
3984 | |
4032 | |
3985 | #if EV_IDLE_ENABLE |
4033 | #if EV_IDLE_ENABLE |
3986 | if (types & EV_IDLE) |
4034 | if (types & EV_IDLE) |
3987 | for (j = NUMPRI; i--; ) |
4035 | for (j = NUMPRI; j--; ) |
3988 | for (i = idlecnt [j]; i--; ) |
4036 | for (i = idlecnt [j]; i--; ) |
3989 | cb (EV_A_ EV_IDLE, idles [j][i]); |
4037 | cb (EV_A_ EV_IDLE, idles [j][i]); |
3990 | #endif |
4038 | #endif |
3991 | |
4039 | |
3992 | #if EV_FORK_ENABLE |
4040 | #if EV_FORK_ENABLE |