接前一篇文章:libdrm全解析三十九 —— 源码全解析(36)
本文参考以下博文:
DRM 驱动程序开发(VKMS)
特此致谢!
前一篇文章讲解完了资源的释放流程中的munmap()和drmIoctl(DRM_IOCTL_MODE_DESTROY_DUMB),本回讲解drmModeFreeConnector函数。drmModeFreeConnector()与drmModeGetConnector()是一对。
drmModeFreeConnector函数在xf86drmMode.c中,代码如下:
drm_public void drmModeFreeConnector(drmModeConnectorPtr ptr)
{if (!ptr)return;drmFree(ptr->encoders);drmFree(ptr->prop_values);drmFree(ptr->props);drmFree(ptr->modes);drmFree(ptr);
}
可见,drmModeFreeConnector函数并没有想象中与之专门对应的DRM_IOCTL_MODE_FREE_CONNECTOR宏,而是调用了drmFree函数释放了多个分配的空间。
前文讲过,drmFree函数在xf86drm.c中,代码如下
drm_public void drmFree(void *pt)
{free(pt);
}
就是free函数的简单封装。
drmModeFreeConnector函数的作用是释放drmModeGetConnector函数中分配的各个空间。
为了便于理解,再次贴出drmModeGetConnector函数代码,在xf86drmMode.c中,如下:
/** Connector manipulation*/
static drmModeConnectorPtr
_drmModeGetConnector(int fd, uint32_t connector_id, int probe)
{struct drm_mode_get_connector conn, counts;drmModeConnectorPtr r = NULL;struct drm_mode_modeinfo stack_mode;memclear(conn);conn.connector_id = connector_id;if (!probe) {conn.count_modes = 1;conn.modes_ptr = VOID2U64(&stack_mode);}if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))return 0;retry:counts = conn;if (conn.count_props) {conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));if (!conn.props_ptr)goto err_allocs;conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));if (!conn.prop_values_ptr)goto err_allocs;}if (conn.count_modes) {conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));if (!conn.modes_ptr)goto err_allocs;} else {conn.count_modes = 1;conn.modes_ptr = VOID2U64(&stack_mode);}if (conn.count_encoders) {conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t)));if (!conn.encoders_ptr)goto err_allocs;}if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))goto err_allocs;/* The number of available connectors and etc may have changed with a* hotplug event in between the ioctls, in which case the field is* silently ignored by the kernel.*/if (counts.count_props < conn.count_props ||counts.count_modes < conn.count_modes ||counts.count_encoders < conn.count_encoders) {drmFree(U642VOID(conn.props_ptr));drmFree(U642VOID(conn.prop_values_ptr));if (U642VOID(conn.modes_ptr) != &stack_mode)drmFree(U642VOID(conn.modes_ptr));drmFree(U642VOID(conn.encoders_ptr));goto retry;}if(!(r = drmMalloc(sizeof(*r)))) {goto err_allocs;}r->connector_id = conn.connector_id;r->encoder_id = conn.encoder_id;r->connection = conn.connection;r->mmWidth = conn.mm_width;r->mmHeight = conn.mm_height;/* convert subpixel from kernel to userspace */r->subpixel = conn.subpixel + 1;r->count_modes = conn.count_modes;r->count_props = conn.count_props;r->props = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t));r->prop_values = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t));r->modes = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo));r->count_encoders = conn.count_encoders;r->encoders = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t));r->connector_type = conn.connector_type;r->connector_type_id = conn.connector_type_id;if ((r->count_props && !r->props) ||(r->count_props && !r->prop_values) ||(r->count_modes && !r->modes) ||(r->count_encoders && !r->encoders)) {drmFree(r->props);drmFree(r->prop_values);drmFree(r->modes);drmFree(r->encoders);drmFree(r);r = 0;}err_allocs:drmFree(U642VOID(conn.prop_values_ptr));drmFree(U642VOID(conn.props_ptr));if (U642VOID(conn.modes_ptr) != &stack_mode)drmFree(U642VOID(conn.modes_ptr));drmFree(U642VOID(conn.encoders_ptr));return r;
}
资源释放流程中的其余函数将在后续文章中进行解析。