diff src/os/unix/ngx_freebsd_rfork_thread.c @ 370:54f76b0b8dca

nginx-0.0.7-2004-06-27-22:01:57 import
author Igor Sysoev <igor@sysoev.ru>
date Sun, 27 Jun 2004 18:01:57 +0000
parents 55e496a8ece3
children 780e93985b93
line wrap: on
line diff
--- 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 *l
         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, 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, IPC_RMID) == -1) {
+            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                          "semctl(IPC_RMID) failed");
+        }
 
-            return NULL;
-        }
+        return NULL;
     }
 
     return m;
@@ -388,7 +385,7 @@ ngx_int_t ngx_mutex_dolock(ngx_mutex_t *
                  * 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 *
 
     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 *
         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 *
 
     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;
+}