PowerVR Connection Server

2025-10-30 44 0

Connection Server 代码详细分析

文件概述

文件名: connection_server.c
功能: 服务器端连接管理,处理来自客户端的连接请求和基于连接的信息管理


核心数据结构

CONNECTION_DATA 结构

CONNECTION_DATA {
    - pid: 进程ID
    - vpid: 虚拟进程ID
    - tid: 线程ID
    - pszProcName: 进程名称
    - psHandleBase: 连接句柄基础
    - psProcessHandleBase: 进程句柄基础
    - psSyncConnectionData: 同步连接数据
    - psPDumpConnectionData: PDump连接数据
    - hOsPrivateData: OS私有数据
    - hProcessStats: 进程统计信息
    - hClientTLStream: 客户端TL流
    - ui32ClientFlags: 客户端标志
    - sConnectionListNode: 连接链表节点
    - sCleanupThreadFn: 清理线程函数
}

关键常量定义

#define CONNECTION_CLEANUP_RETRY_TIMEOUT_MS (MAX_HW_TIME_US / 1000 * 240)
  • 作用: 设置清理线程销毁连接资源的最大重试时间
  • 计算: 基于 MAX_HW_TIME_US (通常500-1000ms),结果为2-4分钟

核心函数详细分析

PVRSRVCommonConnectionConnect()

功能: 建立客户端到服务器的连接

流程图

代码流程

  1. 内存分配
    psConnection = OSAllocZMemNoStats(sizeof(*psConnection));
    
    • 使用无统计的分配方式(因为进程尚未注册)
  2. 进程统计注册
    #if defined(PVRSRV_ENABLE_PROCESS_STATS)
    PVRSRVStatsRegisterProcess(&psConnection->hProcessStats);
    #endif
    
  3. OS层初始化
    OSConnectionPrivateDataInit(&psConnection->hOsPrivateData, pvOSData);
    
  4. 设备状态检查
    if (psDevNode->eDevState == PVRSRV_DEVICE_STATE_DEINIT ||
       psDevNode->eDevState == PVRSRV_DEVICE_STATE_DESTRUCTING)
    
  5. 进程信息记录
    psConnection->pid = OSGetCurrentClientProcessIDKM();
    psConnection->vpid = OSGetCurrentVirtualProcessID();
    psConnection->tid = OSGetCurrentClientThreadIDKM();
    OSStringSafeCopy(psConnection->pszProcName, ...);
    
  6. DMA支持初始化 (可选)
    #if defined(SUPPORT_DMA_TRANSFER)
    - 创建DMA请求锁
    - 创建DMA事件对象
    - 初始化DMA子系统
    - 增加引用计数
    #endif
    
  7. 同步系统注册
    SyncRegisterConnection(&psConnection->psSyncConnectionData);
    
  8. PDump注册
    PDumpRegisterConnection(psDevNode,
                          psConnection->psSyncConnectionData,
                          SyncConnectionPDumpSyncBlocks,
                          &psConnection->psPDumpConnectionData);
    
  9. 句柄分配
    PVRSRVAllocHandleBase(&psConnection->psHandleBase,
                        PVRSRV_HANDLE_BASE_TYPE_CONNECTION);
    PVRSRVAcquireProcessHandleBase(&psProcessHandleBase);
    
  10. 加入设备连接列表
    OSLockAcquire(psDevNode->hConnectionsLock);
    dllist_add_to_tail(&psDevNode->sConnections, 
                       &psConnection->sConnectionListNode);
    OSLockRelease(psDevNode->hConnectionsLock);
    

ConnectionDataDestroy()

功能: 销毁连接数据并释放所有关联资源

流程图

重要特性

  1. 重试机制
    • 如果资源正被固件使用,返回 PVRSRV_ERROR_RETRY
    • 允许进行中的工作完成后再进行清理
  2. 资源释放顺序
    HWPerf流 → 句柄基础 → 同步数据 → PDump数据 → 
    设备统计 → OS数据 → 进程统计 → 内存
    
  3. 时间控制
    if (psPVRSRVData->bUnload)
       ui64MaxBridgeTime = 0;  // 驱动卸载时不允许释放桥锁
    else
       ui64MaxBridgeTime = CONNECTION_DEFERRED_CLEANUP_TIMESLICE_NS;
    

PVRSRVCommonConnectionDisconnect()

功能: 断开客户端连接

流程图

DMA清理机制

#if defined(SUPPORT_DMA_TRANSFER)
1. 设置 bAcceptDmaRequests = IMG_FALSE
2. WaitForOutstandingDma() - 等待进行中的传输
3. 减少引用计数
4. 如果引用计数为0,反初始化DMA
5. 销毁事件对象和锁
#endif

延迟清理配置

psConnectionData->sCleanupThreadFn.pfnFree = _CleanupThreadPurgeConnectionData;
psConnectionData->sCleanupThreadFn.pvData = psConnectionData;
psConnectionData->sCleanupThreadFn.bDependsOnHW = IMG_TRUE;
psConnectionData->sCleanupThreadFn.eCleanupType = PVRSRV_CLEANUP_TYPE_CONNECTION;
CLEANUP_THREAD_SET_RETRY_TIMEOUT(&psConnectionData->sCleanupThreadFn,
                                 CONNECTION_CLEANUP_RETRY_TIMEOUT_MS);

WaitForOutstandingDma()

功能: 等待所有未完成的DMA传输完成

实现细节

static void WaitForOutstandingDma(CONNECTION_DATA *psConnectionData)
{
    IMG_UINT32 ui32Tries = 100;  // 最多等待5秒 (100 * 50ms)

    while (OSAtomicRead(&psConnectionData->ui32NumDmaTransfersInFlight) != 0)
    {
        OSSleepms(50);  // 每次睡眠50ms
        if (!ui32Tries)
        {
            // 超时处理
            PVR_DPF((PVR_DBG_ERROR, "Timeout waiting on DMA transfers!"));
            break;
        }
        ui32Tries--;
    }
}

_CleanupThreadPurgeConnectionData()

功能: 清理线程中执行的连接数据清除

流程

static PVRSRV_ERROR _CleanupThreadPurgeConnectionData(void *pvConnectionData)
{
    1. 记录当前清除的连接PID
       gCurrentPurgeConnectionPid = psConnectionData->pid;

    2. 销毁连接数据
       eErrorConnection = ConnectionDataDestroy(psConnectionData);

    3. 检查全局句柄基础是否需要调整大小
       eErrorKernel = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE);

    4. 清除当前PID记录
       gCurrentPurgeConnectionPid = 0;

    5. 返回结果
}

PVRSRVConnectionDebugNotify()

功能: 输出连接调试信息

输出格式

Connections Device ID:X(Y) P<pid>-V<vpid>-T<tid>-<process_name>, ...

特性

  1. 批量显示: 将多个连接信息组合在一行
  2. 智能换行: 当剩余空间不足时自动换行
  3. 缩进保持: 后续行保持相同缩进
  4. 线程安全: 使用 hConnectionsLock 保护

系统架构图


连接生命周期


关键机制说明

句柄管理

两级句柄系统:
1. 连接句柄基础 (psHandleBase)
- 类型: PVRSRV_HANDLE_BASE_TYPE_CONNECTION
- 生命周期: 绑定到单个连接

  1. 进程句柄基础 (psProcessHandleBase)
    • 跨连接共享
    • 引用计数管理

重试机制

触发条件:
- 固件正在处理工作负载
- 资源正被使用无法立即释放

实现:

if (PVRSRVIsRetryError(eError))
{
    return eError;  // 通知调用者重试
}

超时设置:

CONNECTION_CLEANUP_RETRY_TIMEOUT_MS = (MAX_HW_TIME_US / 1000 * 240)
// 通常为 2-4 分钟

DMA传输管理

引用计数机制:

if (psDevNode->ui32RefCountDMA == 0)
    PVRSRVInitialiseDMA(psDevNode);
psDevNode->ui32RefCountDMA++;

// 断开时
if (--psDevNode->ui32RefCountDMA == 0)
    PVRSRVDeInitialiseDMA(psDevNode);

传输跟踪:

OSAtomicWrite(&psConnection->ui32NumDmaTransfersInFlight, 0);
psConnection->bAcceptDmaRequests = IMG_TRUE;

同步与PDump

注册顺序:
1. 注册同步连接
2. 使用同步数据注册PDump
3. PDump回调: SyncConnectionPDumpSyncBlocks

HWPerf主机流

连接通知:

if (TLStreamIsOpenForReading(psRgxDevInfo->hHWPerfHostStream))
{
    RGXSRV_HWPERF_HOST_CLIENT_INFO_PROCESS_NAME(
        psDevNode, 
        psConnection->pid, 
        psConnection->pszProcName
    );
}

错误处理策略

连接建立失败

failure:
    ConnectionDataDestroy(psConnection);
    return eError;
  • 清理已分配的所有资源
  • 返回错误码

断开连接失败

if (PVRSRVIsRetryError(eErrorConnection))
{
    // 延迟销毁,稍后重试
}
  • 加入清理线程队列
  • 定期重试

DMA超时处理

if (!ui32Tries)
{
    PVR_DPF((PVR_DBG_ERROR, "Timeout waiting on DMA!"));
    break;  // 强制继续,记录错误
}

线程安全

锁的使用

  1. 连接链表锁 (hConnectionsLock)
    OSLockAcquire(psDevNode->hConnectionsLock);
    dllist_add_to_tail(&psDevNode->sConnections, ...);
    OSLockRelease(psDevNode->hConnectionsLock);
    
  2. DMA请求锁 (hDmaReqLock)
    OSLockAcquire(psConnectionData->hDmaReqLock);
    psConnectionData->bAcceptDmaRequests = IMG_FALSE;
    OSLockRelease(psConnectionData->hDmaReqLock);
    
  3. HWPerf流锁 (hLockHWPerfHostStream)
    OSLockAcquire(psRgxDevInfo->hLockHWPerfHostStream);
    bHostStreamIsNull = (psRgxDevInfo->hHWPerfHostStream == NULL);
    OSLockRelease(psRgxDevInfo->hLockHWPerfHostStream);
    

原子操作

OSAtomicWrite(&psConnection->ui32NumDmaTransfersInFlight, 0);
OSAtomicRead(&psConnectionData->ui32NumDmaTransfersInFlight);

性能考虑

内存分配策略

  1. 初期分配: 使用 OSAllocZMemNoStats (无统计开销)
  2. 后期分配: 进程注册后使用正常分配

延迟清理

CONNECTION_DEFERRED_CLEANUP_TIMESLICE_NS
  • 避免长时间持有桥锁
  • 分时段清理资源

批量操作

  • 调试输出时批量处理连接信息
  • 减少锁的获取次数

调试支持

日志级别

PVR_DPF((PVR_DBG_MESSAGE, ...));  // 消息
PVR_DPF((PVR_DBG_ERROR, ...));    // 错误
PVR_DPF((PVR_DBG_DEBUG, ...));    // 调试

调试宏

#if defined(DEBUG) || defined(PDUMP)
PVR_LOG(("%s connected - (devID = %u)", ...));
#endif

连接信息转储

PVRSRVConnectionDebugNotify()
  • 输出所有活动连接
  • 包含进程ID、虚拟PID、线程ID和进程名

编译选项

宏定义 功能
PVRSRV_ENABLE_PROCESS_STATS 启用进程统计
PVRSRV_DEBUG_LINUX_MEMORY_STATS Linux内存统计调试
SUPPORT_DMA_TRANSFER DMA传输支持
PVRSRV_ENABLE_GPU_MEMORY_INFO GPU内存信息
SUPPORT_PMR_DEFERRED_FREE PMR延迟释放
PVRSRV_FORCE_UNLOAD_IF_BAD_STATE 强制卸载
DEBUG / PDUMP 调试和PDump
DMA_VERBOSE DMA详细日志

总结

核心职责

  1. 连接管理: 建立、维护、断开客户端连接
  2. 资源分配: 句柄、内存、子系统注册
  3. 生命周期管理: 优雅的资源清理和重试机制
  4. 调试支持: 完善的日志和信息转储

设计亮点

  1. 延迟清理机制: 避免阻塞主流程
  2. 重试策略: 处理固件繁忙情况
  3. 两级句柄系统: 连接级和进程级
  4. 线程安全: 完善的锁保护
  5. 错误恢复: 失败时完整清理

关键流程时序

Connect: 分配 → 初始化 → 注册 → 加入列表
Disconnect: 移除 → 通知 → 标记 → 延迟清理
Cleanup: 检查 → 销毁 → 重试 → 完成

性能特性

  • 无锁原子操作
  • 分时段资源释放
  • 批量操作优化
  • 最小化临界区

使用建议

  1. 连接建立: 确保检查返回值,处理失败情况
  2. 资源清理: 依赖延迟清理机制,不要同步等待
  3. DMA操作: 断开前确保所有传输完成
  4. 调试: 使用 PVRSRVConnectionDebugNotify 查看活动连接
  5. 异常处理: 注意 PVRSRV_ERROR_RETRY 的特殊含义

文档生成时间: 2025-10-30
基于源文件: connection_server.c

相关文章

PowerVR Rogue ZS Buffer
PowerVR RGX Parameter Buffer And Ring Buffer
PowerVR Rogue FreeList
PowerVR RGX Firmware Utils
PowerVR RGX BVNC
PowerVR RGX Multicore

发布评论