[asterisk-commits] russell: branch russell/frame_caching r38610 -
/team/russell/frame_caching/ch...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Mon Jul 31 13:26:50 MST 2006
Author: russell
Date: Mon Jul 31 15:26:50 2006
New Revision: 38610
URL: http://svn.digium.com/view/asterisk?rev=38610&view=rev
Log:
And now, add a thread local cache of iax_frame structures!
Modified:
team/russell/frame_caching/channels/chan_iax2.c
team/russell/frame_caching/channels/iax2-parser.c
team/russell/frame_caching/channels/iax2-parser.h
Modified: team/russell/frame_caching/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/russell/frame_caching/channels/chan_iax2.c?rev=38610&r1=38609&r2=38610&view=diff
==============================================================================
--- team/russell/frame_caching/channels/chan_iax2.c (original)
+++ team/russell/frame_caching/channels/chan_iax2.c Mon Jul 31 15:26:50 2006
@@ -611,11 +611,11 @@
};
static struct ast_iax2_queue {
- struct iax_frame *head;
- struct iax_frame *tail;
+ AST_LIST_HEAD(, iax_frame) queue;
int count;
- ast_mutex_t lock;
-} iaxq;
+} iaxq = {
+ .queue = AST_LIST_HEAD_INIT_VALUE
+};
static AST_LIST_HEAD_STATIC(users, iax2_user);
@@ -1067,7 +1067,6 @@
static struct iax_frame *iaxfrdup2(struct iax_frame *fr)
{
- /* Malloc() a copy of a frame */
struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen);
if (new) {
memcpy(new, fr, sizeof(struct iax_frame));
@@ -1749,7 +1748,7 @@
ast_queue_hangup(owner);
}
- for (cur = iaxq.head; cur ; cur = cur->next) {
+ AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
/* Cancel any pending transmissions */
if (cur->callno == pvt->callno)
cur->retries = -1;
@@ -1868,17 +1867,10 @@
/* Do not try again */
if (freeme) {
/* Don't attempt delivery, just remove it from the queue */
- ast_mutex_lock(&iaxq.lock);
- if (f->prev)
- f->prev->next = f->next;
- else
- iaxq.head = f->next;
- if (f->next)
- f->next->prev = f->prev;
- else
- iaxq.tail = f->prev;
+ AST_LIST_LOCK(&iaxq.queue);
+ AST_LIST_REMOVE(&iaxq.queue, f, list);
iaxq.count--;
- ast_mutex_unlock(&iaxq.lock);
+ AST_LIST_UNLOCK(&iaxq.queue);
f->retrans = -1;
/* Free the IAX frame */
iax2_frame_free(f);
@@ -2075,7 +2067,7 @@
int cnt = 0, dead=0, final=0;
if (argc != 3)
return RESULT_SHOWUSAGE;
- for (cur = iaxq.head; cur ; cur = cur->next) {
+ AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
if (cur->retries < 0)
dead++;
if (cur->final)
@@ -2362,24 +2354,13 @@
static int iax2_transmit(struct iax_frame *fr)
{
/* Lock the queue and place this packet at the end */
- fr->next = NULL;
- fr->prev = NULL;
/* By setting this to 0, the network thread will send it for us, and
queue retransmission if necessary */
fr->sentyet = 0;
- ast_mutex_lock(&iaxq.lock);
- if (!iaxq.head) {
- /* Empty queue */
- iaxq.head = fr;
- iaxq.tail = fr;
- } else {
- /* Double link */
- iaxq.tail->next = fr;
- fr->prev = iaxq.tail;
- iaxq.tail = fr;
- }
+ AST_LIST_LOCK(&iaxq.queue);
+ AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list);
iaxq.count++;
- ast_mutex_unlock(&iaxq.lock);
+ AST_LIST_UNLOCK(&iaxq.queue);
/* Wake up the network and scheduler thread */
pthread_kill(netthreadid, SIGURG);
signal_condition(&sched_lock, &sched_cond);
@@ -5315,15 +5296,15 @@
pvt->lastsent = 0;
pvt->nextpred = 0;
pvt->pingtime = DEFAULT_RETRY_TIME;
- ast_mutex_lock(&iaxq.lock);
- for (cur = iaxq.head; cur ; cur = cur->next) {
+ AST_LIST_LOCK(&iaxq.queue);
+ AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
/* We must cancel any packets that would have been transmitted
because now we're talking to someone new. It's okay, they
were transmitted to someone that didn't care anyway. */
if (callno == cur->callno)
cur->retries = -1;
}
- ast_mutex_unlock(&iaxq.lock);
+ AST_LIST_UNLOCK(&iaxq.queue);
return 0;
}
@@ -5819,17 +5800,16 @@
static void vnak_retransmit(int callno, int last)
{
struct iax_frame *f;
- ast_mutex_lock(&iaxq.lock);
- f = iaxq.head;
- while(f) {
+
+ AST_LIST_LOCK(&iaxq.queue);
+ AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
/* Send a copy immediately */
if ((f->callno == callno) && iaxs[f->callno] &&
(f->oseqno >= last)) {
send_packet(f);
}
- f = f->next;
- }
- ast_mutex_unlock(&iaxq.lock);
+ }
+ AST_LIST_UNLOCK(&iaxq.queue);
}
static void __iax2_poke_peer_s(void *data)
@@ -6554,8 +6534,8 @@
/* Ack the packet with the given timestamp */
if (option_debug && iaxdebug)
ast_log(LOG_DEBUG, "Cancelling transmission of packet %d\n", x);
- ast_mutex_lock(&iaxq.lock);
- for (cur = iaxq.head; cur ; cur = cur->next) {
+ AST_LIST_LOCK(&iaxq.queue);
+ AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
/* If it's our call, and our timestamp, mark -1 retries */
if ((fr->callno == cur->callno) && (x == cur->oseqno)) {
cur->retries = -1;
@@ -6567,7 +6547,7 @@
}
}
}
- ast_mutex_unlock(&iaxq.lock);
+ AST_LIST_UNLOCK(&iaxq.queue);
}
/* Note how much we've received acknowledgement for */
if (iaxs[fr->callno])
@@ -6707,13 +6687,13 @@
case IAX_COMMAND_TXACC:
if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) {
/* Ack the packet with the given timestamp */
- ast_mutex_lock(&iaxq.lock);
- for (cur = iaxq.head; cur ; cur = cur->next) {
+ AST_LIST_LOCK(&iaxq.queue);
+ AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
/* Cancel any outstanding txcnt's */
if ((fr->callno == cur->callno) && (cur->transfer))
cur->retries = -1;
}
- ast_mutex_unlock(&iaxq.lock);
+ AST_LIST_UNLOCK(&iaxq.queue);
memset(&ied1, 0, sizeof(ied1));
iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno);
send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1);
@@ -8015,49 +7995,42 @@
/* Our job is simple: Send queued messages, retrying if necessary. Read frames
from the network, and queue them for delivery to the channels */
int res, count;
- struct iax_frame *f, *freeme;
+ struct iax_frame *f;
+
if (timingfd > -1)
ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
+
for(;;) {
/* Go through the queue, sending messages which have not yet been
sent, and scheduling retransmissions if appropriate */
- ast_mutex_lock(&iaxq.lock);
- f = iaxq.head;
+ AST_LIST_LOCK(&iaxq.queue);
count = 0;
- while(f) {
- freeme = NULL;
- if (!f->sentyet) {
- f->sentyet++;
- /* Send a copy immediately -- errors here are ok, so don't bother locking */
- if (iaxs[f->callno]) {
- send_packet(f);
- count++;
- }
- if (f->retries < 0) {
- /* This is not supposed to be retransmitted */
- if (f->prev)
- f->prev->next = f->next;
- else
- iaxq.head = f->next;
- if (f->next)
- f->next->prev = f->prev;
- else
- iaxq.tail = f->prev;
- iaxq.count--;
- /* Free the iax frame */
- freeme = f;
- } else {
- /* We need reliable delivery. Schedule a retransmission */
- f->retries++;
- f->retrans = ast_sched_add(sched, f->retrytime, attempt_transmit, f);
- signal_condition(&sched_lock, &sched_cond);
- }
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) {
+ if (f->sentyet)
+ continue;
+
+ f->sentyet++;
+ /* Send a copy immediately -- errors here are ok, so don't bother locking */
+ if (iaxs[f->callno]) {
+ send_packet(f);
+ count++;
+ }
+ if (f->retries < 0) {
+ /* This is not supposed to be retransmitted */
+ AST_LIST_REMOVE(&iaxq.queue, f, list);
+ iaxq.count--;
+ /* Free the iax frame */
+ iax_frame_free(f);
+ } else {
+ /* We need reliable delivery. Schedule a retransmission */
+ f->retries++;
+ f->retrans = ast_sched_add(sched, f->retrytime, attempt_transmit, f);
+ signal_condition(&sched_lock, &sched_cond);
}
- f = f->next;
- if (freeme)
- iax_frame_free(freeme);
- }
- ast_mutex_unlock(&iaxq.lock);
+ }
+ AST_LIST_TRAVERSE_SAFE_END
+ AST_LIST_UNLOCK(&iaxq.queue);
+
if (count >= 20)
ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
@@ -9711,7 +9684,6 @@
static int unload_module(void *mod)
{
- ast_mutex_destroy(&iaxq.lock);
ast_mutex_destroy(&waresl.lock);
ast_custom_function_unregister(&iaxpeer_function);
return __unload_module();
@@ -9763,7 +9735,6 @@
}
ast_netsock_init(netsock);
- ast_mutex_init(&iaxq.lock);
ast_mutex_init(&waresl.lock);
ast_cli_register_multiple(iax2_cli, sizeof(iax2_cli) / sizeof(iax2_cli[0]));
Modified: team/russell/frame_caching/channels/iax2-parser.c
URL: http://svn.digium.com/view/asterisk/team/russell/frame_caching/channels/iax2-parser.c?rev=38610&r1=38609&r2=38610&view=diff
==============================================================================
--- team/russell/frame_caching/channels/iax2-parser.c (original)
+++ team/russell/frame_caching/channels/iax2-parser.c Mon Jul 31 15:26:50 2006
@@ -40,6 +40,7 @@
#include "asterisk/utils.h"
#include "asterisk/unaligned.h"
#include "asterisk/lock.h"
+#include "asterisk/threadstorage.h"
#include "iax2.h"
#include "iax2-parser.h"
@@ -48,6 +49,15 @@
static int frames = 0;
static int iframes = 0;
static int oframes = 0;
+
+static void frame_cache_cleanup(void *data);
+
+/*! \brief A per-thread cache of iax_frame structures */
+AST_THREADSTORAGE_CUSTOM(frame_cache, frame_cache_init, frame_cache_cleanup);
+
+/*! \brief This is just so iax_frames, a list head struct for holding a list of
+ * iax_frame structures, is defined. */
+AST_LIST_HEAD_NOLOCK(iax_frames, iax_frame);
static void internaloutput(const char *str)
{
@@ -926,22 +936,42 @@
struct iax_frame *iax_frame_new(int direction, int datalen)
{
+ struct iax_frames *iax_frames;
struct iax_frame *fr;
- fr = malloc((int)sizeof(struct iax_frame) + datalen);
- if (fr) {
- fr->direction = direction;
- fr->retrans = -1;
- ast_atomic_fetchadd_int(&frames, 1);
- if (fr->direction == DIRECTION_INGRESS)
- ast_atomic_fetchadd_int(&iframes, 1);
- else
- ast_atomic_fetchadd_int(&oframes, 1);
- }
+
+ /* Attempt to get a frame from this thread's cache */
+ if ((iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
+ AST_LIST_TRAVERSE_SAFE_BEGIN(iax_frames, fr, list) {
+ if (fr->mallocd_datalen >= datalen) {
+ size_t mallocd_datalen = fr->mallocd_datalen;
+ AST_LIST_REMOVE_CURRENT(iax_frames, list);
+ memset(fr, 0, sizeof(*fr));
+ fr->mallocd_datalen = mallocd_datalen;
+ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END
+ }
+
+ if (!fr && !(fr = ast_calloc(1, sizeof(*fr) + datalen)))
+ return NULL;
+
+ fr->direction = direction;
+ fr->retrans = -1;
+
+ ast_atomic_fetchadd_int(&frames, 1);
+ if (fr->direction == DIRECTION_INGRESS)
+ ast_atomic_fetchadd_int(&iframes, 1);
+ else
+ ast_atomic_fetchadd_int(&oframes, 1);
+
return fr;
}
-void iax_frame_free(struct iax_frame *fr)
-{
+static void __iax_frame_free(struct iax_frame *fr, int cache)
+{
+ struct iax_frames *iax_frames;
+
/* Note: does not remove from scheduler! */
if (fr->direction == DIRECTION_INGRESS)
ast_atomic_fetchadd_int(&iframes, -1);
@@ -952,8 +982,35 @@
return;
}
fr->direction = 0;
- free(fr);
ast_atomic_fetchadd_int(&frames, -1);
+
+ if (!cache) {
+ free(fr);
+ return;
+ }
+
+ if (!(iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
+ free(fr);
+ return;
+ }
+
+ AST_LIST_INSERT_HEAD(iax_frames, fr, list);
+}
+
+static void frame_cache_cleanup(void *data)
+{
+ struct iax_frames *frames = data;
+ struct iax_frame *cur;
+
+ while ((cur = AST_LIST_REMOVE_HEAD(frames, list)))
+ __iax_frame_free(cur, 0);
+
+ free(frames);
+}
+
+void iax_frame_free(struct iax_frame *fr)
+{
+ __iax_frame_free(fr, 1);
}
int iax_get_frames(void) { return frames; }
Modified: team/russell/frame_caching/channels/iax2-parser.h
URL: http://svn.digium.com/view/asterisk/team/russell/frame_caching/channels/iax2-parser.h?rev=38610&r1=38609&r2=38610&view=diff
==============================================================================
--- team/russell/frame_caching/channels/iax2-parser.h (original)
+++ team/russell/frame_caching/channels/iax2-parser.h Mon Jul 31 15:26:50 2006
@@ -17,6 +17,8 @@
#ifndef _IAX2_PARSER_H
#define _IAX2_PARSER_H
+
+#include "asterisk/linkedlists.h"
struct iax_ies {
char *called_number;
@@ -115,8 +117,7 @@
/* Retransmission ID */
int retrans;
/* Easy linking */
- struct iax_frame *next;
- struct iax_frame *prev;
+ AST_LIST_ENTRY(iax_frame) list;
/* Actual, isolated frame header */
struct ast_frame af;
/*! Amount of space _allocated_ for data */
More information about the asterisk-commits
mailing list