aboutsummaryrefslogtreecommitdiff
path: root/src/os/unix
diff options
context:
space:
mode:
Diffstat (limited to 'src/os/unix')
-rw-r--r--src/os/unix/ngx_atomic.h327
-rw-r--r--src/os/unix/ngx_freebsd.h2
-rw-r--r--src/os/unix/ngx_linux.h5
-rw-r--r--src/os/unix/ngx_linux_init.c21
-rw-r--r--src/os/unix/ngx_os.h4
-rw-r--r--src/os/unix/ngx_process.h9
-rw-r--r--src/os/unix/ngx_setproctitle.c19
-rw-r--r--src/os/unix/ngx_solaris.h6
8 files changed, 321 insertions, 72 deletions
diff --git a/src/os/unix/ngx_atomic.h b/src/os/unix/ngx_atomic.h
index 2de61cf81..c31396468 100644
--- a/src/os/unix/ngx_atomic.h
+++ b/src/os/unix/ngx_atomic.h
@@ -12,11 +12,14 @@
#include <ngx_core.h>
-#if ( __i386__ || __amd64__ )
+#if ( __i386__ )
#define NGX_HAVE_ATOMIC_OPS 1
-typedef volatile uint32_t ngx_atomic_t;
+typedef uint32_t ngx_atomic_int_t;
+typedef volatile ngx_atomic_int_t ngx_atomic_t;
+#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
+
#if (NGX_SMP)
#define NGX_SMP_LOCK "lock;"
@@ -24,57 +27,149 @@ typedef volatile uint32_t ngx_atomic_t;
#define NGX_SMP_LOCK
#endif
+/*
+ * the "=q" is any of the %eax, %ebx, %ecx, or %edx registers.
+ * the '"0" (1)' parameter preloads 1 into %0.
+ * the "cc" means that flags were changed.
+ */
-static ngx_inline uint32_t ngx_atomic_inc(ngx_atomic_t *value)
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_inc(ngx_atomic_t *value)
{
- uint32_t old;
+ ngx_atomic_int_t old;
__asm__ volatile (
- NGX_SMP_LOCK
- " xaddl %0, %2; "
- " incl %0; "
+ NGX_SMP_LOCK
+ " xaddl %0, %2; "
+ " incl %0; "
- : "=q" (old) : "0" (1), "m" (*value));
+ : "=q" (old) : "0" (1), "m" (*value) : "cc", "memory");
return old;
}
-#if 0
-
-static ngx_inline uint32_t ngx_atomic_dec(ngx_atomic_t *value)
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_dec(ngx_atomic_t *value)
{
- uint32_t old;
+ ngx_atomic_int_t old;
__asm__ volatile (
- NGX_SMP_LOCK
- " xaddl %0, %1; "
- " decl %0; "
+ NGX_SMP_LOCK
+ " xaddl %0, %2; "
+ " decl %0; "
- : "=q" (old) : "0" (-1), "m" (*value));
+ : "=q" (old) : "0" (-1), "m" (*value) : "cc", "memory");
return old;
}
+
+/*
+ * the "q" is any of the %eax, %ebx, %ecx, or %edx registers.
+ * the "=a" and "a" are the %eax register. Although we can return result
+ * in any register, we use %eax because it is used in cmpxchg anyway.
+ *
+ * "cmpxchg r, [m]":
+ *
+ * if (eax == [m]) {
+ * zf = 1;
+ * [m] = r;
+ * } else {
+ * zf = 0;
+ * eax = [m];
+ * }
+ */
+
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_int_t old,
+ ngx_atomic_int_t set)
+{
+ ngx_atomic_int_t res;
+
+ __asm__ volatile (
+
+ NGX_SMP_LOCK
+ " cmpxchgl %3, %1; "
+ " setz %b0; "
+ " movzbl %b0, %0; "
+
+ : "=a" (res) : "m" (*lock), "a" (old), "q" (set) : "cc", "memory");
+
+ return res;
+}
+
+
+#elif ( __amd64__ )
+
+#define NGX_HAVE_ATOMIC_OPS 1
+
+typedef int64_t ngx_atomic_int_t;
+typedef volatile ngx_atomic_int_t ngx_atomic_t;
+#define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1
+
+
+#if (NGX_SMP)
+#define NGX_SMP_LOCK "lock;"
+#else
+#define NGX_SMP_LOCK
#endif
-static ngx_inline uint32_t ngx_atomic_cmp_set(ngx_atomic_t *lock,
- ngx_atomic_t old,
- ngx_atomic_t set)
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_inc(ngx_atomic_t *value)
+{
+ ngx_atomic_int_t old;
+
+ __asm__ volatile (
+
+ NGX_SMP_LOCK
+ " xaddq %0, %2; "
+ " incq %0; "
+
+ : "=r" (old) : "0" (1), "m" (*value) : "cc", "memory");
+
+ return old;
+}
+
+
+/* the '"0" (-1LL)' parameter preloads -1 into the 64-bit %0 register */
+
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_dec(ngx_atomic_t *value)
{
- uint32_t res;
+ ngx_atomic_int_t old;
__asm__ volatile (
- NGX_SMP_LOCK
- " cmpxchgl %3, %1; "
- " setz %%al; "
- " movzbl %%al, %0; "
+ NGX_SMP_LOCK
+ " xaddq %0, %2; "
+ " decq %0; "
+
+ : "=r" (old) : "0" (-1LL), "m" (*value) : "cc", "memory");
- : "=a" (res) : "m" (*lock), "a" (old), "q" (set));
+ return old;
+}
+
+
+/* the "=a" and "a" are the %rax register. */
+
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_int_t old,
+ ngx_atomic_int_t set)
+{
+ ngx_atomic_int_t res;
+
+ __asm__ volatile (
+
+ NGX_SMP_LOCK
+ " cmpxchgq %3, %1; "
+ " setz %b0; "
+ " movzbq %b0, %0; "
+
+ : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory");
return res;
}
@@ -84,12 +179,38 @@ static ngx_inline uint32_t ngx_atomic_cmp_set(ngx_atomic_t *lock,
#define NGX_HAVE_ATOMIC_OPS 1
-typedef volatile uint32_t ngx_atomic_t;
+#if (NGX_PTR_SIZE == 8)
+typedef uint64_t ngx_atomic_int_t;
+#define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1
+#define NGX_CASXA "casxa"
+#else
+typedef uint32_t ngx_atomic_int_t;
+#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
+#define NGX_CASXA "casa"
+#endif
+
+typedef volatile ngx_atomic_int_t ngx_atomic_t;
+
+/*
+ * the "+r" means the general register used for both input and output.
+ *
+ * "casa [r1] 0x80, r2, r0" and
+ * "casxa [r1] 0x80, r2, r0" do the following:
+ *
+ * if ([r1] == r2) {
+ * swap(r0, [r1]);
+ * } else {
+ * r0 = [r1];
+ * }
+ *
+ * so "r0 == r2" means that the operation was successfull.
+ */
-static ngx_inline uint32_t ngx_atomic_inc(ngx_atomic_t *value)
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_inc(ngx_atomic_t *value)
{
- uint32_t old, new, res;
+ ngx_atomic_int_t old, new, res;
old = *value;
@@ -100,9 +221,36 @@ static ngx_inline uint32_t ngx_atomic_inc(ngx_atomic_t *value)
__asm__ volatile (
- "casa [%1] 0x80, %2, %0"
+ NGX_CASXA " [%1] 0x80, %2, %0"
+
+ : "+r" (res) : "r" (value), "r" (old) : "memory");
+
+ if (res == old) {
+ return new;
+ }
+
+ old = res;
+ }
+}
+
+
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_dec(ngx_atomic_t *value)
+{
+ ngx_atomic_int_t old, new, res;
+
+ old = *value;
+
+ for ( ;; ) {
+
+ new = old - 1;
+ res = new;
+
+ __asm__ volatile (
+
+ NGX_CASXA " [%1] 0x80, %2, %0"
- : "+r" (res) : "r" (value), "r" (old));
+ : "+r" (res) : "r" (value), "r" (old) : "memory");
if (res == old) {
return new;
@@ -113,33 +261,128 @@ static ngx_inline uint32_t ngx_atomic_inc(ngx_atomic_t *value)
}
-static ngx_inline uint32_t ngx_atomic_cmp_set(ngx_atomic_t *lock,
- ngx_atomic_t old,
- ngx_atomic_t set)
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_int_t old, ngx_atomic_int_t set)
+{
+ __asm__ volatile (
+
+ NGX_CASXA " [%1] 0x80, %2, %0"
+
+ : "+r" (set) : "r" (lock), "r" (old) : "memory");
+
+ return (set == old);
+}
+
+
+#elif ( __ppc__ )
+
+#define NGX_HAVE_ATOMIC_OPS 1
+
+#if (NGX_PTR_SIZE == 8)
+typedef uint64_t ngx_atomic_int_t;
+#define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1
+#else
+#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
+typedef uint32_t ngx_atomic_int_t;
+#endif
+
+typedef volatile ngx_atomic_int_t ngx_atomic_t;
+
+
+/*
+ * the ppc assembler treats ";" as comment, so we have to use "\n".
+ * the minus in "bne-" is a hint for the branch prediction unit that
+ * this branch is unlikely to be taken.
+ *
+ * the "=&r" means that no input registers can be used.
+ * the "=&b" means that the base registers can be used only, i.e. any register
+ * except r0. the r0 register can not be used in "addi r0, r0, 1".
+ * the "1b" means the nearest backward label "1" and the "1f" means
+ * the nearest forward label "1".
+ */
+
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_inc(ngx_atomic_t *value)
+{
+ ngx_atomic_int_t res;
+
+ __asm__ volatile (
+
+ "1: lwarx %0, 0, %1 \n" /* load from [value] into "res" */
+ /* and store reservation */
+ " addi %0, %0, 1 \n" /* add "1" to "res" */
+ " stwcx. %0, 0, %1 \n" /* store "res" into [value] if reservation */
+ /* is not cleared */
+ " bne- 1b \n" /* try again if reservation was cleared */
+
+ : "=&b" (res) : "r" (value) : "cc", "memory");
+
+ return res;
+}
+
+
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_dec(ngx_atomic_t *value)
{
- uint32_t res = (uint32_t) set;
+ ngx_atomic_int_t res;
__asm__ volatile (
- "casa [%1] 0x80, %2, %0"
+ "1: lwarx %0, 0, %1 \n" /* load from [value] into "res" */
+ /* and store reservation */
+ " addi %0, %0, -1 \n" /* sub "1" from "res" */
+ " stwcx. %0, 0, %1 \n" /* store "res" into [value] if reservation */
+ /* is not cleared */
+ " bne- 1b \n" /* try again if reservation was cleared */
+
+ : "=&b" (res) : "r" (value) : "cc", "memory");
+
+ return res;
+}
+
+
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_int_t old,
+ ngx_atomic_int_t set)
+{
+ ngx_atomic_int_t res, temp;
- : "+r" (res) : "r" (lock), "r" (old));
+ __asm__ volatile (
- return (res == old);
+ " li %0, 0 \n" /* preset "0" to "res" */
+ " lwarx %1, 0, %2 \n" /* load from [lock] into "temp" */
+ /* and store reservation */
+ " cmpw %1, %3 \n" /* compare "temp" and "old" */
+ " bne- 1f \n" /* not equal */
+ " stwcx. %4, 0, %2 \n" /* store "set" into [lock] if reservation */
+ /* is not cleared */
+ " bne- 1f \n" /* the reservation was cleared */
+ " li %0, 1 \n" /* set "1" to "res" */
+ "1: \n"
+
+ : "=&r" (res), "=&r" (temp)
+ : "r" (lock), "r" (old), "r" (set)
+ : "cc", "memory");
+
+ return res;
}
+
#else
#define NGX_HAVE_ATOMIC_OPS 0
-typedef volatile uint32_t ngx_atomic_t;
+typedef uint32_t ngx_atomic_int_t;
+typedef volatile ngx_atomic_int_t ngx_atomic_t;
-#define ngx_atomic_inc(x) ++(*(x));
+#define ngx_atomic_inc(x) ++(*(x))
+#define ngx_atomic_dec(x) --(*(x))
-static ngx_inline uint32_t ngx_atomic_cmp_set(ngx_atomic_t *lock,
- ngx_atomic_t old,
- ngx_atomic_t set)
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_int_t old,
+ ngx_atomic_int_t set)
{
+ *lock = set;
return 1;
}
diff --git a/src/os/unix/ngx_freebsd.h b/src/os/unix/ngx_freebsd.h
index 7a1e2031e..4e865a3c0 100644
--- a/src/os/unix/ngx_freebsd.h
+++ b/src/os/unix/ngx_freebsd.h
@@ -9,7 +9,7 @@
ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in,
- off_t limit);
+ off_t limit);
extern int ngx_freebsd_kern_osreldate;
extern int ngx_freebsd_hw_ncpu;
diff --git a/src/os/unix/ngx_linux.h b/src/os/unix/ngx_linux.h
index 4a8f8f3da..e871ba9b0 100644
--- a/src/os/unix/ngx_linux.h
+++ b/src/os/unix/ngx_linux.h
@@ -8,11 +8,8 @@
#define _NGX_LINUX_H_INCLUDED_
-ngx_int_t ngx_init_setproctitle(ngx_log_t *log);
-void ngx_setproctitle(char *title);
-
ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in,
- off_t limit);
+ off_t limit);
extern int ngx_linux_rtsig_max;
diff --git a/src/os/unix/ngx_linux_init.c b/src/os/unix/ngx_linux_init.c
index 9c1c84758..7f7be890a 100644
--- a/src/os/unix/ngx_linux_init.c
+++ b/src/os/unix/ngx_linux_init.c
@@ -28,7 +28,8 @@ ngx_os_io_t ngx_os_io = {
};
-ngx_int_t ngx_os_init(ngx_log_t *log)
+ngx_int_t
+ngx_os_init(ngx_log_t *log)
{
int name[2];
size_t len;
@@ -37,28 +38,29 @@ ngx_int_t ngx_os_init(ngx_log_t *log)
name[0] = CTL_KERN;
name[1] = KERN_OSTYPE;
len = sizeof(ngx_linux_kern_ostype);
- if (sysctl(name, sizeof(name), ngx_linux_kern_ostype, &len, NULL, 0)
- == -1) {
+
+ if (sysctl(name, 2, ngx_linux_kern_ostype, &len, NULL, 0) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
"sysctl(KERN_OSTYPE) failed");
return NGX_ERROR;
}
- name[0] = CTL_KERN;
+ /* name[0] = CTL_KERN; */
name[1] = KERN_OSRELEASE;
len = sizeof(ngx_linux_kern_osrelease);
- if (sysctl(name, sizeof(name), ngx_linux_kern_osrelease, &len, NULL, 0)
- == -1) {
+
+ if (sysctl(name, 2, ngx_linux_kern_osrelease, &len, NULL, 0) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
"sysctl(KERN_OSRELEASE) failed");
return NGX_ERROR;
}
- name[0] = CTL_KERN;
+ /* name[0] = CTL_KERN; */
name[1] = KERN_RTSIGMAX;
len = sizeof(ngx_linux_rtsig_max);
- if (sysctl(name, sizeof(name), &ngx_linux_rtsig_max, &len, NULL, 0) == -1) {
+
+ if (sysctl(name, 2, &ngx_linux_rtsig_max, &len, NULL, 0) == -1) {
err = ngx_errno;
if (err != NGX_ENOTDIR) {
@@ -78,7 +80,8 @@ ngx_int_t ngx_os_init(ngx_log_t *log)
}
-void ngx_os_status(ngx_log_t *log)
+void
+ngx_os_status(ngx_log_t *log)
{
ngx_log_error(NGX_LOG_INFO, log, 0, "OS: %s %s",
ngx_linux_kern_ostype, ngx_linux_kern_osrelease);
diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h
index 42fc88629..e39aab0ef 100644
--- a/src/os/unix/ngx_os.h
+++ b/src/os/unix/ngx_os.h
@@ -20,7 +20,7 @@ typedef ssize_t (*ngx_recv_pt)(ngx_connection_t *c, u_char *buf, size_t size);
typedef ssize_t (*ngx_recv_chain_pt)(ngx_connection_t *c, ngx_chain_t *in);
typedef ssize_t (*ngx_send_pt)(ngx_connection_t *c, u_char *buf, size_t size);
typedef ngx_chain_t *(*ngx_send_chain_pt)(ngx_connection_t *c, ngx_chain_t *in,
- off_t limit);
+ off_t limit);
typedef struct {
ngx_recv_pt recv;
@@ -44,7 +44,7 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size);
ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry);
ssize_t ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size);
ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in,
- off_t limit);
+ off_t limit);
extern ngx_os_io_t ngx_os_io;
diff --git a/src/os/unix/ngx_process.h b/src/os/unix/ngx_process.h
index 12703b3e3..995e93ce2 100644
--- a/src/os/unix/ngx_process.h
+++ b/src/os/unix/ngx_process.h
@@ -49,8 +49,7 @@ typedef struct {
#define ngx_log_pid ngx_pid
ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle,
- ngx_spawn_proc_pt proc, void *data,
- char *name, ngx_int_t respawn);
+ ngx_spawn_proc_pt proc, void *data, char *name, ngx_int_t respawn);
ngx_pid_t ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx);
void ngx_process_get_status(void);
void ngx_debug_point(void);
@@ -63,6 +62,12 @@ void ngx_debug_point(void);
#endif
+#if !defined(ngx_setproctitle)
+ngx_int_t ngx_init_setproctitle(ngx_log_t *log);
+void ngx_setproctitle(char *title);
+#endif
+
+
extern int ngx_argc;
extern char **ngx_argv;
extern char **ngx_os_argv;
diff --git a/src/os/unix/ngx_setproctitle.c b/src/os/unix/ngx_setproctitle.c
index 2e41108b5..6c95cdf4e 100644
--- a/src/os/unix/ngx_setproctitle.c
+++ b/src/os/unix/ngx_setproctitle.c
@@ -30,9 +30,10 @@ extern char **environ;
static char *ngx_os_argv_last;
-ngx_int_t ngx_init_setproctitle(ngx_log_t *log)
+ngx_int_t
+ngx_init_setproctitle(ngx_log_t *log)
{
- char *p;
+ u_char *p;
size_t size;
ngx_uint_t i;
@@ -60,8 +61,8 @@ ngx_int_t ngx_init_setproctitle(ngx_log_t *log)
size = ngx_strlen(environ[i]) + 1;
ngx_os_argv_last = environ[i] + size;
- ngx_cpystrn(p, environ[i], size);
- environ[i] = p;
+ ngx_cpystrn(p, (u_char *) environ[i], size);
+ environ[i] = (char *) p;
p += size;
}
}
@@ -72,7 +73,8 @@ ngx_int_t ngx_init_setproctitle(ngx_log_t *log)
}
-void ngx_setproctitle(char *title)
+void
+ngx_setproctitle(char *title)
{
u_char *p;
@@ -131,13 +133,16 @@ void ngx_setproctitle(char *title)
#elif !defined(ngx_setproctitle)
-ngx_int_t ngx_init_setproctitle(ngx_log_t *log)
+ngx_int_t
+ngx_init_setproctitle(ngx_log_t *log)
{
return NGX_OK;
}
-void ngx_setproctitle(char *title)
+void
+ngx_setproctitle(char *title)
{
+ return;
}
#endif
diff --git a/src/os/unix/ngx_solaris.h b/src/os/unix/ngx_solaris.h
index 705cd57ee..44ce79679 100644
--- a/src/os/unix/ngx_solaris.h
+++ b/src/os/unix/ngx_solaris.h
@@ -8,12 +8,8 @@
#define _NGX_SOLARIS_H_INCLUDED_
-ngx_int_t ngx_init_setproctitle(ngx_log_t *log);
-void ngx_setproctitle(char *title);
-
-
ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in,
- off_t limit);
+ off_t limit);
#endif /* _NGX_SOLARIS_H_INCLUDED_ */