Linux对I/O端口资源的管理(3)

  ②如果tmp指针为空,说明已经遍历完整个child链表,因此执行break语句推出for循环。由于在遍历过程中没有在child链表中找到参数old所指定的资源节点,因此最后返回错误值-EINVAL,表示参数old是一个无效的值。

  ③接下来,判断当前被扫描节点是否就是参数old所指定的资源节点。如果是,那就将old从child链表中去除,也即让当前结点tmp的前一 个兄弟节点的sibling指针指向tmp的下一个节点,然后将old->parent指针设置为NULL。最后返回0值表示执行成功。

  ④如果当前被扫描节点不是资源old,那就继续扫描child链表中的下一个元素。因此将指针p指向tmp->sibling成员。

  3.2.3 检查资源是否已被占用,

  函数check_resource()用于实现检查某一段I/O资源是否已被占用。其源代���如下:

int check_resource(struct resource *root, unsigned long start, unsigned long len){ struct resource *conflict, tmp; tmp.start = start; tmp.end = start + len - 1; write_lock(&resource_lock); conflict = __request_resource(root, &tmp); if (!conflict)  __release_resource(&tmp); write_unlock(&resource_lock); return conflict ? -EBUSY : 0;}

  对该函数的NOTE如下:

  ①构造一个临时资源tmp,表示所要检查的资源[start,start+end-1]。

  ②调用__request_resource()函数在根节点root申请tmp所表示的资源。如果tmp所描述的资源还被人使用,则该函数返 回NULL,否则返回非空指针。因此接下来在conflict为NULL的情况下,调用__release_resource()将刚刚申请的资源释放 掉。

  ③最后根据conflict是否为NULL,返回-EBUSY或0值。

  3.2.4 寻找可用资源

  函数find_resource()用于在一颗资源树中寻找未被使用的、且满足给定条件的(也即资源长度大小为size,且在[min,max]区间内)的资源。其函数源代码如下:

/* * Find empty slot in the resource tree given range and alignment. */static int find_resource(struct resource *root, struct resource *new,    unsigned long size,    unsigned long min, unsigned long max,    unsigned long align,    void (*alignf)(void *, struct resource *, unsigned long),    void *alignf_data){ struct resource *this = root->child; new->start = root->start; for(;;) {  if (this)   new->end = this->start;  else   new->end = root->end;  if (new->start < min)   new->start = min;  if (new->end > max)   new->end = max;  new->start = (new->start + align - 1) & ~(align - 1);  if (alignf)   alignf(alignf_data, new, size);  if (new->start < new->end && new->end - new->start + 1 >= size)                   {   new->end = new->start + size - 1;   return 0;  }  if (!this)   break;  new->start = this->end + 1;  this = this->sibling; } return -EBUSY;}

  对该函数的NOTE如下:

  同样,该函数也要遍历root的child链表,以寻找未被使用的资源空洞。为此,它让this指针表示当前正被扫描的子资源节点,其初始值等 于root->child,即指向child链表中的第一个节点,并让new->start的初始值等于root->start,然后 用一个for循环开始扫描child链表,对于每一个被扫描的节点,循环体执行如下操作:

  ①首先,判断this指针是否为NULL。如果不为空,就让new->end等于this->start,也即让资源new表示当前资源节点this前面那一段未使用的资源区间。

  ②如果this指针为空,那就让new->end等于root->end。这有两层意思:第一种情况就是根结点的child指针为 NULL(即根节点没有任何子资源)。因此此时先暂时将new->end放到最大。第二种情况就是已经遍历完整个child链表,所以此时就让 new表示最后一个子资源后面那一段未使用的资源区间。

  ③根据参数min和max修正new->[start,end]的值,以使资源new被包含在[min,max]区域内。

  ④接下来进行对齐操作。

  ⑤然后,判断经过上述这些步骤所形成的资源区域new是否是一段有效的资源(end必须大于或等于start),而且资源区域的长度满足 size参数的要求(end-start+1>=size)。如果这两个条件均满足,则说明我们已经找到了一段满足条件的资源空洞。因此在对new ->end的值进行修正后,然后就可以返回了(返回值0表示成功)。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/25128.html