[PATCH] Intel DLB(Dynamic Load Banlander) demo in NGINX

Meng, Fino fino.meng at intel.com
Fri Oct 21 13:42:27 UTC 2022


IntelĀ® Dynamic Load Balancer (IntelĀ® DLB) is a hardware managed system of queues
and arbiters connecting producers and consumers. It is a PCI device envisaged to
live in the server CPU uncore and can interact with software running on cores,
and potentially with other devices. This demo need run on next generation
Xeon processer(code name Sapphire Rapids).

Signed-off-by: Meng, Fino <fino.meng at intel.com>
---
 auto/configure                         |   1 +
 auto/dlbque                            |  20 ++
 auto/options                           |   4 +
 src/core/ngx_thread_pool.c             | 454 ++++++++++++++++++++++++-
 src/core/ngx_thread_pool.h             |   3 +
 src/http/ngx_http_copy_filter_module.c |   3 +
 src/http/ngx_http_file_cache.c         |   3 +
 src/http/ngx_http_parse.c              |  24 ++
 src/http/ngx_http_request.c            |  15 +
 src/http/ngx_http_request.h            |   3 +
 src/http/ngx_http_upstream.c           |   3 +
 11 files changed, 523 insertions(+), 10 deletions(-)
 create mode 100644 auto/dlbque

diff --git a/auto/configure b/auto/configure
index 474d69e8..92a86de2 100755
--- a/auto/configure
+++ b/auto/configure
@@ -59,6 +59,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then
 fi
 
 . auto/threads
+. auto/dlbque
 . auto/modules
 . auto/lib/conf
 
diff --git a/auto/dlbque b/auto/dlbque
new file mode 100644
index 00000000..af2c4d25
--- /dev/null
+++ b/auto/dlbque
@@ -0,0 +1,20 @@
+
+# Copyright (C) Nginx, Inc.
+
+if [ $USE_DLBQUE = YES ]; then
+
+    if [ "$NGX_PLATFORM" = win32 ]; then
+        cat << END
+
+$0: --with-dlbque is not supported on Windows
+
+END
+        exit 1
+    fi
+
+    have=NGX_DLBQUE . auto/have
+    #CORE_DEPS="$CORE_DEPS $DLBQUE_DEPS"
+    #CORE_SRCS="$CORE_SRCS $DLBQUE_SRCS"
+    CORE_INCS="$CORE_INCS $DLBQUE_LIB_PATH"
+    CORE_LIBS="$CORE_LIBS -L $DLBQUE_LIB_PATH -ldlb -lrt"
+fi
diff --git a/auto/options b/auto/options
index 48f3a1a4..06738680 100644
--- a/auto/options
+++ b/auto/options
@@ -42,6 +42,8 @@ EVENT_SELECT=NO
 EVENT_POLL=NO
 
 USE_THREADS=NO
+USE_DLBQUE=NO
+DLBQUE_LIB_PATH=
 
 NGX_FILE_AIO=NO
 
@@ -208,6 +210,8 @@ do
         --without-poll_module)           EVENT_POLL=NONE            ;;
 
         --with-threads)                  USE_THREADS=YES            ;;
+        --with-dlbque)                   USE_DLBQUE=YES             ;;
+        --dlbque-lib-path=*)             DLBQUE_LIB_PATH="$value"   ;;
 
         --with-file-aio)                 NGX_FILE_AIO=YES           ;;
 
diff --git a/src/core/ngx_thread_pool.c b/src/core/ngx_thread_pool.c
index 7fb0f7f8..412ce282 100644
--- a/src/core/ngx_thread_pool.c
+++ b/src/core/ngx_thread_pool.c
@@ -11,6 +11,44 @@
 #include <ngx_thread_pool.h>
 
 
+#if (NGX_DLBQUE)
+
+#include "dlb.h"
+
+#define DLB2  1
+#define NUM_EVENTS_PER_BATCH 1
+#define DLB_NUM  4
+
+#define CQ_DEPTH 2
+static int partial_resources = 4;
+
+typedef struct {
+    int dev_id;
+    int domain_id;
+    int queue_id;
+    int tx_port_id;
+    int rx_port_id;
+    dlb_hdl_t dlb;
+    dlb_domain_hdl_t domain;
+    dlb_port_hdl_t  tx_port;
+    dlb_port_hdl_t  rx_port;
+    dlb_dev_cap_t cap;
+    dlb_resources_t rsrcs;
+    int ldb_pool_id;
+    int dir_pool_id;
+    int num_credit_combined;
+    int num_credit_ldb;
+    int num_credit_dir;
+}ngx_ldb_t;
+
+enum wait_mode_t {
+    POLL,
+    INTERRUPT,
+} wait_mode = POLL;
+
+#endif
+
+
 typedef struct {
     ngx_array_t               pools;
 } ngx_thread_pool_conf_t;
@@ -40,8 +78,11 @@ struct ngx_thread_pool_s {
 
     u_char                   *file;
     ngx_uint_t                line;
-};
 
+#if (NGX_DLBQUE)
+    ngx_ldb_t                 loadbal_queue;
+#endif
+};
 
 static ngx_int_t ngx_thread_pool_init(ngx_thread_pool_t *tp, ngx_log_t *log,
     ngx_pool_t *pool);
@@ -102,6 +143,203 @@ static ngx_uint_t               ngx_thread_pool_task_id;
 static ngx_atomic_t             ngx_thread_pool_done_lock;
 static ngx_thread_pool_queue_t  ngx_thread_pool_done;
 
+#if (NGX_DLBQUE)
+
+static int create_sched_domain(
+    dlb_hdl_t dlb,
+    ngx_ldb_t *ldb_p)
+{
+    dlb_create_sched_domain_t args;
+    int p_rsrsc = partial_resources;
+
+    args.num_ldb_queues = 1;
+    args.num_ldb_ports = 2;
+    args.num_dir_ports = 2;
+    args.num_ldb_event_state_entries = 2 * args.num_ldb_ports * CQ_DEPTH;
+
+    if (!ldb_p->cap.combined_credits) {
+        args.num_ldb_credits = ldb_p->rsrcs.max_contiguous_ldb_credits * p_rsrsc / 100;
+        args.num_dir_credits = ldb_p->rsrcs.max_contiguous_dir_credits * p_rsrsc / 100;
+        args.num_ldb_credit_pools = 1;
+        args.num_dir_credit_pools = 1;
+    } else {
+        args.num_credits = ldb_p->rsrcs.num_credits * p_rsrsc / 100;
+        args.num_credit_pools = 1;
+    }
+
+    args.num_sn_slots[0] = ldb_p->rsrcs.num_sn_slots[0] * p_rsrsc / 100;
+    args.num_sn_slots[1] = ldb_p->rsrcs.num_sn_slots[1] * p_rsrsc / 100;
+
+    return dlb_create_sched_domain(dlb, &args);
+}
+
+static int create_ldb_queue(
+    dlb_domain_hdl_t domain)
+{
+    dlb_create_ldb_queue_t args = {0};
+    args.num_sequence_numbers = 0;
+    return dlb_create_ldb_queue(domain, &args);
+}
+
+static int create_ldb_port(
+    ngx_ldb_t *ldb_p,
+    dlb_domain_hdl_t domain,
+    int ldb_pool,
+    int dir_pool)
+{
+    dlb_create_port_t args;
+
+    if (!ldb_p->cap.combined_credits) {
+        args.ldb_credit_pool_id = ldb_pool;
+        args.dir_credit_pool_id = dir_pool;
+    } else {
+        args.credit_pool_id = ldb_pool;
+    }
+    args.cq_depth = CQ_DEPTH;
+    args.num_ldb_event_state_entries = CQ_DEPTH*2;
+#ifdef DLB2
+    args.cos_id = DLB_PORT_COS_ID_ANY;
+#endif
+    return dlb_create_ldb_port(domain, &args);
+}
+
+static ngx_int_t
+ngx_loadbalance_init(ngx_thread_pool_t *tp, int index)
+{
+    int domain_id, tx_port_id, rx_port_id;
+    int ret;
+    ngx_ldb_t *ldb_p = &tp->loadbal_queue;
+    static int dlb_index = 0;
+
+    ldb_p->num_credit_combined  = 2048;
+    ldb_p->num_credit_ldb       = 2048;
+    ldb_p->num_credit_dir       = 1024;
+    index = 0;
+
+    ldb_p->dev_id = index % DLB_NUM;
+
+    while( index < DLB_NUM ) {
+        ngx_log_error(NGX_LOG_INFO,tp->log, 0, "ngx_loadbalance_init index %d dlb_indx %d ldb_p %lx", index, dlb_index, ldb_p);
+
+        ret = dlb_open(ldb_p->dev_id, &ldb_p->dlb);
+        if (ret < 0) {
+        ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_open fail %d errno %d", ret, errno);
+        goto retry;
+        }
+
+        if (dlb_get_dev_capabilities(ldb_p->dlb, &ldb_p->cap)) {
+            ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_get_dev_capabilities errno %u, return", errno);
+            return NGX_ERROR;
+        }
+
+        if (dlb_get_num_resources(ldb_p->dlb, &ldb_p->rsrcs)) {
+            ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_get_dev_capabilities errno %u, return", errno);
+            return NGX_ERROR;
+        }
+
+        unsigned int sns_per_queue;
+        ret = dlb_get_ldb_sequence_number_allocation(ldb_p->dlb, 0, &sns_per_queue);
+        if (ret < 0 ) {
+            ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_set_ldb_sequence_number_allocation errno %d, return", ret, errno);
+            return NGX_ERROR;
+        }
+
+        domain_id = create_sched_domain(ldb_p->dlb, ldb_p);
+        if (domain_id < 0) {
+            ngx_log_error(NGX_LOG_ERR,tp->log, 0, "create_sched_domain errno %d, index %d ", errno, index);
+            goto retry;
+        } else {
+        ldb_p->domain_id = domain_id;
+        ldb_p->domain = dlb_attach_sched_domain(ldb_p->dlb, domain_id);
+        if (ldb_p->domain == NULL) {
+            ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_attach_sched_domain errno %d", errno);
+            return NGX_ERROR;
+        }
+        if (!ldb_p->cap.combined_credits) {
+            int max_ldb_credits = ldb_p->rsrcs.num_ldb_credits * partial_resources / 100;
+            int max_dir_credits = ldb_p->rsrcs.num_dir_credits * partial_resources / 100;
+
+            ldb_p->ldb_pool_id = dlb_create_ldb_credit_pool(ldb_p->domain, max_ldb_credits);
+            if (ldb_p->ldb_pool_id == -1) {
+                ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_create_ldb_credit_pool number %d, errno %d", max_ldb_credits, errno);
+                goto retry;
+            }
+            ldb_p->dir_pool_id = dlb_create_dir_credit_pool(ldb_p->domain, max_dir_credits);
+            if (ldb_p->dir_pool_id == -1) {
+                ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_create_dir_credit_pool errno %d", errno);
+                goto retry;
+            }
+        } else {
+            int max_credits = ldb_p->rsrcs.num_credits * partial_resources / 100;
+
+            ldb_p->ldb_pool_id = dlb_create_credit_pool(ldb_p->domain, max_credits);
+            if (ldb_p->ldb_pool_id == -1) {
+                ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_create_credit_pool errno %d", errno);
+                goto retry;
+            }
+        }
+        break;
+      }
+
+retry:
+      ldb_p->dev_id = ++index;
+    }
+
+    if (index >= DLB_NUM)  {
+        ngx_log_error(NGX_LOG_ERR,tp->log, 0, "no DLB resource left, used up to %d", index);
+        return NGX_ERROR;
+    }
+
+    ldb_p->queue_id = create_ldb_queue(ldb_p->domain);
+    if (ldb_p->queue_id == -1) {
+        ngx_log_error(NGX_LOG_ERR,tp->log, 0, "create_ldb_queue %d errno %d", ldb_p->queue_id, errno);
+        return NGX_ERROR;
+    }
+
+    tx_port_id = create_ldb_port(ldb_p, ldb_p->domain, ldb_p->ldb_pool_id, ldb_p->dir_pool_id);
+    if (tx_port_id == -1) {
+        ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_create_credit_pool errno %d", errno);
+        return NGX_ERROR;
+    }
+
+    ldb_p->tx_port = dlb_attach_ldb_port(ldb_p->domain, tx_port_id);
+    if (ldb_p->tx_port == NULL) {
+        ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_create_credit_pool errno %d", errno);
+        return NGX_ERROR;
+    }
+
+    rx_port_id = create_ldb_port(ldb_p, ldb_p->domain, ldb_p->ldb_pool_id, ldb_p->dir_pool_id);
+    if (rx_port_id == -1) {
+        ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_create_credit_pool errno %d", errno);
+        return NGX_ERROR;
+    }
+
+    ldb_p->rx_port = dlb_attach_ldb_port(ldb_p->domain, rx_port_id);
+    if (ldb_p->rx_port == NULL) {
+        ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_create_credit_pool errno %d", errno);
+        return NGX_ERROR;
+    }
+
+    if (dlb_link_queue(ldb_p->rx_port, ldb_p->queue_id, 0) == -1) {
+        ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_link_queue errno %d", errno);
+        return NGX_ERROR;
+    }
+
+    if (dlb_launch_domain_alert_thread(ldb_p->domain, NULL, NULL)) {
+        ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_launch_domain_alert_thread errno %d", errno);
+        return NGX_ERROR;
+    }
+
+    if (dlb_start_sched_domain(ldb_p->domain)) {
+        ngx_log_error(NGX_LOG_ERR,tp->log, 0, "dlb_start_sched_domain errno %d", errno);
+        return NGX_ERROR;
+    }
+
+    ngx_log_error(NGX_LOG_INFO,tp->log, 0, "DLB created Success on device %d", ldb_p->dev_id);
+
+    return NGX_OK;
+}
+#endif
 
 static ngx_int_t
 ngx_thread_pool_init(ngx_thread_pool_t *tp, ngx_log_t *log, ngx_pool_t *pool)
@@ -144,20 +382,13 @@ ngx_thread_pool_init(ngx_thread_pool_t *tp, ngx_log_t *log, ngx_pool_t *pool)
         return NGX_ERROR;
     }
 
-#if 0
-    err = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
-    if (err) {
-        ngx_log_error(NGX_LOG_ALERT, log, err,
-                      "pthread_attr_setstacksize() failed");
-        return NGX_ERROR;
-    }
-#endif
-
     for (n = 0; n < tp->threads; n++) {
+
         err = pthread_create(&tid, &attr, ngx_thread_pool_cycle, tp);
         if (err) {
             ngx_log_error(NGX_LOG_ALERT, log, err,
                           "pthread_create() failed");
+
             return NGX_ERROR;
         }
     }
@@ -194,6 +425,34 @@ ngx_thread_pool_destroy(ngx_thread_pool_t *tp)
         task.event.active = 0;
     }
 
+#if (NGX_DLBQUE)
+
+    if (dlb_disable_port(tp->loadbal_queue.rx_port))
+        ngx_log_error(NGX_LOG_ERR, tp->log, 0,
+                    "dlb_disable_port() rx_port failed with errno %d", errno);
+
+    if (dlb_detach_port(tp->loadbal_queue.rx_port) == -1)
+        ngx_log_error(NGX_LOG_ERR, tp->log, 0,
+                    "dlb_detach_port() rx_port failed with errno %d", errno);
+
+    if (dlb_detach_port(tp->loadbal_queue.tx_port) == -1)
+        ngx_log_error(NGX_LOG_ERR, tp->log, 0,
+                    "dlb_detach_port() tx_port failed with errno %d", errno);
+
+    if (dlb_detach_sched_domain(tp->loadbal_queue.domain) == -1)
+        ngx_log_error(NGX_LOG_ERR, tp->log, 0,
+                        "dlb_detach_sched_domain() failed with errno %d", errno);
+
+    if (dlb_reset_sched_domain(tp->loadbal_queue.dlb, tp->loadbal_queue.domain_id) == -1)
+        ngx_log_error(NGX_LOG_ERR, tp->log, 0,
+                        "dlb_reset_sched_domain() failed with errno %d", errno);
+
+    if(dlb_close(tp->loadbal_queue.dlb) == -1)
+        ngx_log_error(NGX_LOG_ERR, tp->log, 0,
+                        "dlb_close() failed with errno %d", errno);
+
+#endif
+
     (void) ngx_thread_cond_destroy(&tp->cond, tp->log);
 
     (void) ngx_thread_mutex_destroy(&tp->mtx, tp->log);
@@ -226,6 +485,79 @@ ngx_thread_task_alloc(ngx_pool_t *pool, size_t size)
     return task;
 }
 
+#if (NGX_DLBQUE)
+
+ngx_int_t
+ngx_thread_task_post(ngx_thread_pool_t *tp, ngx_thread_task_t *task)
+{
+    int ret;
+    dlb_event_t dlb_events[NUM_EVENTS_PER_BATCH];
+    static uint16_t i = 0;
+
+    task->event.active = 1;
+    task->id = ngx_thread_pool_task_id++;
+    task->next = NULL;
+
+    //send stored task first
+    while(tp->queue.first != NULL) {
+        task = tp->queue.first;
+        tp->queue.first = task->next;
+        if (tp->queue.first == NULL) {
+            tp->queue.last = &tp->queue.first;
+        }
+        tp->waiting --;
+
+        dlb_events[0].send.queue_id = tp->loadbal_queue.queue_id;
+        dlb_events[0].send.sched_type = SCHED_UNORDERED;
+        dlb_events[0].send.priority = task->priority * 2;    //priority map to 0/2/4/6
+        dlb_events[0].send.udata64 = (uint64_t)task;
+        dlb_events[0].send.udata64 = (uint64_t)task;
+        dlb_events[0].send.udata64 = (uint64_t)task;
+        dlb_events[0].send.udata16 = (uint16_t)++i;
+        ret = dlb_send(tp->loadbal_queue.tx_port, 1, &dlb_events[0]);
+        if (ret <= 0) {
+            //dlb_send failed case, just put the task in one software queue
+            if (tp->waiting >= tp->max_queue) {
+                ngx_log_error(NGX_LOG_ERR, tp->log, 0,
+                            "thread pool \"%V\" queue overflow: %i tasks waiting",
+                            &tp->name, tp->waiting);
+                return NGX_ERROR;
+            }
+            //put the task in the queue again
+            *tp->queue.last = task;
+            tp->queue.last = &task->next;
+            tp->waiting++;
+            ngx_log_error(NGX_LOG_ALERT, tp->log, 0, "resend task %u failed with ret %d errno %d",task->id, ret, errno);
+            return NGX_OK;
+        }
+    }
+
+    dlb_events[0].send.queue_id = tp->loadbal_queue.queue_id;
+    dlb_events[0].send.sched_type = SCHED_UNORDERED;
+    dlb_events[0].send.priority = task->priority * 2;    //priority map to 0/2/4/6
+    dlb_events[0].send.udata64 = (uint64_t)task;
+    dlb_events[0].send.udata16 = (uint16_t)++i;
+
+    ret = dlb_send(tp->loadbal_queue.tx_port, 1, &dlb_events[0]);
+    if (ret <= 0) {
+        //dlb_send failed case, just put the task in one software queue
+        if (tp->waiting >= tp->max_queue) {
+            ngx_log_error(NGX_LOG_ERR, tp->log, 0,
+                        "thread pool \"%V\" queue overflow: %i tasks waiting",
+                        &tp->name, tp->waiting);
+            return NGX_ERROR;
+        }
+        *tp->queue.last = task;
+        tp->queue.last = &task->next;
+        tp->waiting++;
+        ngx_log_error(NGX_LOG_ALERT, tp->log, 0,
+                        "task %lu send failed, store in the sw queue first", task->id);
+    }
+
+    return NGX_OK;
+}
+
+#else
 
 ngx_int_t
 ngx_thread_task_post(ngx_thread_pool_t *tp, ngx_thread_task_t *task)
@@ -273,6 +605,99 @@ ngx_thread_task_post(ngx_thread_pool_t *tp, ngx_thread_task_t *task)
     return NGX_OK;
 }
 
+#endif
+
+
+
+#if (NGX_DLBQUE)
+
+static void *
+ngx_thread_pool_cycle(void *data)
+{
+    ngx_thread_pool_t* tp = (ngx_thread_pool_t*)data;
+    ngx_thread_task_t  *task;
+    sigset_t            set;
+    int ret;
+    static uint16_t seq=0;
+
+    dlb_event_t events[NUM_EVENTS_PER_BATCH];
+
+    ngx_log_debug1(NGX_LOG_DEBUG_CORE, tp->log, 0,
+                   "ldb thread in pool \"%V\" started", &tp->name);
+
+    sigfillset(&set);
+
+    sigdelset(&set, SIGILL);
+    sigdelset(&set, SIGFPE);
+    sigdelset(&set, SIGSEGV);
+    sigdelset(&set, SIGBUS);
+
+    ret = pthread_sigmask(SIG_BLOCK, &set, NULL);
+    if (ret) {
+        ngx_log_error(NGX_LOG_ALERT, tp->log, ret, "ldb pthread_sigmask() failed");
+        return NULL;
+    }
+
+    for ( ;; ) {
+
+        if (ngx_thread_mutex_lock(&tp->mtx, tp->log) != NGX_OK) {
+            return NULL;
+        }
+
+        ret = dlb_recv(tp->loadbal_queue.rx_port,
+                    NUM_EVENTS_PER_BATCH,
+                    (wait_mode == POLL),
+                     events);
+
+        /* The port was disabled, indicating the thread should return */
+        if (ret == -1 && errno == EACCES){
+            ngx_log_error(NGX_LOG_ALERT, tp->log, ret, "dlb_recv() error");
+            exit(1);
+        }
+
+        if (dlb_release(tp->loadbal_queue.rx_port, ret) != ret) {
+              ngx_log_error(NGX_LOG_ALERT, tp->log, ret, "Failed to release all %d events !\n");
+              return NULL;
+        }
+
+        if (ngx_thread_mutex_unlock(&tp->mtx, tp->log) != NGX_OK) {
+            return NULL;
+        }
+
+        for (int i =0; i < ret; i++){
+          task = (ngx_thread_task_t*)events[i].recv.udata64;
+
+          ngx_log_debug2(NGX_LOG_DEBUG_CORE, tp->log, 0,
+                         "run task #%ui in ldb thread pool \"%V\"",
+                         task->id, &tp->name);
+
+          task->handler(task->ctx, tp->log);
+
+          seq++;
+
+          ngx_log_debug2(NGX_LOG_DEBUG_CORE, tp->log, 0,
+                         "complete task #%ui in ldb thread pool \"%V\"",
+                         task->id, &tp->name);
+
+          task->next = NULL;
+
+          ngx_spinlock(&ngx_thread_pool_done_lock, 1, 2048);
+
+          *ngx_thread_pool_done.last = task;
+          ngx_thread_pool_done.last = &task->next;
+
+          ngx_memory_barrier();
+
+          ngx_unlock(&ngx_thread_pool_done_lock);
+
+          (void) ngx_notify(ngx_thread_pool_handler);
+
+        }
+     }
+}
+
+
+#else
 
 static void *
 ngx_thread_pool_cycle(void *data)
@@ -360,6 +785,7 @@ ngx_thread_pool_cycle(void *data)
     }
 }
 
+#endif
 
 static void
 ngx_thread_pool_handler(ngx_event_t *ev)
@@ -604,6 +1030,14 @@ ngx_thread_pool_init_worker(ngx_cycle_t *cycle)
     tpp = tcf->pools.elts;
 
     for (i = 0; i < tcf->pools.nelts; i++) {
+        tpp[i]->log = cycle->log;
+
+#if (NGX_DLBQUE)
+        if (ngx_loadbalance_init(tpp[i], i) != NGX_OK) {
+            return NGX_ERROR;
+        }
+#endif
+
         if (ngx_thread_pool_init(tpp[i], cycle->log, cycle->pool) != NGX_OK) {
             return NGX_ERROR;
         }
diff --git a/src/core/ngx_thread_pool.h b/src/core/ngx_thread_pool.h
index 5e5adf62..96a39889 100644
--- a/src/core/ngx_thread_pool.h
+++ b/src/core/ngx_thread_pool.h
@@ -20,6 +20,9 @@ struct ngx_thread_task_s {
     void                *ctx;
     void               (*handler)(void *data, ngx_log_t *log);
     ngx_event_t          event;
+#if (NGX_DLBQUE)
+    int16_t              priority;
+#endif
 };
 
 
diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c
index bd3028bc..636b133f 100644
--- a/src/http/ngx_http_copy_filter_module.c
+++ b/src/http/ngx_http_copy_filter_module.c
@@ -259,6 +259,9 @@ ngx_http_copy_thread_handler(ngx_thread_task_t *task, ngx_file_t *file)
 
     task->event.data = r;
     task->event.handler = ngx_http_copy_thread_event_handler;
+#if (NGX_DLBQUE)
+    task->priority = r->priority;
+#endif
 
     if (ngx_thread_task_post(tp, task) != NGX_OK) {
         return NGX_ERROR;
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c
index 4d2f6c42..055996a4 100644
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -781,6 +781,9 @@ ngx_http_cache_thread_handler(ngx_thread_task_t *task, ngx_file_t *file)
 
     task->event.data = r;
     task->event.handler = ngx_http_cache_thread_event_handler;
+#if (NGX_DLBQUE)
+    task->priority = r->priority;
+#endif
 
     if (ngx_thread_task_post(tp, task) != NGX_OK) {
         return NGX_ERROR;
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index d4f2dae8..f0569c8c 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -100,6 +100,29 @@ static uint32_t  usual[] = {
 
 /* gcc, icc, msvc and others compile these switches as an jump table */
 
+static void http_set_priority(ngx_http_request_t* r, u_char* m, ngx_buf_t *b)
+{
+
+  u_char * p;
+  for (p = m+10; p < b->last; p++) {
+    if(ngx_str5cmp(p, 'V', 'I', 'D', 'E', 'O')) {
+      r->priority = 0;
+      break;
+    }
+    else if(ngx_str5cmp(p, 'A', 'U', 'D', 'I', 'O')) {
+      r->priority = 1;
+      break;
+    }
+    else if (ngx_str4cmp(p, 'T', 'E', 'X', 'T')) {
+      r->priority = 2;
+      break;
+    }
+  }
+
+  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                 "URI priority : \"%d\"", r->priority);
+}
+
 ngx_int_t
 ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
 {
@@ -164,6 +187,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
                 case 3:
                     if (ngx_str3_cmp(m, 'G', 'E', 'T', ' ')) {
                         r->method = NGX_HTTP_GET;
+                        http_set_priority(r, m, b);
                         break;
                     }
 
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 131a2c83..bffacabe 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -573,6 +573,8 @@ ngx_http_alloc_request(ngx_connection_t *c)
 
     r->header_in = hc->busy ? hc->busy->buf : c->buffer;
 
+    r->priority = 3;
+
     if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
                       sizeof(ngx_table_elt_t))
         != NGX_OK)
@@ -1323,6 +1325,19 @@ ngx_http_process_request_uri(ngx_http_request_t *r)
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http args: \"%V\"", &r->args);
 
+    ngx_str_t dlb_priority;
+    if (ngx_http_arg(r, (u_char *) "dlb_priority", 12, &dlb_priority) == NGX_OK) {
+        ngx_int_t dlb_priority_int = ngx_atoi(dlb_priority.data, dlb_priority.len);
+        if (dlb_priority_int >=0 && dlb_priority_int <=255) {
+            r->priority = dlb_priority_int;
+            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                    "dlb_priority: \"%V\", %d", &dlb_priority, dlb_priority_int);
+	} else {
+	    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+	            "invalid dlb_priority: %d", dlb_priority_int);
+	}
+    }
+
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http exten: \"%V\"", &r->exten);
 
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 8c9eed24..15b11a1a 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -597,6 +597,9 @@ struct ngx_http_request_s {
     u_char                           *port_start;
     u_char                           *port_end;
 
+    //priority
+    u_char                            priority;  //0~3
+
     unsigned                          http_minor:16;
     unsigned                          http_major:16;
 };
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 3ae822bb..ea7b8252 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -3920,6 +3920,9 @@ ngx_http_upstream_thread_handler(ngx_thread_task_t *task, ngx_file_t *file)
 
     task->event.data = r;
     task->event.handler = ngx_http_upstream_thread_event_handler;
+#if (NGX_DLBQUE)
+    task->priority = r->priority;
+#endif
 
     if (ngx_thread_task_post(tp, task) != NGX_OK) {
         return NGX_ERROR;
-- 
2.34.1



More information about the nginx-devel mailing list