view src/os/unix/ngx_freebsd_rfork_thread.c @ 86:3973260705cc

nginx-0.0.1-2003-05-12-19:52:24 import
author Igor Sysoev <igor@sysoev.ru>
date Mon, 12 May 2003 15:52:24 +0000
parents 3549c2bf9eaf
children 738fe44c70d5
line wrap: on
line source


#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();


static char        *usrstack;
static int          red_zone = 4096;

static size_t       stack_size;
static size_t       usable_stack_size;
static char        *last_stack;

static int          threads;
static int          nthreads;
static ngx_tid_t   *tids;

/* the thread-safe errno */

static int   errno0;   /* the main thread's errno */
static int  *errnos;

int *__error()
{
    int  tid;

    tid = ngx_gettid();

    return tid ? &errnos[tid - 1] : &errno0;
}


int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg,
                      ngx_log_t *log)
{
    int         id, err;
    char       *stack, *stack_top;

    if (threads >= nthreads) {
        ngx_log_error(NGX_LOG_CRIT, log, 0,
                      "no more than %d threads can be created", nthreads);
        return NGX_ERROR;
    }

    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);
        return NGX_ERROR;
    }

    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
    id = rfork_thread(RFPROC|RFMEM, stack_top, func, arg);
#elif 1
    id = rfork_thread(RFFDG|RFCFDG, stack_top, func, arg);
#else
    id = rfork(RFFDG|RFCFDG);
#endif

    err = errno;

    if (id == -1) {
        ngx_log_error(NGX_LOG_ALERT, log, err, "rfork() failed");

    } else {
        *tid = id;
        threads = (usrstack - stack_top) / stack_size;
        tids[threads] = id;

        /* allow the spinlock in libc malloc() */
        __isthreaded = 1;
    }

    return err;
}


int ngx_init_thread_env(int n, size_t size, ngx_log_t *log)
{
    int    len;
    char  *rz, *zone;

    nthreads = n;

    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 */
    rz = usrstack - (size + red_zone);

printf("red zone: %08X\n", rz);

    zone = mmap(rz, red_zone, PROT_NONE, MAP_ANON, -1, 0);
    if (zone == MAP_FAILED) {
        ngx_log_error(NGX_LOG_ALERT, log, errno,
                      "mmap(%08X:%d, PROT_NONE, MAP_ANON) red zone failed",
                      rz, red_zone);
        return NGX_ERROR;
    }

    if (zone != rz) {
        ngx_log_error(NGX_LOG_ALERT, log, 0, "red zone address was changed");
    }

    /* 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);

    tids[0] = ngx_getpid();
    threads = 1;

    last_stack = zone + red_zone;
    usable_stack_size = size;
    stack_size = size + red_zone;

    return NGX_OK;
}


ngx_tid_t ngx_thread_self()
{
    int        tid;
    ngx_tid_t  pid;

    tid = ngx_gettid();

    if (tids[tid] == 0) {
        pid = ngx_getpid();
        tids[tid] = pid;
        return pid;
    }

    return tids[tid];
}


static inline int ngx_gettid()
{   
    char  *sp;

    if (stack_size == 0) {
        return 0;
    }

    __asm__ ("mov %%esp, %0" : "=q" (sp));

    return (usrstack - sp) / stack_size;
}