|
NOTE:
①首先,调用kmalloc()函数在SLAB分配器缓存中分配一个resource结构。
②然后,相应的根据参数值初始化所分配的resource结构。注意!flags成员被初始化为IORESOURCE_BUSY。
③接下来,用一个for循环开始进行资源分配,循环体的步骤如下:
首先,调用__request_resource()函数进行资源分配。如果返回NULL,说明分配成功,因此就执行break语句推出for循环,返回所分配的resource结构的指针,函数成功地结束。
如果__request_resource()函数分配不成功,则进一步判断所返回的冲突资源节点是否就是父资源节点parent。如果不是,则把分配行为下降一个层次,即试图在当前冲突的资源节点中进行分配(只有在冲突的资源节点没有设置IORESOURCE_BUSY的情况下才可以),于是让parent指针等于conflict,并在conflict->flags&IORESOURCE_BUSY为0的情况下执行continue语句继续for循环。
否则如果相冲突的资源节点就是父节点parent,或者相冲突资源节点设置了IORESOURCE_BUSY标志位,则宣告分配失败。于是调用kfree()函数释放所分配的resource结构,并把res指针置为NULL,最后用break语句推出for循环。
④最后,返回所分配的resource结构的指针。
2 I/O Region的释放
函数__release_region()实现在一个父资源节点parent中释放给定范围的I/O Region。实际上该函数的实现思想与__release_resource()相类似。其源代码如下:
void __release_region(struct resource *parent,
unsigned long start, unsigned long n)
{
struct resource **p;
unsigned long end;
p = &parent->child;
end = start + n - 1;
for (;;) {
struct resource *res = *p;
if (!res)
break;
if (res->start <= start && res->end >= end) {
if (!(res->flags & IORESOURCE_BUSY)) {
p = &res->child;
continue;
}
if (res->start != start' 'res->end != end)
break;
*p = res->sibling;
kfree(res);
return;
}
p = &res->sibling;
}
printk("Trying to free nonexistent resource <%08lx-%08lx>
", start, end);
}
|
类似地,该函数也是通过一个for循环来遍历父资源parent的child链表。为此,它让指针res指向当前正被扫描的子资源节点,指针p指向前一个子资源节点的sibling成员变量,p的初始值为指向parent->child。For循环体的步骤如下:
①让res指针指向当前被扫描的子资源节点(res=*p)。
②如果res指针为NULL,说明已经扫描完整个child链表,所以退出for循环。
③如果res指针不为NULL,则继续看看所指定的I/O区域范围是否完全包含在当前资源节点中,也即看看[start,start+n-1]是否包含在res->[start,end]中。如果不属于,则让p指向当前资源节点的sibling成员,然后继续for循环。如果属于,则执行下列步骤:
先看看当前资源节点是否设置了IORESOURCE_BUSY标志位。如果没有设置该标志位,则说明该资源节点下面可能还会有子节点,因此把扫描过程下降一个层次,于是修改p指针,使它指向res->child,然后执行continue语句继续for循环。
如果设置了IORESOURCE_BUSY标志位。则一定要确保当前资源节点就是所指定的I/O区域,然后把当前资源节点从其父资源的child链表中去除。这可以通过让前一个兄弟资源节点的sibling指针指向当前资源节点的下一个兄弟资源节点来实现(即让*p=res->sibling),最后调用kfree()函数释放当前资源节点的resource结构。然后函数就可以成功返回了。
3 检查指定的I/O Region是否已被占用
函数__check_region()检查指定的I/O Region是否已被占用。其源代码如下:
int __check_region(struct resource *parent,
unsigned long start, unsigned long n)
{
struct resource * res;
res = __request_region(parent, start, n, "check-region");
if (!res)
return -EBUSY;
release_resource(res);
kfree(res);
return 0;
}
|
该函数的实现与__check_resource()的实现思想类似。首先,它通过调用__request_region()函数试图在父资源parent中分配指定的I/O Region。如果分配不成功,把返回NULL,因此此时函数返回错误值-EBUSY表示所指定的I/O Region已被占用。如果res指针不为空则说明所指定的I/O Region没有被占用。于是调用__release_resource()函数把刚刚分配的资源释放掉(实际上是把res结构从parent的child链表去除),然后调用kfree()函数释放res结构所占用的内存。最后,返回0值表示指定的I/O Region没有被占用。
共6页: 上一页 [1] 2 [3] [4] [5] [6] 下一页
|