--- /dev/null
+
+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
cat << END > $NGX_AUTOTEST.c
-#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
+#include <stdio.h>
#include <sys/resource.h>
$NGX_INTTYPES_H
$NGX_AUTO_CONFIG
int main() {
- printf("$fmt", ($ngx_type) $ngx_max_size);
+ printf("$fmt", ($ngx_type) $ngx_max_value);
return 0;
}
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
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
cat << END > $NGX_AUTOTEST.c
int main() {
- printf("$fmt", ($ngx_type) $ngx_max_size);
+ printf("$fmt", ($ngx_type) $ngx_max_value);
return 0;
}
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
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
+++ /dev/null
-
-cat << END >> $NGX_AUTO_CONFIG_H
-
-#ifndef $ngx_type_max_value
-#define $ngx_type_max_value $ngx_max_size
-#endif
echo >> $NGX_ERR
echo "checking for $ngx_type size" >> $NGX_ERR
-ngx_bytes=
+ngx_size=
cat << END > $NGX_AUTOTEST.c
#include <sys/types.h>
#include <sys/time.h>
-#include <sys/resource.h>
$NGX_UNISTD_H
+#include <signal.h>
+#include <sys/resource.h>
$NGX_INTTYPES_H
$NGX_AUTO_CONFIG
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'
;;
*)
cat << END > $NGX_AUTOTEST.c
-#include <signal.h>
#include <sys/types.h>
+#include <signal.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/resource.h>
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
--- /dev/null
+
+cat << END >> $NGX_AUTO_CONFIG_H
+
+#ifndef $ngx_param
+#define $ngx_param $ngx_value
+#endif
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
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
#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_ */
/* 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
#if (HAVE_IOCP)
unsigned accept_context_updated:1;
#endif
+
+#if (NGX_THREADS)
+ ngx_atomic_t lock;
+#endif
};
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 <ngx_atomic.h>
#include <ngx_time.h>
#include <ngx_socket.h>
#include <ngx_connection.h>
-
-#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"
* 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;
}
#include <ngx_core.h>
+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;
+volatile time_t *ngx_cached_time;
+static time_t cached_time[NGX_TIME_SLOTS];
-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;
+#else
+
+volatile time_t ngx_cached_time;
+
+#endif
-static ngx_tm_t ngx_cached_gmtime;
-static ngx_int_t ngx_gmtoff;
-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";
+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_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" };
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);
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",
#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)
#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",
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",
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 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;
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;
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,
#endif
+#if (NGX_THREADS)
+ ngx_atomic_t *lock;
+#endif
+
+
#if 0
/* the threads support */
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);
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
#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_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
- "kevent: stale event " PTR_FMT, ev);
- return;
- }
+ ngx_event_t *ev, **ep;
- if (ev->posted) {
- ev->posted = 0;
- }
+ 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;
+ }
- ev->event_handler(ev);
+ *ep = ev->next;
+
+ 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;
+ }
+
+ 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;
+ }
+ }
}
#endif
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;
+
+
#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
}
} else {
- date = ngx_cached_time;
+ date = ngx_time();
}
if (expires < date) {
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);
}
}
}
*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);
}
*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);
}
*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);
}
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) {
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);
#endif
-/* STUB: autoconf */
#define ngx_setproctitle setproctitle
-/* STUB */
-#define HAVE_LITTLE_ENDIAN 1
-
-
extern char *malloc_options;
#include <ngx_core.h>
/*
- * 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;
ngx_mutex_t *ngx_mutex_init(ngx_log_t *log, uint flags)
{
- int nsem, i;
ngx_mutex_t *m;
union semun op;
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, IPC_RMID) == -1) {
- ngx_log_error(NGX_LOG_ALERT, m->log, ngx_errno,
- "semctl(IPC_RMID) failed");
- }
+ if (semctl(m->semid, 0, SETVAL, op) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "semctl(SETVAL) failed");
- return NULL;
+ if (semctl(m->semid, 0, IPC_RMID) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ "semctl(IPC_RMID) failed");
}
+
+ return NULL;
}
return m;
* 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;
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;
}
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;
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;
+}
#define ngx_setproctitle(title)
-/* STUB */
-#define HAVE_LITTLE_ENDIAN 1
-
-
#endif /* _NGX_LINUX_CONFIG_H_INCLUDED_ */
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)
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
#define ngx_setproctitle(title)
-/* STUB */
-#define HAVE_LITTLE_ENDIAN 1
-
-
#endif /* _NGX_SOLARIS_CONFIG_H_INCLUDED_ */
} 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
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
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