diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2016-04-10 19:12:37 +0000 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2016-04-10 19:12:37 +0000 |
commit | ff21b86d1ae552add51867028d99e13dd0121810 (patch) | |
tree | 20599bc6bd468cdf88cd660411eb4456f135f9f2 | |
parent | cf295a42e24599a1e4b6e33afa58fa724d40eb76 (diff) | |
download | libmicrohttpd-ff21b86d1ae552add51867028d99e13dd0121810.tar.gz libmicrohttpd-ff21b86d1ae552add51867028d99e13dd0121810.zip |
Use less locking with MHD_USE_THREAD_PER_CONNECTION.
Do not maintain global list out timeouts as each thread use individual timeout.
As result - global mutex is not acquired after each single send()/recv().
-rw-r--r-- | src/microhttpd/connection.c | 62 | ||||
-rw-r--r-- | src/microhttpd/daemon.c | 79 | ||||
-rw-r--r-- | src/microhttpd/internal.h | 5 |
3 files changed, 81 insertions, 65 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 3aa0d16c..e1bc1f7e 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -2132,22 +2132,19 @@ update_last_activity (struct MHD_Connection *connection) | |||
2132 | struct MHD_Daemon *daemon = connection->daemon; | 2132 | struct MHD_Daemon *daemon = connection->daemon; |
2133 | 2133 | ||
2134 | connection->last_activity = MHD_monotonic_sec_counter(); | 2134 | connection->last_activity = MHD_monotonic_sec_counter(); |
2135 | if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) | ||
2136 | return; /* each connection has personal timeout */ | ||
2137 | |||
2135 | if (connection->connection_timeout != daemon->connection_timeout) | 2138 | if (connection->connection_timeout != daemon->connection_timeout) |
2136 | return; /* custom timeout, no need to move it in "normal" DLL */ | 2139 | return; /* custom timeout, no need to move it in "normal" DLL */ |
2137 | 2140 | ||
2138 | /* move connection to head of timeout list (by remove + add operation) */ | 2141 | /* move connection to head of timeout list (by remove + add operation) */ |
2139 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && | ||
2140 | (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) ) | ||
2141 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); | ||
2142 | XDLL_remove (daemon->normal_timeout_head, | 2142 | XDLL_remove (daemon->normal_timeout_head, |
2143 | daemon->normal_timeout_tail, | 2143 | daemon->normal_timeout_tail, |
2144 | connection); | 2144 | connection); |
2145 | XDLL_insert (daemon->normal_timeout_head, | 2145 | XDLL_insert (daemon->normal_timeout_head, |
2146 | daemon->normal_timeout_tail, | 2146 | daemon->normal_timeout_tail, |
2147 | connection); | 2147 | connection); |
2148 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && | ||
2149 | (MHD_YES != MHD_mutex_unlock_ (&daemon->cleanup_connection_mutex)) ) | ||
2150 | MHD_PANIC ("Failed to release cleanup mutex\n"); | ||
2151 | } | 2148 | } |
2152 | 2149 | ||
2153 | 2150 | ||
@@ -2397,17 +2394,22 @@ cleanup_connection (struct MHD_Connection *connection) | |||
2397 | MHD_destroy_response (connection->response); | 2394 | MHD_destroy_response (connection->response); |
2398 | connection->response = NULL; | 2395 | connection->response = NULL; |
2399 | } | 2396 | } |
2400 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && | 2397 | if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) |
2401 | (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) ) | 2398 | { |
2402 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); | 2399 | if (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) |
2403 | if (connection->connection_timeout == daemon->connection_timeout) | 2400 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); |
2404 | XDLL_remove (daemon->normal_timeout_head, | 2401 | } |
2405 | daemon->normal_timeout_tail, | ||
2406 | connection); | ||
2407 | else | 2402 | else |
2408 | XDLL_remove (daemon->manual_timeout_head, | 2403 | { |
2409 | daemon->manual_timeout_tail, | 2404 | if (connection->connection_timeout == daemon->connection_timeout) |
2410 | connection); | 2405 | XDLL_remove (daemon->normal_timeout_head, |
2406 | daemon->normal_timeout_tail, | ||
2407 | connection); | ||
2408 | else | ||
2409 | XDLL_remove (daemon->manual_timeout_head, | ||
2410 | daemon->manual_timeout_tail, | ||
2411 | connection); | ||
2412 | } | ||
2411 | if (MHD_YES == connection->suspended) | 2413 | if (MHD_YES == connection->suspended) |
2412 | DLL_remove (daemon->suspended_connections_head, | 2414 | DLL_remove (daemon->suspended_connections_head, |
2413 | daemon->suspended_connections_tail, | 2415 | daemon->suspended_connections_tail, |
@@ -3040,37 +3042,33 @@ MHD_set_connection_option (struct MHD_Connection *connection, | |||
3040 | switch (option) | 3042 | switch (option) |
3041 | { | 3043 | { |
3042 | case MHD_CONNECTION_OPTION_TIMEOUT: | 3044 | case MHD_CONNECTION_OPTION_TIMEOUT: |
3043 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && | 3045 | if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && |
3044 | (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) ) | 3046 | (MHD_YES != connection->suspended) ) |
3045 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); | ||
3046 | if (MHD_YES != connection->suspended) | ||
3047 | { | 3047 | { |
3048 | if (connection->connection_timeout == daemon->connection_timeout) | 3048 | if (connection->connection_timeout == daemon->connection_timeout) |
3049 | XDLL_remove (daemon->normal_timeout_head, | 3049 | XDLL_remove (daemon->normal_timeout_head, |
3050 | daemon->normal_timeout_tail, | 3050 | daemon->normal_timeout_tail, |
3051 | connection); | 3051 | connection); |
3052 | else | 3052 | else |
3053 | XDLL_remove (daemon->manual_timeout_head, | 3053 | XDLL_remove (daemon->manual_timeout_head, |
3054 | daemon->manual_timeout_tail, | 3054 | daemon->manual_timeout_tail, |
3055 | connection); | 3055 | connection); |
3056 | } | 3056 | } |
3057 | va_start (ap, option); | 3057 | va_start (ap, option); |
3058 | connection->connection_timeout = va_arg (ap, unsigned int); | 3058 | connection->connection_timeout = va_arg (ap, unsigned int); |
3059 | va_end (ap); | 3059 | va_end (ap); |
3060 | if (MHD_YES != connection->suspended) | 3060 | if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && |
3061 | (MHD_YES != connection->suspended) ) | ||
3061 | { | 3062 | { |
3062 | if (connection->connection_timeout == daemon->connection_timeout) | 3063 | if (connection->connection_timeout == daemon->connection_timeout) |
3063 | XDLL_insert (daemon->normal_timeout_head, | 3064 | XDLL_insert (daemon->normal_timeout_head, |
3064 | daemon->normal_timeout_tail, | 3065 | daemon->normal_timeout_tail, |
3065 | connection); | 3066 | connection); |
3066 | else | 3067 | else |
3067 | XDLL_insert (daemon->manual_timeout_head, | 3068 | XDLL_insert (daemon->manual_timeout_head, |
3068 | daemon->manual_timeout_tail, | 3069 | daemon->manual_timeout_tail, |
3069 | connection); | 3070 | connection); |
3070 | } | 3071 | } |
3071 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && | ||
3072 | (MHD_YES != MHD_mutex_unlock_ (&daemon->cleanup_connection_mutex)) ) | ||
3073 | MHD_PANIC ("Failed to release cleanup mutex\n"); | ||
3074 | return MHD_YES; | 3072 | return MHD_YES; |
3075 | default: | 3073 | default: |
3076 | return MHD_NO; | 3074 | return MHD_NO; |
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index ea958204..2c5d220d 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -842,7 +842,6 @@ MHD_handle_connection (void *data) | |||
842 | MHD_socket maxsock; | 842 | MHD_socket maxsock; |
843 | struct timeval tv; | 843 | struct timeval tv; |
844 | struct timeval *tvp; | 844 | struct timeval *tvp; |
845 | unsigned int timeout; | ||
846 | time_t now; | 845 | time_t now; |
847 | #if WINDOWS | 846 | #if WINDOWS |
848 | MHD_pipe spipe = con->daemon->wpipe[0]; | 847 | MHD_pipe spipe = con->daemon->wpipe[0]; |
@@ -857,10 +856,10 @@ MHD_handle_connection (void *data) | |||
857 | struct pollfd p[1 + EXTRA_SLOTS]; | 856 | struct pollfd p[1 + EXTRA_SLOTS]; |
858 | #endif | 857 | #endif |
859 | 858 | ||
860 | timeout = con->daemon->connection_timeout; | ||
861 | while ( (MHD_YES != con->daemon->shutdown) && | 859 | while ( (MHD_YES != con->daemon->shutdown) && |
862 | (MHD_CONNECTION_CLOSED != con->state) ) | 860 | (MHD_CONNECTION_CLOSED != con->state) ) |
863 | { | 861 | { |
862 | unsigned const int timeout = con->daemon->connection_timeout; | ||
864 | tvp = NULL; | 863 | tvp = NULL; |
865 | #if HTTPS_SUPPORT | 864 | #if HTTPS_SUPPORT |
866 | if (MHD_YES == con->tls_read_ready) | 865 | if (MHD_YES == con->tls_read_ready) |
@@ -1563,12 +1562,15 @@ internal_add_connection (struct MHD_Daemon *daemon, | |||
1563 | } | 1562 | } |
1564 | #endif | 1563 | #endif |
1565 | 1564 | ||
1566 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && | 1565 | if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) |
1567 | (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) ) | 1566 | { |
1568 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); | 1567 | if (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) |
1569 | XDLL_insert (daemon->normal_timeout_head, | 1568 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); |
1570 | daemon->normal_timeout_tail, | 1569 | } |
1571 | connection); | 1570 | else |
1571 | XDLL_insert (daemon->normal_timeout_head, | ||
1572 | daemon->normal_timeout_tail, | ||
1573 | connection); | ||
1572 | DLL_insert (daemon->connections_head, | 1574 | DLL_insert (daemon->connections_head, |
1573 | daemon->connections_tail, | 1575 | daemon->connections_tail, |
1574 | connection); | 1576 | connection); |
@@ -1655,15 +1657,18 @@ internal_add_connection (struct MHD_Daemon *daemon, | |||
1655 | if (0 != MHD_socket_close_ (client_socket)) | 1657 | if (0 != MHD_socket_close_ (client_socket)) |
1656 | MHD_PANIC ("close failed\n"); | 1658 | MHD_PANIC ("close failed\n"); |
1657 | MHD_ip_limit_del (daemon, addr, addrlen); | 1659 | MHD_ip_limit_del (daemon, addr, addrlen); |
1658 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && | 1660 | if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) |
1659 | (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) ) | 1661 | { |
1660 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); | 1662 | if (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) |
1663 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); | ||
1664 | } | ||
1665 | else | ||
1666 | XDLL_remove (daemon->normal_timeout_head, | ||
1667 | daemon->normal_timeout_tail, | ||
1668 | connection); | ||
1661 | DLL_remove (daemon->connections_head, | 1669 | DLL_remove (daemon->connections_head, |
1662 | daemon->connections_tail, | 1670 | daemon->connections_tail, |
1663 | connection); | 1671 | connection); |
1664 | XDLL_remove (daemon->normal_timeout_head, | ||
1665 | daemon->normal_timeout_tail, | ||
1666 | connection); | ||
1667 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && | 1672 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && |
1668 | (MHD_YES != MHD_mutex_unlock_ (&daemon->cleanup_connection_mutex)) ) | 1673 | (MHD_YES != MHD_mutex_unlock_ (&daemon->cleanup_connection_mutex)) ) |
1669 | MHD_PANIC ("Failed to release cleanup mutex\n"); | 1674 | MHD_PANIC ("Failed to release cleanup mutex\n"); |
@@ -1712,23 +1717,28 @@ MHD_suspend_connection (struct MHD_Connection *connection) | |||
1712 | daemon = connection->daemon; | 1717 | daemon = connection->daemon; |
1713 | if (MHD_USE_SUSPEND_RESUME != (daemon->options & MHD_USE_SUSPEND_RESUME)) | 1718 | if (MHD_USE_SUSPEND_RESUME != (daemon->options & MHD_USE_SUSPEND_RESUME)) |
1714 | MHD_PANIC ("Cannot suspend connections without enabling MHD_USE_SUSPEND_RESUME!\n"); | 1719 | MHD_PANIC ("Cannot suspend connections without enabling MHD_USE_SUSPEND_RESUME!\n"); |
1715 | if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && | 1720 | if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) |
1716 | (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) ) | 1721 | { |
1717 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); | 1722 | if (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) |
1723 | MHD_PANIC ("Failed to acquire cleanup mutex\n"); | ||
1724 | } | ||
1725 | else | ||
1726 | { | ||
1727 | if (connection->connection_timeout == daemon->connection_timeout) | ||
1728 | XDLL_remove (daemon->normal_timeout_head, | ||
1729 | daemon->normal_timeout_tail, | ||
1730 | connection); | ||
1731 | else | ||
1732 | XDLL_remove (daemon->manual_timeout_head, | ||
1733 | daemon->manual_timeout_tail, | ||
1734 | connection); | ||
1735 | } | ||
1718 | DLL_remove (daemon->connections_head, | 1736 | DLL_remove (daemon->connections_head, |
1719 | daemon->connections_tail, | 1737 | daemon->connections_tail, |
1720 | connection); | 1738 | connection); |
1721 | DLL_insert (daemon->suspended_connections_head, | 1739 | DLL_insert (daemon->suspended_connections_head, |
1722 | daemon->suspended_connections_tail, | 1740 | daemon->suspended_connections_tail, |
1723 | connection); | 1741 | connection); |
1724 | if (connection->connection_timeout == daemon->connection_timeout) | ||
1725 | XDLL_remove (daemon->normal_timeout_head, | ||
1726 | daemon->normal_timeout_tail, | ||
1727 | connection); | ||
1728 | else | ||
1729 | XDLL_remove (daemon->manual_timeout_head, | ||
1730 | daemon->manual_timeout_tail, | ||
1731 | connection); | ||
1732 | #if EPOLL_SUPPORT | 1742 | #if EPOLL_SUPPORT |
1733 | if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) | 1743 | if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) |
1734 | { | 1744 | { |
@@ -1826,14 +1836,17 @@ resume_suspended_connections (struct MHD_Daemon *daemon) | |||
1826 | DLL_insert (daemon->connections_head, | 1836 | DLL_insert (daemon->connections_head, |
1827 | daemon->connections_tail, | 1837 | daemon->connections_tail, |
1828 | pos); | 1838 | pos); |
1829 | if (pos->connection_timeout == daemon->connection_timeout) | 1839 | if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) |
1830 | XDLL_insert (daemon->normal_timeout_head, | 1840 | { |
1831 | daemon->normal_timeout_tail, | 1841 | if (pos->connection_timeout == daemon->connection_timeout) |
1832 | pos); | 1842 | XDLL_insert (daemon->normal_timeout_head, |
1833 | else | 1843 | daemon->normal_timeout_tail, |
1834 | XDLL_insert (daemon->manual_timeout_head, | 1844 | pos); |
1835 | daemon->manual_timeout_tail, | 1845 | else |
1836 | pos); | 1846 | XDLL_insert (daemon->manual_timeout_head, |
1847 | daemon->manual_timeout_tail, | ||
1848 | pos); | ||
1849 | } | ||
1837 | #if EPOLL_SUPPORT | 1850 | #if EPOLL_SUPPORT |
1838 | if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) | 1851 | if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) |
1839 | { | 1852 | { |
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h index 3856a623..58317040 100644 --- a/src/microhttpd/internal.h +++ b/src/microhttpd/internal.h | |||
@@ -976,12 +976,15 @@ struct MHD_Daemon | |||
976 | * All connections by default start in this list; if a custom | 976 | * All connections by default start in this list; if a custom |
977 | * timeout that does not match @e connection_timeout is set, they | 977 | * timeout that does not match @e connection_timeout is set, they |
978 | * are moved to the @e manual_timeout_head-XDLL. | 978 | * are moved to the @e manual_timeout_head-XDLL. |
979 | * Not used in MHD_USE_THREAD_PER_CONNECTION mode as each thread | ||
980 | * needs only one connection-specific timeout. | ||
979 | */ | 981 | */ |
980 | struct MHD_Connection *normal_timeout_head; | 982 | struct MHD_Connection *normal_timeout_head; |
981 | 983 | ||
982 | /** | 984 | /** |
983 | * Tail of the XDLL of ALL connections with a default timeout, | 985 | * Tail of the XDLL of ALL connections with a default timeout, |
984 | * sorted by timeout (earliest timeout at the tail). | 986 | * sorted by timeout (earliest timeout at the tail). |
987 | * Not used in MHD_USE_THREAD_PER_CONNECTION mode. | ||
985 | */ | 988 | */ |
986 | struct MHD_Connection *normal_timeout_tail; | 989 | struct MHD_Connection *normal_timeout_tail; |
987 | 990 | ||
@@ -989,12 +992,14 @@ struct MHD_Daemon | |||
989 | * Head of the XDLL of ALL connections with a non-default/custom | 992 | * Head of the XDLL of ALL connections with a non-default/custom |
990 | * timeout, unsorted. MHD will do a O(n) scan over this list to | 993 | * timeout, unsorted. MHD will do a O(n) scan over this list to |
991 | * determine the current timeout. | 994 | * determine the current timeout. |
995 | * Not used in MHD_USE_THREAD_PER_CONNECTION mode. | ||
992 | */ | 996 | */ |
993 | struct MHD_Connection *manual_timeout_head; | 997 | struct MHD_Connection *manual_timeout_head; |
994 | 998 | ||
995 | /** | 999 | /** |
996 | * Tail of the XDLL of ALL connections with a non-default/custom | 1000 | * Tail of the XDLL of ALL connections with a non-default/custom |
997 | * timeout, unsorted. | 1001 | * timeout, unsorted. |
1002 | * Not used in MHD_USE_THREAD_PER_CONNECTION mode. | ||
998 | */ | 1003 | */ |
999 | struct MHD_Connection *manual_timeout_tail; | 1004 | struct MHD_Connection *manual_timeout_tail; |
1000 | 1005 | ||