diff options
Diffstat (limited to 'src/os/unix')
-rw-r--r-- | src/os/unix/ngx_freebsd_config.h | 5 | ||||
-rw-r--r-- | src/os/unix/ngx_freebsd_rfork_thread.c | 152 | ||||
-rw-r--r-- | src/os/unix/ngx_linux_config.h | 4 | ||||
-rw-r--r-- | src/os/unix/ngx_process_cycle.c | 23 | ||||
-rw-r--r-- | src/os/unix/ngx_solaris_config.h | 4 | ||||
-rw-r--r-- | src/os/unix/ngx_thread.h | 11 | ||||
-rw-r--r-- | src/os/unix/ngx_time.c | 8 |
7 files changed, 160 insertions, 47 deletions
diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h index 570eee89b..67f5fb3ed 100644 --- a/src/os/unix/ngx_freebsd_config.h +++ b/src/os/unix/ngx_freebsd_config.h @@ -108,14 +108,9 @@ pid_t rfork_thread(int flags, void *stack, int (*func)(void *arg), void *arg); #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 740fb525d..c4cd30205 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_tid_t ngx_thread_self() ngx_mutex_t *ngx_mutex_init(ngx_log_t *log, uint flags) { - int nsem, i; ngx_mutex_t *m; union semun op; @@ -277,27 +278,23 @@ ngx_mutex_t *ngx_mutex_init(ngx_log_t *log, uint flags) 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; @@ -388,7 +385,7 @@ ngx_int_t ngx_mutex_dolock(ngx_mutex_t *m, ngx_int_t try) * The number of the waiting threads has been increased * and we would wait on the SysV semaphore. * A semaphore should wake up us more efficiently than - * a simple usleep(). + * a simple sched_yield() or usleep(). */ op.sem_num = 0; @@ -456,7 +453,7 @@ ngx_int_t ngx_mutex_unlock(ngx_mutex_t *m) if (!(old & NGX_MUTEX_LOCK_BUSY)) { ngx_log_error(NGX_LOG_ALERT, m->log, 0, - "tring to unlock the free mutex " PTR_FMT, m); + "trying to unlock the free mutex " PTR_FMT, m); return NGX_ERROR; } @@ -479,7 +476,7 @@ ngx_int_t ngx_mutex_unlock(ngx_mutex_t *m) return NGX_OK; } - /* check weather we need to wake up a waiting thread */ + /* check whether we need to wake up a waiting thread */ old = m->lock; @@ -525,3 +522,108 @@ ngx_int_t ngx_mutex_unlock(ngx_mutex_t *m) 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 8a75e229f..c01584e71 100644 --- a/src/os/unix/ngx_linux_config.h +++ b/src/os/unix/ngx_linux_config.h @@ -91,8 +91,4 @@ extern ssize_t sendfile(int s, int fd, int32_t *offset, size_t size); #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 21966f272..6d7fe06c2 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -625,6 +625,13 @@ static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) exit(2); } + if (!(ngx_posted_events_cv = ngx_cv_init(cycle->log))) { + /* fatal */ + exit(2); + } + + ngx_posted_events_mutex = &ngx_posted_events_cv->mutex; + for (i = 0; i < 1; i++) { if (ngx_create_thread(&tid, ngx_worker_thread_cycle, cycle, cycle->log) != 0) @@ -767,23 +774,25 @@ int ngx_worker_thread_cycle(void *data) return 1; } - - /* STUB */ - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, ngx_errno, "thread %d started", ngx_thread_self()); ngx_setproctitle("worker thread"); - sleep(5); + for ( ;; ) { + if (ngx_cv_wait(ngx_posted_events_cv) == NGX_ERROR) { + return 1; + } - ngx_gettimeofday(&tv); - ngx_time_update(tv.tv_sec); + if (ngx_event_thread_process_posted(cycle) == NGX_ERROR) { + return 1; + } + } ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, ngx_errno, "thread %d done", ngx_thread_self()); - return 1; + return 0; } #endif diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h index b1e71cd4e..1bae50e23 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 52252747e..6412fe8b2 100644 --- a/src/os/unix/ngx_thread.h +++ b/src/os/unix/ngx_thread.h @@ -36,6 +36,11 @@ typedef volatile struct { } ngx_mutex_t; +typedef struct { + ngx_mutex_t mutex; +} ngx_cv_t; + + #define ngx_thread_sigmask(how, set, oset) \ (sigprocmask(how, set, oset) == -1) ? ngx_errno : 0 @@ -102,6 +107,12 @@ ngx_int_t ngx_mutex_dolock(ngx_mutex_t *m, ngx_int_t try); 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 5ba95bc30..8647e0e69 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 |