# HG changeset patch # User Igor Sysoev # Date 1077643906 0 # Node ID 83205e0b55223a248ed8e8415d5d53f90865f961 # Parent 5238e93961a189c13eefff01f8eccfe863159c72 nginx-0.0.2-2004-02-24-20:31:46 import diff --git a/auto/fmt/ptrfmt b/auto/fmt/ptrfmt new file mode 100644 --- /dev/null +++ b/auto/fmt/ptrfmt @@ -0,0 +1,62 @@ + +echo $ngx_n "checking for $ngx_type printf() format ..." $ngx_c +echo >> $NGX_ERR +echo "checking for $ngx_type printf() format" >> $NGX_ERR + +ngx_fmt=no +comma= +fmtX= + +for fmt in $ngx_formats +do + + cat << END > $NGX_AUTOTEST.c + +int main() { + printf("$fmt", ($ngx_type) $ngx_max_size); + return 0; +} + +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*\$//"` + + if [ -x $NGX_AUTOTEST ]; then + if [ "`$NGX_AUTOTEST`" = $max_size ]; then + ngx_fmt=$fmt + fi + fi + + rm $NGX_AUTOTEST* + + if [ $ngx_fmt != no ]; then + break + fi + + fmtX=`echo $fmt | sed -e "s/d/X/"` + + echo $ngx_n "$comma \"${fmtX}\" is not appropriate" $ngx_c + comma="," +done + + +if [ $ngx_fmt = no ]; then + echo "$0: error: printf() $ngx_type format not found" + exit 1 +fi + +fmtX="%0`expr 2 \* ${ngx_ptr_bytes}`" +ngx_fmt=`echo $ngx_fmt | sed -e "s/d/X/" -e "s/^%/$fmtX/"` + +echo "$comma \"${ngx_fmt}\" used" + +cat << END >> $NGX_AUTO_CONFIG_H + +#ifndef $ngx_fmt_name +#define $ngx_fmt_name "$ngx_fmt" +#endif + +END diff --git a/auto/make b/auto/make --- a/auto/make +++ b/auto/make @@ -59,7 +59,7 @@ echo "nginx: \\" for src in $CORE_SRCS $HTTP_SRCS do - obj=`echo $src | sed -e "s/\.c\$/.$OBJEXT/"` + obj=`echo $src | sed -e "s/\.c\$/.$OBJEXT/" -e "s/\.S\$/.$OBJEXT/"` echo " $OBJS/$obj \\" >> $MAKEFILE done @@ -74,7 +74,7 @@ echo " \$(CC) ${BINOUT}nginx \\" for src in $CORE_SRCS $HTTP_SRCS do - obj=`echo $src | sed -e "s/\.c\$/.$OBJEXT/"` + obj=`echo $src | sed -e "s/\.c\$/.$OBJEXT/" -e "s/\.S\$/.$OBJEXT/"` echo " $OBJS/$obj \\" >> $MAKEFILE done @@ -100,7 +100,7 @@ echo for src in $CORE_SRCS do - obj=`echo $src | sed -e "s/\.c\$/.$OBJEXT/"` + obj=`echo $src | sed -e "s/\.c\$/.$OBJEXT/" -e "s/\.S\$/.$OBJEXT/"` echo "$OBJS/$obj: \\" >> $MAKEFILE echo " $src $deps" >> $MAKEFILE diff --git a/auto/os/freebsd b/auto/os/freebsd --- a/auto/os/freebsd +++ b/auto/os/freebsd @@ -11,9 +11,21 @@ version=`grep "#define __FreeBSD_version | sed -e 's/^.* \(.*\)$/\1/'` +# setproctitle() in libutil + +if [ \( $version -ge 500000 -a $version -lt 500012 \) \ + -o $version -lt 410002 ] +then + echo " + setproctitle() in libutil" + + CORE_LIBS="$CORE_LIBS -lutil" +fi + # sendfile if [ $version -gt 300007 ]; then + echo " + sendfile() found" + have=HAVE_SENDFILE . auto/have CORE_SRCS="$CORE_SRCS $FREEBSD_SENDFILE_SRCS" fi @@ -24,6 +36,8 @@ fi if [ \( $version -lt 500000 -a $version -ge 410000 \) \ -o $version -ge 500011 ] then + echo " + kqueue found" + have=HAVE_KQUEUE . auto/have have=HAVE_CLEAR_EVENT . auto/have CORE_SRCS="$CORE_SRCS $KQUEUE_SRCS" @@ -37,6 +51,8 @@ fi if [ \( $version -lt 500000 -a $version -ge 430000 \) \ -o $version -ge 500018 ] then + echo " + kqueue's NOTE_LAWAT found" + have=HAVE_LOWAT_EVENT . auto/have fi diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -120,6 +120,7 @@ FREEBSD_DEPS=src/os/unix/ngx_freebsd_con 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" +FREEBSD_RFORK_THREAD_SRCS="src/os/unix/rfork_thread.S" LINUX_DEPS=src/os/unix/ngx_linux_config.h LINUX_SRCS=src/os/unix/ngx_linux_init.c diff --git a/auto/threads b/auto/threads --- a/auto/threads +++ b/auto/threads @@ -1,7 +1,13 @@ 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" + + if [ $version -lt 501000 ]; then + CORE_SRCS="$CORE_SRCS $FREEBSD_RFORK_THREAD_SRCS" + fi + fi diff --git a/auto/unix b/auto/unix --- a/auto/unix +++ b/auto/unix @@ -4,16 +4,18 @@ ngx_fmt_collect=yes # C types -ngx_type="int"; . auto/types/sizeof; +ngx_type="int"; . auto/types/sizeof ngx_formats="%d"; . auto/fmt/fmt -ngx_type="long"; . auto/types/sizeof; +ngx_type="long"; . auto/types/sizeof ngx_formats="%ld"; . auto/fmt/fmt -ngx_type="long long"; . auto/types/sizeof; +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_fmt_name=PTR_FMT; +eval ngx_formats=\${ngx_${ngx_bytes}_fmt}; . auto/fmt/ptrfmt # POSIX types diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -649,10 +649,18 @@ static void ngx_worker_process_cycle(ngx #if (NGX_THREADS) - ngx_init_threads(5, 128 * 1024 * 1024, cycle->log); + if (ngx_init_threads(5, 128 * 1024 * 1024, cycle->log) == NGX_ERROR) { + /* fatal */ + exit(1); + } for (i = 0; i < 1; i++) { - ngx_create_thread(&tid, ngx_worker_thread_cycle, cycle, cycle->log); + if (ngx_create_thread(&tid, ngx_worker_thread_cycle, + cycle, cycle->log) != 0) + { + /* fatal */ + exit(1); + } } #endif diff --git a/src/core/ngx_alloc.c b/src/core/ngx_alloc.c --- a/src/core/ngx_alloc.c +++ b/src/core/ngx_alloc.c @@ -9,10 +9,11 @@ void *ngx_alloc(size_t size, ngx_log_t * if (!(p = malloc(size))) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, - "malloc() %d bytes failed", size); + "malloc() " SIZE_T_FMT " bytes failed", size); } - ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %08x:%d", p, size); + ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, + "malloc: " PTR_FMT ":" SIZE_T_FMT, p, size); return p; } @@ -57,7 +58,7 @@ void ngx_destroy_pool(ngx_pool_t *pool) for (l = pool->large; l; l = l->next) { ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, - "free: %08x", l->alloc); + "free: " PTR_FMT, l->alloc); if (l->alloc) { free(l->alloc); @@ -72,7 +73,8 @@ void ngx_destroy_pool(ngx_pool_t *pool) */ for (p = pool, n = pool->next; /* void */; p = n, n = n->next) { - ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %08x", p); + ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, + "free: " PTR_FMT, p); if (n == NULL) { break; @@ -179,7 +181,7 @@ void ngx_pfree(ngx_pool_t *pool, void *p for (l = pool->large; l; l = l->next) { if (p == l->alloc) { ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, - "free: %08x", l->alloc); + "free: " PTR_FMT, l->alloc); free(l->alloc); l->alloc = NULL; } 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 @@ -6,9 +6,9 @@ #include -#ifdef __i386__ +#if ( __i386__ || __amd64__ ) -typedef uint32_t ngx_atomic_t; +typedef volatile uint32_t ngx_atomic_t; #if (NGX_SMP) #define NGX_SMP_LOCK "lock" @@ -21,13 +21,13 @@ static ngx_inline uint32_t ngx_atomic_in { uint32_t old; - __asm__ __volatile (" + __asm__ volatile ( - movl $1, %0 - " NGX_SMP_LOCK - " xaddl %0, %1 + " movl $1, %0; " + NGX_SMP_LOCK + " xaddl %0, %1; " - ": "=a" (old) : "m" (*value)); + : "=a" (old) : "m" (*value)); return old; } @@ -37,13 +37,13 @@ static ngx_inline uint32_t ngx_atomic_de { uint32_t old; - __asm__ __volatile (" + __asm__ volatile ( - movl $-1, %0 - " NGX_SMP_LOCK - " xaddl %0, %1 + " movl $-1, %0; " + NGX_SMP_LOCK + " xaddl %0, %1; " - ": "=a" (old) : "m" (*value)); + : "=a" (old) : "m" (*value)); return old; } @@ -55,21 +55,21 @@ static ngx_inline uint32_t ngx_atomic_cm { uint32_t res; - __asm__ __volatile (" + __asm__ volatile ( - " NGX_SMP_LOCK - " cmpxchgl %3, %1 - setzb %%al - movzbl %%al, %0 + NGX_SMP_LOCK + " cmpxchgl %3, %1; " + " setzb %%al; " + " movzbl %%al, %0; " - ": "=a" (res) : "m" (*lock), "a" (old), "q" (set)); + : "=a" (res) : "m" (*lock), "a" (old), "q" (set)); return res; } #else -typedef uint32_t ngx_atomic_t; +typedef volatile uint32_t ngx_atomic_t; /* STUB */ #define ngx_atomic_inc(x) x++; 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 @@ -46,10 +46,6 @@ typedef u_int ngx_uint_t; typedef int ngx_flag_t; -/* STUB: autoconf */ -#define PTR_FMT "%08X" - - #ifndef NGX_SERVER_ROOT #define NGX_SERVER_ROOT "./" #if 0 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 @@ -29,6 +29,7 @@ #include #include #include +#include /* setproctitle() brefore 4.1 */ #include #include @@ -72,6 +73,12 @@ #endif +#if (__FreeBSD_version < 430000 || __FreeBSD_version < 500012) + +pid_t rfork_thread(int flags, void *stack, int (*func)(void *arg), void *arg); + +#endif + #ifndef IOV_MAX #define IOV_MAX 1024 #endif 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 @@ -15,12 +15,12 @@ * 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. + * + * This threads implementation currently works on i486 and amd64 + * platforms only. */ -extern int __isthreaded; - - static inline int ngx_gettid(); @@ -36,7 +36,7 @@ static ngx_uint_t max_threads; static ngx_tid_t *tids; /* the threads tids array */ -/* the thread-safe errno */ +/* the thread-safe libc errno */ static int errno0; /* the main thread's errno */ static int *errnos; /* the threads errno's array */ @@ -51,6 +51,41 @@ int *__error() } +/* + * __isthreaded enables spinlock() in some libc functions, i.e. in malloc() + * and some other places. Nevertheless we protect our malloc()/free() calls + * by own mutex that is more efficient than the spinlock. + * + * We define own _spinlock() because a weak referenced _spinlock() stub in + * src/lib/libc/gen/_spinlock_stub.c does nothing. + */ + +extern int __isthreaded; + +void _spinlock(ngx_atomic_t *lock) +{ + ngx_int_t tries; + + tries = 0; + for ( ;; ) { + + if (*lock) { + if (ngx_freebsd_hw_ncpu > 1 && tries++ < 1000) { + continue; + } + + sched_yield(); + tries = 0; + + } else { + if (ngx_atomic_cmp_set(lock, 0, 1)) { + return; + } + } + } +} + + int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg, ngx_log_t *log) { @@ -70,7 +105,8 @@ int ngx_create_thread(ngx_tid_t *tid, in if (stack == MAP_FAILED) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - "mmap(%08X:%d, MAP_STACK) thread stack failed", + "mmap(" PTR_FMT ":" SIZE_T_FMT + ", MAP_STACK) thread stack failed", last_stack, usable_stack_size); return NGX_ERROR; } @@ -82,7 +118,7 @@ int ngx_create_thread(ngx_tid_t *tid, in stack_top = stack + usable_stack_size; ngx_log_debug2(NGX_LOG_DEBUG_CORE, log, 0, - "thread stack: %08X-%08X", stack, stack_top); + "thread stack: " PTR_FMT "-" PTR_FMT, stack, stack_top); #if 1 id = rfork_thread(RFPROC|RFTHREAD|RFMEM, stack_top, func, arg); @@ -113,12 +149,12 @@ int ngx_create_thread(ngx_tid_t *tid, in ngx_int_t ngx_init_threads(int n, size_t size, ngx_log_t *log) { - int len; - char *red_zone, *zone; + size_t len; + char *red_zone, *zone; max_threads = n; - len = 4; + len = sizeof(usrstack); if (sysctlbyname("kern.usrstack", &usrstack, &len, NULL, 0) == -1) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "sysctlbyname(kern.usrstack) failed"); @@ -129,12 +165,14 @@ ngx_int_t ngx_init_threads(int n, size_t red_zone = usrstack - (size + rz_size); ngx_log_debug2(NGX_LOG_DEBUG_CORE, log, 0, - "usrstack: %08X, red zone: %08X", usrstack, red_zone); + "usrstack: " PTR_FMT " red zone: " PTR_FMT, + usrstack, red_zone); zone = mmap(red_zone, rz_size, PROT_NONE, MAP_ANON, -1, 0); if (zone == MAP_FAILED) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - "mmap(%08X:%d, PROT_NONE, MAP_ANON) red zone failed", + "mmap(" PTR_FMT ":" SIZE_T_FMT + ", PROT_NONE, MAP_ANON) red zone failed", red_zone, rz_size); return NGX_ERROR; } @@ -177,7 +215,15 @@ static inline int ngx_gettid() return 0; } - __asm__ ("mov %%esp, %0" : "=q" (sp)); +#if ( __i386__ ) + + __asm__ volatile ("mov %%esp, %0" : "=q" (sp)); + +#elif ( __amd64__ ) + + __asm__ volatile ("mov %%rsp, %0" : "=q" (sp)); + +#endif return (usrstack - sp) / stack_size; } @@ -258,7 +304,7 @@ void ngx_mutex_done(ngx_mutex_t *m) "semctl(IPC_RMID) failed"); } - ngx_free(m); + ngx_free((void *) m); } @@ -271,10 +317,10 @@ ngx_int_t ngx_mutex_do_lock(ngx_mutex_t #if (NGX_DEBUG) if (try) { ngx_log_debug2(NGX_LOG_DEBUG_CORE, m->log, 0, - "try lock mutex %08X lock:%X", m, m->lock); + "try lock mutex " PTR_FMT " lock:%X", m, m->lock); } else { ngx_log_debug2(NGX_LOG_DEBUG_CORE, m->log, 0, - "lock mutex %08X lock:%X", m, m->lock); + "lock mutex " PTR_FMT " lock:%X", m, m->lock); } #endif @@ -305,7 +351,7 @@ ngx_int_t ngx_mutex_do_lock(ngx_mutex_t } ngx_log_debug2(NGX_LOG_DEBUG_CORE, m->log, 0, - "mutex %08X lock:%X", m, m->lock); + "mutex " PTR_FMT " lock:%X", m, m->lock); /* * The mutex is locked so we increase a number @@ -316,8 +362,8 @@ ngx_int_t ngx_mutex_do_lock(ngx_mutex_t 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", + "%d threads wait for mutex " PTR_FMT + ", while only %d threads are available", lock & ~NGX_MUTEX_LOCK_BUSY, m, nthreads); return NGX_ERROR; } @@ -325,7 +371,7 @@ ngx_int_t ngx_mutex_do_lock(ngx_mutex_t 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); + "wait mutex " PTR_FMT " lock:%X", m, m->lock); /* * The number of the waiting threads has been increased @@ -341,7 +387,7 @@ ngx_int_t ngx_mutex_do_lock(ngx_mutex_t 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); + "on mutex " PTR_FMT, m); return NGX_ERROR; } @@ -368,7 +414,7 @@ ngx_int_t ngx_mutex_do_lock(ngx_mutex_t if (tries++ > 1000) { ngx_log_debug1(NGX_LOG_DEBUG_CORE, m->log, 0, - "mutex %08X is contested", m); + "mutex " PTR_FMT " is contested", m); /* the mutex is probably contested so we are giving up now */ @@ -380,7 +426,7 @@ ngx_int_t ngx_mutex_do_lock(ngx_mutex_t } ngx_log_debug2(NGX_LOG_DEBUG_CORE, m->log, 0, - "mutex %08X is locked, lock:%X", m, m->lock); + "mutex " PTR_FMT " is locked, lock:%X", m, m->lock); return NGX_OK; } @@ -395,7 +441,7 @@ ngx_int_t ngx_mutex_unlock(ngx_mutex_t * if (!(old & NGX_MUTEX_LOCK_BUSY)) { ngx_log_error(NGX_LOG_ALERT, m->log, ngx_errno, - "tring to unlock the free mutex %0X", m); + "tring to unlock the free mutex " PTR_FMT, m); return NGX_ERROR; } @@ -413,7 +459,7 @@ ngx_int_t ngx_mutex_unlock(ngx_mutex_t * if (m->semid == -1) { ngx_log_debug1(NGX_LOG_DEBUG_CORE, m->log, 0, - "mutex %08X is unlocked", m); + "mutex " PTR_FMT " is unlocked", m); return NGX_OK; } @@ -448,8 +494,8 @@ ngx_int_t ngx_mutex_unlock(ngx_mutex_t * 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); + "semop() failed while waking up on mutex " + PTR_FMT, m); return NGX_ERROR; } @@ -460,7 +506,7 @@ ngx_int_t ngx_mutex_unlock(ngx_mutex_t * } ngx_log_debug1(NGX_LOG_DEBUG_CORE, m->log, 0, - "mutex %08X is unlocked", m); + "mutex " PTR_FMT " is unlocked", m); return NGX_OK; } 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 @@ -28,7 +28,7 @@ typedef pid_t ngx_tid_t; #define NGX_MUTEX_LOCK_BUSY 0x80000000 -typedef struct { +typedef volatile struct { ngx_atomic_t lock; ngx_log_t *log; int semid; diff --git a/src/os/unix/rfork_thread.S b/src/os/unix/rfork_thread.S new file mode 100644 --- /dev/null +++ b/src/os/unix/rfork_thread.S @@ -0,0 +1,69 @@ + +#include +#include + +/* + * rfork_thread(3) - rfork_thread(flags, stack, func, arg); + */ + +#define KERNCALL int $0x80 + +ENTRY(rfork_thread) + push %ebp + mov %esp, %ebp + push %esi + + mov 12(%ebp), %esi # the stack address + + sub $4, %esi + mov 20(%ebp), %eax # the thread argument + mov %eax, (%esi) + + sub $4, %esi + mov 16(%ebp), %eax # the start thread address + mov %eax, (%esi) + + push 8(%ebp) # rfork(2) flags + push $0 + mov $SYS_rfork, %eax + KERNCALL + jc error + + cmp $0, %edx + jne child + +parent: + add $8, %esp + pop %esi + mov %ebp, %esp + pop %ebp + ret + +child: + mov %esi, %esp + pop %eax + call *%eax # call a thread start address ... + add $4, %esp + + push %eax + push $0 + mov $SYS_exit, %eax # ... and exit(2) after a thread would return + KERNCALL + +error: + add $8, %esp + pop %esi + mov %ebp, %esp + pop %ebp + PIC_PROLOGUE + + /* libc's cerror: jmp PIC_PLT(HIDENAME(cerror)) */ + + push %eax + call PIC_PLT(CNAME(__error)) + pop %ecx + PIC_EPILOGUE + mov %ecx, (%eax) + mov $-1, %eax + mov $-1, %edx + ret