nginx-0.0.7-2004-06-27-22:01:57 import
diff --git a/src/core/ngx_atomic.h b/src/core/ngx_atomic.h index 5511ea7..bbf4a76 100644 --- a/src/core/ngx_atomic.h +++ b/src/core/ngx_atomic.h
@@ -93,4 +93,18 @@ #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 index 465e1bf..a6e5b09 100644 --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h
@@ -75,10 +75,6 @@ /* 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 index 67275bd..09684c5 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h
@@ -108,6 +108,10 @@ #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 index ed6e373..58b1d12 100644 --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h
@@ -15,6 +15,15 @@ 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> @@ -49,16 +58,6 @@ #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"
diff --git a/src/core/ngx_garbage_collector.c b/src/core/ngx_garbage_collector.c index 3b67330..924f11a 100644 --- a/src/core/ngx_garbage_collector.c +++ b/src/core/ngx_garbage_collector.c
@@ -254,7 +254,7 @@ * 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 index aa461c5..2717d5c 100644 --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c
@@ -3,32 +3,62 @@ #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 -static ngx_tm_t ngx_cached_gmtime; -static ngx_int_t ngx_gmtoff; +volatile time_t ngx_cached_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"; +#endif -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"; +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_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 @@ 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 @@ 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 @@ #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 @@ #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 @@ 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 index 8fdf685..1fb712d 100644 --- 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 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 index 4a844e9..001d6a8 100644 --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c
@@ -582,14 +582,17 @@ 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 index 6d497e0..58a5f0f 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c
@@ -265,6 +265,9 @@ 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 index 87b02e1..8e30ccd 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h
@@ -154,6 +154,11 @@ #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 index bdc9f46..984570f 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c
@@ -278,6 +278,11 @@ 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 index 96475f3..4787443 100644 --- 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 @@ #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; - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, - "kevent: stale event " PTR_FMT, ev); - return; + 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; + + 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; + } } - - if (ev->posted) { - ev->posted = 0; - } - - ev->event_handler(ev); } #endif
diff --git a/src/event/ngx_event_posted.h b/src/event/ngx_event_posted.h index 78f302e..b060cc6 100644 --- 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; + + #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 index 5f3825e..5c6d0d1 100644 --- a/src/http/modules/ngx_http_gzip_filter.c +++ b/src/http/modules/ngx_http_gzip_filter.c
@@ -351,7 +351,7 @@ } } 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 index 7f74b47..b850ee3 100644 --- a/src/http/modules/ngx_http_headers_filter.c +++ b/src/http/modules/ngx_http_headers_filter.c
@@ -118,24 +118,22 @@ 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 index 99ac1aa..b7177a3 100644 --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -708,7 +708,7 @@ *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 @@ *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 @@ *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 index 8ce73cf..4bff8cc 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c
@@ -1463,7 +1463,7 @@ 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 @@ 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 index 570eee8..67f5fb3 100644 --- a/src/os/unix/ngx_freebsd_config.h +++ b/src/os/unix/ngx_freebsd_config.h
@@ -108,14 +108,9 @@ #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 index 740fb52..c4cd302 100644 --- a/src/os/unix/ngx_freebsd_rfork_thread.c +++ b/src/os/unix/ngx_freebsd_rfork_thread.c
@@ -8,26 +8,28 @@ #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; @@ -261,7 +263,6 @@ 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 @@ 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) { + + 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, 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"); - } - - return NULL; + "semctl(IPC_RMID) failed"); } + + return NULL; } return m; @@ -388,7 +385,7 @@ * 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 @@ 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 @@ 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 @@ 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 index 8a75e22..c01584e 100644 --- a/src/os/unix/ngx_linux_config.h +++ b/src/os/unix/ngx_linux_config.h
@@ -91,8 +91,4 @@ #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 index 21966f2..6d7fe06 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c
@@ -625,6 +625,13 @@ 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 @@ 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 index b1e71cd..1bae50e 100644 --- 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 index 5225274..6412fe8 100644 --- a/src/os/unix/ngx_thread.h +++ b/src/os/unix/ngx_thread.h
@@ -36,6 +36,11 @@ } 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_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 index 5ba95bc..8647e0e 100644 --- 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