view src/os/unix/ngx_pthread_thread.c @ 391:1d9bef53cd8e

Range filter: late_ranges functionality. Add one more filtering point after postpone filter. This allows to serve range capable replies with subrequests. It's not as efficient as range filtering for static data (i.e. doesn't save us from reading data from disk if some filter needs them in memory), but it may save some network bandwidth for us and for our users.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 21 Jul 2008 05:33:01 +0400
parents df17fbafec8f
children
line wrap: on
line source


/*
 * Copyright (C) Igor Sysoev
 */


#include <ngx_config.h>
#include <ngx_core.h>


static ngx_uint_t   nthreads;
static ngx_uint_t   max_threads;


static pthread_attr_t  thr_attr;


ngx_err_t
ngx_create_thread(ngx_tid_t *tid, ngx_thread_value_t (*func)(void *arg),
    void *arg, ngx_log_t *log)
{
    int  err;

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

    err = pthread_create(tid, &thr_attr, func, arg);

    if (err != 0) {
        ngx_log_error(NGX_LOG_ALERT, log, err, "pthread_create() failed");
        return err;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0,
                   "thread is created: " NGX_TID_T_FMT, *tid);

    nthreads++;

    return err;
}


ngx_int_t
ngx_init_threads(int n, size_t size, ngx_cycle_t *cycle)
{
    int  err;

    max_threads = n;

    err = pthread_attr_init(&thr_attr);

    if (err != 0) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
                      "pthread_attr_init() failed");
        return NGX_ERROR;
    }

    err = pthread_attr_setstacksize(&thr_attr, size);

    if (err != 0) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
                      "pthread_attr_setstacksize() failed");
        return NGX_ERROR;
    }

    ngx_threaded = 1;

    return NGX_OK;
}


ngx_mutex_t *
ngx_mutex_init(ngx_log_t *log, ngx_uint_t flags)
{
    int           err;
    ngx_mutex_t  *m;

    m = ngx_alloc(sizeof(ngx_mutex_t), log);
    if (m == NULL) {
        return NULL;
    }

    m->log = log;

    err = pthread_mutex_init(&m->mutex, NULL);

    if (err != 0) {
        ngx_log_error(NGX_LOG_ALERT, m->log, err,
                      "pthread_mutex_init() failed");
        return NULL;
    }

    return m;
}


void
ngx_mutex_destroy(ngx_mutex_t *m)
{
    int  err;

    err = pthread_mutex_destroy(&m->mutex);

    if (err != 0) {
        ngx_log_error(NGX_LOG_ALERT, m->log, err,
                      "pthread_mutex_destroy(%p) failed", m);
    }

    ngx_free(m);
}


void
ngx_mutex_lock(ngx_mutex_t *m)
{
    int  err;

    if (!ngx_threaded) {
        return;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "lock mutex %p", m);

    err = pthread_mutex_lock(&m->mutex);

    if (err != 0) {
        ngx_log_error(NGX_LOG_ALERT, m->log, err,
                      "pthread_mutex_lock(%p) failed", m);
        ngx_abort();
    }

    ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is locked", m);

    return;
}


ngx_int_t
ngx_mutex_trylock(ngx_mutex_t *m)
{
    int  err;

    if (!ngx_threaded) {
        return NGX_OK;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "try lock mutex %p", m);

    err = pthread_mutex_trylock(&m->mutex);

    if (err == NGX_EBUSY) {
        return NGX_AGAIN;
    }

    if (err != 0) {
        ngx_log_error(NGX_LOG_ALERT, m->log, err,
                      "pthread_mutex_trylock(%p) failed", m);
        ngx_abort();
    }

    ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is locked", m);

    return NGX_OK;
}


void
ngx_mutex_unlock(ngx_mutex_t *m)
{
    int  err;

    if (!ngx_threaded) {
        return;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "unlock mutex %p", m);

    err = pthread_mutex_unlock(&m->mutex);

    if (err != 0) {
        ngx_log_error(NGX_LOG_ALERT, m->log, err,
                      "pthread_mutex_unlock(%p) failed", m);
        ngx_abort();
    }

    ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is unlocked", m);

    return;
}


ngx_cond_t *
ngx_cond_init(ngx_log_t *log)
{
    int          err;
    ngx_cond_t  *cv;

    cv = ngx_alloc(sizeof(ngx_cond_t), log);
    if (cv == NULL) {
        return NULL;
    }

    cv->log = log;

    err = pthread_cond_init(&cv->cond, NULL);

    if (err != 0) {
        ngx_log_error(NGX_LOG_ALERT, cv->log, err,
                      "pthread_cond_init() failed");
        return NULL;
    }

    return cv;
}


void
ngx_cond_destroy(ngx_cond_t *cv)
{
    int  err;

    err = pthread_cond_destroy(&cv->cond);

    if (err != 0) {
        ngx_log_error(NGX_LOG_ALERT, cv->log, err,
                      "pthread_cond_destroy(%p) failed", cv);
    }

    ngx_free(cv);
}


ngx_int_t
ngx_cond_wait(ngx_cond_t *cv, ngx_mutex_t *m)
{
    int  err;

    ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p wait", cv);

    err = pthread_cond_wait(&cv->cond, &m->mutex);

    if (err != 0) {
        ngx_log_error(NGX_LOG_ALERT, cv->log, err,
                      "pthread_cond_wait(%p) failed", cv);
        return NGX_ERROR;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p is waked up", cv);

    ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is locked", m);

    return NGX_OK;
}


ngx_int_t
ngx_cond_signal(ngx_cond_t *cv)
{
    int  err;

    ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p to signal", cv);

    err = pthread_cond_signal(&cv->cond);

    if (err != 0) {
        ngx_log_error(NGX_LOG_ALERT, cv->log, err,
                      "pthread_cond_signal(%p) failed", cv);
        return NGX_ERROR;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p is signaled", cv);

    return NGX_OK;
}