#include "smartpqi_includes.h"
#ifndef LOCKFREE_STACK
void
pqisrc_put_tag(pqi_taglist_t *taglist, uint32_t elem)
{
OS_ACQUIRE_SPINLOCK(&(taglist->lock));
ASSERT(taglist->num_elem < taglist->max_elem);
if (taglist->num_elem < taglist->max_elem) {
taglist->elem_array[taglist->tail] = elem;
taglist->num_elem++;
taglist->tail = (taglist->tail + 1) % taglist->max_elem;
}
OS_RELEASE_SPINLOCK(&taglist->lock);
}
uint32_t
pqisrc_get_tag(pqi_taglist_t *taglist)
{
uint32_t elem = INVALID_ELEM;
OS_ACQUIRE_SPINLOCK(&taglist->lock);
ASSERT(taglist->num_elem > 0);
if (taglist->num_elem > 0) {
elem = taglist->elem_array[taglist->head];
taglist->num_elem--;
taglist->head = (taglist->head + 1) % taglist->max_elem;
}
OS_RELEASE_SPINLOCK(&taglist->lock);
return elem;
}
int
pqisrc_init_taglist(pqisrc_softstate_t *softs, pqi_taglist_t *taglist,
uint32_t max_elem)
{
int ret = PQI_STATUS_SUCCESS;
int i = 0;
DBG_FUNC("IN\n");
taglist->max_elem = max_elem;
taglist->num_elem = 0;
taglist->head = 0;
taglist->tail = 0;
taglist->elem_array = os_mem_alloc(softs,
(max_elem * sizeof(uint32_t)));
if (!(taglist->elem_array)) {
DBG_FUNC("Unable to allocate memory for taglist\n");
ret = PQI_STATUS_FAILURE;
goto err_out;
}
os_strlcpy(taglist->lockname, "tag_lock", LOCKNAME_SIZE);
ret = os_init_spinlock(softs, &taglist->lock, taglist->lockname);
if(ret){
DBG_ERR("tag lock initialization failed\n");
taglist->lockcreated=false;
goto err_lock;
}
taglist->lockcreated = true;
for (i=1; i <= max_elem; i++) {
softs->rcb[i].tag = INVALID_ELEM;
pqisrc_put_tag(taglist, i);
}
DBG_FUNC("OUT\n");
return ret;
err_lock:
os_mem_free(softs, (char *)taglist->elem_array,
(taglist->max_elem * sizeof(uint32_t)));
taglist->elem_array = NULL;
err_out:
DBG_FUNC("OUT failed\n");
return ret;
}
void
pqisrc_destroy_taglist(pqisrc_softstate_t *softs, pqi_taglist_t *taglist)
{
DBG_FUNC("IN\n");
os_mem_free(softs, (char *)taglist->elem_array,
(taglist->max_elem * sizeof(uint32_t)));
taglist->elem_array = NULL;
if(taglist->lockcreated==true){
os_uninit_spinlock(&taglist->lock);
taglist->lockcreated = false;
}
DBG_FUNC("OUT\n");
}
#else
int
pqisrc_init_taglist(pqisrc_softstate_t *softs, lockless_stack_t *stack,
uint32_t max_elem)
{
int ret = PQI_STATUS_SUCCESS;
int index = 0;
DBG_FUNC("IN\n");
stack->max_elem = max_elem + 1;
stack->head.data = 0;
DBG_INFO("Stack head address :%p\n",&stack->head);
stack->next_index_array = (uint32_t*)os_mem_alloc(softs,
(stack->max_elem * sizeof(uint32_t)));
if (!(stack->next_index_array)) {
DBG_ERR("Unable to allocate memory for stack\n");
ret = PQI_STATUS_FAILURE;
goto err_out;
}
for (index = 1; index < stack->max_elem ; index++) {
softs->rcb[index].tag = INVALID_ELEM;
pqisrc_put_tag(stack, index);
}
DBG_FUNC("OUT\n");
return ret;
err_out:
DBG_FUNC("Failed OUT\n");
return ret;
}
void
pqisrc_destroy_taglist(pqisrc_softstate_t *softs, lockless_stack_t *stack)
{
DBG_FUNC("IN\n");
if (stack->next_index_array) {
os_mem_free(softs,(char*)stack->next_index_array,
(stack->max_elem * sizeof(uint32_t)));
stack->next_index_array = NULL;
}
DBG_FUNC("OUT\n");
}
void
pqisrc_put_tag(lockless_stack_t *stack, uint32_t index)
{
union head_list cur_head, new_head;
DBG_FUNC("IN\n");
DBG_INFO("push tag :%u\n",index);
if (index >= stack->max_elem) {
ASSERT(false);
DBG_INFO("Pushed Invalid index\n");
return;
}
if (stack->next_index_array[index] != 0) {
ASSERT(false);
DBG_INFO("Index already present as tag in the stack\n");
return;
}
do {
cur_head = stack->head;
new_head.top.seq_no = cur_head.top.seq_no + 1;
new_head.top.index = index;
stack->next_index_array[index] = cur_head.top.index;
}while(!os_atomic64_cas(&stack->head.data,cur_head.data,new_head.data));
stack->num_elem++;
DBG_FUNC("OUT\n");
return;
}
uint32_t
pqisrc_get_tag(lockless_stack_t *stack)
{
union head_list cur_head, new_head;
DBG_FUNC("IN\n");
do {
cur_head = stack->head;
if (cur_head.top.index == 0)
return INVALID_ELEM;
new_head.top.seq_no = cur_head.top.seq_no + 1;
new_head.top.index = stack->next_index_array[cur_head.top.index];
}while(!os_atomic64_cas(&stack->head.data,cur_head.data,new_head.data));
stack->next_index_array[cur_head.top.index] = 0;
stack->num_elem--;
DBG_INFO("pop tag: %u\n",cur_head.top.index);
DBG_FUNC("OUT\n");
return cur_head.top.index;
}
#endif