25 RCSID(
"$Id: 986864d4ac3fcfcc45754b9048f12929e9f54319 $")
27 #include <freeradius-devel/io/message.h>
28 #include <freeradius-devel/util/strerror.h>
36 #define MPRINT(...) fprintf(stderr, __VA_ARGS__)
41 #define MSG_ARRAY_SIZE (16)
43 #define CACHE_ALIGN(_x) do { _x += 63; _x &= ~(size_t) 63; } while (0)
134 if (num_messages < 8) num_messages = 8;
136 if ((num_messages & (num_messages - 1)) != 0) {
146 if (message_size > 1024) {
256 l = talloc_memdup(ctx, m, message_size);
308 int messages_cleaned = 0;
314 if (size == 0)
break;
335 if (messages_cleaned >= max_to_clean)
break;
338 MPRINT(
"CLEANED %d (%p) left\n", messages_cleaned, mr);
339 return messages_cleaned;
355 int arrays_freed, arrays_used, empty_slot;
356 int largest_free_slot;
358 size_t largest_free_size;
368 for (i = 0; i <= ms->
mr_max; i++) {
372 total_cleaned += cleaned;
373 fr_assert(total_cleaned <= max_to_clean);
378 if (total_cleaned == max_to_clean)
break;
384 if (total_cleaned == 0)
return;
393 for (i = ms->
mr_max; i >= 0; i--) {
396 if (arrays_used < 2) {
397 MPRINT(
"\tleaving entry %d alone\n", i);
407 MPRINT(
"\tfreeing entry %d\n", i);
413 MPRINT(
"\tstill in use entry %d\n", i);
421 MPRINT(
"TRYING TO PACK from %d free arrays out of %d\n", arrays_freed, ms->
rb_max + 1);
429 for (i = 0; i <= ms->
mr_max; i++) {
438 if (empty_slot < 0) empty_slot = i;
448 if (empty_slot < 0)
continue;
459 for (j = empty_slot + 1; j <= i; j++) {
471 ms->
mr_max -= arrays_freed;
476 for (i = 0; i <= ms->
mr_max; i++) {
496 for (i = ms->
rb_max; i >= 0; i--) {
499 if (arrays_used < 2) {
500 MPRINT(
"\tleaving entry %d alone\n", i);
506 MPRINT(
"\tfreeing entry %d\n", i);
512 MPRINT(
"\tstill in use entry %d\n", i);
518 if (arrays_freed > 0) {
519 MPRINT(
"TRYING TO PACK from %d free arrays out of %d\n", arrays_freed, ms->
rb_max + 1);
527 for (i = 0; i <= ms->
rb_max; i++) {
536 if (empty_slot < 0) empty_slot = i;
546 if (empty_slot < 0)
continue;
557 for (j = empty_slot + 1; j <= i; j++) {
569 ms->
rb_max -= arrays_freed;
574 for (i = 0; i <= ms->
rb_max; i++) {
590 largest_free_slot = ms->
rb_max;
594 for (i = 0; i < ms->
rb_max; i++) {
601 if (largest_free_size < free_size) {
602 largest_free_slot = i;
603 largest_free_size = free_size;
713 MPRINT(
"ALLOC after cleanup\n");
730 for (i = ms->
mr_max; i >= 0; i--) {
736 MPRINT(
"ALLOC from changed ring buffer\n");
778 MPRINT(
"ALLOC after doubled message ring\n");
805 if (m->
data)
return m;
817 if (ms->
rb_max == 0)
goto alloc_rb;
835 if (m->
data)
return m;
837 MPRINT(
"CLEANUP RING BUFFER FAILED\n");
853 for (i = ms->
rb_max; i >= 0; i--) {
858 MPRINT(
"MOVED TO RING BUFFER %d\n", i);
884 MPRINT(
"RING BUFFER DOUBLES\n");
900 if (m->
data)
return m;
903 MPRINT(
"OUT OF MEMORY\n");
951 MPRINT(
"Failed to reserve message\n");
1011 if (actual_packet_size == 0) {
1083 size_t m_rb_size, align_size;
1087 align_size = actual_packet_size;
1123 if (!m2)
return NULL;
1153 if (m2->
data != (m->
data + actual_packet_size)) {
1154 memmove(m2->
data, m->
data + actual_packet_size, leftover);
1176 if (m2->
data != (m->
data + actual_packet_size)) {
1177 memmove(m2->
data, m->
data + actual_packet_size, leftover);
1187 if (m2->
rb != m->
rb) {
1219 for (i = 0; i <= ms->
mr_max; i++) {
1247 for (i = 0; i <= ms->
mr_max; i++) {
1268 fprintf(fp,
"message arrays = %d\t(current %d)\n", ms->
mr_max + 1, ms->
mr_current);
1269 fprintf(fp,
"ring buffers = %d\t(current %d)\n", ms->
rb_max + 1, ms->
rb_current);
1271 for (i = 0; i <= ms->
mr_max; i++) {
1274 fprintf(fp,
"messages[%d] =\tsize %zu, used %zu\n",
1278 for (i = 0; i <= ms->
rb_max; i++) {
1279 fprintf(fp,
"ring buffer[%d] =\tsize %zu, used %zu\n",
static fr_ring_buffer_t * rb
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
static fr_message_t * fr_message_get_message(fr_message_set_t *ms, bool *p_cleaned)
Allocate a fr_message_t, WITHOUT a ring buffer.
fr_ring_buffer_t * rb_array[MSG_ARRAY_SIZE]
array of ring buffers
size_t message_size
size of the callers message, including fr_message_t
int mr_current
current used message ring entry
static fr_message_t * fr_message_ring_alloc(fr_message_set_t *ms, fr_ring_buffer_t *mr, bool clean)
Allocate a message from a message ring.
fr_ring_buffer_t * mr_array[MSG_ARRAY_SIZE]
array of message arrays
fr_message_set_t * fr_message_set_create(TALLOC_CTX *ctx, int num_messages, size_t message_size, size_t ring_buffer_size)
Create a message set.
static void fr_message_gc(fr_message_set_t *ms, int max_to_clean)
Garbage collect "done" messages.
int fr_message_done(fr_message_t *m)
Mark a message as done.
fr_message_t * fr_message_localize(TALLOC_CTX *ctx, fr_message_t *m, size_t message_size)
Localize a message by copying it to local storage.
int rb_max
max used ring buffer entry
static fr_message_t * fr_message_get_ring_buffer(fr_message_set_t *ms, fr_message_t *m, bool cleaned_up)
Get a ring buffer for a message.
fr_message_t * fr_message_reserve(fr_message_set_t *ms, size_t reserve_size)
Reserve a message.
int fr_message_set_messages_used(fr_message_set_t *ms)
Count the number of used messages.
void fr_message_set_debug(fr_message_set_t *ms, FILE *fp)
Print debug information about the message set.
void fr_message_set_gc(fr_message_set_t *ms)
Garbage collect the message set.
int mr_max
max used message ring entry
int mr_cleaned
where we last cleaned
static int fr_message_ring_gc(fr_message_set_t *ms, fr_ring_buffer_t *mr, int max_to_clean)
Clean up messages in a message ring.
size_t max_allocation
maximum allocation size
fr_message_t * fr_message_alloc(fr_message_set_t *ms, fr_message_t *m, size_t actual_packet_size)
Allocate packet data for a message.
fr_message_t * fr_message_alloc_reserve(fr_message_set_t *ms, fr_message_t *m, size_t actual_packet_size, size_t leftover, size_t reserve_size)
Allocate packet data for a message, and reserve a new message.
int rb_current
current used ring buffer entry
A Message set, composed of message headers and ring buffer data.
fr_ring_buffer_t * rb
pointer to the ring buffer
size_t rb_size
cache-aligned size in the ring buffer
uint8_t * data
pointer to the data in the ring buffer
size_t data_size
size of the data in the ring buffer
fr_message_status_t status
free, used, done, etc.
static size_t reserve_size
fr_ring_buffer_t * fr_ring_buffer_create(TALLOC_CTX *ctx, size_t size)
Create a ring buffer.
uint8_t * fr_ring_buffer_reserve(fr_ring_buffer_t *rb, size_t size)
Reserve room in the ring buffer.
int fr_ring_buffer_free(fr_ring_buffer_t *rb, size_t size_to_free)
Mark data as free,.
size_t fr_ring_buffer_used(fr_ring_buffer_t *rb)
Get the amount of data used in a ring buffer.
size_t fr_ring_buffer_size(fr_ring_buffer_t *rb)
Get the size of the ring buffer.
int fr_ring_buffer_start(fr_ring_buffer_t *rb, uint8_t **p_start, size_t *p_size)
Get a pointer to the data at the start of the ring buffer.
uint8_t * fr_ring_buffer_alloc(fr_ring_buffer_t *rb, size_t size)
Mark data as allocated.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const_push(_msg)
#define fr_strerror_const(_msg)