{
struct resource *conflict;
write_lock(&resource_lock);
conflict = __request_resource(root, new);
write_unlock(&resource_lock);
return conflict ? -EBUSY : 0;
}
对上述函数的NOTE如下:
①资源锁resource_lock对任何资源树进行读写保护,任何代码段在访问某一颗资源树之前都必须先持有该锁。其定义如下(kernel/Resource.c):
static rwlock_t resource_lock = RW_LOCK_UNLOCKED;
②能够看出,函数实际上是通过调用内部静态函数__request_resource()来完成实际的资源分配工作。假如该函数返回非空指针,则表示有资源冲突;否则,返回NULL就表示分配成功。
③最后,假如conflict指针为NULL,则request_resource()函数返回返回值0,表示成功;否则返回-EBUSY表示想要分配的资源已被占用。
函数__request_resource()完成实际的资源分配工作。假如参数new所描述的资源中的一部分或全部已被其他节点所占用,则函数返回和new相冲突的resource结构的指针。否则就返回NULL。该函数的源代码如下
(kernel/Resource.c):
/* Return the conflict entry if you can't request it */
static struct resource * __request_resource
(struct resource *root, struct resource *new)
{
unsigned long start = new->start;
unsigned long end = new->end;
struct resource *tmp, **p;
if (end < start)
return root;
if (start < root->start)
return root;
if (end > root->end)
return root;
p = &root->child;
for (;;) {
tmp = *p;
if (!tmp || tmp->start > end) {
new->sibling = tmp;
*p = new;
new->parent = root;
return NULL;
}
p = &tmp->sibling;
if (tmp->end < start)
continue;
return tmp;
}
}
对函数的NOTE:
①前三个if语句判断new所描述的资源范围是否被包含在root内,连同是否是一段有效的资源(因为end必须大于start)。否则就返回root指针,表示和根结点相冲突。
②接下来用一个for循环遍历根节点root的child链表,以便检查是否有资源冲突,并将new插入到child链表中的合适位置(child 链表是以I/O资源物理地址从低到高的顺序排列的)。为此,他用tmp指针指向当前正被扫描的resource结构,用指针p指向前一个resource 结构的sibling指针成员变量,p的初始值为指向root->sibling。For循环体的执行步骤如下:
l 让tmp指向当前正被扫描的resource结构(tmp=*p)。
l 判断tmp指针是否为空(tmp指针为空说明已遍历完整个child链表),或当前被扫描节点的起始位置start是否比new的结束位置end还要大。只要这两个条件之一成立的话,就说明没有资源冲突,于是就能够把new链入child链表中:①配置new的sibling指针指向当前正被扫描的节点tmp(new->sibling=tmp);②当前节点tmp的前一个兄弟节点的sibling指针被修改为指向new这个节点(*p= new);③将new的parent指针配置为指向root。然后函数就能够返回了(返回值NULL表示没有资源冲突)。
l 假如上述两个条件都不成立,这说明当前被扫描节点的资源域有可能和new相冲突(实际上就是两个闭区间有交集),因此需要进一步判断。为此他首先修改指针 p,让他指向tmp->sibling,以便于继续扫描child链表。然后,判断tmp->end是否小于new->start,假如小于,则说明当前节点tmp和new没有资源冲突,因此执行continue语句,继续向下扫描child链表。否则,假如tmp->end大于或等于new->start,则说明tmp->[start,end]和new->[start,end]之间有交集。所以返回当前节点的指针tmp,表示发生资源冲突。
3.2.2 资源的释放
函数release_resource()用于实现I/O资源的释放。该函数只有一个参数——即指针old,他指向所要释放的资源。起源代码如下:
int release_resource(struct resource *old)
{
int retval;
write_lock(&resource_lock);
retval = __release_resource(old);
write_unlock(&resource_lock);
return retval;
}
能够看出,他实际上通过调用__release_resource()这个内部静态函数来完成实际的资源释放工作。函数 __release_resource()的主要任务就是将资源区域old(假如已存在的话)从其父资源的child链表重摘除,他的源代码如下:
static int __release_resource(struct resource *old)
{
struct resource *tmp, **p;
p = &old->parent->child;
for (;;) {
tmp = *p;
if (!tmp)
break;
if (tmp == old) {
*p = tmp->sibling;
old->parent = NULL;
return 0;
}
p = &tmp->sibling;
}
return -EINVAL;
}
对上述函数代码的NOTE如下:
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!



