nginx/src/os/unix/ngx_freebsd_rfork_thread.c

182 lines
3.8 KiB
C
Raw Normal View History

2003-05-07 01:03:16 +08:00
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_process.h>
#include <ngx_log.h>
#include <ngx_alloc.h>
extern int __isthreaded;
typedef int ngx_tid_t;
static inline int ngx_gettid();
2003-05-12 23:52:24 +08:00
static char *usrstack;
static int red_zone = 4096;
2003-05-07 01:03:16 +08:00
static size_t stack_size;
2003-05-12 23:52:24 +08:00
static size_t usable_stack_size;
2003-05-07 01:03:16 +08:00
static char *last_stack;
2003-05-12 23:52:24 +08:00
static int threads;
static int nthreads;
static ngx_tid_t *tids;
2003-05-07 01:03:16 +08:00
/* the thread-safe errno */
2003-05-12 23:52:24 +08:00
static int errno0; /* the main thread's errno */
static int *errnos;
2003-05-07 01:03:16 +08:00
int *__error()
{
2003-05-12 23:52:24 +08:00
int tid;
tid = ngx_gettid();
return tid ? &errnos[tid - 1] : &errno0;
2003-05-07 01:03:16 +08:00
}
2003-05-12 23:52:24 +08:00
int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg,
ngx_log_t *log)
2003-05-07 01:03:16 +08:00
{
int id, err;
2003-05-12 23:52:24 +08:00
char *stack, *stack_top;
2003-05-07 01:03:16 +08:00
2003-05-12 23:52:24 +08:00
if (threads >= nthreads) {
ngx_log_error(NGX_LOG_CRIT, log, 0,
"no more than %d threads can be created", nthreads);
return NGX_ERROR;
}
2003-05-07 01:03:16 +08:00
2003-05-12 23:52:24 +08:00
last_stack -= stack_size;
stack = mmap(last_stack, usable_stack_size, PROT_READ|PROT_WRITE,
MAP_STACK, -1, 0);
if (stack == MAP_FAILED) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
"mmap(%08X:%d, MAP_STACK) thread stack failed",
last_stack, usable_stack_size);
2003-05-07 01:03:16 +08:00
return NGX_ERROR;
}
2003-05-12 23:52:24 +08:00
if (stack != last_stack) {
ngx_log_error(NGX_LOG_ALERT, log, 0, "stack address was changed");
}
stack_top = stack + usable_stack_size;
printf("stack: %08X-%08X\n", stack, stack_top);
#if 1
id = rfork_thread(RFPROC|RFTHREAD|RFMEM, stack_top, func, arg);
#elif 1
2003-05-07 01:03:16 +08:00
id = rfork_thread(RFPROC|RFMEM, stack_top, func, arg);
2003-05-12 23:52:24 +08:00
#elif 1
id = rfork_thread(RFFDG|RFCFDG, stack_top, func, arg);
2003-05-07 01:03:16 +08:00
#else
2003-05-12 23:52:24 +08:00
id = rfork(RFFDG|RFCFDG);
2003-05-07 01:03:16 +08:00
#endif
2003-05-12 23:52:24 +08:00
2003-05-07 01:03:16 +08:00
err = errno;
if (id == -1) {
ngx_log_error(NGX_LOG_ALERT, log, err, "rfork() failed");
} else {
*tid = id;
2003-05-12 23:52:24 +08:00
threads = (usrstack - stack_top) / stack_size;
tids[threads] = id;
2003-05-07 01:03:16 +08:00
/* allow the spinlock in libc malloc() */
__isthreaded = 1;
}
return err;
}
2003-05-12 23:52:24 +08:00
int ngx_init_thread_env(int n, size_t size, ngx_log_t *log)
2003-05-07 01:03:16 +08:00
{
2003-05-12 23:52:24 +08:00
int len;
char *rz, *zone;
2003-05-07 01:03:16 +08:00
2003-05-12 23:52:24 +08:00
nthreads = n;
2003-05-07 01:03:16 +08:00
len = 4;
if (sysctlbyname("kern.usrstack", &usrstack, &len, NULL, 0) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
"sysctlbyname(kern.usrstack) failed");
return NGX_ERROR;
}
printf("usrstack: %08X\n", usrstack);
/* red zone */
2003-05-12 23:52:24 +08:00
rz = usrstack - (size + red_zone);
printf("red zone: %08X\n", rz);
zone = mmap(rz, red_zone, PROT_NONE, MAP_ANON, -1, 0);
2003-05-07 01:03:16 +08:00
if (zone == MAP_FAILED) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
2003-05-12 23:52:24 +08:00
"mmap(%08X:%d, PROT_NONE, MAP_ANON) red zone failed",
rz, red_zone);
2003-05-07 01:03:16 +08:00
return NGX_ERROR;
}
2003-05-12 23:52:24 +08:00
if (zone != rz) {
ngx_log_error(NGX_LOG_ALERT, log, 0, "red zone address was changed");
2003-05-07 01:03:16 +08:00
}
2003-05-12 23:52:24 +08:00
/* create the thread errno array */
ngx_test_null(errnos, ngx_calloc(n * sizeof(int), log), NGX_ERROR);
/* create the thread tid array */
ngx_test_null(tids, ngx_calloc((n + 1) * sizeof(ngx_tid_t), log),
NGX_ERROR);
2003-05-07 01:03:16 +08:00
tids[0] = ngx_getpid();
2003-05-12 23:52:24 +08:00
threads = 1;
last_stack = zone + red_zone;
usable_stack_size = size;
stack_size = size + red_zone;
2003-05-07 01:03:16 +08:00
return NGX_OK;
}
ngx_tid_t ngx_thread_self()
{
2003-05-12 23:52:24 +08:00
int tid;
ngx_tid_t pid;
tid = ngx_gettid();
if (tids[tid] == 0) {
pid = ngx_getpid();
tids[tid] = pid;
return pid;
}
return tids[tid];
2003-05-07 01:03:16 +08:00
}
static inline int ngx_gettid()
{
char *sp;
2003-05-12 23:52:24 +08:00
if (stack_size == 0) {
return 0;
}
2003-05-07 01:03:16 +08:00
__asm__ ("mov %%esp, %0" : "=q" (sp));
2003-05-12 23:52:24 +08:00
return (usrstack - sp) / stack_size;
2003-05-07 01:03:16 +08:00
}