PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va) { IMG_UINT32 *pui32StrLen; IMG_INT32 *pi32Count; IMG_CHAR **ppszStr; pui32StrLen = va_arg(va, IMG_UINT32*); pi32Count = va_arg(va, IMG_INT32*); ppszStr = va_arg(va, IMG_CHAR**); CHECK_SPACE(*pui32StrLen); *pi32Count = OSSNPrintf(*ppszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType); UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen); if(psDeviceNode->sDevMemoryInfo.pBMKernelContext) { CHECK_SPACE(*pui32StrLen); *pi32Count = OSSNPrintf(*ppszStr, 100, "\nKernel Context:\n"); UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen); List_BM_HEAP_ForEach_va(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psBMHeap, PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb, ppszStr, pui32StrLen); } return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.pBMContext, PVRSRVGetMiscInfoKM_BMContext_AnyVaCb, pui32StrLen, pi32Count, ppszStr); }
static PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContext, va_list va) { IMG_UINT32 *pui32StrLen; IMG_INT32 *pi32Count; IMG_CHAR **ppszStr; IMG_UINT32 ui32Mode; pui32StrLen = va_arg(va, IMG_UINT32*); pi32Count = va_arg(va, IMG_INT32*); ppszStr = va_arg(va, IMG_CHAR**); ui32Mode = va_arg(va, IMG_UINT32); CHECK_SPACE(*pui32StrLen); *pi32Count = OSSNPrintf(*ppszStr, 100, "\nApplication Context (hDevMemContext) %p:\n", (IMG_HANDLE)psBMContext); UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen); List_BM_HEAP_ForEach_va(psBMContext->psBMHeap, &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb, ppszStr, pui32StrLen, ui32Mode); return PVRSRV_OK; }
/* Locate a record in a VPD blob * * Note: This works with VPD LIDs. It will scan until it finds * the first 0x84, so it will skip all those 0's that the VPD * LIDs seem to contain */ const void *vpd_find_record(const void *vpd, size_t vpd_size, const char *record, size_t *sz) { const uint8_t *p = vpd, *end = vpd + vpd_size; bool first_start = true; size_t rec_sz; uint8_t namesz = 0; const char *rec_name; if (!vpd) return NULL; while (CHECK_SPACE(p, 4, end)) { /* Get header byte */ if (*(p++) != 0x84) { /* Skip initial crap in VPD LIDs */ if (first_start) continue; break; } first_start = false; rec_sz = *(p++); rec_sz |= *(p++) << 8; if (!CHECK_SPACE(p, rec_sz, end)) { prerror("VPD: Malformed or truncated VPD," " record size doesn't fit\n"); return NULL; } /* Find record name */ rec_name = vpd_find_keyword(p, rec_sz, "RT", &namesz); if (rec_name && strncmp(record, rec_name, namesz) == 0) { *sz = rec_sz; return p; } p += rec_sz; if (*(p++) != 0x78) { prerror("VPD: Malformed or truncated VPD," " missing final 0x78 in record %.4s\n", rec_name ? rec_name : "????"); return NULL; } } return NULL; }
/* Low level keyword search in a record. Can be used when we * need to find the next keyword of a given type, for example * when having multiple MF/SM keyword pairs */ const void *vpd_find_keyword(const void *rec, size_t rec_sz, const char *kw, uint8_t *kw_size) { const uint8_t *p = rec, *end = rec + rec_sz; while (CHECK_SPACE(p, 3, end)) { uint8_t k1 = *(p++); uint8_t k2 = *(p++); uint8_t sz = *(p++); if (k1 == kw[0] && k2 == kw[1]) { if (kw_size) *kw_size = sz; return p; } p += sz; } return NULL; }
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo) #endif { SYS_DATA *psSysData; if(!psMiscInfo) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psMiscInfo->ui32StatePresent = 0; if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT |PVRSRV_MISC_INFO_MEMSTATS_PRESENT |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT |PVRSRV_MISC_INFO_DDKVERSION_PRESENT |PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT |PVRSRV_MISC_INFO_RESET_PRESENT |PVRSRV_MISC_INFO_FREEMEM_PRESENT |PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT)) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags")); return PVRSRV_ERROR_INVALID_PARAMS; } SysAcquireData(&psSysData); if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) && (psSysData->pvSOCTimerRegisterKM != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT; psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM; psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle; } else { psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL; psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL; } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) && (psSysData->pvSOCClockGateRegsBase != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT; psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase; psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize; } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { RA_ARENA **ppArena; IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT; ppArena = &psSysData->apsLocalDevMemArena[0]; while(*ppArena) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); RA_GetStats(*ppArena, &pszStr, &ui32StrLen); ppArena++; } List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, &PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr, PVRSRV_MISC_INFO_MEMSTATS_PRESENT); i32Count = OSSNPrintf(pszStr, 100, "\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0) && psMiscInfo->pszMemoryStr) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT; List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, &PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr, PVRSRV_MISC_INFO_FREEMEM_PRESENT); i32Count = OSSNPrintf(pszStr, 100, "\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) && (psSysData->psGlobalEventObject != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT; psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject; } if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL) && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_UINT32 ui32LenStrPerNum = 12; IMG_INT32 i32Count; IMG_INT i; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT; psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ; psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN; psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BUILD_HI; psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD_LO; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; for (i=0; i<4; i++) { if (ui32StrLen < ui32LenStrPerNum) { return PVRSRV_ERROR_INVALID_PARAMS; } i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); if (i != 3) { i32Count = OSSNPrintf(pszStr, 2, "."); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } } } if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT; if(psMiscInfo->sCacheOpCtl.bDeferOp) { psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType; } else { #if defined (SUPPORT_SID_INTERFACE) PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = psMiscInfo->sCacheOpCtl.psKernelMemInfo; if(!psMiscInfo->sCacheOpCtl.psKernelMemInfo) #else PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; PVRSRV_PER_PROCESS_DATA *psPerProc; if(!psMiscInfo->sCacheOpCtl.u.psKernelMemInfo) #endif { PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " "Ignoring non-deferred cache op with no meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " "Deferred cache op is pending. It is unlikely you want " "to combine deferred cache ops with immediate ones")); } #if defined (SUPPORT_SID_INTERFACE) PVR_DBG_BREAK #else psPerProc = PVRSRVFindPerProcessData(); if(PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_PVOID *)&psKernelMemInfo, psMiscInfo->sCacheOpCtl.u.psKernelMemInfo, PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: " "Can't find kernel meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } #endif if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) { if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, psMiscInfo->sCacheOpCtl.pvBaseVAddr, psMiscInfo->sCacheOpCtl.ui32Length)) { return PVRSRV_ERROR_CACHEOP_FAILED; } } else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) { /*if(psMiscInfo->sCacheOpCtl.bStridedCacheOp == IMG_TRUE) { IMG_BYTE *pbRowStart, *pbRowEnd, *pbRowThresh; IMG_UINT32 ui32Stride; pbRowStart = psMiscInfo->sCacheOpCtl.pbRowStart; pbRowEnd = psMiscInfo->sCacheOpCtl.pbRowEnd; pbRowThresh = psMiscInfo->sCacheOpCtl.pbRowThresh; ui32Stride = psMiscInfo->sCacheOpCtl.ui32Stride; do { if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, (IMG_VOID *)pbRowStart, (IMG_UINT32)(pbRowEnd - pbRowStart))) { return PVRSRV_ERROR_CACHEOP_FAILED; } pbRowStart += ui32Stride; pbRowEnd += ui32Stride; } while(pbRowEnd <= pbRowThresh); } else { if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, psMiscInfo->sCacheOpCtl.pvBaseVAddr, psMiscInfo->sCacheOpCtl.ui32Length)) { return PVRSRV_ERROR_CACHEOP_FAILED; } }*/ if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, psMiscInfo->sCacheOpCtl.pvBaseVAddr, psMiscInfo->sCacheOpCtl.ui32Length)) return PVRSRV_ERROR_CACHEOP_FAILED; } } } if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT) != 0UL) { #if !defined (SUPPORT_SID_INTERFACE) PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; PVRSRV_PER_PROCESS_DATA *psPerProc; #endif psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT; #if defined (SUPPORT_SID_INTERFACE) PVR_DBG_BREAK #else psPerProc = PVRSRVFindPerProcessData(); if(PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_PVOID *)&psKernelMemInfo, psMiscInfo->sGetRefCountCtl.u.psKernelMemInfo, PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: " "Can't find kernel meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } psMiscInfo->sGetRefCountCtl.ui32RefCount = psKernelMemInfo->ui32RefCount; #endif } #if defined(PVRSRV_RESET_ON_HWTIMEOUT) if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL) { PVR_LOG(("User requested OS reset")); OSPanic(); } #endif return PVRSRV_OK; }
IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo) { SYS_DATA *psSysData; if(!psMiscInfo) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psMiscInfo->ui32StatePresent = 0; if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT |PVRSRV_MISC_INFO_MEMSTATS_PRESENT |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT |PVRSRV_MISC_INFO_DDKVERSION_PRESENT |PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT |PVRSRV_MISC_INFO_RESET_PRESENT |PVRSRV_MISC_INFO_FREEMEM_PRESENT)) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags")); return PVRSRV_ERROR_INVALID_PARAMS; } SysAcquireData(&psSysData); if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) && (psSysData->pvSOCTimerRegisterKM != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT; psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM; psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle; } else { psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL; psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL; } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) && (psSysData->pvSOCClockGateRegsBase != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT; psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase; psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize; } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { RA_ARENA **ppArena; IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT; ppArena = &psSysData->apsLocalDevMemArena[0]; while(*ppArena) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); RA_GetStats(*ppArena, &pszStr, &ui32StrLen); ppArena++; } List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, &PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr, PVRSRV_MISC_INFO_MEMSTATS_PRESENT); i32Count = OSSNPrintf(pszStr, 100, "\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) && psMiscInfo->pszMemoryStr) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT; List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, &PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr, PVRSRV_MISC_INFO_FREEMEM_PRESENT); i32Count = OSSNPrintf(pszStr, 100, "\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) && (psSysData->psGlobalEventObject != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT; psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject; } if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL) && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_UINT32 ui32LenStrPerNum = 12; IMG_INT32 i32Count; PVRSRV_SGXDEV_INFO *sgx_dev_info; PVRSRV_SGX_MISCINFO_INFO *sgx_misc_info; PVRSRV_SGX_MISCINFO_FEATURES *sgx_features; unsigned long fw_ver; IMG_INT i; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT; /* * Since the kernel driver has already made sure that the * firmware version is supported by the kernel driver in * SGXDevInitCompatCheck, it's redundant for the user space * part to perform the same check. In order to support older * user space libraries where this check hasn't yet been removed, * simply report the version of the downloaded firmware which * will result in an exact match in user space. */ sgx_dev_info = pvr_get_sgx_dev_info(); if (!sgx_dev_info || !sgx_dev_info->psKernelSGXMiscMemInfo || !sgx_dev_info->psKernelSGXMiscMemInfo->pvLinAddrKM) return PVRSRV_ERROR_INVALID_DEVICE; sgx_misc_info = sgx_dev_info->psKernelSGXMiscMemInfo->pvLinAddrKM; sgx_features = &sgx_misc_info->sSGXFeatures; fw_ver = sgx_features->ui32DDKVersion; psMiscInfo->aui32DDKVersion[0] = PVR_FW_VER_MAJOR(fw_ver); psMiscInfo->aui32DDKVersion[1] = PVR_FW_VER_MINOR(fw_ver); psMiscInfo->aui32DDKVersion[2] = PVR_FW_VER_BRANCH(fw_ver); psMiscInfo->aui32DDKVersion[3] = sgx_features->ui32DDKBuild; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; for (i=0; i<4; i++) { if (ui32StrLen < ui32LenStrPerNum) { return PVRSRV_ERROR_INVALID_PARAMS; } i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); if (i != 3) { i32Count = OSSNPrintf(pszStr, 2, "."); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } } } if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT; if(psMiscInfo->sCacheOpCtl.bDeferOp) { psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType; } else { PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; PVRSRV_PER_PROCESS_DATA *psPerProc; if(!psMiscInfo->sCacheOpCtl.u.psKernelMemInfo) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " "Ignoring non-deferred cache op with no meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " "Deferred cache op is pending. It is unlikely you want " "to combine deferred cache ops with immediate ones")); } psPerProc = PVRSRVFindPerProcessData(); if(PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_PVOID *)&psKernelMemInfo, psMiscInfo->sCacheOpCtl.u.psKernelMemInfo, PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: " "Can't find kernel meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) { if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, psMiscInfo->sCacheOpCtl.pvBaseVAddr, psMiscInfo->sCacheOpCtl.ui32Length)) { return PVRSRV_ERROR_CACHEOP_FAILED; } } else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) { if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, psMiscInfo->sCacheOpCtl.pvBaseVAddr, psMiscInfo->sCacheOpCtl.ui32Length)) { return PVRSRV_ERROR_CACHEOP_FAILED; } } } } #if defined(PVRSRV_RESET_ON_HWTIMEOUT) if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL) { PVR_LOG(("User requested OS reset")); OSPanic(); } #endif return PVRSRV_OK; }
/** The event occurs when an updating statement is done. */ Query_event::Query_event(const char* buf, unsigned int event_len, const Format_description_event *description_event, Log_event_type event_type) : Binary_log_event(&buf, description_event->binlog_version, description_event->server_version), query(0), db(0), catalog(0), time_zone_str(0), user(0), user_len(0), host(0), host_len(0), db_len(0), status_vars_len(0), q_len(0), flags2_inited(0), sql_mode_inited(0), charset_inited(0), auto_increment_increment(1), auto_increment_offset(1), time_zone_len(0), catalog_len(0), lc_time_names_number(0), charset_database_number(0), table_map_for_update(0), master_data_written(0), mts_accessed_dbs(OVER_MAX_DBS_IN_EVENT_MTS), last_committed(SEQ_UNINIT), sequence_number(SEQ_UNINIT) { //buf is advanced in Binary_log_event constructor to point to //beginning of post-header uint32_t tmp; uint8_t common_header_len, post_header_len; Log_event_header::Byte *start; const Log_event_header::Byte *end; query_data_written= 0; common_header_len= description_event->common_header_len; post_header_len= description_event->post_header_len[event_type - 1]; /* We test if the event's length is sensible, and if so we compute data_len. We cannot rely on QUERY_HEADER_LEN here as it would not be format-tolerant. We use QUERY_HEADER_MINIMAL_LEN which is the same for 3.23, 4.0 & 5.0. */ if (event_len < (unsigned int)(common_header_len + post_header_len)) return; data_len= event_len - (common_header_len + post_header_len); memcpy(&thread_id, buf + Q_THREAD_ID_OFFSET, sizeof(thread_id)); thread_id= le32toh(thread_id); memcpy(&query_exec_time, buf + Q_EXEC_TIME_OFFSET, sizeof(query_exec_time)); query_exec_time= le32toh(query_exec_time); db_len= (unsigned int)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars memcpy(&error_code, buf + Q_ERR_CODE_OFFSET, sizeof(error_code)); error_code= le16toh(error_code); /* 5.0 format starts here. Depending on the format, we may or not have affected/warnings etc The remnent post-header to be parsed has length: */ tmp= post_header_len - QUERY_HEADER_MINIMAL_LEN; if (tmp) { memcpy(&status_vars_len, buf + Q_STATUS_VARS_LEN_OFFSET, sizeof(status_vars_len)); status_vars_len= le16toh(status_vars_len); /* Check if status variable length is corrupt and will lead to very wrong data. We could be even more strict and require data_len to be even bigger, but this will suffice to catch most corruption errors that can lead to a crash. */ if (status_vars_len > std::min<unsigned long>(data_len, MAX_SIZE_LOG_EVENT_STATUS)) { query= 0; return; } data_len-= status_vars_len; tmp-= 2; } else { /* server version < 5.0 / binlog_version < 4 master's event is relay-logged with storing the original size of the event in Q_MASTER_DATA_WRITTEN_CODE status variable. The size is to be restored at reading Q_MASTER_DATA_WRITTEN_CODE-marked event from the relay log. */ BAPI_ASSERT(description_event->binlog_version < 4); master_data_written= header()->data_written; } /* We have parsed everything we know in the post header for QUERY_EVENT, the rest of post header is either comes from older version MySQL or dedicated to derived events (e.g. Execute_load_query...) */ /* variable-part: the status vars; only in MySQL 5.0 */ start= (Log_event_header::Byte*) (buf + post_header_len); end= (const Log_event_header::Byte*) (start + status_vars_len); for (const Log_event_header::Byte* pos= start; pos < end;) { switch (*pos++) { case Q_FLAGS2_CODE: CHECK_SPACE(pos, end, 4); flags2_inited= 1; memcpy(&flags2, pos, sizeof(flags2)); flags2= le32toh(flags2); pos+= 4; break; case Q_SQL_MODE_CODE: { CHECK_SPACE(pos, end, 8); sql_mode_inited= 1; memcpy(&sql_mode, pos, sizeof(sql_mode)); sql_mode= le64toh(sql_mode); pos+= 8; break; } case Q_CATALOG_NZ_CODE: if ((catalog_len= *pos)) catalog= (const char*) (pos + 1); CHECK_SPACE(pos, end, catalog_len + 1); pos+= catalog_len + 1; break; case Q_AUTO_INCREMENT: CHECK_SPACE(pos, end, 4); memcpy(&auto_increment_increment, pos, sizeof(auto_increment_increment)); auto_increment_increment= le16toh(auto_increment_increment); memcpy(&auto_increment_offset, pos + 2, sizeof(auto_increment_offset)); auto_increment_offset= le16toh(auto_increment_offset); pos+= 4; break; case Q_CHARSET_CODE: { CHECK_SPACE(pos, end, 6); charset_inited= 1; memcpy(charset, pos, 6); pos+= 6; break; } case Q_TIME_ZONE_CODE: { if ((time_zone_len= *pos)) time_zone_str= (const char*)(pos + 1); pos+= time_zone_len + 1; break; } case Q_CATALOG_CODE: /* for 5.0.x where 0<=x<=3 masters */ CHECK_SPACE(pos, end, 1); if ((catalog_len= *pos)) catalog= (const char*) (pos+1); CHECK_SPACE(pos, end, catalog_len + 2); pos+= catalog_len + 2; // leap over end 0 break; case Q_LC_TIME_NAMES_CODE: CHECK_SPACE(pos, end, 2); memcpy(&lc_time_names_number, pos, sizeof(lc_time_names_number)); lc_time_names_number= le16toh(lc_time_names_number); pos+= 2; break; case Q_CHARSET_DATABASE_CODE: CHECK_SPACE(pos, end, 2); memcpy(&charset_database_number, pos, sizeof(lc_time_names_number)); charset_database_number= le16toh(charset_database_number); pos+= 2; break; case Q_TABLE_MAP_FOR_UPDATE_CODE: CHECK_SPACE(pos, end, 8); memcpy(&table_map_for_update, pos, sizeof(table_map_for_update)); table_map_for_update= le64toh(table_map_for_update); pos+= 8; break; case Q_MASTER_DATA_WRITTEN_CODE: CHECK_SPACE(pos, end, 4); memcpy(&master_data_written, pos, sizeof(master_data_written)); master_data_written= le32toh(static_cast<uint32_t>(master_data_written)); header()->data_written= master_data_written; pos+= 4; break; case Q_MICROSECONDS: { CHECK_SPACE(pos, end, 3); uint32_t temp_usec= 0; memcpy(&temp_usec, pos, 3); header()->when.tv_usec= le32toh(temp_usec); pos+= 3; break; } case Q_INVOKER: { CHECK_SPACE(pos, end, 1); user_len= *pos++; CHECK_SPACE(pos, end, user_len); user= (const char*)pos; pos+= user_len; CHECK_SPACE(pos, end, 1); host_len= *pos++; CHECK_SPACE(pos, end, host_len); host= (const char*)pos; pos+= host_len; break; } case Q_UPDATED_DB_NAMES: { unsigned char i= 0; #ifndef DBUG_OFF bool is_corruption_injected= false; #endif CHECK_SPACE(pos, end, 1); mts_accessed_dbs= *pos++; /* Notice, the following check is positive also in case of the master's MAX_DBS_IN_EVENT_MTS > the slave's one and the event contains e.g the master's MAX_DBS_IN_EVENT_MTS db:s. */ if (mts_accessed_dbs > MAX_DBS_IN_EVENT_MTS) { mts_accessed_dbs= OVER_MAX_DBS_IN_EVENT_MTS; break; } BAPI_ASSERT(mts_accessed_dbs != 0); for (i= 0; i < mts_accessed_dbs && pos < start + status_vars_len; i++) { #ifndef DBUG_OFF /* This is specific to mysql test run on the server for the keyword "query_log_event_mts_corrupt_db_names" */ if (binary_log_debug::debug_query_mts_corrupt_db_names) { if (mts_accessed_dbs == 2) { BAPI_ASSERT(pos[sizeof("d?") - 1] == 0); ((char*) pos)[sizeof("d?") - 1]= 'a'; is_corruption_injected= true; } } #endif strncpy(mts_accessed_db_names[i], (char*) pos, std::min<unsigned long>(NAME_LEN, start + status_vars_len - pos)); mts_accessed_db_names[i][NAME_LEN - 1]= 0; pos+= 1 + strlen((const char*) pos); } if (i != mts_accessed_dbs #ifndef DBUG_OFF || is_corruption_injected #endif ) return; break; } case Q_COMMIT_TS2: CHECK_SPACE(pos, end, COMMIT_SEQ_LEN); last_committed= 0; memcpy(&last_committed, pos, 8); last_committed= le64toh(last_committed); sequence_number= 0; memcpy(&sequence_number, pos + 8, 8); sequence_number= le64toh(sequence_number); pos+= COMMIT_SEQ_LEN; break; default: /* That's why you must write status vars in growing order of code */ pos= (const unsigned char*) end; // Break loop } } if (catalog_len) // If catalog is given query_data_written+= catalog_len + 1; if (time_zone_len) query_data_written+= time_zone_len + 1; if (user_len > 0) query_data_written+= user_len + 1; if (host_len > 0) query_data_written+= host_len + 1; /* if time_zone_len or catalog_len are 0, then time_zone and catalog are uninitialized at this point. shouldn't they point to the zero-length null-terminated strings we allocated space for in the my_alloc call above? /sven */ /* A 2nd variable part; this is common to all versions */ query_data_written+= data_len + 1; db= (const char* )end; q_len= data_len - db_len -1; start[status_vars_len + data_len]= '\0'; query= (const char *)(end + db_len + 1); return; }
Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError &r_err, CallState *p_state) { if (!_code_ptr) { return Variant(); } r_err.error = Variant::CallError::CALL_OK; Variant self; Variant retvalue; Variant *stack = NULL; Variant **call_args; int defarg = 0; #ifdef DEBUG_ENABLED //GDScriptLanguage::get_singleton()->calls++; #endif uint32_t alloca_size = 0; GDScript *_class; int ip = 0; int line = _initial_line; if (p_state) { //use existing (supplied) state (yielded) stack = (Variant *)p_state->stack.ptr(); call_args = (Variant **)stack + sizeof(Variant) * p_state->stack_size; line = p_state->line; ip = p_state->ip; alloca_size = p_state->stack.size(); _class = p_state->_class; p_instance = p_state->instance; defarg = p_state->defarg; self = p_state->self; //stack[p_state->result_pos]=p_state->result; //assign stack with result } else { if (p_argcount != _argument_count) { if (p_argcount > _argument_count) { r_err.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; r_err.argument = _argument_count; return Variant(); } else if (p_argcount < _argument_count - _default_arg_count) { r_err.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_err.argument = _argument_count - _default_arg_count; return Variant(); } else { defarg = _argument_count - p_argcount; } } alloca_size = sizeof(Variant *) * _call_size + sizeof(Variant) * _stack_size; if (alloca_size) { uint8_t *aptr = (uint8_t *)alloca(alloca_size); if (_stack_size) { stack = (Variant *)aptr; for (int i = 0; i < p_argcount; i++) memnew_placement(&stack[i], Variant(*p_args[i])); for (int i = p_argcount; i < _stack_size; i++) memnew_placement(&stack[i], Variant); } else { stack = NULL; } if (_call_size) { call_args = (Variant **)&aptr[sizeof(Variant) * _stack_size]; } else { call_args = NULL; } } else { stack = NULL; call_args = NULL; } if (p_instance) { if (p_instance->base_ref && static_cast<Reference *>(p_instance->owner)->is_referenced()) { self = REF(static_cast<Reference *>(p_instance->owner)); } else { self = p_instance->owner; } _class = p_instance->script.ptr(); } else { _class = _script; } } String err_text; #ifdef DEBUG_ENABLED if (ScriptDebugger::get_singleton()) GDScriptLanguage::get_singleton()->enter_function(p_instance, this, stack, &ip, &line); #define CHECK_SPACE(m_space) \ ERR_BREAK((ip + m_space) > _code_size) #define GET_VARIANT_PTR(m_v, m_code_ofs) \ Variant *m_v; \ m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, _class, self, stack, err_text); \ if (!m_v) \ break; #else #define CHECK_SPACE(m_space) #define GET_VARIANT_PTR(m_v, m_code_ofs) \ Variant *m_v; \ m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, _class, self, stack, err_text); #endif #ifdef DEBUG_ENABLED uint64_t function_start_time; uint64_t function_call_time; if (GDScriptLanguage::get_singleton()->profiling) { function_start_time = OS::get_singleton()->get_ticks_usec(); function_call_time = 0; profile.call_count++; profile.frame_call_count++; } #endif bool exit_ok = false; while (ip < _code_size) { int last_opcode = _code_ptr[ip]; switch (_code_ptr[ip]) { case OPCODE_OPERATOR: { CHECK_SPACE(5); bool valid; Variant::Operator op = (Variant::Operator)_code_ptr[ip + 1]; ERR_BREAK(op >= Variant::OP_MAX); GET_VARIANT_PTR(a, 2); GET_VARIANT_PTR(b, 3); GET_VARIANT_PTR(dst, 4); #ifdef DEBUG_ENABLED Variant ret; Variant::evaluate(op, *a, *b, ret, valid); #else Variant::evaluate(op, *a, *b, *dst, valid); #endif if (!valid) { #ifdef DEBUG_ENABLED if (ret.get_type() == Variant::STRING) { //return a string when invalid with the error err_text = ret; err_text += " in operator '" + Variant::get_operator_name(op) + "'."; } else { err_text = "Invalid operands '" + Variant::get_type_name(a->get_type()) + "' and '" + Variant::get_type_name(b->get_type()) + "' in operator '" + Variant::get_operator_name(op) + "'."; } #endif break; } #ifdef DEBUG_ENABLED *dst = ret; #endif ip += 5; continue; } case OPCODE_EXTENDS_TEST: { CHECK_SPACE(4); GET_VARIANT_PTR(a, 1); GET_VARIANT_PTR(b, 2); GET_VARIANT_PTR(dst, 3); #ifdef DEBUG_ENABLED if (a->get_type() != Variant::OBJECT || a->operator Object *() == NULL) { err_text = "Left operand of 'extends' is not an instance of anything."; break; } if (b->get_type() != Variant::OBJECT || b->operator Object *() == NULL) { err_text = "Right operand of 'extends' is not a class."; break; } #endif Object *obj_A = *a; Object *obj_B = *b; GDScript *scr_B = obj_B->cast_to<GDScript>(); bool extends_ok = false; if (scr_B) { //if B is a script, the only valid condition is that A has an instance which inherits from the script //in other situation, this shoul return false. if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language() == GDScriptLanguage::get_singleton()) { GDScript *cmp = static_cast<GDScript *>(obj_A->get_script_instance()->get_script().ptr()); //bool found=false; while (cmp) { if (cmp == scr_B) { //inherits from script, all ok extends_ok = true; break; } cmp = cmp->_base; } } } else { GDNativeClass *nc = obj_B->cast_to<GDNativeClass>(); if (!nc) { err_text = "Right operand of 'extends' is not a class (type: '" + obj_B->get_class() + "')."; break; } extends_ok = ClassDB::is_parent_class(obj_A->get_class_name(), nc->get_name()); } *dst = extends_ok; ip += 4; continue; } case OPCODE_SET: { CHECK_SPACE(3); GET_VARIANT_PTR(dst, 1); GET_VARIANT_PTR(index, 2); GET_VARIANT_PTR(value, 3); bool valid; dst->set(*index, *value, &valid); if (!valid) { String v = index->operator String(); if (v != "") { v = "'" + v + "'"; } else { v = "of type '" + _get_var_type(index) + "'"; } err_text = "Invalid set index " + v + " (on base: '" + _get_var_type(dst) + "')."; break; } ip += 4; continue; } case OPCODE_GET: { CHECK_SPACE(3); GET_VARIANT_PTR(src, 1); GET_VARIANT_PTR(index, 2); GET_VARIANT_PTR(dst, 3); bool valid; #ifdef DEBUG_ENABLED //allow better error message in cases where src and dst are the same stack position Variant ret = src->get(*index, &valid); #else *dst = src->get(*index, &valid); #endif if (!valid) { String v = index->operator String(); if (v != "") { v = "'" + v + "'"; } else { v = "of type '" + _get_var_type(index) + "'"; } err_text = "Invalid get index " + v + " (on base: '" + _get_var_type(src) + "')."; break; } #ifdef DEBUG_ENABLED *dst = ret; #endif ip += 4; continue; } case OPCODE_SET_NAMED: { CHECK_SPACE(3); GET_VARIANT_PTR(dst, 1); GET_VARIANT_PTR(value, 3); int indexname = _code_ptr[ip + 2]; ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; bool valid; dst->set_named(*index, *value, &valid); if (!valid) { String err_type; err_text = "Invalid set index '" + String(*index) + "' (on base: '" + _get_var_type(dst) + "')."; break; } ip += 4; continue; } case OPCODE_GET_NAMED: { CHECK_SPACE(4); GET_VARIANT_PTR(src, 1); GET_VARIANT_PTR(dst, 3); int indexname = _code_ptr[ip + 2]; ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; bool valid; #ifdef DEBUG_ENABLED //allow better error message in cases where src and dst are the same stack position Variant ret = src->get_named(*index, &valid); #else *dst = src->get_named(*index, &valid); #endif if (!valid) { if (src->has_method(*index)) { err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "'). Did you mean '." + index->operator String() + "()' ?"; } else { err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "')."; } break; } #ifdef DEBUG_ENABLED *dst = ret; #endif ip += 4; continue; } case OPCODE_SET_MEMBER: { CHECK_SPACE(3); int indexname = _code_ptr[ip + 1]; ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; GET_VARIANT_PTR(src, 2); bool valid; bool ok = ClassDB::set_property(p_instance->owner, *index, *src, &valid); #ifdef DEBUG_ENABLED if (!ok) { err_text = "Internal error setting property: " + String(*index); break; } else if (!valid) { err_text = "Error setting property '" + String(*index) + "' with value of type " + Variant::get_type_name(src->get_type()) + "."; break; } #endif ip += 3; continue; } case OPCODE_GET_MEMBER: { CHECK_SPACE(3); int indexname = _code_ptr[ip + 1]; ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; GET_VARIANT_PTR(dst, 2); bool ok = ClassDB::get_property(p_instance->owner, *index, *dst); #ifdef DEBUG_ENABLED if (!ok) { err_text = "Internal error getting property: " + String(*index); break; } #endif ip += 3; continue; } case OPCODE_ASSIGN: { CHECK_SPACE(3); GET_VARIANT_PTR(dst, 1); GET_VARIANT_PTR(src, 2); *dst = *src; ip += 3; continue; } case OPCODE_ASSIGN_TRUE: { CHECK_SPACE(2); GET_VARIANT_PTR(dst, 1); *dst = true; ip += 2; continue; } case OPCODE_ASSIGN_FALSE: { CHECK_SPACE(2); GET_VARIANT_PTR(dst, 1); *dst = false; ip += 2; continue; } case OPCODE_CONSTRUCT: { CHECK_SPACE(2); Variant::Type t = Variant::Type(_code_ptr[ip + 1]); int argc = _code_ptr[ip + 2]; CHECK_SPACE(argc + 2); Variant **argptrs = call_args; for (int i = 0; i < argc; i++) { GET_VARIANT_PTR(v, 3 + i); argptrs[i] = v; } GET_VARIANT_PTR(dst, 3 + argc); Variant::CallError err; *dst = Variant::construct(t, (const Variant **)argptrs, argc, err); if (err.error != Variant::CallError::CALL_OK) { err_text = _get_call_error(err, "'" + Variant::get_type_name(t) + "' constructor", (const Variant **)argptrs); break; } ip += 4 + argc; //construct a basic type continue; } case OPCODE_CONSTRUCT_ARRAY: { CHECK_SPACE(1); int argc = _code_ptr[ip + 1]; Array array; //arrays are always shared array.resize(argc); CHECK_SPACE(argc + 2); for (int i = 0; i < argc; i++) { GET_VARIANT_PTR(v, 2 + i); array[i] = *v; } GET_VARIANT_PTR(dst, 2 + argc); *dst = array; ip += 3 + argc; continue; } case OPCODE_CONSTRUCT_DICTIONARY: { CHECK_SPACE(1); int argc = _code_ptr[ip + 1]; Dictionary dict; //arrays are always shared CHECK_SPACE(argc * 2 + 2); for (int i = 0; i < argc; i++) { GET_VARIANT_PTR(k, 2 + i * 2 + 0); GET_VARIANT_PTR(v, 2 + i * 2 + 1); dict[*k] = *v; } GET_VARIANT_PTR(dst, 2 + argc * 2); *dst = dict; ip += 3 + argc * 2; continue; } case OPCODE_CALL_RETURN: case OPCODE_CALL: { CHECK_SPACE(4); bool call_ret = _code_ptr[ip] == OPCODE_CALL_RETURN; int argc = _code_ptr[ip + 1]; GET_VARIANT_PTR(base, 2); int nameg = _code_ptr[ip + 3]; ERR_BREAK(nameg < 0 || nameg >= _global_names_count); const StringName *methodname = &_global_names_ptr[nameg]; ERR_BREAK(argc < 0); ip += 4; CHECK_SPACE(argc + 1); Variant **argptrs = call_args; for (int i = 0; i < argc; i++) { GET_VARIANT_PTR(v, i); argptrs[i] = v; } #ifdef DEBUG_ENABLED uint64_t call_time; if (GDScriptLanguage::get_singleton()->profiling) { call_time = OS::get_singleton()->get_ticks_usec(); } #endif Variant::CallError err; if (call_ret) { GET_VARIANT_PTR(ret, argc); base->call_ptr(*methodname, (const Variant **)argptrs, argc, ret, err); } else { base->call_ptr(*methodname, (const Variant **)argptrs, argc, NULL, err); } #ifdef DEBUG_ENABLED if (GDScriptLanguage::get_singleton()->profiling) { function_call_time += OS::get_singleton()->get_ticks_usec() - call_time; } #endif if (err.error != Variant::CallError::CALL_OK) { String methodstr = *methodname; String basestr = _get_var_type(base); if (methodstr == "call") { if (argc >= 1) { methodstr = String(*argptrs[0]) + " (via call)"; if (err.error == Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) { err.argument -= 1; } } } else if (methodstr == "free") { if (err.error == Variant::CallError::CALL_ERROR_INVALID_METHOD) { if (base->is_ref()) { err_text = "Attempted to free a reference."; break; } else if (base->get_type() == Variant::OBJECT) { err_text = "Attempted to free a locked object (calling or emitting)."; break; } } } err_text = _get_call_error(err, "function '" + methodstr + "' in base '" + basestr + "'", (const Variant **)argptrs); break; } //_call_func(NULL,base,*methodname,ip,argc,p_instance,stack); ip += argc + 1; continue; } case OPCODE_CALL_BUILT_IN: { CHECK_SPACE(4); GDFunctions::Function func = GDFunctions::Function(_code_ptr[ip + 1]); int argc = _code_ptr[ip + 2]; ERR_BREAK(argc < 0); ip += 3; CHECK_SPACE(argc + 1); Variant **argptrs = call_args; for (int i = 0; i < argc; i++) { GET_VARIANT_PTR(v, i); argptrs[i] = v; } GET_VARIANT_PTR(dst, argc); Variant::CallError err; GDFunctions::call(func, (const Variant **)argptrs, argc, *dst, err); if (err.error != Variant::CallError::CALL_OK) { String methodstr = GDFunctions::get_func_name(func); if (dst->get_type() == Variant::STRING) { //call provided error string err_text = "Error calling built-in function '" + methodstr + "': " + String(*dst); } else { err_text = _get_call_error(err, "built-in function '" + methodstr + "'", (const Variant **)argptrs); } break; } ip += argc + 1; continue; } case OPCODE_CALL_SELF: { break; } case OPCODE_CALL_SELF_BASE: { CHECK_SPACE(2); int self_fun = _code_ptr[ip + 1]; #ifdef DEBUG_ENABLED if (self_fun < 0 || self_fun >= _global_names_count) { err_text = "compiler bug, function name not found"; break; } #endif const StringName *methodname = &_global_names_ptr[self_fun]; int argc = _code_ptr[ip + 2]; CHECK_SPACE(2 + argc + 1); Variant **argptrs = call_args; for (int i = 0; i < argc; i++) { GET_VARIANT_PTR(v, i + 3); argptrs[i] = v; } GET_VARIANT_PTR(dst, argc + 3); const GDScript *gds = _script; const Map<StringName, GDFunction *>::Element *E = NULL; while (gds->base.ptr()) { gds = gds->base.ptr(); E = gds->member_functions.find(*methodname); if (E) break; } Variant::CallError err; if (E) { *dst = E->get()->call(p_instance, (const Variant **)argptrs, argc, err); } else if (gds->native.ptr()) { if (*methodname != GDScriptLanguage::get_singleton()->strings._init) { MethodBind *mb = ClassDB::get_method(gds->native->get_name(), *methodname); if (!mb) { err.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; } else { *dst = mb->call(p_instance->owner, (const Variant **)argptrs, argc, err); } } else { err.error = Variant::CallError::CALL_OK; } } else { if (*methodname != GDScriptLanguage::get_singleton()->strings._init) { err.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; } else { err.error = Variant::CallError::CALL_OK; } } if (err.error != Variant::CallError::CALL_OK) { String methodstr = *methodname; err_text = _get_call_error(err, "function '" + methodstr + "'", (const Variant **)argptrs); break; } ip += 4 + argc; continue; } case OPCODE_YIELD: case OPCODE_YIELD_SIGNAL: { int ipofs = 1; if (_code_ptr[ip] == OPCODE_YIELD_SIGNAL) { CHECK_SPACE(4); ipofs += 2; } else { CHECK_SPACE(2); } Ref<GDFunctionState> gdfs = memnew(GDFunctionState); gdfs->function = this; gdfs->state.stack.resize(alloca_size); //copy variant stack for (int i = 0; i < _stack_size; i++) { memnew_placement(&gdfs->state.stack[sizeof(Variant) * i], Variant(stack[i])); } gdfs->state.stack_size = _stack_size; gdfs->state.self = self; gdfs->state.alloca_size = alloca_size; gdfs->state._class = _class; gdfs->state.ip = ip + ipofs; gdfs->state.line = line; gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_ID() : 0; gdfs->state.script_id = _class->get_instance_ID(); //gdfs->state.result_pos=ip+ipofs-1; gdfs->state.defarg = defarg; gdfs->state.instance = p_instance; gdfs->function = this; retvalue = gdfs; if (_code_ptr[ip] == OPCODE_YIELD_SIGNAL) { GET_VARIANT_PTR(argobj, 1); GET_VARIANT_PTR(argname, 2); //do the oneshot connect if (argobj->get_type() != Variant::OBJECT) { err_text = "First argument of yield() not of type object."; break; } if (argname->get_type() != Variant::STRING) { err_text = "Second argument of yield() not a string (for signal name)."; break; } Object *obj = argobj->operator Object *(); String signal = argname->operator String(); #ifdef DEBUG_ENABLED if (!obj) { err_text = "First argument of yield() is null."; break; } if (ScriptDebugger::get_singleton()) { if (!ObjectDB::instance_validate(obj)) { err_text = "First argument of yield() is a previously freed instance."; break; } } if (signal.length() == 0) { err_text = "Second argument of yield() is an empty string (for signal name)."; break; } #endif Error err = obj->connect(signal, gdfs.ptr(), "_signal_callback", varray(gdfs), Object::CONNECT_ONESHOT); if (err != OK) { err_text = "Error connecting to signal: " + signal + " during yield()."; break; } } exit_ok = true; break; } case OPCODE_YIELD_RESUME: { CHECK_SPACE(2); if (!p_state) { err_text = ("Invalid Resume (bug?)"); break; } GET_VARIANT_PTR(result, 1); *result = p_state->result; ip += 2; continue; } case OPCODE_JUMP: { CHECK_SPACE(2); int to = _code_ptr[ip + 1]; ERR_BREAK(to < 0 || to > _code_size); ip = to; continue; } case OPCODE_JUMP_IF: { CHECK_SPACE(3); GET_VARIANT_PTR(test, 1); bool valid; bool result = test->booleanize(valid); #ifdef DEBUG_ENABLED if (!valid) { err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type()); break; } #endif if (result) { int to = _code_ptr[ip + 2]; ERR_BREAK(to < 0 || to > _code_size); ip = to; continue; } ip += 3; continue; } case OPCODE_JUMP_IF_NOT: { CHECK_SPACE(3); GET_VARIANT_PTR(test, 1); bool valid; bool result = test->booleanize(valid); #ifdef DEBUG_ENABLED if (!valid) { err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type()); break; } #endif if (!result) { int to = _code_ptr[ip + 2]; ERR_BREAK(to < 0 || to > _code_size); ip = to; continue; } ip += 3; continue; } case OPCODE_JUMP_TO_DEF_ARGUMENT: { CHECK_SPACE(2); ip = _default_arg_ptr[defarg]; continue; } case OPCODE_RETURN: { CHECK_SPACE(2); GET_VARIANT_PTR(r, 1); retvalue = *r; exit_ok = true; break; } case OPCODE_ITERATE_BEGIN: { CHECK_SPACE(8); //space for this an regular iterate GET_VARIANT_PTR(counter, 1); GET_VARIANT_PTR(container, 2); bool valid; if (!container->iter_init(*counter, valid)) { if (!valid) { err_text = "Unable to iterate on object of type " + Variant::get_type_name(container->get_type()) + "'."; break; } int jumpto = _code_ptr[ip + 3]; ERR_BREAK(jumpto < 0 || jumpto > _code_size); ip = jumpto; continue; } GET_VARIANT_PTR(iterator, 4); *iterator = container->iter_get(*counter, valid); if (!valid) { err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "'."; break; } ip += 5; //skip regular iterate which is always next continue; } case OPCODE_ITERATE: { CHECK_SPACE(4); GET_VARIANT_PTR(counter, 1); GET_VARIANT_PTR(container, 2); bool valid; if (!container->iter_next(*counter, valid)) { if (!valid) { err_text = "Unable to iterate on object of type " + Variant::get_type_name(container->get_type()) + "' (type changed since first iteration?)."; break; } int jumpto = _code_ptr[ip + 3]; ERR_BREAK(jumpto < 0 || jumpto > _code_size); ip = jumpto; continue; } GET_VARIANT_PTR(iterator, 4); *iterator = container->iter_get(*counter, valid); if (!valid) { err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "' (but was obtained on first iteration?)."; break; } ip += 5; //loop again continue; } case OPCODE_ASSERT: { CHECK_SPACE(2); GET_VARIANT_PTR(test, 1); #ifdef DEBUG_ENABLED bool valid; bool result = test->booleanize(valid); if (!valid) { err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type()); break; } if (!result) { err_text = "Assertion failed."; break; } #endif ip += 2; continue; } case OPCODE_BREAKPOINT: { #ifdef DEBUG_ENABLED if (ScriptDebugger::get_singleton()) { GDScriptLanguage::get_singleton()->debug_break("Breakpoint Statement", true); } #endif ip += 1; continue; } case OPCODE_LINE: { CHECK_SPACE(2); line = _code_ptr[ip + 1]; ip += 2; if (ScriptDebugger::get_singleton()) { // line bool do_break = false; if (ScriptDebugger::get_singleton()->get_lines_left() > 0) { if (ScriptDebugger::get_singleton()->get_depth() <= 0) ScriptDebugger::get_singleton()->set_lines_left(ScriptDebugger::get_singleton()->get_lines_left() - 1); if (ScriptDebugger::get_singleton()->get_lines_left() <= 0) do_break = true; } if (ScriptDebugger::get_singleton()->is_breakpoint(line, source)) do_break = true; if (do_break) { GDScriptLanguage::get_singleton()->debug_break("Breakpoint", true); } ScriptDebugger::get_singleton()->line_poll(); } continue; } case OPCODE_END: { exit_ok = true; break; } default: { err_text = "Illegal opcode " + itos(_code_ptr[ip]) + " at address " + itos(ip); break; } } if (exit_ok) break; //error // function, file, line, error, explanation String err_file; if (p_instance) err_file = p_instance->script->path; else if (_class) err_file = _class->path; if (err_file == "") err_file = "<built-in>"; String err_func = name; if (p_instance && p_instance->script->name != "") err_func = p_instance->script->name + "." + err_func; int err_line = line; if (err_text == "") { err_text = "Internal Script Error! - opcode #" + itos(last_opcode) + " (report please)."; } if (!GDScriptLanguage::get_singleton()->debug_break(err_text, false)) { // debugger break did not happen _err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text.utf8().get_data(), ERR_HANDLER_SCRIPT); } break; } #ifdef DEBUG_ENABLED if (GDScriptLanguage::get_singleton()->profiling) { uint64_t time_taken = OS::get_singleton()->get_ticks_usec() - function_start_time; profile.total_time += time_taken; profile.self_time += time_taken - function_call_time; profile.frame_total_time += time_taken; profile.frame_self_time += time_taken - function_call_time; GDScriptLanguage::get_singleton()->script_frame_time += time_taken - function_call_time; } #endif if (ScriptDebugger::get_singleton()) GDScriptLanguage::get_singleton()->exit_function(); if (_stack_size) { //free stack for (int i = 0; i < _stack_size; i++) stack[i].~Variant(); } return retvalue; }
static size_t xstrftime( char *str, /* output buffer */ size_t bsz, /* space available */ const char *fmt, struct tm *tm, double usec, double fulltime) { size_t l = 0; /* chars written so far */ int incr = 0; /* chars just written */ char *s = str; TBOOLEAN sign_printed = FALSE; memset(str, '\0', bsz); while (*fmt != '\0') { if (*fmt != '%') { if (l >= bsz-1) return 0; *s++ = *fmt++; l++; } else { /* set up format modifiers */ int w = 0; int z = 0; int p = 0; if (*++fmt == '0') { z = 1; ++fmt; } while (*fmt >= '0' && *fmt <= '9') { w = w * 10 + (*fmt - '0'); ++fmt; } if (*fmt == '.') { ++fmt; while (*fmt >= '0' && *fmt <= '9') { p = p * 10 + (*fmt - '0'); ++fmt; } if (p > 6) p = 6; } switch (*fmt++) { /* some shorthands : check that there is space in the * output string. */ #define CHECK_SPACE(n) do { \ if ((l+(n)) > bsz) return 0; \ } while (0) /* copy a fixed string, checking that there's room */ #define COPY_STRING(z) do { \ CHECK_SPACE(strlen(z)) ; \ strcpy(s, z); \ } while (0) /* format a string, using default spec if none given w * and z are width and zero-flag dw and dz are the * defaults for these In fact, CHECK_SPACE(w) is not a * sufficient test, since sprintf("%2d", 365) outputs * three characters */ #define FORMAT_STRING(dz, dw, x) do { \ if (w==0) { \ w=(dw); \ if (!z) \ z=(dz); \ } \ incr = snprintf(s, bsz-l-1, z ? "%0*d" : "%*d", w, (x)); \ CHECK_SPACE(incr); \ } while(0) case '%': CHECK_SPACE(1); *s = '%'; break; case 'a': COPY_STRING(abbrev_day_names[tm->tm_wday]); break; case 'A': COPY_STRING(full_day_names[tm->tm_wday]); break; case 'b': case 'h': COPY_STRING(abbrev_month_names[tm->tm_mon]); break; case 'B': COPY_STRING(full_month_names[tm->tm_mon]); break; case 'd': FORMAT_STRING(1, 2, tm->tm_mday); /* %02d */ break; case 'D': if (!xstrftime(s, bsz - l, "%m/%d/%y", tm, 0., fulltime)) return 0; break; case 'F': if (!xstrftime(s, bsz - l, "%Y-%m-%d", tm, 0., fulltime)) return 0; break; case 'H': FORMAT_STRING(1, 2, tm->tm_hour); /* %02d */ break; case 'I': FORMAT_STRING(1, 2, (tm->tm_hour + 11) % 12 + 1); /* %02d */ break; case 'j': FORMAT_STRING(1, 3, tm->tm_yday + 1); /* %03d */ break; /* not in linux strftime man page. Not really needed now */ case 'k': FORMAT_STRING(0, 2, tm->tm_hour); /* %2d */ break; case 'l': FORMAT_STRING(0, 2, (tm->tm_hour + 11) % 12 + 1); /* %2d */ break; case 'm': FORMAT_STRING(1, 2, tm->tm_mon + 1); /* %02d */ break; case 'M': FORMAT_STRING(1, 2, tm->tm_min); /* %02d */ break; case 'p': CHECK_SPACE(2); strcpy(s, (tm->tm_hour < 12) ? "am" : "pm"); break; case 'r': if (!xstrftime(s, bsz - l, "%I:%M:%S %p", tm, 0., fulltime)) return 0; break; case 'R': if (!xstrftime(s, bsz - l, "%H:%M", tm, 0., fulltime)) return 0; break; case 's': CHECK_SPACE(12); /* large enough for year 9999 */ sprintf(s, "%.0f", gtimegm(tm)); break; case 'S': FORMAT_STRING(1, 2, tm->tm_sec); /* %02d */ /* EAM FIXME - need to implement an actual format specifier */ if (p > 0) { double base = pow(10., (double)p); int msec = floor(0.5 + base * usec); char *f = &s[strlen(s)]; CHECK_SPACE(p+1); sprintf(f, ".%0*d", p, msec<(int)base?msec:(int)base-1); } break; case 'T': if (!xstrftime(s, bsz - l, "%H:%M:%S", tm, 0., fulltime)) return 0; break; case 't': /* Time (as opposed to Date) formats */ { int tminute, tsecond; switch (*fmt++) { case 'H': /* +/- fractional hours (not wrapped at 24h) */ if (p > 0) { incr = snprintf(s, bsz-l-1, "%*.*f", w, p, fulltime/3600.); CHECK_SPACE(incr); break; } /* Set flag in case minutes come next */ if (fulltime < 0) { CHECK_SPACE(1); /* the minus sign */ sign_printed = TRUE; *s++ = '-'; l++; } /* +/- integral hour truncated toward zero */ sprintf(s, "%0*d", w, (int)floor(fabs(fulltime/3600.))); break; case 'M': /* +/- fractional minutes (not wrapped at 60m) */ if (p > 0) { incr = snprintf(s, bsz-l-1, "%*.*f", w, p, sign_printed ? fabs(fulltime)/60. : fulltime/60.); CHECK_SPACE(incr); break; } /* +/- integral minute truncated toward zero */ tminute = floor(60. * (fabs(fulltime/3600.) - floor(fabs(fulltime/3600.)))); if (fulltime < 0) { if (!sign_printed) { sign_printed = TRUE; *s++ = '-'; l++; } } FORMAT_STRING(1, 2, tminute); /* %02d */ break; case 'S': /* +/- fractional seconds */ tsecond = floor(60. * (fabs(fulltime/60.) - floor(fabs(fulltime/60.)))); if (fulltime < 0) { if (usec > 0) usec = 1.0 - usec; if (!sign_printed) { *s++ = '-'; l++; } } FORMAT_STRING(1, 2, tsecond); /* %02d */ if (p > 0) { double base = pow(10., (double)p); int msec = floor(0.5 + base * usec); char *f = &s[strlen(s)]; CHECK_SPACE(p+1); sprintf(f, ".%0*d", p, msec<(int)base?msec:(int)base-1); } break; default: break; } break; } case 'W': /* mon 1 day of week */ { int week; if (tm->tm_yday <= tm->tm_wday) { week = 1; if ((tm->tm_mday - tm->tm_yday) > 4) { week = 52; } if (tm->tm_yday == tm->tm_wday && tm->tm_wday == 0) week = 52; } else { /* sun prev week */ int bw = tm->tm_yday - tm->tm_wday; if (tm->tm_wday > 0) bw += 7; /* sun end of week */ week = (int) bw / 7; if ((bw % 7) > 2) /* jan 1 is before friday */ week++; } FORMAT_STRING(1, 2, week); /* %02d */ break; } case 'U': /* sun 1 day of week */ { int week, bw; if (tm->tm_yday <= tm->tm_wday) { week = 1; if ((tm->tm_mday - tm->tm_yday) > 4) { week = 52; } } else { /* sat prev week */ bw = tm->tm_yday - tm->tm_wday - 1; if (tm->tm_wday >= 0) bw += 7; /* sat end of week */ week = (int) bw / 7; if ((bw % 7) > 1) { /* jan 1 is before friday */ week++; } } FORMAT_STRING(1, 2, week); /* %02d */ break; } case 'w': /* day of week, sun=0 */ FORMAT_STRING(1, 2, tm->tm_wday); /* %02d */ break; case 'y': FORMAT_STRING(1, 2, tm->tm_year % 100); /* %02d */ break; case 'Y': FORMAT_STRING(1, 4, tm->tm_year); /* %04d */ break; } /* switch */ while (*s != '\0') { s++; l++; } #undef CHECK_SPACE #undef COPY_STRING #undef FORMAT_STRING } /* switch(fmt letter) */ } /* if(fmt letter not '%') */ return (l); }
enum PVRSRV_ERROR RA_GetStats(struct RA_ARENA *pArena, char **ppszStr, u32 *pui32StrLen) { char *pszStr = *ppszStr; u32 ui32StrLen = *pui32StrLen; s32 i32Count; struct BT *pBT; CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, " allocCB=%08X freeCB=%08X handle=%08X quantum=%d\n", pArena->pImportAlloc, pArena->pImportFree, pArena->pImportHandle, pArena->uQuantum); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "span count\t\t%lu\n", pArena->sStatistics.uSpanCount); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "live segment count\t%lu\n", pArena->sStatistics.uLiveSegmentCount); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "free segment count\t%lu\n", pArena->sStatistics.uFreeSegmentCount); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%lu (0x%x)\n", pArena->sStatistics.uFreeResourceCount, (unsigned)pArena->sStatistics.uFreeResourceCount); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "total allocs\t\t%lu\n", pArena->sStatistics.uCumulativeAllocs); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "total frees\t\t%lu\n", pArena->sStatistics.uCumulativeFrees); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "import count\t\t%lu\n", pArena->sStatistics.uImportCount); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "export count\t\t%lu\n", pArena->sStatistics.uExportCount); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, " segment Chain:\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); if (pArena->pHeadSegment != NULL && pArena->pHeadSegment->pPrevSegment != NULL) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, " error: head boundary tag has invalid pPrevSegment\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if (pArena->pTailSegment != NULL && pArena->pTailSegment->pNextSegment != NULL) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, " error: tail boundary tag has invalid pNextSegment\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } for (pBT = pArena->pHeadSegment; pBT != NULL; pBT = pBT->pNextSegment) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\tbase=0x%x size=0x%x type=%s ref=%08X\n", (u32) pBT->base, pBT->uSize, _BTType(pBT->type), pBT->psMapping); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } *ppszStr = pszStr; *pui32StrLen = ui32StrLen; return PVRSRV_OK; }
enum PVRSRV_ERROR PVRSRVGetMiscInfoKM(struct PVRSRV_MISC_INFO *psMiscInfo) { struct SYS_DATA *psSysData; enum PVRSRV_ERROR eError; if (!psMiscInfo) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: invalid parameters"); return PVRSRV_ERROR_INVALID_PARAMS; } psMiscInfo->ui32StatePresent = 0; if (psMiscInfo->ui32StateRequest & ~( PVRSRV_MISC_INFO_TIMER_PRESENT | PVRSRV_MISC_INFO_CLOCKGATE_PRESENT | PVRSRV_MISC_INFO_MEMSTATS_PRESENT | PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT | PVRSRV_MISC_INFO_DDKVERSION_PRESENT)) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: invalid state request flags"); return PVRSRV_ERROR_INVALID_PARAMS; } eError = SysAcquireData(&psSysData); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: Failed to get SysData"); return eError; } if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) && (psSysData->pvSOCTimerRegisterKM != NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT; psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM; psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle; } else { psMiscInfo->pvSOCTimerRegisterKM = NULL; psMiscInfo->hSOCTimerRegisterOSMemHandle = NULL; } if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) && (psSysData->pvSOCClockGateRegsBase != NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT; psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase; psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize; } if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) && (psMiscInfo->pszMemoryStr != NULL)) { struct RA_ARENA **ppArena; struct BM_HEAP *psBMHeap; struct BM_CONTEXT *psBMContext; struct PVRSRV_DEVICE_NODE *psDeviceNode; char *pszStr; u32 ui32StrLen; s32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT; ppArena = &psSysData->apsLocalDevMemArena[0]; while (*ppArena) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); RA_GetStats(*ppArena, &pszStr, &ui32StrLen); ppArena++; } psDeviceNode = psSysData->psDeviceNodeList; while (psDeviceNode) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); if (psDeviceNode->sDevMemoryInfo.pBMKernelContext) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\nKernel Context:\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); psBMHeap = psDeviceNode->sDevMemoryInfo. pBMKernelContext->psBMHeap; while (psBMHeap) { if (psBMHeap->pImportArena) { RA_GetStats(psBMHeap-> pImportArena, &pszStr, &ui32StrLen); } if (psBMHeap->pVMArena) { RA_GetStats(psBMHeap->pVMArena, &pszStr, &ui32StrLen); } psBMHeap = psBMHeap->psNext; } } psBMContext = psDeviceNode->sDevMemoryInfo.pBMContext; while (psBMContext) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\nApplication Context (hDevMemContext) 0x%08X:\n", (void *)psBMContext); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); psBMHeap = psBMContext->psBMHeap; while (psBMHeap) { if (psBMHeap->pImportArena) { RA_GetStats(psBMHeap-> pImportArena, &pszStr, &ui32StrLen); } if (psBMHeap->pVMArena) { RA_GetStats(psBMHeap->pVMArena, &pszStr, &ui32StrLen); } psBMHeap = psBMHeap->psNext; } psBMContext = psBMContext->psNext; } psDeviceNode = psDeviceNode->psNext; } i32Count = OSSNPrintf(pszStr, 100, "\n\0"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) && (psSysData->psGlobalEventObject != NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT; psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject; } if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL) && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL) && (psMiscInfo->pszMemoryStr != NULL)) { char *pszStr; u32 ui32StrLen; u32 ui32LenStrPerNum = 12; s32 i32Count; int i; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT; psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ; psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN; psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BRANCH; psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; for (i = 0; i < 4; i++) { if (ui32StrLen < ui32LenStrPerNum) return PVRSRV_ERROR_INVALID_PARAMS; i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%ld", psMiscInfo->aui32DDKVersion[i]); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); if (i != 3) { i32Count = OSSNPrintf(pszStr, 2, "."); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } } } return PVRSRV_OK; }
IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo) { SYS_DATA *psSysData; if(!psMiscInfo) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psMiscInfo->ui32StatePresent = 0; if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT |PVRSRV_MISC_INFO_MEMSTATS_PRESENT |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT |PVRSRV_MISC_INFO_DDKVERSION_PRESENT)) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags")); return PVRSRV_ERROR_INVALID_PARAMS; } SysAcquireData(&psSysData); if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) && (psSysData->pvSOCTimerRegisterKM != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT; psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM; psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle; } else { psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL; psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL; } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) && (psSysData->pvSOCClockGateRegsBase != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT; psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase; psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize; } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { RA_ARENA **ppArena; IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT; ppArena = &psSysData->apsLocalDevMemArena[0]; while(*ppArena) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); RA_GetStats(*ppArena, &pszStr, &ui32StrLen); ppArena++; } List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr); i32Count = OSSNPrintf(pszStr, 100, "\n\0"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) && (psSysData->psGlobalEventObject != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT; psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject; } if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL) && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_UINT32 ui32LenStrPerNum = 12; IMG_INT32 i32Count; IMG_INT i; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT; psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ; psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN; psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BRANCH; psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; for (i=0; i<4; i++) { if (ui32StrLen < ui32LenStrPerNum) { return PVRSRV_ERROR_INVALID_PARAMS; } i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%ld", psMiscInfo->aui32DDKVersion[i]); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); if (i != 3) { i32Count = OSSNPrintf(pszStr, 2, "."); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } } } return PVRSRV_OK; }
IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo) { SYS_DATA *psSysData; if(!psMiscInfo) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psMiscInfo->ui32StatePresent = 0; if(psMiscInfo->ui32StateRequest & ~( PVRSRV_MISC_INFO_TIMER_PRESENT |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT |PVRSRV_MISC_INFO_MEMSTATS_PRESENT |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT |PVRSRV_MISC_INFO_DDKVERSION_PRESENT |PVRSRV_MISC_INFO_CPUCACHEFLUSH_PRESENT |PVRSRV_MISC_INFO_RESET_PRESENT)) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags")); return PVRSRV_ERROR_INVALID_PARAMS; } SysAcquireData(&psSysData); if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) && (psSysData->pvSOCTimerRegisterKM != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT; psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM; psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle; } else { psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL; psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL; } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) && (psSysData->pvSOCClockGateRegsBase != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT; psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase; psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize; } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { RA_ARENA **ppArena; IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT; ppArena = &psSysData->apsLocalDevMemArena[0]; while(*ppArena) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); RA_GetStats(*ppArena, &pszStr, &ui32StrLen); ppArena++; } List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr); i32Count = OSSNPrintf(pszStr, 100, "\n\0"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) && (psSysData->psGlobalEventObject != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT; psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject; } if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL) && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_UINT32 ui32LenStrPerNum = 12; IMG_INT32 i32Count; IMG_INT i; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT; psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ; psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN; psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BRANCH; psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; for (i=0; i<4; i++) { if (ui32StrLen < ui32LenStrPerNum) { return PVRSRV_ERROR_INVALID_PARAMS; } i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%ld", psMiscInfo->aui32DDKVersion[i]); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); if (i != 3) { i32Count = OSSNPrintf(pszStr, 2, "."); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } } } #if defined(SUPPORT_CPU_CACHED_BUFFERS) if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEFLUSH_PRESENT) != 0UL) { if(psMiscInfo->bDeferCPUCacheFlush) { if(!psMiscInfo->bCPUCacheFlushAll) { PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVGetMiscInfoKM: don't support deferred range flushes")); PVR_DPF((PVR_DBG_MESSAGE," using deferred flush all instead")); } psSysData->bFlushAll = IMG_TRUE; } else { if(psMiscInfo->bCPUCacheFlushAll) { OSFlushCPUCacheKM(); psSysData->bFlushAll = IMG_FALSE; } else { OSFlushCPUCacheRangeKM(psMiscInfo->pvRangeAddrStart, psMiscInfo->pvRangeAddrEnd); } } } #endif #if defined(PVRSRV_RESET_ON_HWTIMEOUT) if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL) { PVR_LOG(("User requested OS reset")); OSPanic(); } #endif return PVRSRV_OK; }
/* * Pack the parameters for a delegate closure call onto the CVM stack. */ static int PackDelegateParams(ILExecThread *thread, ILMethod *method, int isCtor, void *_this, void *userData) { void **args = ((PackDelegateUserData *)userData)->args; ILMethod *pinvokeInfo = ((PackDelegateUserData *)userData)->pinvokeInfo; ILType *signature = ILMethod_Signature(method); CVMWord *stacktop, *stacklimit; ILUInt32 param, numParams; ILType *paramType; void *ptr; ILUInt32 size, sizeInWords; ILNativeFloat tempFloat; ILUInt32 marshalType; char *customName; int customNameLen; char *customCookie; int customCookieLen; char *strValue; /* Get the top and extent of the stack */ stacktop = thread->stackTop; stacklimit = thread->stackLimit; /* Push the arguments onto the evaluation stack */ if(ILType_HasThis(signature)) { /* Push the "this" argument */ CHECK_SPACE(1); if(((PackDelegateUserData *)userData)->needThis) { /* We get the "this" value from the incoming arguments */ stacktop->ptrValue = *((void **)(*args)); ++args; } else { /* We get the "this" value from the delegate object */ stacktop->ptrValue = _this; } ++stacktop; } numParams = ILTypeNumParams(signature); for(param = 1; param <= numParams; ++param) { /* Marshal parameters that need special handling */ marshalType = ILPInvokeGetMarshalType(0, pinvokeInfo, param, &customName, &customNameLen, &customCookie, &customCookieLen, ILTypeGetParam(signature, param)); if(marshalType != IL_META_MARSHAL_DIRECT) { switch(marshalType) { case IL_META_MARSHAL_ANSI_STRING: { /* Marshal an ANSI string from the native world */ CHECK_SPACE(1); strValue = *((char **)(*args)); if(strValue) { stacktop->ptrValue = ILStringCreate(thread, strValue); /* Free the native string */ ILFreeNativeString(strValue); if(!(stacktop->ptrValue)) { return 1; } } else { stacktop->ptrValue = 0; } ++args; ++stacktop; } continue; case IL_META_MARSHAL_UTF8_STRING: { /* Marshal a UTF-8 string from the native world */ CHECK_SPACE(1); strValue = *((char **)(*args)); if(strValue) { stacktop->ptrValue = ILStringCreateUTF8(thread, strValue); /* Free the native string */ ILFreeNativeString(strValue); if(!(stacktop->ptrValue)) { return 1; } } else { stacktop->ptrValue = 0; } ++args; ++stacktop; } continue; case IL_META_MARSHAL_UTF16_STRING: { /* Marshal a UTF-16 string from the native world */ CHECK_SPACE(1); strValue = *((char **)(*args)); if(strValue) { stacktop->ptrValue = ILStringWCreate(thread, (ILUInt16 *)strValue); /* Free the native string */ ILFreeNativeString(strValue); if(!(stacktop->ptrValue)) { return 1; } } else { stacktop->ptrValue = 0; } ++args; ++stacktop; } continue; case IL_META_MARSHAL_CUSTOM: { /* Marshal a custom value from the native world */ CHECK_SPACE(1); stacktop->ptrValue = _ILCustomToObject (thread, *((void **)(*args)), customName, customNameLen, customCookie, customCookieLen); if(_ILExecThreadHasException(thread)) { return 1; } ++args; ++stacktop; } continue; } } /* Marshal the parameter directly */ paramType = ILTypeGetEnumType(ILTypeGetParam(signature, param)); if(ILType_IsPrimitive(paramType)) { /* Process a primitive value */ switch(ILType_ToElement(paramType)) { case IL_META_ELEMTYPE_VOID: break; case IL_META_ELEMTYPE_BOOLEAN: case IL_META_ELEMTYPE_I1: case IL_META_ELEMTYPE_U1: case IL_META_ELEMTYPE_I2: case IL_META_ELEMTYPE_U2: case IL_META_ELEMTYPE_CHAR: case IL_META_ELEMTYPE_I4: case IL_META_ELEMTYPE_U4: #ifdef IL_NATIVE_INT32 case IL_META_ELEMTYPE_I: case IL_META_ELEMTYPE_U: #endif { CHECK_SPACE(1); stacktop->intValue = *((ILInt32 *)(*args)); ++args; ++stacktop; } break; case IL_META_ELEMTYPE_I8: case IL_META_ELEMTYPE_U8: #ifdef IL_NATIVE_INT64 case IL_META_ELEMTYPE_I: case IL_META_ELEMTYPE_U: #endif { CHECK_SPACE(CVM_WORDS_PER_LONG); ILMemCpy(stacktop, *args, sizeof(ILInt64)); ++args; stacktop += CVM_WORDS_PER_LONG; } break; case IL_META_ELEMTYPE_R4: { CHECK_SPACE(CVM_WORDS_PER_NATIVE_FLOAT); tempFloat = (ILNativeFloat)(*((ILFloat *)(*args))); ILMemCpy(stacktop, &tempFloat, sizeof(ILNativeFloat)); ++args; stacktop += CVM_WORDS_PER_NATIVE_FLOAT; } break; case IL_META_ELEMTYPE_R8: { CHECK_SPACE(CVM_WORDS_PER_NATIVE_FLOAT); tempFloat = (ILNativeFloat)(*((ILDouble *)(*args))); ILMemCpy(stacktop, &tempFloat, sizeof(ILNativeFloat)); ++args; stacktop += CVM_WORDS_PER_NATIVE_FLOAT; } break; case IL_META_ELEMTYPE_R: { CHECK_SPACE(CVM_WORDS_PER_NATIVE_FLOAT); ILMemCpy(stacktop, *args, sizeof(ILNativeFloat)); ++args; stacktop += CVM_WORDS_PER_NATIVE_FLOAT; } break; case IL_META_ELEMTYPE_TYPEDBYREF: { CHECK_SPACE(CVM_WORDS_PER_TYPED_REF); ILMemCpy(stacktop, *args, sizeof(ILTypedRef)); ++args; stacktop += CVM_WORDS_PER_TYPED_REF; } break; } } else if(ILType_IsClass(paramType)) { /* Process an object reference */ CHECK_SPACE(1); stacktop->ptrValue = *((void **)(*args)); ++args; ++stacktop; } else if(ILType_IsValueType(paramType)) { /* Process a value type which was passed by value */ ptr = *args; ++args; size = ILSizeOfType(thread, paramType); sizeInWords = ((size + sizeof(CVMWord) - 1) / sizeof(CVMWord)); CHECK_SPACE(sizeInWords); ILMemCpy(stacktop, ptr, size); stacktop += sizeInWords; } else if(paramType != 0 && ILType_IsComplex(paramType) && (ILType_Kind(paramType) == IL_TYPE_COMPLEX_BYREF || ILType_Kind(paramType) == IL_TYPE_COMPLEX_PTR)) { /* Process a value that is being passed by reference */ CHECK_SPACE(1); stacktop->ptrValue = *((void **)(*args)); ++args; ++stacktop; } else { /* Assume that everything else is an object reference */ CHECK_SPACE(1); stacktop->ptrValue = *args; ++args; ++stacktop; } } /* Update the stack top */ thread->stackTop = stacktop; return 0; }
/*! ****************************************************************************** @Function PVRSRVGetMiscInfoKM @Description Retrieves misc. info. @Output PVRSRV_MISC_INFO @Return PVRSRV_ERROR : ******************************************************************************/ IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo) { SYS_DATA *psSysData; if(!psMiscInfo) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psMiscInfo->ui32StatePresent = 0; /* do a basic check for uninitialised request flag */ if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT |PVRSRV_MISC_INFO_MEMSTATS_PRESENT |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT |PVRSRV_MISC_INFO_DDKVERSION_PRESENT |PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT |PVRSRV_MISC_INFO_RESET_PRESENT |PVRSRV_MISC_INFO_FREEMEM_PRESENT |PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT |PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT |PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT)) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags")); return PVRSRV_ERROR_INVALID_PARAMS; } SysAcquireData(&psSysData); /* return SOC Timer registers */ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) && (psSysData->pvSOCTimerRegisterKM != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT; psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM; psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle; } else { psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL; psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL; } /* return SOC Clock Gating registers */ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) && (psSysData->pvSOCClockGateRegsBase != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT; psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase; psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize; } /* memory stats */ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { RA_ARENA **ppArena; /* BM_HEAP *psBMHeap; BM_CONTEXT *psBMContext; PVRSRV_DEVICE_NODE *psDeviceNode;*/ IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT; /* Local backing stores */ ppArena = &psSysData->apsLocalDevMemArena[0]; while(*ppArena) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); RA_GetStats(*ppArena, &pszStr, &ui32StrLen); /* advance through the array */ ppArena++; } /* per device */ /* psDeviceNode = psSysData->psDeviceNodeList;*/ /*triple loop; devices:contexts:heaps*/ List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, &PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr, PVRSRV_MISC_INFO_MEMSTATS_PRESENT); /* attach a new line and string terminate */ i32Count = OSSNPrintf(pszStr, 100, "\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } /* Lean version of mem stats: only show free mem on each RA */ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0) && psMiscInfo->pszMemoryStr) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT; /* triple loop over devices:contexts:heaps */ List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, &PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr, PVRSRV_MISC_INFO_FREEMEM_PRESENT); i32Count = OSSNPrintf(pszStr, 100, "\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) && (psSysData->psGlobalEventObject != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT; psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject; } /* DDK version and memstats not supported in same call to GetMiscInfo */ if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL) && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_UINT32 ui32LenStrPerNum = 12; /* string length per UI32: 10 digits + '.' + '\0' = 12 bytes */ IMG_INT32 i32Count; IMG_INT i; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT; /* construct DDK string */ psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ; psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN; psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BUILD_HI; psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD_LO; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; for (i=0; i<4; i++) { if (ui32StrLen < ui32LenStrPerNum) { return PVRSRV_ERROR_INVALID_PARAMS; } i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); if (i != 3) { i32Count = OSSNPrintf(pszStr, 2, "."); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } } } if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT; if(psMiscInfo->sCacheOpCtl.bDeferOp) { /* For now, assume deferred ops are "full" cache ops, * and we don't need (or expect) a meminfo. */ psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType; } else { PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; PVRSRV_PER_PROCESS_DATA *psPerProc; if(!psMiscInfo->sCacheOpCtl.u.psKernelMemInfo) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " "Ignoring non-deferred cache op with no meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " "Deferred cache op is pending. It is unlikely you want " "to combine deferred cache ops with immediate ones")); } psPerProc = PVRSRVFindPerProcessData(); if(PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_PVOID *)&psKernelMemInfo, psMiscInfo->sCacheOpCtl.u.psKernelMemInfo, PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: " "Can't find kernel meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) { if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, 0, psMiscInfo->sCacheOpCtl.pvBaseVAddr, psMiscInfo->sCacheOpCtl.ui32Length)) { return PVRSRV_ERROR_CACHEOP_FAILED; } } else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) { if(psMiscInfo->sCacheOpCtl.ui32Length!=0) { if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, 0, psMiscInfo->sCacheOpCtl.pvBaseVAddr, psMiscInfo->sCacheOpCtl.ui32Length)) { return PVRSRV_ERROR_CACHEOP_FAILED; } } } } } if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT) != 0UL) { PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; PVRSRV_PER_PROCESS_DATA *psPerProc; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT; psPerProc = PVRSRVFindPerProcessData(); if(PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_PVOID *)&psKernelMemInfo, psMiscInfo->sGetRefCountCtl.u.psKernelMemInfo, PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: " "Can't find kernel meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } psMiscInfo->sGetRefCountCtl.ui32RefCount = psKernelMemInfo->ui32RefCount; } if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT) != 0UL) { psMiscInfo->ui32PageSize = HOST_PAGESIZE(); psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT; } #if defined(PVRSRV_RESET_ON_HWTIMEOUT) if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL) { PVR_LOG(("User requested OS reset")); OSPanic(); } #endif /* #if defined(PVRSRV_RESET_ON_HWTIMEOUT) */ #if defined(SUPPORT_PVRSRV_DEVICE_CLASS) if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT) != 0UL) { PVRSRVProcessQueues(IMG_TRUE); psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT; } #endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */ return PVRSRV_OK; }
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo) #endif { SYS_DATA *psSysData; if(!psMiscInfo) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psMiscInfo->ui32StatePresent = 0; if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT |PVRSRV_MISC_INFO_MEMSTATS_PRESENT |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT |PVRSRV_MISC_INFO_DDKVERSION_PRESENT |PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT |PVRSRV_MISC_INFO_RESET_PRESENT |PVRSRV_MISC_INFO_FREEMEM_PRESENT)) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags")); return PVRSRV_ERROR_INVALID_PARAMS; } SysAcquireData(&psSysData); if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) && (psSysData->pvSOCTimerRegisterKM != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT; psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM; psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle; } else { psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL; psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL; } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) && (psSysData->pvSOCClockGateRegsBase != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT; psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase; psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize; } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { RA_ARENA **ppArena; IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT; ppArena = &psSysData->apsLocalDevMemArena[0]; while(*ppArena) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); RA_GetStats(*ppArena, &pszStr, &ui32StrLen); ppArena++; } List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, &PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr, PVRSRV_MISC_INFO_MEMSTATS_PRESENT); i32Count = OSSNPrintf(pszStr, 100, "\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0) && psMiscInfo->pszMemoryStr) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT; List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, &PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr, PVRSRV_MISC_INFO_FREEMEM_PRESENT); i32Count = OSSNPrintf(pszStr, 100, "\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) && (psSysData->psGlobalEventObject != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT; psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject; } if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL) && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_UINT32 ui32LenStrPerNum = 12; IMG_INT32 i32Count; IMG_INT i; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT; psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ; psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN; psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BRANCH; psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; for (i=0; i<4; i++) { if (ui32StrLen < ui32LenStrPerNum) { return PVRSRV_ERROR_INVALID_PARAMS; } i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); if (i != 3) { i32Count = OSSNPrintf(pszStr, 2, "."); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } } } if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT; if(psMiscInfo->sCacheOpCtl.bDeferOp) { psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType; } else { #if defined (SUPPORT_SID_INTERFACE) PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = psMiscInfo->sCacheOpCtl.psKernelMemInfo; if(!psMiscInfo->sCacheOpCtl.psKernelMemInfo) #else PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; PVRSRV_PER_PROCESS_DATA *psPerProc; if(!psMiscInfo->sCacheOpCtl.u.psKernelMemInfo) #endif { PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " "Ignoring non-deferred cache op with no meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " "Deferred cache op is pending. It is unlikely you want " "to combine deferred cache ops with immediate ones")); } #if defined (SUPPORT_SID_INTERFACE) PVR_DBG_BREAK #else psPerProc = PVRSRVFindPerProcessData(); if(PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_PVOID *)&psKernelMemInfo, psMiscInfo->sCacheOpCtl.u.psKernelMemInfo, PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: " "Can't find kernel meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } #endif if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) { if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, psMiscInfo->sCacheOpCtl.pvBaseVAddr, psMiscInfo->sCacheOpCtl.ui32Length)) { return PVRSRV_ERROR_CACHEOP_FAILED; } } else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) { if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, psMiscInfo->sCacheOpCtl.pvBaseVAddr, psMiscInfo->sCacheOpCtl.ui32Length)) { return PVRSRV_ERROR_CACHEOP_FAILED; } } /* FIXME: Temporary fix needs to be revisited * LinuxMemArea struct listing is not registered for memory areas * wrapped through PVR2DMemWrap() call. For now, we are doing * cache flush/inv by grabbing the physical pages through * get_user_pages() for every blt call. */ else if (psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CUSTOM_FLUSH) { #if defined(CONFIG_OUTER_CACHE) && defined(PVR_NO_FULL_CACHE_OPS) if (1) { IMG_SIZE_T uPageOffset, uPageCount; IMG_VOID *pvPageAlignedCPUVAddr; IMG_SYS_PHYADDR *psIntSysPAddr = IMG_NULL; IMG_HANDLE hOSWrapMem = IMG_NULL; PVRSRV_ERROR eError; int i; uPageOffset = (IMG_UINTPTR_T)psMiscInfo->sCacheOpCtl.pvBaseVAddr & (HOST_PAGESIZE() - 1); uPageCount = HOST_PAGEALIGN(psMiscInfo->sCacheOpCtl.ui32Length + uPageOffset)/HOST_PAGESIZE(); pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)psMiscInfo->sCacheOpCtl.pvBaseVAddr - uPageOffset); if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, uPageCount * sizeof(IMG_SYS_PHYADDR), (IMG_VOID **)&psIntSysPAddr, IMG_NULL, "Array of Page Addresses") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block")); return PVRSRV_ERROR_OUT_OF_MEMORY; } eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr, uPageCount * HOST_PAGESIZE(), psIntSysPAddr, &hOSWrapMem); for (i = 0; i < uPageCount; i++) { outer_flush_range(psIntSysPAddr[i].uiAddr, psIntSysPAddr[i].uiAddr + HOST_PAGESIZE() -1); } OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, uPageCount * sizeof(IMG_SYS_PHYADDR), psIntSysPAddr, IMG_NULL); OSReleasePhysPageAddr(hOSWrapMem); } #else OSFlushCPUCacheKM(); #endif /* CONFIG_OUTER_CACHE && PVR_NO_FULL_CACHE_OPS*/ } else if (psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CUSTOM_INV) { #if defined(CONFIG_OUTER_CACHE) /* TODO: Need to check full cache invalidation, but * currently it is not exported through * outer_cache interface. */ if (1) { IMG_SIZE_T uPageOffset, uPageCount; IMG_VOID *pvPageAlignedCPUVAddr; IMG_SYS_PHYADDR *psIntSysPAddr = IMG_NULL; IMG_HANDLE hOSWrapMem = IMG_NULL; PVRSRV_ERROR eError; int i; uPageOffset = (IMG_UINTPTR_T)psMiscInfo->sCacheOpCtl.pvBaseVAddr & (HOST_PAGESIZE() - 1); uPageCount = HOST_PAGEALIGN(psMiscInfo->sCacheOpCtl.ui32Length + uPageOffset)/HOST_PAGESIZE(); pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)psMiscInfo->sCacheOpCtl.pvBaseVAddr - uPageOffset); if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, uPageCount * sizeof(IMG_SYS_PHYADDR), (IMG_VOID **)&psIntSysPAddr, IMG_NULL, "Array of Page Addresses") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block")); return PVRSRV_ERROR_OUT_OF_MEMORY; } eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr, uPageCount * HOST_PAGESIZE(), psIntSysPAddr, &hOSWrapMem); for (i = 0; i < uPageCount; i++) { outer_inv_range(psIntSysPAddr[i].uiAddr, psIntSysPAddr[i].uiAddr + HOST_PAGESIZE() -1); } OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, uPageCount * sizeof(IMG_SYS_PHYADDR), psIntSysPAddr, IMG_NULL); OSReleasePhysPageAddr(hOSWrapMem); } #endif /* CONFIG_OUTER_CACHE */ } } } #if defined(PVRSRV_RESET_ON_HWTIMEOUT) if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL) { PVR_LOG(("User requested OS reset")); OSPanic(); } #endif return PVRSRV_OK; }
static size_t xstrftime( char *str, /* output buffer */ size_t bsz, /* space available */ const char *fmt, struct tm *tm) { size_t l = 0; /* chars written so far */ char *s = str; memset(s, '\0', bsz); while (*fmt != '\0') { if (*fmt != '%') { if (l >= bsz) return (0); *s++ = *fmt++; l++; } else { /* set up format modifiers */ int w = 0; int z = 0; if (*++fmt == '0') { z = 1; ++fmt; } while (*fmt >= '0' && *fmt <= '9') { w = w * 10 + (*fmt - '0'); ++fmt; } switch (*fmt++) { /* some shorthands : check that there is space in the * output string. */ #define CHECK_SPACE(n) do { \ if ((l+(n)) > bsz) return 0; \ } while (0) /* copy a fixed string, checking that there's room */ #define COPY_STRING(z) do { \ CHECK_SPACE(strlen(z)) ; \ strcpy(s, z); \ } while (0) /* format a string, using default spec if none given w * and z are width and zero-flag dw and dz are the * defaults for these In fact, CHECK_SPACE(w) is not a * sufficient test, since sprintf("%2d", 365) outputs * three characters */ #define FORMAT_STRING(dz, dw, x) do { \ if (w==0) { \ w=(dw); \ if (!z) \ z=(dz); \ } \ CHECK_SPACE(w); \ sprintf(s, z ? "%0*d" : "%*d", w, (x)); \ } while(0) case '%': CHECK_SPACE(1); *s = '%'; break; case 'a': COPY_STRING(abbrev_day_names[tm->tm_wday]); break; case 'A': COPY_STRING(full_day_names[tm->tm_wday]); break; case 'b': case 'h': COPY_STRING(abbrev_month_names[tm->tm_mon]); break; case 'B': COPY_STRING(full_month_names[tm->tm_mon]); break; #if 0 /* %x not currently supported, so neither is c */ case 'c': if (!xstrftime(s, bsz - l, "%x %X", tm)) return (0); break; #endif case 'd': FORMAT_STRING(1, 2, tm->tm_mday); /* %02d */ break; case 'D': if (!xstrftime(s, bsz - l, "%m/%d/%y", tm)) return (0); break; case 'F': if (!xstrftime(s, bsz - l, "%Y-%m-%d", tm)) return (0); break; case 'H': FORMAT_STRING(1, 2, tm->tm_hour); /* %02d */ break; case 'I': FORMAT_STRING(1, 2, (tm->tm_hour + 11) % 12 + 1); /* %02d */ break; case 'j': FORMAT_STRING(1, 3, tm->tm_yday + 1); /* %03d */ break; /* not in linux strftime man page. Not really needed now */ case 'k': FORMAT_STRING(0, 2, tm->tm_hour); /* %2d */ break; case 'l': FORMAT_STRING(0, 2, (tm->tm_hour + 11) % 12 + 1); /* %2d */ break; case 'm': FORMAT_STRING(1, 2, tm->tm_mon + 1); /* %02d */ break; case 'M': FORMAT_STRING(1, 2, tm->tm_min); /* %02d */ break; case 'p': CHECK_SPACE(2); strcpy(s, (tm->tm_hour < 12) ? "am" : "pm"); break; case 'r': if (!xstrftime(s, bsz - l, "%I:%M:%S %p", tm)) return (0); break; case 'R': if (!xstrftime(s, bsz - l, "%H:%M", tm)) return (0); break; case 'S': FORMAT_STRING(1, 2, tm->tm_sec); /* %02d */ break; case 'T': if (!xstrftime(s, bsz - l, "%H:%M:%S", tm)) return (0); break; case 'W': /* mon 1 day of week */ { int week; if (tm->tm_yday <= tm->tm_wday) { week = 1; if ((tm->tm_mday - tm->tm_yday) > 4) { week = 52; } if (tm->tm_yday == tm->tm_wday && tm->tm_wday == 0) week = 52; } else { /* sun prev week */ int bw = tm->tm_yday - tm->tm_wday; if (tm->tm_wday > 0) bw += 7; /* sun end of week */ week = (int) bw / 7; if ((bw % 7) > 2) /* jan 1 is before friday */ week++; } FORMAT_STRING(1, 2, week); /* %02d */ break; } case 'U': /* sun 1 day of week */ { int week, bw; if (tm->tm_yday <= tm->tm_wday) { week = 1; if ((tm->tm_mday - tm->tm_yday) > 4) { week = 52; } } else { /* sat prev week */ bw = tm->tm_yday - tm->tm_wday - 1; if (tm->tm_wday >= 0) bw += 7; /* sat end of week */ week = (int) bw / 7; if ((bw % 7) > 1) { /* jan 1 is before friday */ week++; } } FORMAT_STRING(1, 2, week); /* %02d */ break; } case 'w': /* day of week, sun=0 */ FORMAT_STRING(1, 2, tm->tm_wday); /* %02d */ break; case 'y': FORMAT_STRING(1, 2, tm->tm_year % 100); /* %02d */ break; case 'Y': FORMAT_STRING(1, 4, tm->tm_year); /* %04d */ break; #if 0 case 'Z': COPY_STRING(tm->tm_zone); break; #endif } /* switch */ while (*s != '\0') { s++; l++; } #undef CHECK_SPACE #undef COPY_STRING #undef FORMAT_STRING } /* switch(fmt letter) */ } /* if(fmt letter not '%') */ return (l); }