aboutsummaryrefslogtreecommitdiff
path: root/src/os/unix
diff options
context:
space:
mode:
Diffstat (limited to 'src/os/unix')
-rw-r--r--src/os/unix/ngx_freebsd_config.h5
-rw-r--r--src/os/unix/ngx_freebsd_rfork_thread.c152
-rw-r--r--src/os/unix/ngx_linux_config.h4
-rw-r--r--src/os/unix/ngx_process_cycle.c23
-rw-r--r--src/os/unix/ngx_solaris_config.h4
-rw-r--r--src/os/unix/ngx_thread.h11
-rw-r--r--src/os/unix/ngx_time.c8
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