diff --git a/src/modules/dmq/README b/src/modules/dmq/README
index 991877f8990..211f9821ac2 100644
--- a/src/modules/dmq/README
+++ b/src/modules/dmq/README
@@ -14,8 +14,6 @@ Edited by
Marius Ovidiu Bucur
-Edited by
-
Charles Chance
Copyright © 2011 Marius Bucur
@@ -41,7 +39,8 @@ Charles Chance
3.2. notification_address(str)
3.3. multi_notify(int)
3.4. num_workers(int)
- 3.5. ping_interval(int)
+ 3.5. worker_usleep(int)
+ 3.6. ping_interval(int)
4. Functions
@@ -74,13 +73,14 @@ Charles Chance
1.3. Set notification_address parameter
1.4. Set multi_notify parameter
1.5. Set num_workers parameter
- 1.6. Set ping_interval parameter
- 1.7. dmq_handle_message usage
- 1.8. dmq_send_message usage
- 1.9. dmq_bcast_message usage
- 1.10. dmq_t_replicate usage
- 1.11. dmq_is_from_node usage
- 1.12. dmq.list_nodes usage
+ 1.6. Set worker_usleep parameter
+ 1.7. Set ping_interval parameter
+ 1.8. dmq_handle_message usage
+ 1.9. dmq_send_message usage
+ 1.10. dmq_bcast_message usage
+ 1.11. dmq_t_replicate usage
+ 1.12. dmq_is_from_node usage
+ 1.13. dmq.list_nodes usage
2.1. dmq_api_t structure
2.2. register_dmq_peer usage
2.3. bcast_message usage
@@ -102,7 +102,8 @@ Chapter 1. Admin Guide
3.2. notification_address(str)
3.3. multi_notify(int)
3.4. num_workers(int)
- 3.5. ping_interval(int)
+ 3.5. worker_usleep(int)
+ 3.6. ping_interval(int)
4. Functions
@@ -178,7 +179,8 @@ sip:192.168.40.17:5060;status=active
3.2. notification_address(str)
3.3. multi_notify(int)
3.4. num_workers(int)
- 3.5. ping_interval(int)
+ 3.5. worker_usleep(int)
+ 3.6. ping_interval(int)
3.1. server_address(str)
@@ -231,14 +233,34 @@ modparam("dmq", "multi_notify", 1)
modparam("dmq", "num_workers", 4)
...
-3.5. ping_interval(int)
+3.5. worker_usleep(int)
+
+ The default locking/synchronisation mechanism between producer/consumer
+ threads is the optimum for most environments. On some systems (e.g.
+ FreeBSD) it can cause high CPU load and in such cases, it can be useful
+ to disable locking and switch to polling for tasks at set intervals
+ instead - putting the thread to sleep in-between and taking it out of
+ process during that time.
+
+ A value >0 will disable the default locking and set the polling
+ interval (in microseconds), which can be tuned to suit the specific
+ environment.
+
+ Default value is 0 (recommended for most systems).
+
+ Example 1.6. Set worker_usleep parameter
+...
+modparam("dmq", "worker_usleep", 1000)
+...
+
+3.6. ping_interval(int)
The number of seconds between node pings (for checking status of other
nodes).
Minimum value is “60” (default).
- Example 1.6. Set ping_interval parameter
+ Example 1.7. Set ping_interval parameter
...
modparam("dmq", "ping_interval", 90)
...
@@ -258,7 +280,7 @@ modparam("dmq", "ping_interval", 90)
This function can be used from REQUEST_ROUTE.
- Example 1.7. dmq_handle_message usage
+ Example 1.8. dmq_handle_message usage
...
if(is_method("KDMQ"))
{
@@ -278,7 +300,7 @@ modparam("dmq", "ping_interval", 90)
This function can be used from any route.
- Example 1.8. dmq_send_message usage
+ Example 1.9. dmq_send_message usage
...
dmq_send_message("peer_name", "sip:10.0.0.21:5060", "Message body...", "
text/plain");
@@ -296,7 +318,7 @@ text/plain");
This function can be used from any route.
- Example 1.9. dmq_bcast_message usage
+ Example 1.10. dmq_bcast_message usage
...
dmq_bcast_message("peer_name", "Message body...", "text/plain");
...
@@ -318,7 +340,7 @@ text/plain");
This function can be used from REQUEST_ROUTE only.
- Example 1.10. dmq_t_replicate usage
+ Example 1.11. dmq_t_replicate usage
...
dmq_t_replicate();
...
@@ -330,7 +352,7 @@ text/plain");
This function can be used from REQUEST_ROUTE only.
- Example 1.11. dmq_is_from_node usage
+ Example 1.12. dmq_is_from_node usage
...
# Example REGISTER block
if (dmq_is_from_node()) {
@@ -351,7 +373,7 @@ op test again
List the DMQ nodes. It has no parameters.
- Example 1.12. dmq.list_nodes usage
+ Example 1.13. dmq.list_nodes usage
...
kamcmd dmq.list_nodes
...
diff --git a/src/modules/dmq/dmq.c b/src/modules/dmq/dmq.c
index 1b4c885e296..c88afd57a03 100644
--- a/src/modules/dmq/dmq.c
+++ b/src/modules/dmq/dmq.c
@@ -57,6 +57,7 @@ int pid = 0;
/* module parameters */
int num_workers = DEFAULT_NUM_WORKERS;
+int worker_usleep = 0;
str dmq_server_address = {0, 0};
str dmq_server_socket = {0, 0};
struct sip_uri dmq_server_uri;
@@ -111,6 +112,7 @@ static param_export_t params[] = {
{"server_address", PARAM_STR, &dmq_server_address},
{"notification_address", PARAM_STR, &dmq_notification_address},
{"multi_notify", INT_PARAM, &multi_notify},
+ {"worker_usleep", INT_PARAM, &worker_usleep},
{0, 0, 0}
};
diff --git a/src/modules/dmq/dmq.h b/src/modules/dmq/dmq.h
index e33744cd2a3..06792f32a14 100644
--- a/src/modules/dmq/dmq.h
+++ b/src/modules/dmq/dmq.h
@@ -37,6 +37,7 @@
#define MIN_PING_INTERVAL 5
extern int num_workers;
+extern int worker_usleep;
extern dmq_worker_t* workers;
extern dmq_peer_t* dmq_notification_peer;
extern str dmq_server_address;
diff --git a/src/modules/dmq/doc/dmq_admin.xml b/src/modules/dmq/doc/dmq_admin.xml
index ab43dfb3ebc..616018a2598 100644
--- a/src/modules/dmq/doc/dmq_admin.xml
+++ b/src/modules/dmq/doc/dmq_admin.xml
@@ -171,6 +171,31 @@ modparam("dmq", "num_workers", 4)
+
+ worker_usleep(int)
+
+ The default locking/synchronisation mechanism between producer/consumer
+ threads is the optimum for most environments. On some systems (e.g. FreeBSD)
+ it can cause high CPU load and in such cases, it can be useful to disable
+ locking and switch to polling for tasks at set intervals instead - putting
+ the thread to sleep in-between and taking it out of process during that time.
+
+
+ A value >0 will disable the default locking and set the polling interval
+ (in microseconds), which can be tuned to suit the specific environment.
+
+
+ Default value is 0 (recommended for most systems).
+
+
+ Set worker_usleep parameter
+
+...
+modparam("dmq", "worker_usleep", 1000)
+...
+
+
+
ping_interval(int)
diff --git a/src/modules/dmq/worker.c b/src/modules/dmq/worker.c
index 2dd198efedb..a3b7a3ae62a 100644
--- a/src/modules/dmq/worker.c
+++ b/src/modules/dmq/worker.c
@@ -79,12 +79,16 @@ void worker_loop(int id)
worker = &workers[id];
for(;;) {
- LM_DBG("dmq_worker [%d %d] getting lock\n", id, my_pid());
- lock_get(&worker->lock);
- LM_DBG("dmq_worker [%d %d] lock acquired\n", id, my_pid());
- /* multiple lock_release calls might be performed, so remove
- * from queue until empty */
- do {
+ if (worker_usleep <= 0) {
+ LM_DBG("dmq_worker [%d %d] getting lock\n", id, my_pid());
+ lock_get(&worker->lock);
+ LM_DBG("dmq_worker [%d %d] lock acquired\n", id, my_pid());
+ } else {
+ sleep_us(worker_usleep);
+ }
+
+ /* remove from queue until empty */
+ while(job_queue_size(worker->queue) > 0) {
/* fill the response with 0's */
memset(&peer_response, 0, sizeof(peer_response));
current_job = job_queue_pop(worker->queue);
@@ -136,7 +140,7 @@ void worker_loop(int id)
shm_free(current_job);
worker->jobs_processed++;
}
- } while(job_queue_size(worker->queue) > 0);
+ }
}
}
@@ -198,7 +202,9 @@ int add_dmq_job(struct sip_msg* msg, dmq_peer_t* peer)
if (job_queue_push(worker->queue, &new_job)<0) {
goto error;
}
- lock_release(&worker->lock);
+ if (worker_usleep <= 0) {
+ lock_release(&worker->lock);
+ }
return 0;
error:
if (cloned_msg!=NULL) {
@@ -213,9 +219,11 @@ int add_dmq_job(struct sip_msg* msg, dmq_peer_t* peer)
void init_worker(dmq_worker_t* worker)
{
memset(worker, 0, sizeof(*worker));
- lock_init(&worker->lock);
- // acquire the lock for the first time - so that dmq_worker_loop blocks
- lock_get(&worker->lock);
+ if (worker_usleep <= 0) {
+ lock_init(&worker->lock);
+ // acquire the lock for the first time - so that dmq_worker_loop blocks
+ lock_get(&worker->lock);
+ }
worker->queue = alloc_job_queue();
}