diff options
Diffstat (limited to 'drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.c')
-rw-r--r-- | drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.c | 1306 |
1 files changed, 1306 insertions, 0 deletions
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.c new file mode 100644 index 000000000000..8b0289705ab0 --- /dev/null +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.c @@ -0,0 +1,1306 @@ +/**************************************************************************** +* +* The MIT License (MIT) +* +* Copyright (c) 2014 - 2020 Vivante Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +* +***************************************************************************** +* +* The GPL License (GPL) +* +* Copyright (C) 2014 - 2020 Vivante Corporation +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +***************************************************************************** +* +* Note: This software is released under dual MIT and GPL licenses. A +* recipient may use this file under the terms of either the MIT license or +* GPL License. If you wish to use only one license not the other, you can +* indicate your decision by deleting one of the above license notices in your +* version of this file. +* +*****************************************************************************/ + + +#include "gc_hal_kernel_precomp.h" +#include <gc_hal_kernel_debug.h> + +/******************************************************************************\ +******************************** Debug Variables ******************************* +\******************************************************************************/ + +static gceSTATUS _lastError = gcvSTATUS_OK; +static gctUINT32 _debugLevel = gcvLEVEL_ERROR; +/* +_debugZones config value +Please Reference define in gc_hal_base.h +*/ +static gctUINT32 _debugZones = gcdZONE_NONE; + +/******************************************************************************\ +********************************* Debug Switches ******************************* +\******************************************************************************/ + +/* + gcdTHREAD_BUFFERS + + When greater then one, will accumulate messages from the specified number + of threads in separate output buffers. +*/ +#define gcdTHREAD_BUFFERS 1 + +/* + gcdSHOW_LINE_NUMBER + + When enabledm each print statement will be preceeded with the current + line number. +*/ +#define gcdSHOW_LINE_NUMBER 0 + +/* + gcdSHOW_PROCESS_ID + + When enabledm each print statement will be preceeded with the current + process ID. +*/ +#define gcdSHOW_PROCESS_ID 0 + +/* + gcdSHOW_THREAD_ID + + When enabledm each print statement will be preceeded with the current + thread ID. +*/ +#define gcdSHOW_THREAD_ID 0 + +/* + gcdSHOW_TIME + + When enabled each print statement will be preceeded with the current + high-resolution time. +*/ +#define gcdSHOW_TIME 0 + + +/******************************************************************************\ +****************************** Miscellaneous Macros **************************** +\******************************************************************************/ + +#if gcdSHOW_TIME || gcdSHOW_LINE_NUMBER || gcdSHOW_PROCESS_ID || gcdSHOW_THREAD_ID +# define gcdHAVEPREFIX 1 +#else +# define gcdHAVEPREFIX 0 +#endif + +/******************************************************************************\ +****************************** Private Structures ****************************** +\******************************************************************************/ + +typedef struct _gcsBUFFERED_OUTPUT * gcsBUFFERED_OUTPUT_PTR; +typedef struct _gcsBUFFERED_OUTPUT +{ +#if gcdTHREAD_BUFFERS > 1 + gctUINT32 threadID; +#endif + +#if gcdSHOW_LINE_NUMBER + gctUINT lineNumber; +#endif + + gctINT indent; + + gcsBUFFERED_OUTPUT_PTR prev; + gcsBUFFERED_OUTPUT_PTR next; +} +gcsBUFFERED_OUTPUT; + +static gcsBUFFERED_OUTPUT _outputBuffer[gcdTHREAD_BUFFERS]; +static gcsBUFFERED_OUTPUT_PTR _outputBufferHead = gcvNULL; +static gcsBUFFERED_OUTPUT_PTR _outputBufferTail = gcvNULL; + +/******************************************************************************\ +******************************* Printing Functions ***************************** +\******************************************************************************/ + +#if gcdHAVEPREFIX + +#if gcdSHOW_TIME +static gcmINLINE gctUINT64 +_GetTime( + void + ) +{ + gctUINT64 time; + gckOS_GetProfileTick(&time); + return time; +} +# define gcdPREFIX_LEADER 1 +# define gcdTIMEFORMAT "%18lld" +# define gcdTIMEVALUE ,_GetTime() +# else +# define gcdTIMEFORMAT +# define gcdTIMEVALUE +# endif + +#if gcdSHOW_LINE_NUMBER +#ifndef gcdPREFIX_LEADER +# define gcdPREFIX_LEADER 1 +# define gcdNUMFORMAT "%8u" +# else +# define gcdNUMFORMAT ", %8u" +# endif +# define gcdNUMVALUE ,OutputBuffer->lineNumber +# else +# define gcdNUMFORMAT +# define gcdNUMVALUE +# endif + +#if gcdSHOW_PROCESS_ID +#ifndef gcdPREFIX_LEADER +# define gcdPREFIX_LEADER 1 +# define gcdPIDFORMAT "pid=%5u" +# else +# define gcdPIDFORMAT ", pid=%5u" +# endif +# define gcdPIDVALUE ,gcmkGETPROCESSID() +# else +# define gcdPIDFORMAT +# define gcdPIDVALUE +# endif + +#if gcdSHOW_THREAD_ID +#ifndef gcdPREFIX_LEADER +# define gcdPREFIX_LEADER 1 +# define gcdTIDFORMAT "tid=%5u" +# else +# define gcdTIDFORMAT ", tid=%5u" +# endif +# define gcdTIDVALUE ,gcmkGETTHREADID() +# else +# define gcdTIDFORMAT +# define gcdTIDVALUE +# endif + +static gctUINT +_PrintPrefix( + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, + IN char Buffer[], + IN gctUINT Size + ) +{ + gctINT len; + + /* Format the string. */ + len = gcmkSPRINTF(Buffer, + Size, + "[" gcdTIMEFORMAT gcdNUMFORMAT gcdPIDFORMAT gcdTIDFORMAT "] " + gcdTIMEVALUE gcdNUMVALUE gcdPIDVALUE gcdTIDVALUE); + + if (len > 0) + { + Buffer[len] = '\0'; + return (gctUINT)len; + } + + return 0; +} +#endif + +static int +_AppendIndent( + IN gctINT Indent, + IN char * Buffer, + IN int BufferSize + ) +{ + gctINT i; + + gctINT len = 0; + gctINT indent = Indent % 40; + + for (i = 0; i < indent; i += 1) + { + Buffer[len++] = ' '; + } + + if (indent != Indent) + { + len += gcmkSPRINTF( + Buffer + len, BufferSize - len, " <%d> ", Indent + ); + + Buffer[len] = '\0'; + } + + return len; +} + +static gctUINT +_PrintString( + IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, + IN gctINT Indent, + IN gctCONST_STRING Message, + IN gctPOINTER Data, + IN char Buffer[], + IN gctUINT Size + ) +{ + gctINT len; + + /* Append the indent string. */ + len = _AppendIndent(Indent, Buffer, Size); + + /* Format the string. */ + len += gcmkVSPRINTF(Buffer + len, Size - len, Message, Data); + Buffer[len] = '\0'; + + /* Add end-of-line if missing. */ + if (Buffer[len - 1] != '\n') + { + Buffer[len++] = '\n'; + Buffer[len] = '\0'; + } + + return (gctUINT)len; +} + +/******************************************************************************\ +******************************* Private Functions ****************************** +\******************************************************************************/ + +static gcmINLINE void +_InitBuffers( + void + ) +{ + int i; + + if (_outputBufferHead == gcvNULL) + { + for (i = 0; i < gcdTHREAD_BUFFERS; i += 1) + { + if (_outputBufferTail == gcvNULL) + { + _outputBufferHead = &_outputBuffer[i]; + } + else + { + _outputBufferTail->next = &_outputBuffer[i]; + } + +#if gcdTHREAD_BUFFERS > 1 + _outputBuffer[i].threadID = ~0U; +#endif + + _outputBuffer[i].prev = _outputBufferTail; + _outputBuffer[i].next = gcvNULL; + + _outputBufferTail = &_outputBuffer[i]; + } + } +} + +static gcmINLINE gcsBUFFERED_OUTPUT_PTR +_GetOutputBuffer( + void + ) +{ + gcsBUFFERED_OUTPUT_PTR outputBuffer; + +#if gcdTHREAD_BUFFERS > 1 + /* Get the current thread ID. */ + gctUINT32 ThreadID = gcmkGETTHREADID(); + + /* Locate the output buffer for the thread. */ + outputBuffer = _outputBufferHead; + + while (outputBuffer != gcvNULL) + { + if (outputBuffer->threadID == ThreadID) + { + break; + } + + outputBuffer = outputBuffer->next; + } + + /* No matching buffer found? */ + if (outputBuffer == gcvNULL) + { + /* Get the tail for the buffer. */ + outputBuffer = _outputBufferTail; + + /* Move it to the head. */ + _outputBufferTail = _outputBufferTail->prev; + _outputBufferTail->next = gcvNULL; + + outputBuffer->prev = gcvNULL; + outputBuffer->next = _outputBufferHead; + + _outputBufferHead->prev = outputBuffer; + _outputBufferHead = outputBuffer; + + /* Reset the buffer. */ + outputBuffer->threadID = ThreadID; +#if gcdSHOW_LINE_NUMBER + outputBuffer->lineNumber = 0; +# endif + } +#else + outputBuffer = _outputBufferHead; +#endif + + return outputBuffer; +} + +static void +_Print( + IN gctCONST_STRING Message, + IN gctARGUMENTS * Arguments + ) +{ + gcsBUFFERED_OUTPUT_PTR outputBuffer; + char buffer[256]; + char *ptr = buffer; + gctINT len = 0; + static gcmkDECLARE_MUTEX(printMutex); + + gcmkMUTEX_LOCK(printMutex); + + /* Initialize output buffer list. */ + _InitBuffers(); + + /* Locate the proper output buffer. */ + outputBuffer = _GetOutputBuffer(); + + /* Print prefix. */ +#if gcdHAVEPREFIX +#if gcdSHOW_LINE_NUMBER + /* Update the line number. */ + outputBuffer->lineNumber += 1; +# endif + + /* Print the prefix. */ + len = _PrintPrefix(outputBuffer, buffer, gcmSIZEOF(buffer)); + ptr += len; +#endif + + /* Form the indent string. */ + if (Message[0] == '-' && Message[1] == '-') + { + outputBuffer->indent -= 2; + } + + /* Print the message. */ + len += _PrintString( + outputBuffer, outputBuffer->indent, + Message, ((gctPOINTER) Arguments), + ptr, gcmSIZEOF(buffer) - outputBuffer->indent - len + ); + + gcmkOUTPUT_STRING(buffer); + + /* Check increasing indent. */ + if (Message[0] == '+' && Message[1] == '+') + { + outputBuffer->indent += 2; + } + + gcmkMUTEX_UNLOCK(printMutex); +} + + +/******************************************************************************\ +********************************* Debug Macros ********************************* +\******************************************************************************/ + +#ifdef __QNXNTO__ + +extern volatile unsigned g_nQnxInIsrs; + +#define gcmDEBUGPRINT(Message) \ +{ \ + if (atomic_add_value(&g_nQnxInIsrs, 1) == 0) \ + { \ + gctARGUMENTS __arguments__; \ + gcmkARGUMENTS_START(__arguments__, Message); \ + _Print(Message, &__arguments__); \ + gcmkARGUMENTS_END(__arguments__); \ + } \ + atomic_sub(&g_nQnxInIsrs, 1); \ +} + +#elif defined(__VXWORKS__) +#define gcmDEBUGPRINT(Message) \ +{ \ + printf(Message); \ +} + +#else + +#define gcmDEBUGPRINT(Message) \ +{ \ + gctARGUMENTS __arguments__; \ + gcmkARGUMENTS_START(__arguments__, Message); \ + _Print(Message, &__arguments__); \ + gcmkARGUMENTS_END(__arguments__); \ +} + +#endif + +/******************************************************************************\ +********************************** Debug Code ********************************** +\******************************************************************************/ + +/******************************************************************************* +** +** gckOS_Print +** +** Send a message to the debugger. +** +** INPUT: +** +** gctCONST_STRING Message +** Pointer to message. +** +** ... +** Optional arguments. +** +** OUTPUT: +** +** Nothing. +*/ + +void +gckOS_Print( + IN gctCONST_STRING Message, + ... + ) +{ + gcmDEBUGPRINT(Message); +} + +/******************************************************************************* +** +** gckOS_DebugTrace +** +** Send a leveled message to the debugger. +** +** INPUT: +** +** gctUINT32 Level +** Debug level of message. +** +** gctCONST_STRING Message +** Pointer to message. +** +** ... +** Optional arguments. +** +** OUTPUT: +** +** Nothing. +*/ + +void +gckOS_DebugTrace( + IN gctUINT32 Level, + IN gctCONST_STRING Message, + ... + ) +{ + if (Level > _debugLevel) + { + return; + } + + gcmDEBUGPRINT(Message); +} + +/******************************************************************************* +** +** gckOS_DebugTraceZone +** +** Send a leveled and zoned message to the debugger. +** +** INPUT: +** +** gctUINT32 Level +** Debug level for message. +** +** gctUINT32 Zone +** Debug zone for message. +** +** gctCONST_STRING Message +** Pointer to message. +** +** ... +** Optional arguments. +** +** OUTPUT: +** +** Nothing. +*/ + +void +gckOS_DebugTraceZone( + IN gctUINT32 Level, + IN gctUINT32 Zone, + IN gctCONST_STRING Message, + ... + ) +{ + if ((Level > _debugLevel) || !(Zone & _debugZones)) + { + return; + } + + gcmDEBUGPRINT(Message); +} + +/******************************************************************************* +** +** gckOS_DebugBreak +** +** Break into the debugger. +** +** INPUT: +** +** Nothing. +** +** OUTPUT: +** +** Nothing. +*/ +void +gckOS_DebugBreak( + void + ) +{ + gckOS_DebugTrace(gcvLEVEL_ERROR, "%s(%d)", __FUNCTION__, __LINE__); +} + +/******************************************************************************* +** +** gckOS_DebugFatal +** +** Send a message to the debugger and break into the debugger. +** +** INPUT: +** +** gctCONST_STRING Message +** Pointer to message. +** +** ... +** Optional arguments. +** +** OUTPUT: +** +** Nothing. +*/ +void +gckOS_DebugFatal( + IN gctCONST_STRING Message, + ... + ) +{ + gcmkPRINT_VERSION(); + gcmDEBUGPRINT(Message); + + /* Break into the debugger. */ + gckOS_DebugBreak(); +} + +/******************************************************************************* +** +** gckOS_SetDebugLevel +** +** Set the debug level. +** +** INPUT: +** +** gctUINT32 Level +** New debug level. +** +** OUTPUT: +** +** Nothing. +*/ + +void +gckOS_SetDebugLevel( + IN gctUINT32 Level + ) +{ + _debugLevel = Level; +} + +/******************************************************************************* +** +** gckOS_SetDebugZone +** +** Set the debug zone. +** +** INPUT: +** +** gctUINT32 Zone +** New debug zone. +** +** OUTPUT: +** +** Nothing. +*/ +void +gckOS_SetDebugZone( + IN gctUINT32 Zone + ) +{ + _debugZones = Zone; +} + +/******************************************************************************* +** +** gckOS_SetDebugLevelZone +** +** Set the debug level and zone. +** +** INPUT: +** +** gctUINT32 Level +** New debug level. +** +** gctUINT32 Zone +** New debug zone. +** +** OUTPUT: +** +** Nothing. +*/ + +void +gckOS_SetDebugLevelZone( + IN gctUINT32 Level, + IN gctUINT32 Zone + ) +{ + _debugLevel = Level; + _debugZones = Zone; +} + +/******************************************************************************* +** +** gckOS_SetDebugZones +** +** Enable or disable debug zones. +** +** INPUT: +** +** gctUINT32 Zones +** Debug zones to enable or disable. +** +** gctBOOL Enable +** Set to gcvTRUE to enable the zones (or the Zones with the current +** zones) or gcvFALSE to disable the specified Zones. +** +** OUTPUT: +** +** Nothing. +*/ + +void +gckOS_SetDebugZones( + IN gctUINT32 Zones, + IN gctBOOL Enable + ) +{ + if (Enable) + { + /* Enable the zones. */ + _debugZones |= Zones; + } + else + { + /* Disable the zones. */ + _debugZones &= ~Zones; + } +} + +/******************************************************************************* +** +** gckOS_Verify +** +** Called to verify the result of a function call. +** +** INPUT: +** +** gceSTATUS Status +** Function call result. +** +** OUTPUT: +** +** Nothing. +*/ + +void +gckOS_Verify( + IN gceSTATUS status + ) +{ + _lastError = status; +} + +gctCONST_STRING +gckOS_DebugStatus2Name( + gceSTATUS status + ) +{ + switch (status) + { + case gcvSTATUS_OK: + return "gcvSTATUS_OK"; + case gcvSTATUS_TRUE: + return "gcvSTATUS_TRUE"; + case gcvSTATUS_NO_MORE_DATA: + return "gcvSTATUS_NO_MORE_DATA"; + case gcvSTATUS_CACHED: + return "gcvSTATUS_CACHED"; + case gcvSTATUS_MIPMAP_TOO_LARGE: + return "gcvSTATUS_MIPMAP_TOO_LARGE"; + case gcvSTATUS_NAME_NOT_FOUND: + return "gcvSTATUS_NAME_NOT_FOUND"; + case gcvSTATUS_NOT_OUR_INTERRUPT: + return "gcvSTATUS_NOT_OUR_INTERRUPT"; + case gcvSTATUS_MISMATCH: + return "gcvSTATUS_MISMATCH"; + case gcvSTATUS_MIPMAP_TOO_SMALL: + return "gcvSTATUS_MIPMAP_TOO_SMALL"; + case gcvSTATUS_LARGER: + return "gcvSTATUS_LARGER"; + case gcvSTATUS_SMALLER: + return "gcvSTATUS_SMALLER"; + case gcvSTATUS_CHIP_NOT_READY: + return "gcvSTATUS_CHIP_NOT_READY"; + case gcvSTATUS_NEED_CONVERSION: + return "gcvSTATUS_NEED_CONVERSION"; + case gcvSTATUS_SKIP: + return "gcvSTATUS_SKIP"; + case gcvSTATUS_DATA_TOO_LARGE: + return "gcvSTATUS_DATA_TOO_LARGE"; + case gcvSTATUS_INVALID_CONFIG: + return "gcvSTATUS_INVALID_CONFIG"; + case gcvSTATUS_CHANGED: + return "gcvSTATUS_CHANGED"; + case gcvSTATUS_NOT_SUPPORT_DITHER: + return "gcvSTATUS_NOT_SUPPORT_DITHER"; + + case gcvSTATUS_INVALID_ARGUMENT: + return "gcvSTATUS_INVALID_ARGUMENT"; + case gcvSTATUS_INVALID_OBJECT: + return "gcvSTATUS_INVALID_OBJECT"; + case gcvSTATUS_OUT_OF_MEMORY: + return "gcvSTATUS_OUT_OF_MEMORY"; + case gcvSTATUS_MEMORY_LOCKED: + return "gcvSTATUS_MEMORY_LOCKED"; + case gcvSTATUS_MEMORY_UNLOCKED: + return "gcvSTATUS_MEMORY_UNLOCKED"; + case gcvSTATUS_HEAP_CORRUPTED: + return "gcvSTATUS_HEAP_CORRUPTED"; + case gcvSTATUS_GENERIC_IO: + return "gcvSTATUS_GENERIC_IO"; + case gcvSTATUS_INVALID_ADDRESS: + return "gcvSTATUS_INVALID_ADDRESS"; + case gcvSTATUS_CONTEXT_LOSSED: + return "gcvSTATUS_CONTEXT_LOSSED"; + case gcvSTATUS_TOO_COMPLEX: + return "gcvSTATUS_TOO_COMPLEX"; + case gcvSTATUS_BUFFER_TOO_SMALL: + return "gcvSTATUS_BUFFER_TOO_SMALL"; + case gcvSTATUS_INTERFACE_ERROR: + return "gcvSTATUS_INTERFACE_ERROR"; + case gcvSTATUS_NOT_SUPPORTED: + return "gcvSTATUS_NOT_SUPPORTED"; + case gcvSTATUS_MORE_DATA: + return "gcvSTATUS_MORE_DATA"; + case gcvSTATUS_TIMEOUT: + return "gcvSTATUS_TIMEOUT"; + case gcvSTATUS_OUT_OF_RESOURCES: + return "gcvSTATUS_OUT_OF_RESOURCES"; + case gcvSTATUS_INVALID_DATA: + return "gcvSTATUS_INVALID_DATA"; + case gcvSTATUS_INVALID_MIPMAP: + return "gcvSTATUS_INVALID_MIPMAP"; + case gcvSTATUS_NOT_FOUND: + return "gcvSTATUS_NOT_FOUND"; + case gcvSTATUS_NOT_ALIGNED: + return "gcvSTATUS_NOT_ALIGNED"; + case gcvSTATUS_INVALID_REQUEST: + return "gcvSTATUS_INVALID_REQUEST"; + case gcvSTATUS_GPU_NOT_RESPONDING: + return "gcvSTATUS_GPU_NOT_RESPONDING"; + case gcvSTATUS_TIMER_OVERFLOW: + return "gcvSTATUS_TIMER_OVERFLOW"; + case gcvSTATUS_VERSION_MISMATCH: + return "gcvSTATUS_VERSION_MISMATCH"; + case gcvSTATUS_LOCKED: + return "gcvSTATUS_LOCKED"; + case gcvSTATUS_INTERRUPTED: + return "gcvSTATUS_INTERRUPTED"; + case gcvSTATUS_DEVICE: + return "gcvSTATUS_DEVICE"; + case gcvSTATUS_NOT_MULTI_PIPE_ALIGNED: + return "gcvSTATUS_NOT_MULTI_PIPE_ALIGNED"; + + /* Linker errors. */ + case gcvSTATUS_GLOBAL_TYPE_MISMATCH: + return "gcvSTATUS_GLOBAL_TYPE_MISMATCH"; + case gcvSTATUS_TOO_MANY_ATTRIBUTES: + return "gcvSTATUS_TOO_MANY_ATTRIBUTES"; + case gcvSTATUS_TOO_MANY_UNIFORMS: + return "gcvSTATUS_TOO_MANY_UNIFORMS"; + case gcvSTATUS_TOO_MANY_VARYINGS: + return "gcvSTATUS_TOO_MANY_VARYINGS"; + case gcvSTATUS_UNDECLARED_VARYING: + return "gcvSTATUS_UNDECLARED_VARYING"; + case gcvSTATUS_VARYING_TYPE_MISMATCH: + return "gcvSTATUS_VARYING_TYPE_MISMATCH"; + case gcvSTATUS_MISSING_MAIN: + return "gcvSTATUS_MISSING_MAIN"; + case gcvSTATUS_NAME_MISMATCH: + return "gcvSTATUS_NAME_MISMATCH"; + case gcvSTATUS_INVALID_INDEX: + return "gcvSTATUS_INVALID_INDEX"; + case gcvSTATUS_UNIFORM_MISMATCH: + return "gcvSTATUS_UNIFORM_MISMATCH"; + case gcvSTATUS_UNSAT_LIB_SYMBOL: + return "gcvSTATUS_UNSAT_LIB_SYMBOL"; + case gcvSTATUS_TOO_MANY_SHADERS: + return "gcvSTATUS_TOO_MANY_SHADERS"; + case gcvSTATUS_LINK_INVALID_SHADERS: + return "gcvSTATUS_LINK_INVALID_SHADERS"; + case gcvSTATUS_CS_NO_WORKGROUP_SIZE: + return "gcvSTATUS_CS_NO_WORKGROUP_SIZE"; + case gcvSTATUS_LINK_LIB_ERROR: + return "gcvSTATUS_LINK_LIB_ERROR"; + case gcvSTATUS_SHADER_VERSION_MISMATCH: + return "gcvSTATUS_SHADER_VERSION_MISMATCH"; + case gcvSTATUS_TOO_MANY_INSTRUCTION: + return "gcvSTATUS_TOO_MANY_INSTRUCTION"; + case gcvSTATUS_SSBO_MISMATCH: + return "gcvSTATUS_SSBO_MISMATCH"; + case gcvSTATUS_TOO_MANY_OUTPUT: + return "gcvSTATUS_TOO_MANY_OUTPUT"; + case gcvSTATUS_TOO_MANY_INPUT: + return "gcvSTATUS_TOO_MANY_INPUT"; + case gcvSTATUS_NOT_SUPPORT_CL: + return "gcvSTATUS_NOT_SUPPORT_CL"; + case gcvSTATUS_NOT_SUPPORT_INTEGER: + return "gcvSTATUS_NOT_SUPPORT_INTEGER"; + case gcvSTATUS_UNIFORM_TYPE_MISMATCH: + return "gcvSTATUS_UNIFORM_TYPE_MISMATCH"; + case gcvSTATUS_MISSING_PRIMITIVE_TYPE: + return "gcvSTATUS_MISSING_PRIMITIVE_TYPE"; + case gcvSTATUS_MISSING_OUTPUT_VERTEX_COUNT: + return "gcvSTATUS_MISSING_OUTPUT_VERTEX_COUNT"; + case gcvSTATUS_NON_INVOCATION_ID_AS_INDEX: + return "gcvSTATUS_NON_INVOCATION_ID_AS_INDEX"; + case gcvSTATUS_INPUT_ARRAY_SIZE_MISMATCH: + return "gcvSTATUS_INPUT_ARRAY_SIZE_MISMATCH"; + case gcvSTATUS_OUTPUT_ARRAY_SIZE_MISMATCH: + return "gcvSTATUS_OUTPUT_ARRAY_SIZE_MISMATCH"; + + /* Compiler errors. */ + case gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR: + return "gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR"; + case gcvSTATUS_COMPILER_FE_PARSER_ERROR: + return "gcvSTATUS_COMPILER_FE_PARSER_ERROR"; + default: + return "nil"; + } +} + +/******************************************************************************* +***** Kernel Dump ************************************************************** +*******************************************************************************/ + +/* + * TODO: Dump to file is only valid in linux currently. + */ +#ifndef gcmkDUMP_STRING +# define gcmkDUMP_STRING(os, s) gcmkOUTPUT_STRING((s)) +#endif + +static gcmkDECLARE_MUTEX(_dumpMutex); +static gctCHAR _dumpStorage[512]; + +/******************************************************************************* +** +** gckOS_Dump +** +** Formated print string to dump pool. +** +** INPUT: +** +** gctCONST_STRING Format +** String format. +** +** OUTPUT: +** +** Nothing. +*/ +void +gckOS_Dump( + IN gckOS Os, + IN gctCONST_STRING Format, + ... + ) +{ + char buffer[256]; + gctINT len; + gctARGUMENTS args; + + gcmkARGUMENTS_START(args, Format); + len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer) - 2, Format, &args); + gcmkARGUMENTS_END(args); + + if (len > 0) + { + if (buffer[len - 1] != '\n') + { + buffer[len] = '\n'; + buffer[len + 1] = '\0'; + } + + gcmkMUTEX_LOCK(_dumpMutex); + gcmkDUMP_STRING(Os, buffer); + gcmkMUTEX_UNLOCK(_dumpMutex); + } +} + +static void +_DumpUserString( + IN gckOS Os, + IN gctPOINTER UserStr, + IN gctSIZE_T Size + ) +{ + gceSTATUS status = gcvSTATUS_OK; + gctSIZE_T offset = 0; + gctSIZE_T length = 0; + gctBOOL needCopy = gcvTRUE; + const gctSIZE_T maxLength = gcmSIZEOF(_dumpStorage) - 1; + + gcmkVERIFY_OK(gckOS_QueryNeedCopy(Os, 0, &needCopy)); + + gcmkMUTEX_LOCK(_dumpMutex); + + while (offset < Size) + { + length = maxLength < (Size - offset) ? maxLength : (Size - offset); + + /* Copy or map from user. */ + if (needCopy) + { + gcmkONERROR(gckOS_CopyFromUserData( + Os, + _dumpStorage, + UserStr, + length + )); + } + else + { + gctPOINTER ptr = gcvNULL; + + gcmkONERROR(gckOS_MapUserPointer( + Os, + UserStr, + length, + (gctPOINTER *)&ptr + )); + + gckOS_MemCopy(_dumpStorage, ptr, length); + gckOS_UnmapUserPointer(Os, UserStr, length, ptr); + } + + _dumpStorage[length] = '\0'; + gcmkDUMP_STRING(Os, _dumpStorage); + + UserStr = (gctUINT8_PTR)UserStr + length; + offset += length; + } + + gcmkDUMP_STRING(Os, "\n"); + +OnError: + gcmkMUTEX_UNLOCK(_dumpMutex); +} + +static void +_DumpDataBuffer( + IN gckOS Os, + IN gceDUMP_BUFFER_TYPE Type, + IN gctPOINTER Data, + IN gctUINT64 Address, + IN gctSIZE_T Size + ) +{ + gceSTATUS status = gcvSTATUS_OK; + gctSIZE_T offset = 0; + gctSIZE_T length = 0; + gctBOOL needCopy = gcvTRUE; + gctCONST_STRING dumpTag; + char buffer[256]; + const gctSIZE_T maxLength = gcmSIZEOF(_dumpStorage); + + switch (Type) + { + case gcvDUMP_BUFFER_VERIFY: + dumpTag = "verify"; + break; + case gcvDUMP_BUFFER_PHYSICAL_MEMORY: + dumpTag = "physical"; + break; + default: + dumpTag = "memory"; + break; + } + + if (Type <= gcvDUMP_BUFFER_USER_TYPE_LAST) + { + gcmkVERIFY_OK(gckOS_QueryNeedCopy(Os, 0, &needCopy)); + } + + gcmkMUTEX_LOCK(_dumpMutex); + + /* Form and print the opening string. */ + if (Type == gcvDUMP_BUFFER_PHYSICAL_MEMORY) + { + gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1, + "@[%s 0x%010llX 0x%08X\n", + dumpTag, (unsigned long long)Address, (gctUINT32)Size); + } + else + { + gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1, + "@[%s 0x%08X 0x%08X\n", + dumpTag, (gctUINT32)Address, (gctUINT32)Size); + } + + gcmkDUMP_STRING(Os, buffer); + + + while (offset < Size) + { + gctPOINTER data = gcvNULL; + gctUINT32_PTR ptr; + gctUINT8_PTR bytePtr; + gctSIZE_T count, tailByteCount; + + length = maxLength < (Size - offset) ? maxLength : (Size - offset); + count = length / 4; + tailByteCount = length % 4; + + ptr = (gctUINT32_PTR)Data; + + if (Type <= gcvDUMP_BUFFER_USER_TYPE_LAST) + { + /* Copy or map from user. */ + if (needCopy) + { + gcmkONERROR(gckOS_CopyFromUserData( + Os, + _dumpStorage, + Data, + length + )); + + ptr = (gctUINT32_PTR)_dumpStorage; + } + else + { + gcmkONERROR(gckOS_MapUserPointer( + Os, + Data, + length, + (gctPOINTER *)&data + )); + + ptr = (gctUINT32_PTR)data; + } + } + + while (count >= 4) + { + gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1, + " 0x%08X 0x%08X 0x%08X 0x%08X\n", + ptr[0], ptr[1], ptr[2], ptr[3]); + + ptr += 4; + count -= 4; + + gcmkDUMP_STRING(Os, buffer); + } + + switch (count) + { + case 3: + gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1, + " 0x%08X 0x%08X 0x%08X", + ptr[0], ptr[1], ptr[2]); + break; + case 2: + gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1, + " 0x%08X 0x%08X", + ptr[0], ptr[1]); + break; + case 1: + gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1, " 0x%08X", ptr[0]); + break; + } + + if (count > 0) + { + gcmkDUMP_STRING(Os, buffer); + } + + bytePtr = (gctUINT8_PTR)(ptr + count); + + if (!count && tailByteCount) + { + /* There is an extra space for the new line. */ + gcmkDUMP_STRING(Os, " "); + } + + switch (tailByteCount) + { + case 3: + gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1, + " 0x00%02X%02X%02X", + bytePtr[2], bytePtr[1], bytePtr[0]); + break; + case 2: + gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1, + " 0x0000%02X%02X", + bytePtr[1], bytePtr[0]); + break; + case 1: + gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1, + " 0x000000%02X", bytePtr[0]); + break; + } + + if (tailByteCount) + { + gcmkDUMP_STRING(Os, buffer); + } + + if (count || tailByteCount) + { + gcmkDUMP_STRING(Os, "\n"); + } + + if (Type <= gcvDUMP_BUFFER_USER_TYPE_LAST && !needCopy) + { + gckOS_UnmapUserPointer(Os, Data, length, data); + } + /* advance to next batch. */ + Data = (gctUINT8_PTR)Data + length; + offset += length; + } + +OnError: + gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1, "] -- %s\n", dumpTag); + gcmkDUMP_STRING(Os, buffer); + + gcmkMUTEX_UNLOCK(_dumpMutex); +} + +/******************************************************************************* +** +** gckOS_DumpBuffer +** +** Print the contents of the specified buffer. +** +** INPUT: +** +** gckOS Os +** Pointer to gckOS object. +** +** gceDUMP_BUFFER_TYPE Type +** Buffer type. +** +** gctPOINTER Buffer +** Pointer to the buffer to print. +** +** gctUINT64 Address +** Address. +** +** gctUINT Size +** Size of the buffer. +** +** +** OUTPUT: +** +** Nothing. +*/ +void +gckOS_DumpBuffer( + IN gckOS Os, + IN gceDUMP_BUFFER_TYPE Type, + IN gctPOINTER Buffer, + IN gctUINT64 Address, + IN gctSIZE_T Size + ) +{ + if (!Buffer) + { + return; + } + + /* memory dump below. */ + if (Type >= gcvDUMP_BUFFER_TYPE_COUNT) + { + gcmkPRINT("#[ERROR: invalid buffer type]\n"); + return; + } + + if (Type == gcvDUMP_BUFFER_USER_STRING) + { + _DumpUserString(Os, Buffer, Size); + } + else + { + _DumpDataBuffer(Os, Type, Buffer, Address, Size); + } +} |