# HG changeset patch # User Igor Sysoev # Date 1088359317 0 # Node ID 54f76b0b8dcae05989953733e7049e653b308f2b # Parent 9c2515d704894008fbb0d29bd97c5b88211a2ffb nginx-0.0.7-2004-06-27-22:01:57 import diff --git a/auto/endianess b/auto/endianess new file mode 100644 --- /dev/null +++ b/auto/endianess @@ -0,0 +1,38 @@ + +echo $ngx_n "checking for system endianess ..." $ngx_c +echo >> $NGX_ERR +echo "checking for system endianess" >> $NGX_ERR + + +cat << END > $NGX_AUTOTEST.c + +int main() { + int i = 0x11223344; + char *p; + + p = (char *) &i; + if (*p == 0x44) return 0; + return 1; +} + +END + +eval "${CC} -o $NGX_AUTOTEST $NGX_AUTOTEST.c >> $NGX_ERR 2>&1" + +if [ -x $NGX_AUTOTEST ]; then + if $NGX_AUTOTEST 2>&1 > /dev/null; then + echo " little endianess" + have=HAVE_LITTLE_ENDIAN . auto/have + else + echo " big endianess" + fi + + rm $NGX_AUTOTEST* + +else + rm $NGX_AUTOTEST* + + echo + echo "$0: error: can not detect system endianess" + exit 1 +fi diff --git a/auto/fmt/fmt b/auto/fmt/fmt --- a/auto/fmt/fmt +++ b/auto/fmt/fmt @@ -11,15 +11,15 @@ do cat << END > $NGX_AUTOTEST.c -#include #include #include +#include #include $NGX_INTTYPES_H $NGX_AUTO_CONFIG int main() { - printf("$fmt", ($ngx_type) $ngx_max_size); + printf("$fmt", ($ngx_type) $ngx_max_value); return 0; } @@ -28,10 +28,10 @@ END eval "$CC_WARN $CC_TEST_FLAGS -o $NGX_AUTOTEST $NGX_AUTOTEST.c \ >> $NGX_ERR 2>&1" - max_size=`echo $ngx_max_size | sed -e "s/L*\$//"` + max_value=`echo $ngx_max_value | sed -e "s/L*\$//"` if [ -x $NGX_AUTOTEST ]; then - if [ "`$NGX_AUTOTEST`" = $max_size ]; then + if [ "`$NGX_AUTOTEST`" = $max_value ]; then if [ $ngx_fmt_collect = yes ]; then echo $ngx_n "$comma \"${fmt}\" is appropriate" $ngx_c else @@ -45,7 +45,7 @@ END if [ $ngx_fmt != no ]; then if [ $ngx_fmt_collect = yes ]; then - eval "ngx_${ngx_bytes}_fmt=\"\${ngx_${ngx_bytes}_fmt} \$ngx_fmt\"" + eval "ngx_${ngx_size}_fmt=\"\${ngx_${ngx_size}_fmt} \$ngx_fmt\"" comma="," continue else diff --git a/auto/fmt/ptrfmt b/auto/fmt/ptrfmt --- a/auto/fmt/ptrfmt +++ b/auto/fmt/ptrfmt @@ -13,7 +13,7 @@ do cat << END > $NGX_AUTOTEST.c int main() { - printf("$fmt", ($ngx_type) $ngx_max_size); + printf("$fmt", ($ngx_type) $ngx_max_value); return 0; } @@ -22,10 +22,10 @@ END eval "$CC_WARN $CC_TEST_FLAGS -o $NGX_AUTOTEST $NGX_AUTOTEST.c \ >> $NGX_ERR 2>&1" - max_size=`echo $ngx_max_size | sed -e "s/L*\$//"` + max_value=`echo $ngx_max_value | sed -e "s/L*\$//"` if [ -x $NGX_AUTOTEST ]; then - if [ "`$NGX_AUTOTEST`" = $max_size ]; then + if [ "`$NGX_AUTOTEST`" = $max_value ]; then ngx_fmt=$fmt fi fi @@ -49,8 +49,8 @@ if [ $ngx_fmt = no ]; then fi -if [ $ngx_ptr_bytes = 4 ]; then - fmtX="%0`expr 2 \* $ngx_ptr_bytes`" +if [ $ngx_ptr_size = 4 ]; then + fmtX="%0`expr 2 \* $ngx_ptr_size`" else fmtX="%" fi diff --git a/auto/types/sizeof b/auto/types/sizeof --- a/auto/types/sizeof +++ b/auto/types/sizeof @@ -3,14 +3,15 @@ echo $ngx_n "checking for $ngx_type size echo >> $NGX_ERR echo "checking for $ngx_type size" >> $NGX_ERR -ngx_bytes= +ngx_size= cat << END > $NGX_AUTOTEST.c #include #include +$NGX_UNISTD_H +#include #include -$NGX_UNISTD_H $NGX_INTTYPES_H $NGX_AUTO_CONFIG @@ -24,27 +25,31 @@ END eval "$CC $CC_TEST_FLAGS -o $NGX_AUTOTEST $NGX_AUTOTEST.c >> $NGX_ERR 2>&1" if [ -x $NGX_AUTOTEST ]; then - ngx_bytes=`$NGX_AUTOTEST` - echo " $ngx_bytes bytes" + ngx_size=`$NGX_AUTOTEST` + echo " $ngx_size bytes" fi rm $NGX_AUTOTEST* -case $ngx_bytes in +case $ngx_size in 4) if [ "$ngx_type"="long" ]; then - ngx_max_size=2147483647L + ngx_max_value=2147483647L else - ngx_max_size=2147483647 + ngx_max_value=2147483647 fi + + ngx_max_len='sizeof("-2147483648") - 1' ;; 8) if [ "$ngx_type"="long long" ]; then - ngx_max_size=9223372036854775807LL + ngx_max_value=9223372036854775807LL else - ngx_max_size=9223372036854775807L + ngx_max_value=9223372036854775807L fi + + ngx_max_len='sizeof("-9223372036854775808") - 1' ;; *) diff --git a/auto/types/typedef b/auto/types/typedef --- a/auto/types/typedef +++ b/auto/types/typedef @@ -10,8 +10,8 @@ do cat << END > $NGX_AUTOTEST.c +#include #include -#include #include #include #include diff --git a/auto/types/uintptr_t b/auto/types/uintptr_t --- a/auto/types/uintptr_t +++ b/auto/types/uintptr_t @@ -30,7 +30,7 @@ rm $NGX_AUTOTEST* if [ $found = no ]; then - found="uint`expr 8 \* $ngx_ptr_bytes`_t" + found="uint`expr 8 \* $ngx_ptr_size`_t" echo ", $found used" echo "typedef $found uintptr_t;" >> $NGX_AUTO_CONFIG_H diff --git a/auto/types/maxvalue b/auto/types/value rename from auto/types/maxvalue rename to auto/types/value --- a/auto/types/maxvalue +++ b/auto/types/value @@ -1,6 +1,6 @@ cat << END >> $NGX_AUTO_CONFIG_H -#ifndef $ngx_type_max_value -#define $ngx_type_max_value $ngx_max_size +#ifndef $ngx_param +#define $ngx_param $ngx_value #endif diff --git a/auto/unix b/auto/unix --- a/auto/unix +++ b/auto/unix @@ -13,32 +13,31 @@ ngx_formats="%ld"; . auto/fmt/fmt ngx_type="long long"; . auto/types/sizeof ngx_formats="%lld %qd"; . auto/fmt/fmt -ngx_type="void *"; . auto/types/sizeof; ngx_ptr_bytes=$ngx_bytes +ngx_type="void *"; . auto/types/sizeof; ngx_ptr_size=$ngx_size ngx_fmt_name=PTR_FMT; -eval ngx_formats=\${ngx_${ngx_bytes}_fmt}; . auto/fmt/ptrfmt +eval ngx_formats=\${ngx_${ngx_ptr_size}_fmt}; . auto/fmt/ptrfmt # POSIX types NGX_AUTO_CONFIG="#include \"../$NGX_AUTO_CONFIG_H\"" -ngx_type="uint64_t" -ngx_types="u_int64_t"; . auto/types/typedef +ngx_type="uint64_t"; ngx_types="u_int64_t"; . auto/types/typedef -ngx_type="sig_atomic_t" -ngx_types="int"; . auto/types/typedef +ngx_type="sig_atomic_t"; ngx_types="int"; . auto/types/typedef +. auto/types/sizeof +ngx_param=SIG_ATOMIC_T_SIZE; ngx_value=$ngx_size; . auto/types/value -ngx_type="socklen_t" -ngx_types="uint32_t"; . auto/types/typedef +ngx_type="socklen_t"; ngx_types="uint32_t"; . auto/types/typedef -ngx_type="in_addr_t" -ngx_types="uint32_t"; . auto/types/typedef +ngx_type="in_addr_t"; ngx_types="uint32_t"; . auto/types/typedef -ngx_type="rlim_t" -ngx_types="int"; . auto/types/typedef +ngx_type="rlim_t"; ngx_types="int"; . auto/types/typedef . auto/types/uintptr_t +. auto/endianess + # printf() formats @@ -46,22 +45,24 @@ CC_WARN=$CC_STRONG ngx_fmt_collect=no ngx_fmt_name=OFF_T_FMT; ngx_type="off_t"; . auto/types/sizeof -ngx_type_max_value=OFF_T_MAX_VALUE; . auto/types/maxvalue -eval ngx_formats=\${ngx_${ngx_bytes}_fmt}; . auto/fmt/fmt +ngx_param=OFF_T_MAX_VALUE; ngx_value=$ngx_max_value; . auto/types/value +eval ngx_formats=\${ngx_${ngx_size}_fmt}; . auto/fmt/fmt ngx_fmt_name=TIME_T_FMT; ngx_type="time_t"; . auto/types/sizeof -eval ngx_formats=\${ngx_${ngx_bytes}_fmt}; . auto/fmt/fmt +ngx_param=TIME_T_SIZE; ngx_value=$ngx_size; . auto/types/value +ngx_param=TIME_T_LEN; ngx_value=$ngx_max_len; . auto/types/value +eval ngx_formats=\${ngx_${ngx_size}_fmt}; . auto/fmt/fmt ngx_fmt_name=SIZE_T_FMT; ngx_type="size_t"; . auto/types/sizeof -eval ngx_formats=\${ngx_${ngx_bytes}_fmt}; . auto/fmt/fmt +eval ngx_formats=\${ngx_${ngx_size}_fmt}; . auto/fmt/fmt ngx_fmt_name=SIZE_T_X_FMT; . auto/fmt/xfmt ngx_fmt_name=PID_T_FMT; ngx_type="pid_t"; . auto/types/sizeof -eval ngx_formats=\${ngx_${ngx_bytes}_fmt}; . auto/fmt/fmt +eval ngx_formats=\${ngx_${ngx_size}_fmt}; . auto/fmt/fmt ngx_fmt_name=RLIM_T_FMT; ngx_type="rlim_t"; . auto/types/sizeof -eval ngx_formats=\${ngx_${ngx_bytes}_fmt}; . auto/fmt/fmt +eval ngx_formats=\${ngx_${ngx_size}_fmt}; . auto/fmt/fmt # syscalls, libc calls and some features diff --git a/src/core/ngx_atomic.h b/src/core/ngx_atomic.h --- a/src/core/ngx_atomic.h +++ b/src/core/ngx_atomic.h @@ -93,4 +93,18 @@ typedef volatile uint32_t ngx_atomic_t; #endif +static ngx_inline ngx_int_t ngx_trylock(ngx_atomic_t *lock) +{ + if (*lock) { + return NGX_BUSY; + } + + if (ngx_atomic_cmp_set(lock, 0, 1)) { + return NGX_OK; + } + + return NGX_BUSY; +} + + #endif /* _NGX_ATOMIC_H_INCLUDED_ */ diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -75,10 +75,6 @@ typedef long ngx_flag_t; /* TODO: auto */ #define NGX_INT32_LEN sizeof("-2147483648") - 1 #define NGX_INT64_LEN sizeof("-9223372036854775808") - 1 -#if 0 -#define NGX_TIME_T_LEN sizeof("-2147483648") - 1 -#endif -#define NGX_TIME_T_LEN sizeof("-9223372036854775808") - 1 #define NGX_OFF_T_LEN sizeof("-9223372036854775808") - 1 diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -108,6 +108,10 @@ struct ngx_connection_s { #if (HAVE_IOCP) unsigned accept_context_updated:1; #endif + +#if (NGX_THREADS) + ngx_atomic_t lock; +#endif }; diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -15,6 +15,15 @@ typedef struct ngx_event_s ngx_eve typedef struct ngx_connection_s ngx_connection_t; +#define NGX_OK 0 +#define NGX_ERROR -1 +#define NGX_AGAIN -2 +#define NGX_BUSY -3 +#define NGX_DONE -4 +#define NGX_DECLINED -5 +#define NGX_ABORT -6 + + #include #include #include @@ -49,16 +58,6 @@ typedef struct ngx_connection_s ngx_con #include - -#define NGX_OK 0 -#define NGX_ERROR -1 -#define NGX_AGAIN -2 -#define NGX_BUSY -3 -#define NGX_DONE -4 -#define NGX_DECLINED -5 -#define NGX_ABORT -6 - - #define LF (u_char) 10 #define CR (u_char) 13 #define CRLF "\x0d\x0a" diff --git a/src/core/ngx_garbage_collector.c b/src/core/ngx_garbage_collector.c --- a/src/core/ngx_garbage_collector.c +++ b/src/core/ngx_garbage_collector.c @@ -254,7 +254,7 @@ int ngx_garbage_collector_temp_handler(n * Unices have the mount option "noatime". */ - if (ngx_cached_time - ngx_de_mtime(dir) < 3600) { + if (ngx_time() - ngx_de_mtime(dir) < 3600) { return NGX_OK; } diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c @@ -3,32 +3,62 @@ #include +ngx_epoch_msec_t ngx_elapsed_msec; +ngx_epoch_msec_t ngx_old_elapsed_msec; +ngx_epoch_msec_t ngx_start_msec; + +static ngx_tm_t ngx_cached_gmtime; +static ngx_int_t ngx_gmtoff; + + +/* + * In the threaded mode only one thread updates cached time and strings + * and these operations are protected by the mutex. The reading of the cached + * time and strings is not protected by the mutex. To avoid the race + * conditions for non-atomic values we use the NGX_TIME_SLOTS slots to store + * time value and strings. Thus thread may get the corrupted values only + * if it is preempted while copying and then it is not scheduled to run + * more than NGX_TIME_SLOTS seconds. + */ + #if (NGX_THREADS) -static ngx_mutex_t *ngx_time_mutex; + +#define NGX_TIME_SLOTS 60 +static ngx_uint_t slot = NGX_TIME_SLOTS; + +static ngx_mutex_t *ngx_time_mutex; + +#else + +#define NGX_TIME_SLOTS 1 +#define slot 0 + #endif -ngx_epoch_msec_t ngx_elapsed_msec; -ngx_epoch_msec_t ngx_old_elapsed_msec; -ngx_epoch_msec_t ngx_start_msec; +#if (NGX_THREADS && (TIME_T_SIZE > SIG_ATOMIC_T_SIZE)) + +volatile time_t *ngx_cached_time; +static time_t cached_time[NGX_TIME_SLOTS]; -volatile time_t ngx_cached_time; +#else -volatile ngx_str_t ngx_cached_err_log_time; -volatile ngx_str_t ngx_cached_http_time; -volatile ngx_str_t ngx_cached_http_log_time; +volatile time_t ngx_cached_time; + +#endif + -static ngx_tm_t ngx_cached_gmtime; -static ngx_int_t ngx_gmtoff; +ngx_thread_volatile ngx_str_t ngx_cached_err_log_time; +ngx_thread_volatile ngx_str_t ngx_cached_http_time; +ngx_thread_volatile ngx_str_t ngx_cached_http_log_time; -static u_char cached_err_log_time0[] = "1970/09/28 12:00:00"; -static u_char cached_err_log_time1[] = "1970/09/28 12:00:00"; -static u_char cached_http_time0[] = "Mon, 28 Sep 1970 06:00:00 GMT"; -static u_char cached_http_time1[] = "Mon, 28 Sep 1970 06:00:00 GMT"; - -static u_char cached_http_log_time0[] = "28/Sep/1970:12:00:00 +0600"; -static u_char cached_http_log_time1[] = "28/Sep/1970:12:00:00 +0600"; +static u_char cached_err_log_time[NGX_TIME_SLOTS] + [sizeof("1970/09/28 12:00:00")]; +static u_char cached_http_time[NGX_TIME_SLOTS] + [sizeof("Mon, 28 Sep 1970 06:00:00 GMT")]; +static u_char cached_http_log_time[NGX_TIME_SLOTS] + [sizeof("28/Sep/1970:12:00:00 +0600")]; static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; @@ -45,16 +75,13 @@ void ngx_time_init() ngx_cached_gmtime.ngx_tm_zone = "GMT"; #endif - ngx_cached_err_log_time.len = sizeof(cached_err_log_time0) - 1; - ngx_cached_err_log_time.data = cached_err_log_time0; + ngx_cached_err_log_time.len = sizeof("1970/09/28 12:00:00") - 1; + ngx_cached_http_time.len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1; + ngx_cached_http_log_time.len = sizeof("28/Sep/1970:12:00:00 +0600") - 1; - ngx_cached_http_time.len = sizeof(cached_http_time0) - 1; - ngx_cached_http_time.data = cached_http_time0; - - ngx_cached_http_log_time.len = sizeof(cached_http_log_time0) - 1; - ngx_cached_http_log_time.data = cached_http_log_time0; - - ngx_cached_time = 0; +#if (TIME_T_SIZE > SIG_ATOMIC_T_SIZE) + ngx_cached_time = &cached_time[0]; +#endif ngx_gettimeofday(&tv); @@ -89,26 +116,34 @@ void ngx_time_update(time_t s) u_char *p; ngx_tm_t tm; - if (ngx_cached_time == s) { + if (ngx_time() == s) { return; } #if (NGX_THREADS) + if (ngx_mutex_trylock(ngx_time_mutex) != NGX_OK) { return; } + + if (slot == NGX_TIME_SLOTS) { + slot = 0; + } else { + slot++; + } + +#if (TIME_T_SIZE > SIG_ATOMIC_T_SIZE) + ngx_cached_time = &cached_time[slot]; #endif - ngx_cached_time = s; +#endif - ngx_gmtime(ngx_cached_time, &ngx_cached_gmtime); + ngx_time() = s; + + ngx_gmtime(s, &ngx_cached_gmtime); - if (ngx_cached_http_time.data == cached_http_time0) { - p = cached_http_time1; - } else { - p = cached_http_time0; - } + p = cached_http_time[slot]; ngx_snprintf((char *) p, sizeof("Mon, 28 Sep 1970 06:00:00 GMT"), "%s, %02d %s %4d %02d:%02d:%02d GMT", @@ -126,7 +161,7 @@ void ngx_time_update(time_t s) #if (HAVE_GETTIMEZONE) ngx_gmtoff = ngx_gettimezone(); - ngx_gmtime(ngx_cached_time + ngx_gmtoff * 60, &tm); + ngx_gmtime(s + ngx_gmtoff * 60, &tm); #elif (HAVE_GMTOFF) @@ -141,11 +176,7 @@ void ngx_time_update(time_t s) #endif - if (ngx_cached_err_log_time.data == cached_err_log_time0) { - p = cached_err_log_time1; - } else { - p = cached_err_log_time0; - } + p = cached_err_log_time[slot]; ngx_snprintf((char *) p, sizeof("1970/09/28 12:00:00"), "%4d/%02d/%02d %02d:%02d:%02d", @@ -156,11 +187,7 @@ void ngx_time_update(time_t s) ngx_cached_err_log_time.data = p; - if (ngx_cached_http_log_time.data == cached_http_log_time0) { - p = cached_http_log_time1; - } else { - p = cached_http_log_time0; - } + p = cached_http_log_time[slot]; ngx_snprintf((char *) p, sizeof("28/Sep/1970:12:00:00 +0600"), "%02d/%s/%d:%02d:%02d:%02d %c%02d%02d", diff --git a/src/core/ngx_times.h b/src/core/ngx_times.h --- a/src/core/ngx_times.h +++ b/src/core/ngx_times.h @@ -7,17 +7,27 @@ void ngx_time_init(); -#if (NGX_THREADS) -ngx_int_t ngx_time_mutex_init(ngx_log_t *log); -#endif void ngx_time_update(time_t s); size_t ngx_http_time(u_char *buf, time_t t); void ngx_gmtime(time_t t, ngx_tm_t *tp); -#define ngx_time() ngx_cached_time +#if (NGX_THREADS) +ngx_int_t ngx_time_mutex_init(ngx_log_t *log); +#endif + +#if (NGX_THREADS && (TIME_T_SIZE > SIG_ATOMIC_T_SIZE)) + +#define ngx_time() *ngx_cached_time +extern volatile time_t *ngx_cached_time; + +#else + +#define ngx_time() ngx_cached_time +extern volatile time_t ngx_cached_time; + +#endif -extern volatile time_t ngx_cached_time; extern volatile ngx_str_t ngx_cached_err_log_time; extern volatile ngx_str_t ngx_cached_http_time; extern volatile ngx_str_t ngx_cached_http_log_time; diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -582,14 +582,17 @@ static ngx_int_t ngx_kqueue_process_even ngx_mutex_unlock(ngx_posted_events_mutex); } - /* TODO: wake up worker thread */ - if (expire && delta) { ngx_event_expire_timers((ngx_msec_t) delta); } - if (!ngx_threaded) { - ngx_event_process_posted(cycle); + if (ngx_posted_events) { + if (ngx_threaded) { + ngx_cv_signal(ngx_posted_events_cv); + + } else { + ngx_event_process_posted(cycle); + } } return NGX_OK; diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -265,6 +265,9 @@ static ngx_int_t ngx_event_process_init( for (i = 0; i < cycle->connection_n; i++) { c[i].fd = (ngx_socket_t) -1; c[i].data = NULL; +#if (NGX_THREADS) + c[i].lock = 0; +#endif } cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * ecf->connections, diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -154,6 +154,11 @@ struct ngx_event_s { #endif +#if (NGX_THREADS) + ngx_atomic_t *lock; +#endif + + #if 0 /* the threads support */ diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -278,6 +278,11 @@ void ngx_event_accept(ngx_event_t *ev) c->number = ngx_atomic_inc(ngx_connection_counter); +#if (NGX_THREADS) + rev->lock = &c->lock; + wev->lock = &c->lock; +#endif + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, "accept: fd:%d c:%d", s, c->number); diff --git a/src/event/ngx_event_posted.c b/src/event/ngx_event_posted.c --- a/src/event/ngx_event_posted.c +++ b/src/event/ngx_event_posted.c @@ -5,8 +5,10 @@ ngx_thread_volatile ngx_event_t *ngx_posted_events; + #if (NGX_THREADS) ngx_mutex_t *ngx_posted_events_mutex; +ngx_cv_t *ngx_posted_events_cv; #endif @@ -55,26 +57,70 @@ void ngx_event_process_posted(ngx_cycle_ #if (NGX_THREADS) -void ngx_event_thread_handler(ngx_event_t *ev) +ngx_int_t ngx_event_thread_process_posted(ngx_cycle_t *cycle) { - if ((!ev->posted && !ev->active) - || (ev->use_instance && ev->instance != ev->returned_instance)) - { - /* - * the stale event from a file descriptor - * that was just closed in this iteration - */ + ngx_event_t *ev, **ep; + + for ( ;; ) { + + ev = (ngx_event_t *) ngx_posted_events; + ep = (ngx_event_t **) &ngx_posted_events; + + for ( ;; ) { + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, + "posted event " PTR_FMT, ev); + + if (ev == NULL) { + ngx_mutex_unlock(ngx_posted_events_mutex); + return NGX_OK; + } + + if (ngx_trylock(ev->lock) == NGX_BUSY) { + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, + "posted event " PTR_FMT " is busy", ev); + + ep = &ev->next; + ev = ev->next; + continue; + } + + *ep = ev->next; - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, - "kevent: stale event " PTR_FMT, ev); - return; - } + if ((!ev->posted && !ev->active) + || (ev->use_instance && ev->instance != ev->returned_instance)) + { + /* + * the stale event from a file descriptor + * that was just closed in this iteration + */ + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, + "kevent: stale event " PTR_FMT, ev); + + ev = ev->next; + + continue; + } - if (ev->posted) { - ev->posted = 0; + ngx_mutex_unlock(ngx_posted_events_mutex); + + if (ev->posted) { + ev->posted = 0; + } + + ev->event_handler(ev); + + *(ev->lock) = 0; + + if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { + return NGX_ERROR; + } + + break; + } } - - ev->event_handler(ev); } #endif diff --git a/src/event/ngx_event_posted.h b/src/event/ngx_event_posted.h --- a/src/event/ngx_event_posted.h +++ b/src/event/ngx_event_posted.h @@ -14,14 +14,15 @@ void ngx_event_process_posted(ngx_cycle_t *cycle); -#if (NGX_THREADS) -void ngx_event_thread_handler(ngx_event_t *ev); -#endif + +extern ngx_thread_volatile ngx_event_t *ngx_posted_events; -extern ngx_thread_volatile ngx_event_t *ngx_posted_events; #if (NGX_THREADS) +ngx_int_t ngx_event_thread_process_posted(ngx_cycle_t *cycle); + extern ngx_mutex_t *ngx_posted_events_mutex; +extern ngx_cv_t *ngx_posted_events_cv; #endif diff --git a/src/http/modules/ngx_http_gzip_filter.c b/src/http/modules/ngx_http_gzip_filter.c --- a/src/http/modules/ngx_http_gzip_filter.c +++ b/src/http/modules/ngx_http_gzip_filter.c @@ -351,7 +351,7 @@ static ngx_int_t ngx_http_gzip_proxied(n } } else { - date = ngx_cached_time; + date = ngx_time(); } if (expires < date) { diff --git a/src/http/modules/ngx_http_headers_filter.c b/src/http/modules/ngx_http_headers_filter.c --- a/src/http/modules/ngx_http_headers_filter.c +++ b/src/http/modules/ngx_http_headers_filter.c @@ -118,24 +118,22 @@ static ngx_int_t ngx_http_headers_filter cc->value.data = (u_char *) "max-age=0"; } else { - ngx_http_time(expires->value.data, - ngx_cached_time + conf->expires); + ngx_http_time(expires->value.data, ngx_time() + conf->expires); if (conf->expires < 0) { cc->value.len = sizeof("no-cache") - 1; cc->value.data = (u_char *) "no-cache"; } else { - cc->value.data = ngx_palloc(r->pool, NGX_TIME_T_LEN + 1); + cc->value.data = ngx_palloc(r->pool, TIME_T_LEN + 1); if (cc->value.data == NULL) { return NGX_ERROR; } cc->value.len = ngx_snprintf((char *) cc->value.data, - sizeof("max-age=") - + NGX_TIME_T_LEN, - "max-age=" TIME_T_FMT, - conf->expires); + sizeof("max-age=") + TIME_T_LEN, + "max-age=" TIME_T_FMT, + conf->expires); } } } diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -708,7 +708,7 @@ static u_char *ngx_http_proxy_log_proxy_ *buf++ = '-'; } else { - buf += ngx_snprintf((char *) buf, NGX_TIME_T_LEN, + buf += ngx_snprintf((char *) buf, TIME_T_LEN, TIME_T_FMT, p->state->expired); } @@ -718,7 +718,7 @@ static u_char *ngx_http_proxy_log_proxy_ *buf++ = '-'; } else { - buf += ngx_snprintf((char *) buf, NGX_TIME_T_LEN, + buf += ngx_snprintf((char *) buf, TIME_T_LEN, TIME_T_FMT, p->state->bl_time); } @@ -752,7 +752,7 @@ static u_char *ngx_http_proxy_log_proxy_ *buf++ = '-'; } else { - buf += ngx_snprintf((char *) buf, NGX_TIME_T_LEN, + buf += ngx_snprintf((char *) buf, TIME_T_LEN, TIME_T_FMT, p->state->expires); } diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -1463,7 +1463,7 @@ static void ngx_http_set_lingering_close rev = c->read; rev->event_handler = ngx_http_lingering_close_handler; - r->lingering_time = ngx_cached_time + clcf->lingering_time / 1000; + r->lingering_time = ngx_time() + clcf->lingering_time / 1000; ngx_add_timer(rev, clcf->lingering_timeout); if (ngx_handle_level_read_event(rev) == NGX_ERROR) { @@ -1526,7 +1526,7 @@ static void ngx_http_lingering_close_han return; } - timer = r->lingering_time - ngx_cached_time; + timer = r->lingering_time - ngx_time(); if (timer <= 0) { ngx_http_close_request(r, 0); ngx_http_close_connection(c); diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h --- a/src/os/unix/ngx_freebsd_config.h +++ b/src/os/unix/ngx_freebsd_config.h @@ -108,14 +108,9 @@ pid_t rfork_thread(int flags, void *stac #endif -/* STUB: autoconf */ #define ngx_setproctitle setproctitle -/* STUB */ -#define HAVE_LITTLE_ENDIAN 1 - - extern char *malloc_options; diff --git a/src/os/unix/ngx_freebsd_rfork_thread.c b/src/os/unix/ngx_freebsd_rfork_thread.c --- a/src/os/unix/ngx_freebsd_rfork_thread.c +++ b/src/os/unix/ngx_freebsd_rfork_thread.c @@ -8,26 +8,28 @@ #include /* - * The threads implementation uses the rfork(RFPROC|RFTHREAD|RFMEM) + * The threads implementation uses the rfork(RFPROC|RFTHREAD|RFMEM) syscall * to create threads. All threads use the stacks of the same size mmap()ed - * below the main stack. Thus the stack pointer is used to determine - * the current thread id. + * below the main stack. Thus the current thread id is determinated through + * the stack pointer. * * The mutex implementation uses the ngx_atomic_cmp_set() operation - * to acquire mutex and the SysV semaphore to wait on a mutex or to wake up - * the waiting threads. + * to acquire a mutex and the SysV semaphore to wait on a mutex or to wake up + * the waiting threads. The light mutex does not use semaphore, so after + * spinning in the lock the thread calls sched_yield(). However the light + * mutecies are intended to be used with the "trylock" operation only. * * The condition variable implementation uses the SysV semaphore set of two * semaphores. The first is used by the CV mutex, and the second is used - * by CV itself. + * by the CV to signal. * - * This threads implementation currently works on i486 and amd64 + * This threads implementation currently works on i386 (486+) and amd64 * platforms only. */ -char *ngx_freebsd_kern_usrstack; -size_t ngx_thread_stack_size; +char *ngx_freebsd_kern_usrstack; +size_t ngx_thread_stack_size; static size_t rz_size; @@ -261,7 +263,6 @@ ngx_tid_t ngx_thread_self() ngx_mutex_t *ngx_mutex_init(ngx_log_t *log, uint flags) { - int nsem, i; ngx_mutex_t *m; union semun op; @@ -277,27 +278,23 @@ ngx_mutex_t *ngx_mutex_init(ngx_log_t *l return m; } - nsem = flags & NGX_MUTEX_CV ? 2 : 1; - - m->semid = semget(IPC_PRIVATE, nsem, SEM_R|SEM_A); + m->semid = semget(IPC_PRIVATE, 1, SEM_R|SEM_A); if (m->semid == -1) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "semget() failed"); return NULL; } op.val = 0; - for (i = 0; i < nsem; i++) { - if (semctl(m->semid, i, SETVAL, op) == -1) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - "semctl(SETVAL) failed"); + + if (semctl(m->semid, 0, SETVAL, op) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "semctl(SETVAL) failed"); - if (semctl(m->semid, 0, IPC_RMID) == -1) { - ngx_log_error(NGX_LOG_ALERT, m->log, ngx_errno, - "semctl(IPC_RMID) failed"); - } + if (semctl(m->semid, 0, IPC_RMID) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "semctl(IPC_RMID) failed"); + } - return NULL; - } + return NULL; } return m; @@ -388,7 +385,7 @@ ngx_int_t ngx_mutex_dolock(ngx_mutex_t * * The number of the waiting threads has been increased * and we would wait on the SysV semaphore. * A semaphore should wake up us more efficiently than - * a simple usleep(). + * a simple sched_yield() or usleep(). */ op.sem_num = 0; @@ -456,7 +453,7 @@ ngx_int_t ngx_mutex_unlock(ngx_mutex_t * if (!(old & NGX_MUTEX_LOCK_BUSY)) { ngx_log_error(NGX_LOG_ALERT, m->log, 0, - "tring to unlock the free mutex " PTR_FMT, m); + "trying to unlock the free mutex " PTR_FMT, m); return NGX_ERROR; } @@ -479,7 +476,7 @@ ngx_int_t ngx_mutex_unlock(ngx_mutex_t * return NGX_OK; } - /* check weather we need to wake up a waiting thread */ + /* check whether we need to wake up a waiting thread */ old = m->lock; @@ -525,3 +522,108 @@ ngx_int_t ngx_mutex_unlock(ngx_mutex_t * return NGX_OK; } + + +ngx_cv_t *ngx_cv_init(ngx_log_t *log) +{ + ngx_cv_t *cv; + u_short val[2]; + union semun op; + + if (!(cv = ngx_alloc(sizeof(ngx_cv_t), log))) { + return NULL; + } + + cv->mutex.lock = 0; + cv->mutex.log = log; + + cv->mutex.semid = semget(IPC_PRIVATE, 2, SEM_R|SEM_A); + if (cv->mutex.semid == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "semget() failed"); + return NULL; + } + + val[0] = 0; + val[1] = 0; + op.array = val; + + if (semctl(cv->mutex.semid, 0, SETALL, op) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "semctl(SETALL) failed"); + + if (semctl(cv->mutex.semid, 0, IPC_RMID) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "semctl(IPC_RMID) failed"); + } + + return NULL; + } + + return cv; +} + + +void ngx_cv_done(ngx_cv_t *cv) +{ + if (semctl(cv->mutex.semid, 0, IPC_RMID) == -1) { + ngx_log_error(NGX_LOG_ALERT, cv->mutex.log, ngx_errno, + "semctl(IPC_RMID) failed"); + } + + ngx_free(cv); +} + + +ngx_int_t ngx_cv_wait(ngx_cv_t *cv) +{ + struct sembuf op[2]; + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->mutex.log, 0, + "cv " PTR_FMT " wait", cv); + + op[0].sem_num = 0; + op[0].sem_op = -1; + op[0].sem_flg = SEM_UNDO; + + op[1].sem_num = 1; + op[1].sem_op = -1; + op[1].sem_flg = SEM_UNDO; + + if (semop(cv->mutex.semid, op, 2) == -1) { + ngx_log_error(NGX_LOG_ALERT, cv->mutex.log, ngx_errno, + "semop() failed while waiting on cv " PTR_FMT, cv); + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->mutex.log, 0, + "cv " PTR_FMT " is waked up", cv); + + return NGX_OK; +} + + +ngx_int_t ngx_cv_signal(ngx_cv_t *cv) +{ + struct sembuf op[2]; + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->mutex.log, 0, + "cv " PTR_FMT " to signal", cv); + + op[0].sem_num = 0; + op[0].sem_op = 1; + op[0].sem_flg = SEM_UNDO; + + op[1].sem_num = 1; + op[1].sem_op = 1; + op[1].sem_flg = SEM_UNDO; + + if (semop(cv->mutex.semid, op, 2) == -1) { + ngx_log_error(NGX_LOG_ALERT, cv->mutex.log, ngx_errno, + "semop() failed while signaling cv " PTR_FMT, cv); + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->mutex.log, 0, + "cv " PTR_FMT " is signaled", cv); + + return NGX_OK; +} diff --git a/src/os/unix/ngx_linux_config.h b/src/os/unix/ngx_linux_config.h --- a/src/os/unix/ngx_linux_config.h +++ b/src/os/unix/ngx_linux_config.h @@ -91,8 +91,4 @@ extern ssize_t sendfile(int s, int fd, i #define ngx_setproctitle(title) -/* STUB */ -#define HAVE_LITTLE_ENDIAN 1 - - #endif /* _NGX_LINUX_CONFIG_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -625,6 +625,13 @@ static void ngx_worker_process_cycle(ngx exit(2); } + if (!(ngx_posted_events_cv = ngx_cv_init(cycle->log))) { + /* fatal */ + exit(2); + } + + ngx_posted_events_mutex = &ngx_posted_events_cv->mutex; + for (i = 0; i < 1; i++) { if (ngx_create_thread(&tid, ngx_worker_thread_cycle, cycle, cycle->log) != 0) @@ -767,23 +774,25 @@ int ngx_worker_thread_cycle(void *data) return 1; } - - /* STUB */ - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, ngx_errno, "thread %d started", ngx_thread_self()); ngx_setproctitle("worker thread"); - sleep(5); + for ( ;; ) { + if (ngx_cv_wait(ngx_posted_events_cv) == NGX_ERROR) { + return 1; + } - ngx_gettimeofday(&tv); - ngx_time_update(tv.tv_sec); + if (ngx_event_thread_process_posted(cycle) == NGX_ERROR) { + return 1; + } + } ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, ngx_errno, "thread %d done", ngx_thread_self()); - return 1; + return 0; } #endif diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h --- a/src/os/unix/ngx_solaris_config.h +++ b/src/os/unix/ngx_solaris_config.h @@ -76,8 +76,4 @@ #define ngx_setproctitle(title) -/* STUB */ -#define HAVE_LITTLE_ENDIAN 1 - - #endif /* _NGX_SOLARIS_CONFIG_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_thread.h b/src/os/unix/ngx_thread.h --- a/src/os/unix/ngx_thread.h +++ b/src/os/unix/ngx_thread.h @@ -36,6 +36,11 @@ typedef volatile struct { } ngx_mutex_t; +typedef struct { + ngx_mutex_t mutex; +} ngx_cv_t; + + #define ngx_thread_sigmask(how, set, oset) \ (sigprocmask(how, set, oset) == -1) ? ngx_errno : 0 @@ -102,6 +107,12 @@ ngx_int_t ngx_mutex_dolock(ngx_mutex_t * ngx_int_t ngx_mutex_unlock(ngx_mutex_t *m); +ngx_cv_t *ngx_cv_init(ngx_log_t *log); +void ngx_cv_done(ngx_cv_t *cv); +ngx_int_t ngx_cv_wait(ngx_cv_t *cv); +ngx_int_t ngx_cv_signal(ngx_cv_t *cv); + + #else /* !NGX_THREADS */ #define ngx_thread_volatile diff --git a/src/os/unix/ngx_time.c b/src/os/unix/ngx_time.c --- a/src/os/unix/ngx_time.c +++ b/src/os/unix/ngx_time.c @@ -6,13 +6,17 @@ void ngx_localtime(ngx_tm_t *tm) { #if (HAVE_LOCALTIME_R) + time_t now; - localtime_r((time_t *) &ngx_cached_time, tm); + now = ngx_time(); + localtime_r(&now, tm); #else + time_t now; ngx_tm_t *t; - t = localtime((time_t *) &ngx_cached_time); + now = ngx_time(); + t = localtime(&now); *tm = *t; #endif