… | |
… | |
381 | } |
381 | } |
382 | |
382 | |
383 | static void ecb_cold |
383 | static void ecb_cold |
384 | etp_thread_init (void) |
384 | etp_thread_init (void) |
385 | { |
385 | { |
|
|
386 | #if !HAVE_PREADWRITE |
|
|
387 | X_MUTEX_CREATE (preadwritelock); |
|
|
388 | #endif |
386 | X_MUTEX_CREATE (wrklock); |
389 | X_MUTEX_CREATE (wrklock); |
387 | X_MUTEX_CREATE (reslock); |
390 | X_MUTEX_CREATE (reslock); |
388 | X_MUTEX_CREATE (reqlock); |
391 | X_MUTEX_CREATE (reqlock); |
389 | X_COND_CREATE (reqwait); |
392 | X_COND_CREATE (reqwait); |
390 | } |
393 | } |
391 | |
394 | |
392 | static void ecb_cold |
395 | static void ecb_cold |
393 | etp_atfork_prepare (void) |
396 | etp_atfork_prepare (void) |
394 | { |
397 | { |
395 | X_LOCK (wrklock); |
|
|
396 | X_LOCK (reqlock); |
|
|
397 | X_LOCK (reslock); |
|
|
398 | #if !HAVE_PREADWRITE |
|
|
399 | X_LOCK (preadwritelock); |
|
|
400 | #endif |
|
|
401 | } |
398 | } |
402 | |
399 | |
403 | static void ecb_cold |
400 | static void ecb_cold |
404 | etp_atfork_parent (void) |
401 | etp_atfork_parent (void) |
405 | { |
402 | { |
406 | #if !HAVE_PREADWRITE |
|
|
407 | X_UNLOCK (preadwritelock); |
|
|
408 | #endif |
|
|
409 | X_UNLOCK (reslock); |
|
|
410 | X_UNLOCK (reqlock); |
|
|
411 | X_UNLOCK (wrklock); |
|
|
412 | } |
403 | } |
413 | |
404 | |
414 | static void ecb_cold |
405 | static void ecb_cold |
415 | etp_atfork_child (void) |
406 | etp_atfork_child (void) |
416 | { |
407 | { |
… | |
… | |
1803 | X_THREAD_PROC (etp_proc) |
1794 | X_THREAD_PROC (etp_proc) |
1804 | { |
1795 | { |
1805 | ETP_REQ *req; |
1796 | ETP_REQ *req; |
1806 | struct timespec ts; |
1797 | struct timespec ts; |
1807 | etp_worker *self = (etp_worker *)thr_arg; |
1798 | etp_worker *self = (etp_worker *)thr_arg; |
|
|
1799 | int timeout; |
1808 | |
1800 | |
1809 | /* try to distribute timeouts somewhat randomly */ |
1801 | /* try to distribute timeouts somewhat evenly */ |
1810 | ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL); |
1802 | ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL); |
1811 | |
1803 | |
1812 | for (;;) |
1804 | for (;;) |
1813 | { |
1805 | { |
|
|
1806 | ts.tv_sec = 0; |
|
|
1807 | |
1814 | X_LOCK (reqlock); |
1808 | X_LOCK (reqlock); |
1815 | |
1809 | |
1816 | for (;;) |
1810 | for (;;) |
1817 | { |
1811 | { |
1818 | self->req = req = reqq_shift (&req_queue); |
1812 | self->req = req = reqq_shift (&req_queue); |
1819 | |
1813 | |
1820 | if (req) |
1814 | if (req) |
1821 | break; |
1815 | break; |
1822 | |
1816 | |
|
|
1817 | if (ts.tv_sec == 1) /* no request, but timeout detected, let's quit */ |
|
|
1818 | { |
|
|
1819 | X_UNLOCK (reqlock); |
|
|
1820 | X_LOCK (wrklock); |
|
|
1821 | --started; |
|
|
1822 | X_UNLOCK (wrklock); |
|
|
1823 | goto quit; |
|
|
1824 | } |
|
|
1825 | |
1823 | ++idle; |
1826 | ++idle; |
1824 | |
1827 | |
1825 | ts.tv_sec = time (0) + idle_timeout; |
1828 | if (idle <= max_idle) |
1826 | if (X_COND_TIMEDWAIT (reqwait, reqlock, ts) == ETIMEDOUT) |
1829 | /* we are allowed to idle, so do so without any timeout */ |
|
|
1830 | X_COND_WAIT (reqwait, reqlock); |
|
|
1831 | else |
1827 | { |
1832 | { |
1828 | if (idle > max_idle) |
1833 | /* initialise timeout once */ |
1829 | { |
1834 | if (!ts.tv_sec) |
1830 | --idle; |
1835 | ts.tv_sec = time (0) + idle_timeout; |
1831 | X_UNLOCK (reqlock); |
|
|
1832 | X_LOCK (wrklock); |
|
|
1833 | --started; |
|
|
1834 | X_UNLOCK (wrklock); |
|
|
1835 | goto quit; |
|
|
1836 | } |
|
|
1837 | |
1836 | |
1838 | /* we are allowed to idle, so do so without any timeout */ |
|
|
1839 | X_COND_WAIT (reqwait, reqlock); |
1837 | if (X_COND_TIMEDWAIT (reqwait, reqlock, ts) == ETIMEDOUT) |
|
|
1838 | ts.tv_sec = 1; /* assuming this is not a value computed above.,.. */ |
1840 | } |
1839 | } |
1841 | |
1840 | |
1842 | --idle; |
1841 | --idle; |
1843 | } |
1842 | } |
1844 | |
1843 | |