|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
This file is provided under a dual BSD/GPLv2 license. When using or
|
|
Packit |
961e70 |
redistributing this file, you may do so under either license.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
GPL LICENSE SUMMARY
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
Copyright(c) 2015 Intel Corporation.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
This program is free software; you can redistribute it and/or modify
|
|
Packit |
961e70 |
it under the terms of version 2 of the GNU General Public License as
|
|
Packit |
961e70 |
published by the Free Software Foundation.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
This program is distributed in the hope that it will be useful, but
|
|
Packit |
961e70 |
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
961e70 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
961e70 |
General Public License for more details.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
Contact Information:
|
|
Packit |
961e70 |
Intel Corporation, www.intel.com
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
BSD LICENSE
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
Copyright(c) 2015 Intel Corporation.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
Redistribution and use in source and binary forms, with or without
|
|
Packit |
961e70 |
modification, are permitted provided that the following conditions
|
|
Packit |
961e70 |
are met:
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
* Redistributions of source code must retain the above copyright
|
|
Packit |
961e70 |
notice, this list of conditions and the following disclaimer.
|
|
Packit |
961e70 |
* Redistributions in binary form must reproduce the above copyright
|
|
Packit |
961e70 |
notice, this list of conditions and the following disclaimer in
|
|
Packit |
961e70 |
the documentation and/or other materials provided with the
|
|
Packit |
961e70 |
distribution.
|
|
Packit |
961e70 |
* Neither the name of Intel Corporation nor the names of its
|
|
Packit |
961e70 |
contributors may be used to endorse or promote products derived
|
|
Packit |
961e70 |
from this software without specific prior written permission.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit |
961e70 |
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit |
961e70 |
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
Packit |
961e70 |
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
Packit |
961e70 |
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
Packit |
961e70 |
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
Packit |
961e70 |
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
Packit |
961e70 |
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
Packit |
961e70 |
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
Packit |
961e70 |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
Packit |
961e70 |
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Copyright (c) 2003-2014 Intel Corporation. All rights reserved. */
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
#include "psm_user.h"
|
|
Packit |
961e70 |
#include "psm_mq_internal.h"
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
*
|
|
Packit |
961e70 |
* System buffer (unexpected message) allocator
|
|
Packit |
961e70 |
*
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
#define MM_FLAG_NONE 0
|
|
Packit |
961e70 |
#define MM_FLAG_TRANSIENT 0x1
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
struct psmi_mem_block_ctrl {
|
|
Packit |
961e70 |
union {
|
|
Packit |
961e70 |
psmi_mem_ctrl_t *mem_handler;
|
|
Packit |
961e70 |
struct psmi_mem_block_ctrl *next;
|
|
Packit |
961e70 |
};
|
|
Packit |
961e70 |
};
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Per MQ allocators */
|
|
Packit |
961e70 |
void psmi_mq_sysbuf_init(psm2_mq_t mq)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
int i;
|
|
Packit |
961e70 |
uint32_t block_sizes[] = {256, 512, 1024, 2048, 4096, 8192, (uint32_t)-1};
|
|
Packit |
961e70 |
uint32_t replenishing_rate[] = {128, 64, 32, 16, 8, 4, 0};
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (mq->mem_ctrl_is_init)
|
|
Packit |
961e70 |
return;
|
|
Packit |
961e70 |
mq->mem_ctrl_is_init = 1;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
for (i=0; i < MM_NUM_OF_POOLS; i++) {
|
|
Packit |
961e70 |
mq->handler_index[i].block_size = block_sizes[i];
|
|
Packit |
961e70 |
mq->handler_index[i].current_available = 0;
|
|
Packit |
961e70 |
mq->handler_index[i].free_list = NULL;
|
|
Packit |
961e70 |
mq->handler_index[i].total_alloc = 0;
|
|
Packit |
961e70 |
mq->handler_index[i].replenishing_rate = replenishing_rate[i];
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (block_sizes[i] == -1) {
|
|
Packit |
961e70 |
psmi_assert_always(replenishing_rate[i] == 0);
|
|
Packit |
961e70 |
mq->handler_index[i].flags = MM_FLAG_TRANSIENT;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
else {
|
|
Packit |
961e70 |
psmi_assert_always(replenishing_rate[i] > 0);
|
|
Packit |
961e70 |
mq->handler_index[i].flags = MM_FLAG_NONE;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Hit once on each block size so we have a pool that's allocated */
|
|
Packit |
961e70 |
for (i=0; i < MM_NUM_OF_POOLS; i++) {
|
|
Packit |
961e70 |
void *ptr;
|
|
Packit |
961e70 |
if (block_sizes[i] == -1)
|
|
Packit |
961e70 |
continue;
|
|
Packit |
961e70 |
ptr = psmi_mq_sysbuf_alloc(mq, block_sizes[i]);
|
|
Packit |
961e70 |
psmi_mq_sysbuf_free(mq, ptr);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
void psmi_mq_sysbuf_fini(psm2_mq_t mq) // free all buffers that is currently not used
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct psmi_mem_block_ctrl *block;
|
|
Packit |
961e70 |
int i;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (mq->mem_ctrl_is_init == 0)
|
|
Packit |
961e70 |
return;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
for (i=0; i < MM_NUM_OF_POOLS; i++) {
|
|
Packit |
961e70 |
while ((block = mq->handler_index[i].free_list) != NULL) {
|
|
Packit |
961e70 |
mq->handler_index[i].free_list = block->next;
|
|
Packit |
961e70 |
psmi_free(block);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
mq->mem_ctrl_is_init = 0;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
void psmi_mq_sysbuf_getinfo(psm2_mq_t mq, char *buf, size_t len)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
snprintf(buf, len-1, "Sysbuf consumption: %"PRIu64" bytes\n",
|
|
Packit |
961e70 |
mq->mem_ctrl_total_bytes);
|
|
Packit |
961e70 |
buf[len-1] = '\0';
|
|
Packit |
961e70 |
return;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
void *psmi_mq_sysbuf_alloc(psm2_mq_t mq, uint32_t alloc_size)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
psmi_mem_ctrl_t *mm_handler = mq->handler_index;
|
|
Packit |
961e70 |
struct psmi_mem_block_ctrl *new_block;
|
|
Packit |
961e70 |
int replenishing;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* There is a timing race with ips initialization, fix later.
|
|
Packit |
961e70 |
* * XXX */
|
|
Packit |
961e70 |
if (!mq->mem_ctrl_is_init)
|
|
Packit |
961e70 |
psmi_mq_sysbuf_init(mq);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
mq->stats.rx_sysbuf_num++;
|
|
Packit |
961e70 |
mq->stats.rx_sysbuf_bytes += alloc_size;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
while (mm_handler->block_size < alloc_size)
|
|
Packit |
961e70 |
mm_handler++;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
replenishing = mm_handler->replenishing_rate;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (mm_handler->current_available == 0) { // allocate more buffers
|
|
Packit |
961e70 |
if (mm_handler->flags & MM_FLAG_TRANSIENT) {
|
|
Packit |
961e70 |
uint32_t newsz = alloc_size + sizeof(struct psmi_mem_block_ctrl);
|
|
Packit |
961e70 |
new_block = psmi_malloc(mq->ep, UNEXPECTED_BUFFERS, newsz);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (new_block) {
|
|
Packit |
961e70 |
new_block->mem_handler = mm_handler;
|
|
Packit |
961e70 |
new_block++;
|
|
Packit |
961e70 |
mm_handler->total_alloc++;
|
|
Packit |
961e70 |
mq->mem_ctrl_total_bytes += newsz;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
return new_block;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
do {
|
|
Packit |
961e70 |
uint32_t newsz = mm_handler->block_size + sizeof(struct psmi_mem_block_ctrl);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
new_block = psmi_malloc(mq->ep, UNEXPECTED_BUFFERS, newsz);
|
|
Packit |
961e70 |
mq->mem_ctrl_total_bytes += newsz;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (new_block) {
|
|
Packit |
961e70 |
mm_handler->current_available++;
|
|
Packit |
961e70 |
mm_handler->total_alloc++;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
new_block->next = mm_handler->free_list;
|
|
Packit |
961e70 |
mm_handler->free_list = new_block;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
} while (--replenishing && new_block);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (mm_handler->current_available) {
|
|
Packit |
961e70 |
mm_handler->current_available--;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
new_block = mm_handler->free_list;
|
|
Packit |
961e70 |
mm_handler->free_list = new_block->next;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
new_block->mem_handler = mm_handler;
|
|
Packit |
961e70 |
new_block++;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
return new_block;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
return NULL;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
void psmi_mq_sysbuf_free(psm2_mq_t mq, void * mem_to_free)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct psmi_mem_block_ctrl * block_to_free;
|
|
Packit |
961e70 |
psmi_mem_ctrl_t *mm_handler;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
psmi_assert_always(mq->mem_ctrl_is_init);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
block_to_free = (struct psmi_mem_block_ctrl *)mem_to_free - 1;
|
|
Packit |
961e70 |
mm_handler = block_to_free->mem_handler;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (mm_handler->flags & MM_FLAG_TRANSIENT) {
|
|
Packit |
961e70 |
psmi_free(block_to_free);
|
|
Packit |
961e70 |
} else {
|
|
Packit |
961e70 |
block_to_free->next = mm_handler->free_list;
|
|
Packit |
961e70 |
mm_handler->free_list = block_to_free;
|
|
Packit |
961e70 |
mm_handler->current_available++;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
return;
|
|
Packit |
961e70 |
}
|