函数意思是返回一个HASHELEMENT指针,HASHBUCKET是一个Element指针的宏定义。
- 首先判断现有的freelist中是否有可用的Element,如果有,进入4,否则进入2
- 如果现有的freelist中没有,就试图扩展freelist,如果无法扩展就进入3
- 循环查找现有的freelist(32取模),如果找到了就返回该Element,如果找不到就返回NULL
- 如果有可用的就找到并返回该Element,nentries加1。
typedef HASHELEMENT* HASHBUCKET;
/* create a new entry if possible */
static HASHBUCKET get_hash_entry(HTAB *hashp, int freelist_idx)
{
HASHHDR *hctl = hashp->hctl;
HASHBUCKET newElement;
int borrow_from_idx;
for (;;)
{
……
/* 试图获取Element */
newElement = hctl->freeList[freelist_idx].freeList;
//判断,如果newElement指向的链表不为空,则跳出循环,获取需要的值
if (newElement != NULL)
break;
/* 如果没有链表就尝试创建一个链表,element_alloc是创建链表的函数*/
if (!element_alloc(hashp, hctl->nelem_alloc, freelist_idx))
{
/*如果创建失败后进入函数内部,再已有的freelist中循环查找*/
if (!IS_PARTITIONED(hctl))
return NULL; /* out of memory */
borrow_from_idx = freelist_idx;
for (;;)
{
/*进行循环查找,每次borrow增加1*/
borrow_from_idx = (borrow_from_idx + 1) % NUM_FREELISTS;
/* 如果找了一圈还没有找到就跳出循环 */
if (borrow_from_idx == freelist_idx)
break;
SpinLockAcquire(&(hctl->freeList[borrow_from_idx].mutex));
newElement = hctl->freeList[borrow_from_idx].freeList;
/*如果能够找到就获取跳出循环*/
if (newElement != NULL)
{
hctl->freeList[borrow_from_idx].freeList = newElement->link;
SpinLockRelease(&(hctl->freeList[borrow_from_idx].mutex));
SpinLockAcquire(&hctl->freeList[freelist_idx].mutex);
hctl->freeList[freelist_idx].nentries++;
SpinLockRelease(&hctl->freeList[freelist_idx].mutex);
break;
}
SpinLockRelease(&(hctl->freeList[borrow_from_idx].mutex));
}
/*返回得到的Element*/
return newElement;
}
}
/* remove entry from freelist, bump nentries */
hctl->freeList[freelist_idx].freeList = newElement->link;
hctl->freeList[freelist_idx].nentries++;
if (IS_PARTITIONED(hctl))
SpinLockRelease(&hctl->freeList[freelist_idx].mutex);
return newElement;
}