mirror of
https://github.com/nginx/nginx.git
synced 2024-12-26 00:41:02 -06:00
nginx-0.0.2-2004-02-23-23:57:12 import
This commit is contained in:
parent
0ee5d3c106
commit
b54698b579
6
auto/configure
vendored
6
auto/configure
vendored
@ -16,6 +16,10 @@ fi
|
||||
. auto/cc
|
||||
. auto/lib/conf
|
||||
|
||||
if [ "$PLATFORM" != win32 ]; then
|
||||
. auto/threads
|
||||
fi
|
||||
|
||||
. auto/make
|
||||
. auto/lib/make
|
||||
|
||||
@ -23,4 +27,6 @@ if [ "$PLATFORM" != win32 ]; then
|
||||
. auto/unix
|
||||
fi
|
||||
|
||||
#have NGX_SMP . auto/have
|
||||
|
||||
. auto/summary
|
||||
|
@ -2,36 +2,60 @@
|
||||
if [ "$PLATFORM" != "win32" ]; then
|
||||
|
||||
if [ $PCRE != NO ]; then
|
||||
echo "$PCRE/.libs/libpcre.a:" >> $MAKEFILE
|
||||
echo " cd $PCRE \\" >> $MAKEFILE
|
||||
echo " && ./configure --disable-shared \\" >> $MAKEFILE
|
||||
echo " && \$(MAKE)" >> $MAKEFILE
|
||||
echo >> $MAKEFILE
|
||||
echo "$PCRE/.libs/libpcre.a:" >> $MAKEFILE
|
||||
echo " cd $PCRE \\" >> $MAKEFILE
|
||||
echo " && ./configure --disable-shared \\" >> $MAKEFILE
|
||||
echo " && \$(MAKE)" >> $MAKEFILE
|
||||
echo >> $MAKEFILE
|
||||
fi
|
||||
|
||||
|
||||
if [ $MD5 != NO ]; then
|
||||
echo "$MD5/libmd5.a:" >> $MAKEFILE
|
||||
echo "$MD5/libmd5.a:" >> $MAKEFILE
|
||||
|
||||
case $PLATFORM in
|
||||
|
||||
SunOS:*)
|
||||
echo " cd $MD5 && \$(MAKE) x86-solaris" >> $MAKEFILE
|
||||
;;
|
||||
SunOS:*:i386)
|
||||
echo " cd $MD5 && \$(MAKE) x86-solaris" >> $MAKEFILE
|
||||
;;
|
||||
|
||||
*:i386)
|
||||
echo " cd $MD5 && \$(MAKE) x86-elf" >> $MAKEFILE
|
||||
;;
|
||||
|
||||
*)
|
||||
if [ $CC = gcc ]; then
|
||||
echo " cd $MD5 && \$(MAKE) gcc" >> $MAKEFILE
|
||||
else
|
||||
echo " cd $MD5 && \$(MAKE) cc" >> $MAKEFILE
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
echo " cd $MD5 && \$(MAKE) x86-elf" >> $MAKEFILE
|
||||
;;
|
||||
esac
|
||||
|
||||
echo >> $MAKEFILE
|
||||
echo >> $MAKEFILE
|
||||
fi
|
||||
|
||||
|
||||
if [ $ZLIB != NO ]; then
|
||||
echo "$ZLIB/libz.a:" >> $MAKEFILE
|
||||
echo " cd $ZLIB && ./configure && \$(MAKE)" >> $MAKEFILE
|
||||
echo >> $MAKEFILE
|
||||
echo "$ZLIB/libz.a:" >> $MAKEFILE
|
||||
|
||||
case $PLATFORM in
|
||||
|
||||
*:i386)
|
||||
echo " cd $ZLIB \\" >> $MAKEFILE
|
||||
echo " && cp contrib/asm686/match.S . \\" >> $MAKEFILE
|
||||
echo " && CFLAGS=\"-O3 -DASMV\" ./configure \\" >> $MAKEFILE
|
||||
echo " && \$(MAKE) OBJA=match.o" >> $MAKEFILE
|
||||
;;
|
||||
|
||||
*)
|
||||
echo " cd $ZLIB && ./configure && \$(MAKE)" >> $MAKEFILE
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
echo >> $MAKEFILE
|
||||
fi
|
||||
|
||||
fi
|
||||
|
@ -27,11 +27,12 @@ ngx_lib_inc="#include <sys/types.h>
|
||||
|
||||
MD5=NO
|
||||
|
||||
# Solaris 8/9
|
||||
ngx_lib="rsaref md5"
|
||||
ngx_lib_test="MD5_CTX md5; MD5Init(&md5)"
|
||||
ngx_libs=-lmd5
|
||||
. auto/lib/test
|
||||
# Solaris 8/9
|
||||
|
||||
ngx_lib="rsaref md5"
|
||||
ngx_lib_test="MD5_CTX md5; MD5Init(&md5)"
|
||||
ngx_libs=-lmd5
|
||||
. auto/lib/test
|
||||
|
||||
|
||||
if [ $ngx_found = yes ]; then
|
||||
@ -42,6 +43,7 @@ ngx_lib_inc="#include <sys/types.h>
|
||||
|
||||
else
|
||||
# FreeBSD
|
||||
|
||||
ngx_lib="rsaref md"
|
||||
ngx_lib_test="MD5_CTX md5; MD5Init(&md5)"
|
||||
ngx_libs=-lmd
|
||||
@ -56,8 +58,9 @@ ngx_lib_inc="#include <sys/types.h>
|
||||
ngx_found=no
|
||||
|
||||
else
|
||||
ngx_lib_inc="#include <sys/types.h>
|
||||
#include <openssl/md5.h>"
|
||||
# OpenSSL crypto library
|
||||
|
||||
ngx_inc="#include <openssl/md5.h>"
|
||||
ngx_lib="OpenSSL md5 crypto"
|
||||
ngx_lib_test="MD5_CTX md5; MD5_Init(&md5)"
|
||||
ngx_libs=-lcrypto
|
||||
|
@ -15,6 +15,8 @@ EVENT_SELECT=NO
|
||||
EVENT_POLL=NO
|
||||
EVENT_AIO=NO
|
||||
|
||||
USE_THREADS=NO
|
||||
|
||||
HTTP_REWRITE=YES
|
||||
HTTP_GZIP=YES
|
||||
HTTP_SSI=YES
|
||||
@ -51,6 +53,9 @@ do
|
||||
--without-poll_module) EVENT_POLL=NONE ;;
|
||||
--with-aio_module) EVENT_AIO=YES ;;
|
||||
|
||||
--with-threads=*) USE_THREADS="$value" ;;
|
||||
--with-threads) USE_THREADS="pthreads" ;;
|
||||
|
||||
--without-http_rewrite_module) HTTP_REWRITE=NO ;;
|
||||
--without-http_ssi_module) HTTP_SSI=NO ;;
|
||||
--without-http_gzip_module) HTTP_GZIP=NO ;;
|
||||
|
@ -5,6 +5,7 @@ CORE_INCS="-I src/core"
|
||||
|
||||
CORE_DEPS="src/core/nginx.h \
|
||||
src/core/ngx_config.h \
|
||||
src/core/ngx_core.h \
|
||||
src/core/ngx_atomic.h \
|
||||
src/core/ngx_log.h \
|
||||
src/core/ngx_alloc.h \
|
||||
@ -98,6 +99,7 @@ UNIX_DEPS="$CORE_DEPS $EVENT_DEPS \
|
||||
src/os/unix/ngx_errno.h \
|
||||
src/os/unix/ngx_files.h \
|
||||
src/os/unix/ngx_process.h \
|
||||
src/os/unix/ngx_thread.h \
|
||||
src/os/unix/ngx_socket.h \
|
||||
src/os/unix/ngx_os.h"
|
||||
|
||||
@ -117,7 +119,7 @@ UNIX_SRCS="$CORE_SRCS $EVENT_SRCS \
|
||||
FREEBSD_DEPS=src/os/unix/ngx_freebsd_config.h
|
||||
FREEBSD_SRCS=src/os/unix/ngx_freebsd_init.c
|
||||
FREEBSD_SENDFILE_SRCS=src/os/unix/ngx_freebsd_sendfile_chain.c
|
||||
|
||||
FREEBSD_RFORK_SRCS="src/os/unix/ngx_freebsd_rfork_thread.c"
|
||||
|
||||
LINUX_DEPS=src/os/unix/ngx_linux_config.h
|
||||
LINUX_SRCS=src/os/unix/ngx_linux_init.c
|
||||
|
7
auto/threads
Normal file
7
auto/threads
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
if [ $USE_THREADS = "rfork" ]; then
|
||||
have=NGX_THREADS . auto/have
|
||||
have=USE_RFORK . auto/have
|
||||
CORE_DEPS="$CORE_DEPS $UNIX_THREADS_DEPS"
|
||||
CORE_SRCS="$CORE_SRCS $FREEBSD_RFORK_SRCS"
|
||||
fi
|
@ -27,6 +27,9 @@ typedef struct {
|
||||
static void ngx_master_process_cycle(ngx_cycle_t *cycle, ngx_master_ctx_t *ctx);
|
||||
static void ngx_master_exit(ngx_cycle_t *cycle, ngx_master_ctx_t *ctx);
|
||||
static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data);
|
||||
#if (NGX_THREADS)
|
||||
static int ngx_worker_thread_cycle(void *data);
|
||||
#endif
|
||||
static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle, char **envp);
|
||||
static ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv);
|
||||
static ngx_int_t ngx_getopt(ngx_master_ctx_t *ctx, ngx_cycle_t *cycle);
|
||||
@ -87,22 +90,22 @@ ngx_module_t ngx_core_module = {
|
||||
};
|
||||
|
||||
|
||||
ngx_int_t ngx_max_module;
|
||||
ngx_uint_t ngx_connection_counter;
|
||||
ngx_int_t ngx_max_module;
|
||||
ngx_atomic_t ngx_connection_counter;
|
||||
|
||||
ngx_int_t ngx_process;
|
||||
ngx_pid_t ngx_pid;
|
||||
ngx_pid_t ngx_new_binary;
|
||||
ngx_int_t ngx_process;
|
||||
ngx_pid_t ngx_pid;
|
||||
ngx_pid_t ngx_new_binary;
|
||||
|
||||
ngx_int_t ngx_inherited;
|
||||
ngx_int_t ngx_reap;
|
||||
ngx_int_t ngx_timer;
|
||||
ngx_int_t ngx_terminate;
|
||||
ngx_int_t ngx_quit;
|
||||
ngx_int_t ngx_noaccept;
|
||||
ngx_int_t ngx_reconfigure;
|
||||
ngx_int_t ngx_reopen;
|
||||
ngx_int_t ngx_change_binary;
|
||||
ngx_int_t ngx_inherited;
|
||||
ngx_int_t ngx_reap;
|
||||
ngx_int_t ngx_timer;
|
||||
ngx_int_t ngx_terminate;
|
||||
ngx_int_t ngx_quit;
|
||||
ngx_int_t ngx_noaccept;
|
||||
ngx_int_t ngx_reconfigure;
|
||||
ngx_int_t ngx_reopen;
|
||||
ngx_int_t ngx_change_binary;
|
||||
|
||||
|
||||
int main(int argc, char *const *argv, char **envp)
|
||||
@ -577,6 +580,9 @@ static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
|
||||
ngx_int_t i;
|
||||
ngx_listening_t *ls;
|
||||
ngx_core_conf_t *ccf;
|
||||
#if (NGX_THREADS)
|
||||
ngx_tid_t tid;
|
||||
#endif
|
||||
|
||||
ngx_process = NGX_PROCESS_WORKER;
|
||||
ngx_last_process = 0;
|
||||
@ -641,7 +647,15 @@ static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
|
||||
|
||||
ngx_setproctitle("worker process");
|
||||
|
||||
/* TODO: threads: start ngx_worker_thread_cycle() */
|
||||
#if (NGX_THREADS)
|
||||
|
||||
ngx_init_threads(5, 128 * 1024 * 1024, cycle->log);
|
||||
|
||||
for (i = 0; i < 1; i++) {
|
||||
ngx_create_thread(&tid, ngx_worker_thread_cycle, cycle, cycle->log);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
for ( ;; ) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
|
||||
@ -688,6 +702,35 @@ static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_THREADS)
|
||||
|
||||
int ngx_worker_thread_cycle(void *data)
|
||||
{
|
||||
ngx_cycle_t *cycle = data;
|
||||
|
||||
struct timeval tv;
|
||||
|
||||
/* 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);
|
||||
|
||||
ngx_gettimeofday(&tv);
|
||||
ngx_time_update(tv.tv_sec);
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, ngx_errno,
|
||||
"thread %d done", ngx_thread_self());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle, char **envp)
|
||||
{
|
||||
char *p, *v;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
extern ngx_module_t ngx_core_module;
|
||||
|
||||
extern ngx_uint_t ngx_connection_counter;
|
||||
extern ngx_atomic_t ngx_connection_counter;
|
||||
|
||||
extern ngx_int_t ngx_process;
|
||||
|
||||
|
@ -6,9 +6,78 @@
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
typedef uint32_t ngx_atomic_t;
|
||||
|
||||
#if (NGX_SMP)
|
||||
#define NGX_SMP_LOCK "lock"
|
||||
#else
|
||||
#define NGX_SMP_LOCK
|
||||
#endif
|
||||
|
||||
|
||||
static ngx_inline uint32_t ngx_atomic_inc(ngx_atomic_t *value)
|
||||
{
|
||||
uint32_t old;
|
||||
|
||||
__asm__ __volatile ("
|
||||
|
||||
movl $1, %0
|
||||
" NGX_SMP_LOCK
|
||||
" xaddl %0, %1
|
||||
|
||||
": "=a" (old) : "m" (*value));
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
static ngx_inline uint32_t ngx_atomic_dec(ngx_atomic_t *value)
|
||||
{
|
||||
uint32_t old;
|
||||
|
||||
__asm__ __volatile ("
|
||||
|
||||
movl $-1, %0
|
||||
" NGX_SMP_LOCK
|
||||
" xaddl %0, %1
|
||||
|
||||
": "=a" (old) : "m" (*value));
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
static ngx_inline uint32_t ngx_atomic_cmp_set(ngx_atomic_t *lock,
|
||||
ngx_atomic_t old,
|
||||
ngx_atomic_t set)
|
||||
{
|
||||
uint32_t res;
|
||||
|
||||
__asm__ __volatile ("
|
||||
|
||||
" NGX_SMP_LOCK
|
||||
" cmpxchgl %3, %1
|
||||
setzb %%al
|
||||
movzbl %%al, %0
|
||||
|
||||
": "=a" (res) : "m" (*lock), "a" (old), "q" (set));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef uint32_t ngx_atomic_t;
|
||||
|
||||
/* STUB */
|
||||
#define ngx_atomic_inc(x) x++;
|
||||
#define ngx_atomic_dec(x) x--;
|
||||
#define ngx_atomic_cmp_set(lock, old, set) 1;
|
||||
/**/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _NGX_ATOMIC_H_INCLUDED_ */
|
||||
|
@ -38,11 +38,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* STUB: ngx_mutex.h */
|
||||
#define ngx_mutex_lock(m)
|
||||
#define ngx_mutex_unlock(m)
|
||||
|
||||
|
||||
/* STUB: autoconf */
|
||||
typedef int ngx_int_t;
|
||||
typedef u_int ngx_uint_t;
|
||||
@ -71,7 +66,7 @@ typedef int ngx_flag_t;
|
||||
/* TODO: #ifndef */
|
||||
#define NGX_SHUTDOWN_SIGNAL QUIT
|
||||
#define NGX_TERMINATE_SIGNAL TERM
|
||||
#define NGX_NOACCEPT_SIGNAL ABRT
|
||||
#define NGX_NOACCEPT_SIGNAL WINCH
|
||||
#define NGX_RECONFIGURE_SIGNAL HUP
|
||||
#define NGX_REOPEN_SIGNAL USR1
|
||||
#define NGX_CHANGEBIN_SIGNAL USR2
|
||||
|
@ -20,6 +20,7 @@ typedef struct ngx_connection_s ngx_connection_t;
|
||||
#include <ngx_socket.h>
|
||||
#include <ngx_errno.h>
|
||||
#include <ngx_process.h>
|
||||
#include <ngx_thread.h>
|
||||
#include <ngx_string.h>
|
||||
#include <ngx_parse.h>
|
||||
#include <ngx_log.h>
|
||||
|
@ -79,7 +79,7 @@ void ngx_log_error_core(int level, ngx_log_t *log, ngx_err_t err,
|
||||
|
||||
/* pid#tid */
|
||||
len += ngx_snprintf(errstr + len, max - len,
|
||||
PID_T_FMT "#%d: ", ngx_pid, /* STUB */ 0);
|
||||
PID_T_FMT "#" TID_T_FMT ": ", ngx_log_pid, ngx_log_tid);
|
||||
|
||||
if (log->data && *(int *) log->data != -1) {
|
||||
len += ngx_snprintf(errstr + len, max - len,
|
||||
|
@ -3,6 +3,11 @@
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#if (NGX_THREADS)
|
||||
static ngx_mutex_t *ngx_time_mutex;
|
||||
#endif
|
||||
|
||||
|
||||
time_t ngx_cached_time;
|
||||
ngx_epoch_msec_t ngx_elapsed_msec;
|
||||
ngx_epoch_msec_t ngx_old_elapsed_msec;
|
||||
@ -46,6 +51,13 @@ void ngx_time_init()
|
||||
ngx_elapsed_msec = 0;
|
||||
|
||||
ngx_time_update(tv.tv_sec);
|
||||
|
||||
#if (NGX_THREADS0)
|
||||
if (!(ngx_time_mutex = ngx_mutex_init(log, NGX_MUTEX_LIGHT);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -57,6 +69,12 @@ void ngx_time_update(time_t s)
|
||||
return;
|
||||
}
|
||||
|
||||
#if (NGX_THREADS0)
|
||||
if (ngx_mutex_trylock(ngx_time_mutex) != NGX_OK) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ngx_cached_time = s;
|
||||
|
||||
ngx_gmtime(ngx_cached_time, &ngx_cached_gmtime);
|
||||
@ -90,6 +108,11 @@ void ngx_time_update(time_t s)
|
||||
tm.ngx_tm_hour,
|
||||
tm.ngx_tm_min,
|
||||
tm.ngx_tm_sec);
|
||||
|
||||
#if (NGX_THREADS0)
|
||||
ngx_mutex_unlock(ngx_time_mutex);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -254,17 +254,17 @@ void ngx_event_accept(ngx_event_t *ev)
|
||||
|
||||
/*
|
||||
* TODO: MT: - atomic increment (x86: lock xadd)
|
||||
* or protection by critical section or mutex
|
||||
* or protection by critical section or light mutex
|
||||
*
|
||||
* TODO: MP: - allocated in a shared memory
|
||||
* - atomic increment (x86: lock xadd)
|
||||
* or protection by critical section or mutex
|
||||
* or protection by critical section or light mutex
|
||||
*/
|
||||
|
||||
c->number = ngx_connection_counter++;
|
||||
c->number = ngx_atomic_inc(&ngx_connection_counter);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
|
||||
"accept: %d, %d", s, c->number);
|
||||
"accept: fd:%d c:%d", s, c->number);
|
||||
|
||||
if (ngx_add_conn) {
|
||||
if (ngx_add_conn(c) == NGX_ERROR) {
|
||||
@ -292,8 +292,6 @@ void ngx_event_accept(ngx_event_t *ev)
|
||||
accepted++;
|
||||
|
||||
} while (ev->available);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,6 +9,10 @@
|
||||
* protected by the single mutex
|
||||
*/
|
||||
|
||||
#if (NGX_THREADS)
|
||||
static ngx_mutex_t *ngx_event_timer_mutex;
|
||||
#endif
|
||||
|
||||
|
||||
ngx_rbtree_t *ngx_event_timer_rbtree;
|
||||
ngx_rbtree_t ngx_event_timer_sentinel;
|
||||
|
@ -61,6 +61,9 @@ typedef struct {
|
||||
size_t nelts;
|
||||
time_t life;
|
||||
time_t update;
|
||||
#if (NGX_THREADS)
|
||||
ngx_mutex_t mutex;
|
||||
#endif
|
||||
ngx_pool_t *pool;
|
||||
} ngx_http_cache_hash_t;
|
||||
|
||||
|
@ -2,31 +2,44 @@
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
extern int __isthreaded;
|
||||
/*
|
||||
* The threads implementation uses the rfork(RFPROC|RFTHREAD|RFMEM)
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
typedef int ngx_tid_t;
|
||||
extern int __isthreaded;
|
||||
|
||||
|
||||
static inline int ngx_gettid();
|
||||
|
||||
|
||||
static char *usrstack;
|
||||
static int red_zone = 4096;
|
||||
static size_t rz_size = /* STUB: PAGE_SIZE */ 4096;
|
||||
|
||||
static size_t stack_size;
|
||||
static size_t usable_stack_size;
|
||||
static char *last_stack;
|
||||
|
||||
static int threads;
|
||||
static int nthreads;
|
||||
static ngx_tid_t *tids;
|
||||
static ngx_uint_t nthreads;
|
||||
static ngx_uint_t max_threads;
|
||||
static ngx_tid_t *tids; /* the threads tids array */
|
||||
|
||||
|
||||
/* the thread-safe errno */
|
||||
|
||||
static int errno0; /* the main thread's errno */
|
||||
static int *errnos;
|
||||
static int *errnos; /* the threads errno's array */
|
||||
|
||||
int *__error()
|
||||
{
|
||||
@ -41,20 +54,22 @@ int *__error()
|
||||
int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg,
|
||||
ngx_log_t *log)
|
||||
{
|
||||
int id, err;
|
||||
char *stack, *stack_top;
|
||||
int id, err;
|
||||
char *stack, *stack_top;
|
||||
|
||||
if (threads >= nthreads) {
|
||||
if (nthreads >= max_threads) {
|
||||
ngx_log_error(NGX_LOG_CRIT, log, 0,
|
||||
"no more than %d threads can be created", nthreads);
|
||||
"no more than %d threads can be created", max_threads);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
last_stack -= stack_size;
|
||||
|
||||
stack = mmap(last_stack, usable_stack_size, PROT_READ|PROT_WRITE,
|
||||
MAP_STACK, -1, 0);
|
||||
|
||||
if (stack == MAP_FAILED) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, errno,
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
"mmap(%08X:%d, MAP_STACK) thread stack failed",
|
||||
last_stack, usable_stack_size);
|
||||
return NGX_ERROR;
|
||||
@ -66,7 +81,8 @@ int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg,
|
||||
|
||||
stack_top = stack + usable_stack_size;
|
||||
|
||||
printf("stack: %08X-%08X\n", stack, stack_top);
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, log, 0,
|
||||
"thread stack: %08X-%08X", stack, stack_top);
|
||||
|
||||
#if 1
|
||||
id = rfork_thread(RFPROC|RFTHREAD|RFMEM, stack_top, func, arg);
|
||||
@ -78,89 +94,78 @@ printf("stack: %08X-%08X\n", stack, stack_top);
|
||||
id = rfork(RFFDG|RFCFDG);
|
||||
#endif
|
||||
|
||||
err = errno;
|
||||
err = ngx_errno;
|
||||
|
||||
if (id == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, err, "rfork() failed");
|
||||
|
||||
} else {
|
||||
*tid = id;
|
||||
threads = (usrstack - stack_top) / stack_size;
|
||||
tids[threads] = id;
|
||||
nthreads = (usrstack - stack_top) / stack_size;
|
||||
tids[nthreads] = id;
|
||||
|
||||
/* allow the spinlock in libc malloc() */
|
||||
__isthreaded = 1;
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "rfork()ed thread: %d", id);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int ngx_init_thread_env(int n, size_t size, ngx_log_t *log)
|
||||
ngx_int_t ngx_init_threads(int n, size_t size, ngx_log_t *log)
|
||||
{
|
||||
int len;
|
||||
char *rz, *zone;
|
||||
char *red_zone, *zone;
|
||||
|
||||
nthreads = n;
|
||||
max_threads = n;
|
||||
|
||||
len = 4;
|
||||
if (sysctlbyname("kern.usrstack", &usrstack, &len, NULL, 0) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, errno,
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
"sysctlbyname(kern.usrstack) failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
printf("usrstack: %08X\n", usrstack);
|
||||
/* the main thread stack red zone */
|
||||
red_zone = usrstack - (size + rz_size);
|
||||
|
||||
/* red zone */
|
||||
rz = usrstack - (size + red_zone);
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, log, 0,
|
||||
"usrstack: %08X, red zone: %08X", usrstack, red_zone);
|
||||
|
||||
printf("red zone: %08X\n", rz);
|
||||
|
||||
zone = mmap(rz, red_zone, PROT_NONE, MAP_ANON, -1, 0);
|
||||
zone = mmap(red_zone, rz_size, PROT_NONE, MAP_ANON, -1, 0);
|
||||
if (zone == MAP_FAILED) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, errno,
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
"mmap(%08X:%d, PROT_NONE, MAP_ANON) red zone failed",
|
||||
rz, red_zone);
|
||||
red_zone, rz_size);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (zone != rz) {
|
||||
if (zone != red_zone) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, 0, "red zone address was changed");
|
||||
}
|
||||
|
||||
/* create the thread errno array */
|
||||
ngx_test_null(errnos, ngx_calloc(n * sizeof(int), log), NGX_ERROR);
|
||||
/* create the threads errno array */
|
||||
|
||||
/* create the thread tid array */
|
||||
ngx_test_null(tids, ngx_calloc((n + 1) * sizeof(ngx_tid_t), log),
|
||||
NGX_ERROR);
|
||||
|
||||
tids[0] = ngx_getpid();
|
||||
threads = 1;
|
||||
|
||||
last_stack = zone + red_zone;
|
||||
usable_stack_size = size;
|
||||
stack_size = size + red_zone;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_tid_t ngx_thread_self()
|
||||
{
|
||||
int tid;
|
||||
ngx_tid_t pid;
|
||||
|
||||
tid = ngx_gettid();
|
||||
|
||||
if (tids[tid] == 0) {
|
||||
pid = ngx_getpid();
|
||||
tids[tid] = pid;
|
||||
return pid;
|
||||
if (!(errnos = ngx_calloc(n * sizeof(int), log))) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return tids[tid];
|
||||
/* create the threads tid array */
|
||||
|
||||
if (!(tids = ngx_calloc((n + 1) * sizeof(ngx_tid_t), log))) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
tids[0] = ngx_pid;
|
||||
nthreads = 1;
|
||||
|
||||
last_stack = zone + rz_size;
|
||||
usable_stack_size = size;
|
||||
stack_size = size + rz_size;
|
||||
|
||||
/* allow the spinlock in libc malloc() */
|
||||
__isthreaded = 1;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -176,3 +181,286 @@ static inline int ngx_gettid()
|
||||
|
||||
return (usrstack - sp) / stack_size;
|
||||
}
|
||||
|
||||
|
||||
ngx_tid_t ngx_thread_self()
|
||||
{
|
||||
int tid;
|
||||
ngx_tid_t pid;
|
||||
|
||||
tid = ngx_gettid();
|
||||
|
||||
if (tids == NULL) {
|
||||
return ngx_pid;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (tids[tid] == 0) {
|
||||
pid = ngx_pid;
|
||||
tids[tid] = pid;
|
||||
return pid;
|
||||
}
|
||||
#endif
|
||||
|
||||
return tids[tid];
|
||||
}
|
||||
|
||||
|
||||
ngx_mutex_t *ngx_mutex_init(ngx_log_t *log, uint flags)
|
||||
{
|
||||
int nsem, i;
|
||||
ngx_mutex_t *m;
|
||||
union semun op;
|
||||
|
||||
if (!(m = ngx_alloc(sizeof(ngx_mutex_t), log))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m->lock = 0;
|
||||
m->log = log;
|
||||
|
||||
if (flags & NGX_MUTEX_LIGHT) {
|
||||
m->semid = -1;
|
||||
return m;
|
||||
}
|
||||
|
||||
nsem = flags & NGX_MUTEX_CV ? 2 : 1;
|
||||
|
||||
m->semid = semget(IPC_PRIVATE, nsem, 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");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
void ngx_mutex_done(ngx_mutex_t *m)
|
||||
{
|
||||
if (semctl(m->semid, 0, IPC_RMID) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, m->log, ngx_errno,
|
||||
"semctl(IPC_RMID) failed");
|
||||
}
|
||||
|
||||
ngx_free(m);
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t ngx_mutex_do_lock(ngx_mutex_t *m, ngx_int_t try)
|
||||
{
|
||||
uint32_t lock, new, old;
|
||||
ngx_uint_t tries;
|
||||
struct sembuf op;
|
||||
|
||||
#if (NGX_DEBUG)
|
||||
if (try) {
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, m->log, 0,
|
||||
"try lock mutex %08X lock:%X", m, m->lock);
|
||||
} else {
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, m->log, 0,
|
||||
"lock mutex %08X lock:%X", m, m->lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
old = m->lock;
|
||||
tries = 0;
|
||||
|
||||
for ( ;; ) {
|
||||
if (old & NGX_MUTEX_LOCK_BUSY) {
|
||||
|
||||
if (try) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (ngx_freebsd_hw_ncpu > 1 && tries++ < 1000) {
|
||||
|
||||
/* the spinlock is used only on the SMP system */
|
||||
|
||||
old = m->lock;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m->semid == -1) {
|
||||
sched_yield();
|
||||
|
||||
tries = 0;
|
||||
old = m->lock;
|
||||
continue;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, m->log, 0,
|
||||
"mutex %08X lock:%X", m, m->lock);
|
||||
|
||||
/*
|
||||
* The mutex is locked so we increase a number
|
||||
* of the threads that are waiting on the mutex
|
||||
*/
|
||||
|
||||
lock = old + 1;
|
||||
|
||||
if ((lock & ~NGX_MUTEX_LOCK_BUSY) > nthreads) {
|
||||
ngx_log_error(NGX_LOG_ALERT, m->log, ngx_errno,
|
||||
"%d threads wait for mutex %0X, "
|
||||
"while only %d threads are available",
|
||||
lock & ~NGX_MUTEX_LOCK_BUSY, m, nthreads);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_atomic_cmp_set(&m->lock, old, lock)) {
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, m->log, 0,
|
||||
"wait mutex %08X lock:%X", m, m->lock);
|
||||
|
||||
/*
|
||||
* 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().
|
||||
*/
|
||||
|
||||
op.sem_num = 0;
|
||||
op.sem_op = -1;
|
||||
op.sem_flg = SEM_UNDO;
|
||||
|
||||
if (semop(m->semid, &op, 1) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, m->log, ngx_errno,
|
||||
"semop() failed while waiting "
|
||||
"on mutex %08X", m);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
tries = 0;
|
||||
old = m->lock;
|
||||
continue;
|
||||
}
|
||||
|
||||
old = m->lock;
|
||||
|
||||
} else {
|
||||
lock = old | NGX_MUTEX_LOCK_BUSY;
|
||||
|
||||
if (ngx_atomic_cmp_set(&m->lock, old, lock)) {
|
||||
|
||||
/* we locked the mutex */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
old = m->lock;
|
||||
}
|
||||
|
||||
if (tries++ > 1000) {
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, m->log, 0,
|
||||
"mutex %08X is contested", m);
|
||||
|
||||
/* the mutex is probably contested so we are giving up now */
|
||||
|
||||
sched_yield();
|
||||
|
||||
tries = 0;
|
||||
old = m->lock;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, m->log, 0,
|
||||
"mutex %08X is locked, lock:%X", m, m->lock);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t ngx_mutex_unlock(ngx_mutex_t *m)
|
||||
{
|
||||
uint32_t lock, new, old;
|
||||
struct sembuf op;
|
||||
|
||||
old = m->lock;
|
||||
|
||||
if (!(old & NGX_MUTEX_LOCK_BUSY)) {
|
||||
ngx_log_error(NGX_LOG_ALERT, m->log, ngx_errno,
|
||||
"tring to unlock the free mutex %0X", m);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/* free the mutex */
|
||||
|
||||
for ( ;; ) {
|
||||
lock = old & ~NGX_MUTEX_LOCK_BUSY;
|
||||
|
||||
if (ngx_atomic_cmp_set(&m->lock, old, lock)) {
|
||||
break;
|
||||
}
|
||||
|
||||
old = m->lock;
|
||||
}
|
||||
|
||||
if (m->semid == -1) {
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, m->log, 0,
|
||||
"mutex %08X is unlocked", m);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
/* check weather we need to wake up a waiting thread */
|
||||
|
||||
old = m->lock;
|
||||
|
||||
for ( ;; ) {
|
||||
if (old & NGX_MUTEX_LOCK_BUSY) {
|
||||
|
||||
/* the mutex is just locked by another thread */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (old == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* there are the waiting threads */
|
||||
|
||||
lock = old - 1;
|
||||
|
||||
if (ngx_atomic_cmp_set(&m->lock, old, lock)) {
|
||||
|
||||
/* wake up the thread that waits on semaphore */
|
||||
|
||||
op.sem_num = 0;
|
||||
op.sem_op = 1;
|
||||
op.sem_flg = SEM_UNDO;
|
||||
|
||||
if (semop(m->semid, &op, 1) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, m->log, ngx_errno,
|
||||
"semop() failed while waking up on mutex %08X",
|
||||
m);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
old = m->lock;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, m->log, 0,
|
||||
"mutex %08X is unlocked", m);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
@ -40,7 +40,8 @@ typedef struct {
|
||||
#define NGX_PROCESS_DETACHED -3
|
||||
|
||||
|
||||
#define ngx_getpid getpid
|
||||
#define ngx_getpid getpid
|
||||
#define ngx_log_pid ngx_pid
|
||||
|
||||
ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle,
|
||||
ngx_spawn_proc_pt proc, void *data,
|
||||
|
74
src/os/unix/ngx_thread.h
Normal file
74
src/os/unix/ngx_thread.h
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef _NGX_THREAD_H_INCLUDED_
|
||||
#define _NGX_THREAD_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
#if (NGX_THREADS)
|
||||
|
||||
#if (USE_RFORK)
|
||||
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
#include <sched.h>
|
||||
|
||||
typedef pid_t ngx_tid_t;
|
||||
|
||||
#define TID_T_FMT PID_T_FMT
|
||||
|
||||
#define ngx_log_tid 0
|
||||
|
||||
#undef ngx_log_pid
|
||||
#define ngx_log_pid ngx_thread_self()
|
||||
|
||||
|
||||
#define NGX_MUTEX_LIGHT 1
|
||||
#define NGX_MUTEX_CV 2
|
||||
|
||||
#define NGX_MUTEX_LOCK_BUSY 0x80000000
|
||||
|
||||
typedef struct {
|
||||
ngx_atomic_t lock;
|
||||
ngx_log_t *log;
|
||||
int semid;
|
||||
} ngx_mutex_t;
|
||||
|
||||
|
||||
#else /* use pthreads */
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
typedef pthread_t ngx_tid_t;
|
||||
|
||||
#define ngx_log_tid ngx_thread_self()
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
ngx_int_t ngx_init_threads(int n, size_t size, ngx_log_t *log);
|
||||
int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg,
|
||||
ngx_log_t *log);
|
||||
ngx_tid_t ngx_thread_self();
|
||||
|
||||
ngx_mutex_t *ngx_mutex_init(ngx_log_t *log, uint flags);
|
||||
void ngx_mutex_done(ngx_mutex_t *m);
|
||||
|
||||
#define ngx_mutex_trylock(m) ngx_mutex_do_lock(m, 1)
|
||||
#define ngx_mutex_lock(m) ngx_mutex_do_lock(m, 0)
|
||||
ngx_int_t ngx_mutex_do_lock(ngx_mutex_t *m, ngx_int_t try);
|
||||
ngx_int_t ngx_mutex_unlock(ngx_mutex_t *m);
|
||||
|
||||
|
||||
#else /* !NGX_THREADS */
|
||||
|
||||
#define ngx_log_tid 0
|
||||
#define TID_T_FMT "%d"
|
||||
|
||||
#define ngx_mutex_lock(m)
|
||||
#define ngx_mutex_unlock(m)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _NGX_THREAD_H_INCLUDED_ */
|
Loading…
Reference in New Issue
Block a user