#if !defined(LOW_MEMORY)
struct iax_frames *iax_frames = NULL;
+ struct iax_frame *smallest;
/* Attempt to get a frame from this thread's cache */
if ((iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
+ smallest = AST_LIST_FIRST(&iax_frames->list);
AST_LIST_TRAVERSE_SAFE_BEGIN(&iax_frames->list, fr, list) {
if (fr->afdatalen >= datalen) {
size_t afdatalen = fr->afdatalen;
memset(fr, 0, sizeof(*fr));
fr->afdatalen = afdatalen;
break;
+ } else if (smallest->afdatalen > fr->afdatalen) {
+ smallest = fr;
}
}
AST_LIST_TRAVERSE_SAFE_END;
}
if (!fr) {
- if (!(fr = ast_calloc_cache(1, sizeof(*fr) + datalen)))
+ if (iax_frames->size >= FRAME_CACHE_MAX_SIZE && smallest) {
+ /* Make useless cache into something more useful */
+ AST_LIST_REMOVE(&iax_frames->list, smallest, list);
+ if (!(fr = ast_realloc(smallest, sizeof(*fr) + datalen))) {
+ AST_LIST_INSERT_TAIL(&iax_frames->list, smallest, list);
+ return NULL;
+ }
+ } else if (!(fr = ast_calloc_cache(1, sizeof(*fr) + datalen)))
return NULL;
fr->afdatalen = datalen;
}
if (iax_frames->size < FRAME_CACHE_MAX_SIZE) {
fr->direction = 0;
- AST_LIST_INSERT_HEAD(&iax_frames->list, fr, list);
+ /* Pseudo-sort: keep smaller frames at the top of the list. This should
+ * increase the chance that we pick the smallest applicable frame for use. */
+ if (AST_LIST_FIRST(&iax_frames->list) && AST_LIST_FIRST(&iax_frames->list)->afdatalen < fr->afdatalen) {
+ AST_LIST_INSERT_TAIL(&iax_frames->list, fr, list);
+ } else {
+ AST_LIST_INSERT_HEAD(&iax_frames->list, fr, list);
+ }
iax_frames->size++;
return;
}