From 162af638a712b5ce94f6cdceed1e5053b5352841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremi=20Jasi=C5=84ski?= Date: Tue, 17 Dec 2019 08:05:58 +0100 Subject: [PATCH 1/5] Move fopen to working thread (increase SDcard operations speed) --- ..._storage_native_Windows_Storage_FileIO.cpp | 648 ++++++++---------- ...e_native_Windows_Storage_StorageFolder.cpp | 364 ++++++---- 2 files changed, 511 insertions(+), 501 deletions(-) diff --git a/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp b/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp index e13c487c49..0514d912fb 100644 --- a/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp +++ b/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp @@ -20,6 +20,7 @@ typedef Library_win_storage_native_Windows_Storage_StorageFile StorageFile; struct FileOperation { FIL* File; + const char* FileName; char* Content; uint32_t ContentLength; }; @@ -28,117 +29,139 @@ struct FileOperation static volatile FRESULT threadOperationResult; // ReadText working thread -static void ReadTextWorkingThread(void * arg) -{ +static void ReadTextWorkingThread(void *arg) { - FileOperation* fileIoOperation = (FileOperation*)arg; + FileOperation *fileIoOperation = (FileOperation *)arg; - // need an extra one for the terminator - uint32_t readLength = fileIoOperation->ContentLength + 1; - - // read string - if(f_gets((TCHAR*)fileIoOperation->Content, readLength, fileIoOperation->File)) - { - threadOperationResult = FR_OK; - } - else - { - threadOperationResult = (FRESULT)f_error(fileIoOperation->File); - } + FIL file; + + // need an extra one for the terminator + uint32_t readLength = fileIoOperation->ContentLength + 1; - // close file - f_close(fileIoOperation->File); + // open file (which is supposed to already exist) + // need to use FA_OPEN_EXISTING because we are reading an existing file content from start + threadOperationResult = f_open(&file, fileIoOperation->FileName, FA_OPEN_EXISTING | FA_READ); + if (threadOperationResult != FR_OK) { // free memory - platform_free(fileIoOperation->File); - platform_free(fileIoOperation); + free(fileIoOperation); + return; + } - // fire event for FileIO operation complete - Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + // read string + if (f_gets((TCHAR *)fileIoOperation->Content, readLength, &file)) { + threadOperationResult = FR_OK; + } else { + threadOperationResult = (FRESULT)f_error(&file); + } - vTaskDelete(NULL); + // close file + f_close(&file); + + // free memory + free(fileIoOperation); + + // fire event for FileIO operation complete + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + + vTaskDelete(NULL); } // WriteText working thread -static void WriteTextWorkingThread(void *arg) -{ +static void WriteTextWorkingThread(void *arg) { - FileOperation* fileIoOperation = (FileOperation*)arg; - if(f_puts(fileIoOperation->Content, fileIoOperation->File) == (int)fileIoOperation->ContentLength) - { - // expected number of bytes written - threadOperationResult = FR_OK; - } + FileOperation *fileIoOperation = (FileOperation *)arg; + + FIL file; - // close file - f_close(fileIoOperation->File); + // open file (which is supposed to already exist) + // need to use FA_OPEN_ALWAYS because we are writting the file content from start + threadOperationResult = f_open(&file, fileIoOperation->FileName, FA_OPEN_ALWAYS | FA_WRITE); + if (threadOperationResult != FR_OK) { // free memory - platform_free(fileIoOperation->File); - platform_free(fileIoOperation); + free(fileIoOperation); + return; + } - // fire event for FileIO operation complete - Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); - - vTaskDelete(NULL); + if (f_puts(fileIoOperation->Content, &file) == (int)fileIoOperation->ContentLength) { + // expected number of bytes written + threadOperationResult = FR_OK; + } + + // close file + f_close(&file); + + // free memory + free(fileIoOperation); + + // fire event for FileIO operation complete + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + + vTaskDelete(NULL); } // WriteBinary working thread -static void WriteBinaryWorkingThread(void *arg) -{ - UINT bytesWritten; - - FileOperation* fileIoOperation = (FileOperation*)arg; +static void WriteBinaryWorkingThread(void *arg) { + UINT bytesWritten; - threadOperationResult = f_write(fileIoOperation->File, fileIoOperation->Content, fileIoOperation->ContentLength, &bytesWritten); + FileOperation *fileIoOperation = reinterpret_cast(arg); - if( (threadOperationResult == FR_OK) && - (bytesWritten == fileIoOperation->ContentLength)) - { - // expected number of bytes written - threadOperationResult = FR_OK; - } + FIL file; - // close file - f_close(fileIoOperation->File); + // open file (which is supposed to already exist) + // need to use FA_OPEN_ALWAYS because we are writting the file content from start + threadOperationResult = f_open(&file, fileIoOperation->FileName, FA_OPEN_ALWAYS | FA_WRITE); + if (threadOperationResult != FR_OK) { // free memory - platform_free(fileIoOperation->File); - platform_free(fileIoOperation); + free(fileIoOperation); + return; + } + + threadOperationResult = f_write(&file, fileIoOperation->Content, fileIoOperation->ContentLength, &bytesWritten); + + if ((threadOperationResult == FR_OK) && (bytesWritten == fileIoOperation->ContentLength)) { + // expected number of bytes written + threadOperationResult = FR_OK; + } + + // close file + f_close(&file); - // fire event for FileIO operation complete - Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); - - vTaskDelete(NULL); + // free memory + free(fileIoOperation); + + // fire event for FileIO operation complete + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + + vTaskDelete(NULL); } // ReadBinary working thread -static void ReadBinaryWorkingThread(void *arg) -{ - UINT bytesRead; +static void ReadBinaryWorkingThread(void *arg) { + UINT bytesRead; - FileOperation* fileIoOperation = (FileOperation*)arg; + FileOperation *fileIoOperation = reinterpret_cast(arg); - threadOperationResult = f_read(fileIoOperation->File, fileIoOperation->Content, fileIoOperation->ContentLength, &bytesRead); + threadOperationResult = f_read(fileIoOperation->File, fileIoOperation->Content, fileIoOperation->ContentLength, &bytesRead); - if( (threadOperationResult == FR_OK) && - (bytesRead == fileIoOperation->ContentLength)) - { - // expected number of bytes read - threadOperationResult = FR_OK; - } + if ((threadOperationResult == FR_OK) && (bytesRead == fileIoOperation->ContentLength)) { + // expected number of bytes read + threadOperationResult = FR_OK; + } - // close file - f_close(fileIoOperation->File); + // close file + f_close(fileIoOperation->File); - // free memory - platform_free(fileIoOperation->File); - platform_free(fileIoOperation); + // free memory + free(fileIoOperation->File); + free(fileIoOperation); + + // fire event for FileIO operation complete + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); - // fire event for FileIO operation complete - Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); - - vTaskDelete(NULL); + vTaskDelete(NULL); } //////////////////////////////////////////////// @@ -158,21 +181,16 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteBytes___STATIC__ CLR_RT_HeapBlock_Array* bufferArray; - char workingDrive[DRIVE_LETTER_LENGTH]; - CLR_RT_HeapBlock hbTimeout; CLR_INT64* timeout; bool eventResult = true; - FileOperation* fileIoOperation; + const TCHAR* filePath; + char* buffer; uint32_t bufferLength; - const TCHAR* filePath; - FIL* file; - FRESULT operationResult; - // get a pointer to the managed object instance and check that it's not NULL CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); @@ -193,51 +211,28 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteBytes___STATIC__ if(stack.m_customState == 1) { - // copy the first 2 letters of the path for the drive - // path is 'D:\folder\file.txt', so we need 'D:' - memcpy(workingDrive, filePath, DRIVE_LETTER_LENGTH); - - // create file struct - file = (FIL*)platform_malloc(sizeof(FIL)); - // check allocation - if(file == NULL) - { - NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); - } - - // open file (which is supposed to already exist) - // need to use FA_OPEN_ALWAYS because we are writting the file content from start - operationResult = f_open(file, filePath, FA_OPEN_ALWAYS | FA_WRITE); - - if(operationResult != FR_OK) - { - NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); - } - else - { - // protect the StorageFile and the content buffer from GC so the working thread can access those - CLR_RT_ProtectFromGC gcStorageFile( *pThis ); - CLR_RT_ProtectFromGC gcContent( *bufferArray ); + // protect the content buffer from GC so the working thread can access those + CLR_RT_ProtectFromGC gcContent( *bufferArray ); - // setup FileIO operation - fileIoOperation = (FileOperation*)platform_malloc(sizeof(FileOperation)); + // setup FileIO operation + FileOperation *fileIoOperation = reinterpret_cast(malloc(sizeof(FileOperation))); - fileIoOperation->File = file; - fileIoOperation->Content = buffer; - fileIoOperation->ContentLength = bufferLength; + //fileIoOperation->File = file; + fileIoOperation->FileName = filePath; + fileIoOperation->Content = buffer; + fileIoOperation->ContentLength = bufferLength; - // spawn working thread to perform the write transaction - BaseType_t ret; - ret = xTaskCreate(WriteBinaryWorkingThread, "WriteBin", 2048, fileIoOperation, configMAX_PRIORITIES - 2, NULL); + // spawn working thread to perform the write transaction + BaseType_t ret; + ret = xTaskCreate(WriteBinaryWorkingThread, "WriteBin", configMINIMAL_STACK_SIZE + 600, fileIoOperation, configMAX_PRIORITIES - 2, NULL); - if (ret != pdPASS) - { - NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); - } - - // bump custom state - stack.m_customState = 2; + if (ret != pdPASS) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); } + + // bump custom state + stack.m_customState = 2; } while(eventResult) @@ -278,123 +273,83 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteBytes___STATIC__ NANOCLR_NOCLEANUP(); } -HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteText___STATIC__VOID__WindowsStorageIStorageFile__STRING( CLR_RT_StackFrame& stack ) -{ - NANOCLR_HEADER(); +HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteText___STATIC__VOID__WindowsStorageIStorageFile__STRING(CLR_RT_StackFrame &stack) { + NANOCLR_HEADER(); - CLR_RT_HeapBlock_String* content; + CLR_RT_HeapBlock_String *content; - char workingDrive[DRIVE_LETTER_LENGTH]; + CLR_RT_HeapBlock hbTimeout; + CLR_INT64 *timeout; + bool eventResult = true; - CLR_RT_HeapBlock hbTimeout; - CLR_INT64* timeout; - bool eventResult = true; + const TCHAR *filePath; - FileOperation* fileIoOperation; + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock *pThis = stack.This(); + FAULT_ON_NULL(pThis); - const TCHAR* filePath; - FIL* file; - FRESULT operationResult; + // get a pointer to the content + content = stack.Arg1().DereferenceString(); - // get a pointer to the managed object instance and check that it's not NULL - CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); - - // get a pointer to the content - content = stack.Arg1().DereferenceString(); - - // get a pointer to the file path - filePath = (TCHAR*)pThis[ StorageFile::FIELD___path ].DereferenceString()->StringText(); - - // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite - hbTimeout.SetInteger((CLR_INT64)-1); + // get a pointer to the file path + filePath = (TCHAR *)pThis[StorageFile::FIELD___path].DereferenceString()->StringText(); - NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); - - if(stack.m_customState == 1) - { - // copy the first 2 letters of the path for the drive - // path is 'D:\folder\file.txt', so we need 'D:' - memcpy(workingDrive, filePath, DRIVE_LETTER_LENGTH); - - // create file struct - file = (FIL*)platform_malloc(sizeof(FIL)); - // check allocation - if(file == NULL) - { - NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); - } + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger((CLR_INT64)-1); - // open file (which is supposed to already exist) - // need to use FA_OPEN_ALWAYS because we are writting the file content from start - operationResult = f_open(file, filePath, FA_OPEN_ALWAYS | FA_WRITE); - - if(operationResult != FR_OK) - { - NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); - } - else - { - // protect the StorageFile and the content buffer from GC so the working thread can access those - CLR_RT_ProtectFromGC gcStorageFile( *pThis ); - CLR_RT_ProtectFromGC gcContent( *content ); + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks(hbTimeout, timeout)); - // setup FileIO operation - fileIoOperation = (FileOperation*)platform_malloc(sizeof(FileOperation)); + if (stack.m_customState == 1) { + // protect the StorageFile and the content buffer from GC so the working thread can access those + CLR_RT_ProtectFromGC gcStorageFile(*pThis); + CLR_RT_ProtectFromGC gcContent(*content); - fileIoOperation->File = file; - fileIoOperation->Content = (char*)content->StringText(); - fileIoOperation->ContentLength = hal_strlen_s(fileIoOperation->Content); + // setup FileIO operation + FileOperation *fileIoOperation = (FileOperation *)malloc(sizeof(FileOperation)); - // spawn working thread to perform the write transaction - BaseType_t ret; - ret = xTaskCreate(WriteTextWorkingThread, "WriteText", 2048, fileIoOperation, configMAX_PRIORITIES - 2, NULL); + fileIoOperation->FileName = filePath; + fileIoOperation->Content = (char *)content->StringText(); + fileIoOperation->ContentLength = hal_strlen_s(fileIoOperation->Content); - if (ret != pdPASS) - { - NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); - } + // spawn working thread to perform the write transaction + BaseType_t ret; + ret = xTaskCreate(WriteTextWorkingThread, "WriteText", configMINIMAL_STACK_SIZE + 400, fileIoOperation, configMAX_PRIORITIES - 2, NULL); - // bump custom state - stack.m_customState = 2; - } + if (ret != pdPASS) { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); } - while(eventResult) - { - // non-blocking wait allowing other threads to run while we wait for the write operation to complete - NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult )); - - if(eventResult) - { - // event occurred - - if(threadOperationResult == FR_DISK_ERR) - { - NANOCLR_SET_AND_LEAVE( CLR_E_FILE_IO ); - } - else if(threadOperationResult == FR_NO_FILE) - { - NANOCLR_SET_AND_LEAVE( CLR_E_FILE_NOT_FOUND ); - } - else if(threadOperationResult == FR_INVALID_DRIVE) - { - // failed to change drive - NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); - } - - // done here - break; - } - else - { - NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); - } + // bump custom state + stack.m_customState = 2; + } + + while (eventResult) { + // non-blocking wait allowing other threads to run while we wait for the write operation to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents(stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult)); + + if (eventResult) { + // event occurred + + if (threadOperationResult == FR_DISK_ERR) { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } else if (threadOperationResult == FR_NO_FILE) { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } else if (threadOperationResult == FR_INVALID_DRIVE) { + // failed to change drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + + // done here + break; + } else { + NANOCLR_SET_AND_LEAVE(CLR_E_TIMEOUT); } + } - // pop timeout heap block from stack - stack.PopValue(); + // pop timeout heap block from stack + stack.PopValue(); - NANOCLR_NOCLEANUP(); + NANOCLR_NOCLEANUP(); } HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___STATIC__VOID__WindowsStorageIStorageFile__BYREF_SZARRAY_U1( CLR_RT_StackFrame& stack ) @@ -405,13 +360,9 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___ST CLR_INT64* timeout; bool eventResult = true; - FileOperation* fileIoOperation; - - char workingDrive[DRIVE_LETTER_LENGTH]; const TCHAR* filePath; FIL* file; - static FILINFO fileInfo; FRESULT operationResult; // get a pointer to the managed object instance and check that it's not NULL @@ -427,15 +378,8 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___ST if(stack.m_customState == 1) { - // protect the StorageFile from GC - CLR_RT_ProtectFromGC gcStorageFile( *pThis ); - - // copy the first 2 letters of the path for the drive - // path is 'D:\folder\file.txt', so we need 'D:' - memcpy(workingDrive, filePath, DRIVE_LETTER_LENGTH); - // create file struct - file = (FIL*)platform_malloc(sizeof(FIL)); + file = (FIL*)malloc(sizeof(FIL)); // check allocation if(file == NULL) { @@ -450,43 +394,43 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___ST { NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); } - else - { - // get file details - f_stat(filePath, &fileInfo); - - CLR_RT_HeapBlock buffer; - buffer.SetObjectReference( NULL ); - CLR_RT_ProtectFromGC gc2( buffer ); + + // get file details + static FILINFO fileInfo; + f_stat(filePath, &fileInfo); - // create a new byte array with the appropriate size (and type) - NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( buffer, (CLR_INT32)fileInfo.fsize, g_CLR_RT_WellKnownTypes.m_UInt8 )); + CLR_RT_HeapBlock buffer; + buffer.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc2( buffer ); - // store this to the argument passed byref - NANOCLR_CHECK_HRESULT(buffer.StoreToReference( stack.Arg1(), 0 )); + // create a new byte array with the appropriate size (and type) + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( buffer, (CLR_INT32)fileInfo.fsize, g_CLR_RT_WellKnownTypes.m_UInt8 )); - // get a pointer to the buffer array to improve readability on the code ahead - CLR_RT_HeapBlock_Array* bufferArray = buffer.DereferenceArray(); + // store this to the argument passed byref + NANOCLR_CHECK_HRESULT(buffer.StoreToReference( stack.Arg1(), 0 )); - // setup FileIO operation - fileIoOperation = (FileOperation*)platform_malloc(sizeof(FileOperation)); + // get a pointer to the buffer array to improve readability on the code ahead + CLR_RT_HeapBlock_Array* bufferArray = buffer.DereferenceArray(); - fileIoOperation->File = file; - fileIoOperation->Content = (char*)bufferArray->GetFirstElement(); - fileIoOperation->ContentLength = bufferArray->m_numOfElements; + // setup FileIO operation + FileOperation *fileIoOperation = reinterpret_cast(malloc(sizeof(FileOperation))); - // spawn working thread to perform the read transaction - BaseType_t ret; - ret = xTaskCreate(ReadBinaryWorkingThread, "ReadBin", 2048, fileIoOperation, configMAX_PRIORITIES - 2, NULL); + fileIoOperation->File = file; + fileIoOperation->Content = (char*)bufferArray->GetFirstElement(); + fileIoOperation->ContentLength = bufferArray->m_numOfElements; - if (ret != pdPASS) - { - NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); - } + // spawn working thread to perform the read transaction + BaseType_t ret; + ret = xTaskCreate(ReadBinaryWorkingThread, "ReadBin", configMINIMAL_STACK_SIZE + 100, fileIoOperation, configMAX_PRIORITIES - 2, NULL); - // bump custom state - stack.m_customState = 2; + if (ret != pdPASS) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); } + + // bump custom state + stack.m_customState = 2; + } while(eventResult) @@ -527,133 +471,91 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___ST NANOCLR_NOCLEANUP(); } -HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadTextNative___STATIC__VOID__WindowsStorageIStorageFile__BYREF_STRING( CLR_RT_StackFrame& stack ) -{ - NANOCLR_HEADER(); +HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadTextNative___STATIC__VOID__WindowsStorageIStorageFile__BYREF_STRING(CLR_RT_StackFrame &stack) { + NANOCLR_HEADER(); - CLR_RT_HeapBlock hbTimeout; - CLR_INT64* timeout; - bool eventResult = true; + CLR_RT_HeapBlock hbTimeout; + CLR_INT64 *timeout; + bool eventResult = true; - FileOperation* fileIoOperation; + const TCHAR *filePath; - char workingDrive[DRIVE_LETTER_LENGTH]; - const TCHAR* filePath; + static FILINFO fileInfo; - FIL* file; - static FILINFO fileInfo; - FRESULT operationResult; + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock *pThis = stack.This(); + FAULT_ON_NULL(pThis); - // get a pointer to the managed object instance and check that it's not NULL - CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger((CLR_INT64)-1); - // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite - hbTimeout.SetInteger((CLR_INT64)-1); + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks(hbTimeout, timeout)); - NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + // get a pointer to the file path + filePath = (TCHAR *)pThis[StorageFile::FIELD___path].DereferenceString()->StringText(); - // get a pointer to the file path - filePath = (TCHAR*)pThis[ StorageFile::FIELD___path ].DereferenceString()->StringText(); - - if(stack.m_customState == 1) - { - // protect the StorageFile and the content buffer from GC so the working thread can access those - CLR_RT_ProtectFromGC gcStorageFile( *pThis ); + if (stack.m_customState == 1) { + // protect the StorageFile and the content buffer from GC so the working thread can access those + CLR_RT_ProtectFromGC gcStorageFile(*pThis); - // copy the first 2 letters of the path for the drive - // path is 'D:\folder\file.txt', so we need 'D:' - memcpy(workingDrive, filePath, DRIVE_LETTER_LENGTH); + // get file details + f_stat(filePath, &fileInfo); - // create file struct - file = (FIL*)platform_malloc(sizeof(FIL)); - // check allocation - if(file == NULL) - { - NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); - } - - // open file (which is supposed to already exist) - // need to use FA_OPEN_EXISTING because we are reading an existing file content from start - operationResult = f_open(file, filePath, FA_OPEN_EXISTING | FA_READ); - - if(operationResult != FR_OK) - { - NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); - } - else - { - // get file details - f_stat(filePath, &fileInfo); + // create a new string object with the appropriate size + CLR_RT_HeapBlock hbText; + hbText.SetObjectReference(NULL); + CLR_RT_ProtectFromGC gc(hbText); - // create a new string object with the appropriate size - CLR_RT_HeapBlock hbText; - hbText.SetObjectReference( NULL ); - CLR_RT_ProtectFromGC gc( hbText ); + CLR_RT_HeapBlock_String *textString = CLR_RT_HeapBlock_String::CreateInstance(hbText, (CLR_UINT32)fileInfo.fsize); + FAULT_ON_NULL(textString); - CLR_RT_HeapBlock_String* textString = CLR_RT_HeapBlock_String::CreateInstance( hbText, (CLR_UINT32)fileInfo.fsize ); - FAULT_ON_NULL(textString); + // store this to the argument passed byref + NANOCLR_CHECK_HRESULT(hbText.StoreToReference(stack.Arg1(), 0)); - // store this to the argument passed byref - NANOCLR_CHECK_HRESULT(hbText.StoreToReference( stack.Arg1(), 0 )); + // setup FileIO operation + FileOperation *fileIoOperation = (FileOperation *)malloc(sizeof(FileOperation)); - // get a pointer to the buffer array to improve readability on the code ahead - hbText.DereferenceString(); + fileIoOperation->FileName = filePath; + fileIoOperation->Content = (char *)textString->StringText(); + fileIoOperation->ContentLength = fileInfo.fsize; - // setup FileIO operation - fileIoOperation = (FileOperation*)platform_malloc(sizeof(FileOperation)); + // spawn working thread to perform the read transaction + BaseType_t ret; + ret = xTaskCreate(ReadTextWorkingThread, "ReadText", configMINIMAL_STACK_SIZE + 300, fileIoOperation, configMAX_PRIORITIES - 2, NULL); - fileIoOperation->File = file; - fileIoOperation->Content = (char*)textString->StringText(); - fileIoOperation->ContentLength = fileInfo.fsize; - - // spawn working thread to perform the read transaction - BaseType_t ret; - ret = xTaskCreate(ReadTextWorkingThread, "ReadText", 2048, fileIoOperation, configMAX_PRIORITIES - 2, NULL); - - if (ret != pdPASS) - { - NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); - } - - // bump custom state - stack.m_customState = 2; - } + if (ret != pdPASS) { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); } - while(eventResult) - { - // non-blocking wait allowing other threads to run while we wait for the write operation to complete - NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult )); - - if(eventResult) - { - // event occurred - - if(threadOperationResult == FR_DISK_ERR) - { - NANOCLR_SET_AND_LEAVE( CLR_E_FILE_IO ); - } - else if(threadOperationResult == FR_NO_FILE) - { - NANOCLR_SET_AND_LEAVE( CLR_E_FILE_NOT_FOUND ); - } - else if(threadOperationResult == FR_INVALID_DRIVE) - { - // failed to change drive - NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); - } - - // done here - break; - } - else - { - NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); - } + // bump custom state + stack.m_customState = 2; + } + + while (eventResult) { + // non-blocking wait allowing other threads to run while we wait for the write operation to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents(stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult)); + + if (eventResult) { + // event occurred + + if (threadOperationResult == FR_DISK_ERR) { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } else if (threadOperationResult == FR_NO_FILE) { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } else if (threadOperationResult == FR_INVALID_DRIVE) { + // failed to change drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + + // done here + break; + } else { + NANOCLR_SET_AND_LEAVE(CLR_E_TIMEOUT); } + } - // pop timeout heap block from stack - stack.PopValue(); + // pop timeout heap block from stack + stack.PopValue(); - NANOCLR_NOCLEANUP(); -} + NANOCLR_NOCLEANUP(); +} \ No newline at end of file diff --git a/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFolder.cpp b/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFolder.cpp index e34dfacf3a..e9add0f12a 100644 --- a/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFolder.cpp +++ b/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFolder.cpp @@ -50,15 +50,11 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetRemovableSt { NANOCLR_HEADER(); - char* stringBuffer; uint32_t driveCount = 0; - char workingDrive[sizeof(DRIVE_PATH_LENGTH)]; - uint16_t driveIterator = 0; CLR_RT_HeapBlock* storageFolder; CLR_RT_TypeDef_Index storageFolderTypeDef; - CLR_RT_HeapBlock* hbObj; - CLR_RT_HeapBlock& top = stack.PushValue(); + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); // is the SD card file system ready? if(sdCardFileSystemReady) @@ -86,8 +82,9 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetRemovableSt // loop until we've loaded all the possible drives // because we are iterating through an enum, need to use its integer values - for(; driveIterator < driveCount; driveIterator++ ) + for(uint16_t driveIterator = 0; driveIterator < driveCount; driveIterator++ ) { + char workingDrive[sizeof(DRIVE_PATH_LENGTH)]; // fill the folder name and path switch(driveIterator) { @@ -106,14 +103,14 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetRemovableSt } // dereference the object in order to reach its fields - hbObj = storageFolder->Dereference(); + CLR_RT_HeapBlock *hbObj = storageFolder->Dereference(); // set the managed fields NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[ Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___name ], workingDrive )); NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[ Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ], workingDrive )); // malloc stringBuffer to work with FS - stringBuffer = (char*)platform_malloc(FF_LFN_BUF + 1); + char* stringBuffer = (char*)malloc(FF_LFN_BUF + 1); // sanity check for successfull malloc if(stringBuffer == NULL) @@ -144,7 +141,7 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetRemovableSt // free stringBuffer - platform_free(stringBuffer); + free(stringBuffer); } // move pointer to the next folder item @@ -157,7 +154,7 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetRemovableSt HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetInternalStorageFoldersNative___SZARRAY_WindowsStorageStorageFolder(CLR_RT_StackFrame& stack) { - NANOCLR_HEADER(); +NANOCLR_HEADER(); { CLR_RT_TypeDef_Index storageFolderTypeDef; @@ -259,8 +256,8 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetStorageFold if(directoryCount > 0) { // allocate memory for buffers - stringBuffer = (char*)platform_malloc(FF_LFN_BUF + 1); - workingBuffer = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + stringBuffer = (char*)malloc(FF_LFN_BUF + 1); + workingBuffer = (char*)malloc(2 * FF_LFN_BUF + 1); // sanity check for successfull malloc if(stringBuffer == NULL || workingBuffer == NULL) @@ -333,11 +330,11 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetStorageFold // free buffers memory, if allocated if(stringBuffer != NULL) { - platform_free(stringBuffer); + free(stringBuffer); } if(workingBuffer != NULL) { - platform_free(workingBuffer); + free(workingBuffer); } NANOCLR_CLEANUP_END(); @@ -357,7 +354,6 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetStorageFile uint32_t startIndex; uint32_t maxItemsToRetrieve; - uint32_t itemIndex = 0; DIR currentDirectory; FRESULT operationResult; @@ -398,6 +394,8 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetStorageFile } else { + uint32_t itemIndex = 0; + // need to perform this in two steps // 1st: count the file objects // 2nd: create the array items with each file object @@ -445,8 +443,8 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetStorageFile if(fileCount > 0) { // allocate memory for buffers - stringBuffer = (char*)platform_malloc(FF_LFN_BUF + 1); - workingBuffer = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + stringBuffer = (char*)malloc(FF_LFN_BUF + 1); + workingBuffer = (char*)malloc(2 * FF_LFN_BUF + 1); // sanity check for successfull malloc if(stringBuffer == NULL || workingBuffer == NULL) @@ -544,19 +542,72 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetStorageFile // free buffers memory, if allocated if(stringBuffer != NULL) { - platform_free(stringBuffer); + free(stringBuffer); } if(workingBuffer != NULL) { - platform_free(workingBuffer); + free(workingBuffer); } NANOCLR_CLEANUP_END(); } +struct FileOperation { + const char *FilePath; + uint8_t mode; + enum CreationCollisionOption options; +}; + +// this is the FileIO working thread +static volatile FRESULT threadOperationResult; + +// CreateFile working thread +static void CreateFileWorkingThread(void *arg) { + + FileOperation *fileIoOperation = reinterpret_cast(arg); + + // create file struct + FIL file; + + // open file + FRESULT operationResult = f_open(&file, fileIoOperation->FilePath, fileIoOperation->mode); + + // process operation result according to creation options + if ((operationResult == FR_EXIST) && (fileIoOperation->options == CreationCollisionOption_FailIfExists)) { + // file already exists + threadOperationResult = FR_EXIST; + f_close(&file); + return; + } + if ((operationResult == FR_NO_FILE) && (fileIoOperation->options == CreationCollisionOption_OpenIfExists)) { + // file doesn't exist + threadOperationResult = FR_NO_FILE; + f_close(&file); + return; + } + + threadOperationResult = FR_OK; + + // close file + f_close(&file); + + // free memory + free((void *)fileIoOperation->FilePath); + free(fileIoOperation); + + // fire event for FileIO operation complete + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + + vTaskDelete(NULL); +} + HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::CreateFileNative___WindowsStorageStorageFile__STRING__U4( CLR_RT_StackFrame& stack ) { NANOCLR_HEADER(); + + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; CLR_RT_TypeDef_Index storageFileTypeDef; CLR_RT_HeapBlock* storageFile; @@ -566,11 +617,7 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::CreateFileNati CreationCollisionOption options; - FIL file; - static FILINFO fileInfo; - SYSTEMTIME fileInfoTime; - FRESULT operationResult; - uint8_t modeFlags = 0; + char* filePath = NULL; // get a pointer to the managed object instance and check that it's not NULL @@ -585,113 +632,155 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::CreateFileNati // get a pointer to the desired file name fileName = stack.Arg1().DereferenceString()->StringText(); - // setup file path - filePath = (char*)platform_malloc(2 * FF_LFN_BUF + 1); - - // sanity check for successfull malloc - if(filePath == NULL) - { - // failed to allocate memory - NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); - } + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger((CLR_INT64)-1); - // clear working buffer - memset(filePath, 0, 2 * FF_LFN_BUF + 1); + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); - // compose file path - CombinePath(filePath, workingPath, fileName); + if(stack.m_customState == 1) + { - // compute mode flags from CreationCollisionOption - switch (options) - { - case CreationCollisionOption_ReplaceExisting: - modeFlags = FA_CREATE_ALWAYS; - break; + // setup file path + filePath = (char*)malloc(2 * FF_LFN_BUF + 1); - case CreationCollisionOption_FailIfExists: - modeFlags = FA_CREATE_NEW; - break; + // sanity check for successfull malloc + if(filePath == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } - case CreationCollisionOption_OpenIfExists: - modeFlags = FA_OPEN_EXISTING; - break; - - case CreationCollisionOption_GenerateUniqueName: - // this operation is not supported in nanoFramework - NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); - break; + // clear working buffer + memset(filePath, 0, 2 * FF_LFN_BUF + 1); - default: - break; - } + // compose file path + CombinePath(filePath, workingPath, fileName); - // open file - operationResult = f_open(&file, filePath, modeFlags); + uint8_t modeFlags = 0; + // compute mode flags from CreationCollisionOption + switch (options) + { + case CreationCollisionOption_ReplaceExisting: + modeFlags = FA_CREATE_ALWAYS; + break; - // process operation result according to creation options - if( (operationResult == FR_EXIST) && - (options == CreationCollisionOption_FailIfExists)) - { - // file already exists - NANOCLR_SET_AND_LEAVE(CLR_E_PATH_ALREADY_EXISTS); - } - if( (operationResult == FR_NO_FILE) && - (options == CreationCollisionOption_OpenIfExists)) - { - // file doesn't exist - NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); - } + case CreationCollisionOption_FailIfExists: + modeFlags = FA_CREATE_NEW; + break; - if(operationResult == FR_OK) - { - // file created (or opened) succesfully - // OK to close it - f_close(&file); + case CreationCollisionOption_OpenIfExists: + modeFlags = FA_OPEN_ALWAYS; + break; - // now get the details - f_stat(fileName, &fileInfo); + case CreationCollisionOption_GenerateUniqueName: + // this operation is not supported in nanoFramework + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; - // compose return object - // find type, don't bother checking the result as it exists for sure - g_CLR_RT_TypeSystem.FindTypeDef( "StorageFile", "Windows.Storage", storageFileTypeDef ); + default: + break; + } - // create a - NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), storageFileTypeDef)); - - // get a handle to the storage file - storageFile = stack.TopValue().Dereference(); + // setup File operation + FileOperation *fileOperation = reinterpret_cast(malloc(sizeof(FileOperation))); - // file name - NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFile[ Library_win_storage_native_Windows_Storage_StorageFile::FIELD___name ], fileName )); + fileOperation->FilePath = filePath; + fileOperation->mode = modeFlags; - NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFile[ Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path ], filePath )); + // spawn working thread to perform the write transaction + BaseType_t ret; + ret = xTaskCreate(CreateFileWorkingThread, "CreateFile", configMINIMAL_STACK_SIZE + 600, fileOperation, configMAX_PRIORITIES - 2, NULL); - // get the date time details and fill in the managed field - // compute directory date - fileInfoTime = GetDateTime(fileInfo.fdate, fileInfo.ftime); + if (ret != pdPASS) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } - // get a reference to the dateCreated managed field... - CLR_RT_HeapBlock& dateFieldRef = storageFile[ Library_win_storage_native_Windows_Storage_StorageFile::FIELD___dateCreated ]; - CLR_INT64* pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; - // ...and set it with the fileInfoTime - *pRes = HAL_Time_ConvertFromSystemTime( &fileInfoTime ); + // bump custom state + stack.m_customState = 2; } - else + + while(eventResult) { - // failed to create the file - NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); - } - + // non-blocking wait allowing other threads to run while we wait for the write operation to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult )); - NANOCLR_CLEANUP(); + if(eventResult) + { + // event occurred - // free buffer memory, if allocated - if(filePath != NULL) - { - platform_free(filePath); + if(threadOperationResult == FR_DISK_ERR) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_IO ); + } + else if(threadOperationResult == FR_NO_FILE) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_NOT_FOUND ); + } + else if(threadOperationResult == FR_EXIST) + { + NANOCLR_SET_AND_LEAVE( CLR_E_PATH_ALREADY_EXISTS); + } + else if(threadOperationResult == FR_INVALID_DRIVE) + { + // failed to change drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + + // pop timeout heap block from stack + stack.PopValue(); + + // compose return object + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFile", "Windows.Storage", storageFileTypeDef ); + + // create a + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), storageFileTypeDef)); + + // get a handle to the storage file + storageFile = stack.TopValue().Dereference(); + + // setup file path + filePath = (char*)malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if(filePath == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // clear working buffer + memset(filePath, 0, 2 * FF_LFN_BUF + 1); + + // compose file path + CombinePath(filePath, workingPath, fileName); + + // file name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFile[ Library_win_storage_native_Windows_Storage_StorageFile::FIELD___name ], fileName )); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFile[ Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path ], filePath )); + + // get a reference to the dateCreated managed field... + CLR_RT_HeapBlock& dateFieldRef = storageFile[ Library_win_storage_native_Windows_Storage_StorageFile::FIELD___dateCreated ]; + CLR_INT64* pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; + // ...and set it with the current DateTime + *pRes = HAL_Time_CurrentDateTime(false); + + free(filePath); + + // done here + break; + } + else + { + NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); + } } + + - NANOCLR_CLEANUP_END(); + NANOCLR_NOCLEANUP(); } HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::CreateFolderNative___WindowsStorageStorageFolder__STRING__U4( CLR_RT_StackFrame& stack ) @@ -723,7 +812,7 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::CreateFolderNa // get a pointer to the desired folder name folderName = stack.Arg1().DereferenceString()->StringText(); - folderPath = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + folderPath = (char*)malloc(2 * FF_LFN_BUF + 1); // sanity check for successfull malloc if(folderPath == NULL) @@ -741,16 +830,29 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::CreateFolderNa //check if folder exists operationResult = f_stat(folderPath, &fileInfo); - //folder not exists - if (operationResult == FR_NO_FILE) + if (operationResult == FR_OK) { - if ( options == CreationCollisionOption_OpenIfExists) + if (options == CreationCollisionOption_FailIfExists) { - // folder doesn't exist - NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_FOUND); + // folder already exists + NANOCLR_SET_AND_LEAVE(CLR_E_PATH_ALREADY_EXISTS); } - else + else if (options == CreationCollisionOption_ReplaceExisting) { + // remove folder + operationResult = f_unlink(folderPath); + if (operationResult == FR_INVALID_NAME) + { + // Invalid path + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + else if (operationResult == FR_DENIED) + { + //folder is propably not empty + //TODO - add recursive deletion of directories and files + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } + // create directory operationResult = f_mkdir(folderPath); @@ -764,18 +866,24 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::CreateFolderNa NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); } } - - } - else + else if (options == CreationCollisionOption_GenerateUniqueName) + { + //TODO - add generating unique name + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } + } + else if (operationResult == FR_NO_FILE) { - if (options == CreationCollisionOption_FailIfExists) + // create directory + operationResult = f_mkdir(folderPath); + + if(operationResult == FR_OK) { - // folder already exists - NANOCLR_SET_AND_LEAVE(CLR_E_PATH_ALREADY_EXISTS); + f_stat(folderPath, &fileInfo); } - else if (options == CreationCollisionOption_GenerateUniqueName) + else { - //TODO - add generating unique name + // failed to create the folder NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); } } @@ -807,7 +915,7 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::CreateFolderNa // free buffer memory, if allocated if(folderPath != NULL) { - platform_free(folderPath); + free(folderPath); } NANOCLR_CLEANUP_END(); @@ -849,7 +957,7 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::DeleteFolderNa strcat(workingDrive, ".."); // change dir to parent - operationResult = f_chdir(workingDrive); + f_chdir(workingDrive); // try remove again operationResult = f_unlink(workingPath); @@ -938,7 +1046,7 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetFolderNativ // get a pointer to the desired folder name folderName = stack.Arg1().DereferenceString()->StringText(); - folderPath = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + folderPath = (char*)malloc(2 * FF_LFN_BUF + 1); // sanity check for successfull malloc if (folderPath == NULL) @@ -1002,7 +1110,7 @@ HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetFolderNativ // free buffer memory, if allocated if (folderPath != NULL) { - platform_free(folderPath); + free(folderPath); } NANOCLR_CLEANUP_END(); From 0600717b59b727e1c85a0d5639f3a46098acac20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremi=20Jasi=C5=84ski?= Date: Tue, 17 Dec 2019 12:45:12 +0100 Subject: [PATCH 2/5] Fix exiting wokring thread without killing task (sdcard) --- ..._storage_native_Windows_Storage_FileIO.cpp | 131 +++++++++--------- 1 file changed, 67 insertions(+), 64 deletions(-) diff --git a/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp b/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp index 0514d912fb..7bc5c2f402 100644 --- a/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp +++ b/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp @@ -4,7 +4,7 @@ // #include -#include "win_storage_native_target.h" +#include "win_storage_native.h" #include #if HAL_USBH_USE_MSD @@ -19,7 +19,6 @@ typedef Library_win_storage_native_Windows_Storage_StorageFile StorageFile; struct FileOperation { - FIL* File; const char* FileName; char* Content; uint32_t ContentLength; @@ -31,7 +30,7 @@ static volatile FRESULT threadOperationResult; // ReadText working thread static void ReadTextWorkingThread(void *arg) { - FileOperation *fileIoOperation = (FileOperation *)arg; + FileOperation *fileIoOperation = reinterpret_cast(arg); FIL file; @@ -45,7 +44,8 @@ static void ReadTextWorkingThread(void *arg) { if (threadOperationResult != FR_OK) { // free memory free(fileIoOperation); - return; + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + vTaskDelete(NULL); } // read string @@ -70,7 +70,7 @@ static void ReadTextWorkingThread(void *arg) { // WriteText working thread static void WriteTextWorkingThread(void *arg) { - FileOperation *fileIoOperation = (FileOperation *)arg; + FileOperation *fileIoOperation = reinterpret_cast(arg); FIL file; @@ -81,7 +81,8 @@ static void WriteTextWorkingThread(void *arg) { if (threadOperationResult != FR_OK) { // free memory free(fileIoOperation); - return; + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + vTaskDelete(NULL); } if (f_puts(fileIoOperation->Content, &file) == (int)fileIoOperation->ContentLength) { @@ -116,16 +117,15 @@ static void WriteBinaryWorkingThread(void *arg) { if (threadOperationResult != FR_OK) { // free memory free(fileIoOperation); - return; + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + vTaskDelete(NULL); } threadOperationResult = f_write(&file, fileIoOperation->Content, fileIoOperation->ContentLength, &bytesWritten); - - if ((threadOperationResult == FR_OK) && (bytesWritten == fileIoOperation->ContentLength)) { - // expected number of bytes written - threadOperationResult = FR_OK; + if (bytesWritten != fileIoOperation->ContentLength) + { + threadOperationResult = FR_DISK_ERR; } - // close file f_close(&file); @@ -140,22 +140,34 @@ static void WriteBinaryWorkingThread(void *arg) { // ReadBinary working thread static void ReadBinaryWorkingThread(void *arg) { - UINT bytesRead; - + FileOperation *fileIoOperation = reinterpret_cast(arg); - threadOperationResult = f_read(fileIoOperation->File, fileIoOperation->Content, fileIoOperation->ContentLength, &bytesRead); + FIL file; + + // need an extra one for the terminator + UINT bytesRead = fileIoOperation->ContentLength + 1; - if ((threadOperationResult == FR_OK) && (bytesRead == fileIoOperation->ContentLength)) { - // expected number of bytes read - threadOperationResult = FR_OK; + // open file (which is supposed to already exist) + // need to use FA_OPEN_EXISTING because we are reading an existing file content from start + threadOperationResult = f_open(&file, fileIoOperation->FileName, FA_OPEN_EXISTING | FA_READ); + + if (threadOperationResult != FR_OK) { + // free memory + free(fileIoOperation); + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + vTaskDelete(NULL); } + threadOperationResult = f_read(&file, fileIoOperation->Content, fileIoOperation->ContentLength, &bytesRead); + + if (bytesRead != fileIoOperation->ContentLength) { + threadOperationResult = FR_DISK_ERR; + } + // close file - f_close(fileIoOperation->File); + f_close(&file); - // free memory - free(fileIoOperation->File); free(fileIoOperation); // fire event for FileIO operation complete @@ -187,7 +199,6 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteBytes___STATIC__ const TCHAR* filePath; - char* buffer; uint32_t bufferLength; @@ -266,7 +277,6 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteBytes___STATIC__ NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); } } - // pop timeout heap block from stack stack.PopValue(); @@ -299,13 +309,14 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteText___STATIC__V NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks(hbTimeout, timeout)); - if (stack.m_customState == 1) { + if (stack.m_customState == 1) + { // protect the StorageFile and the content buffer from GC so the working thread can access those CLR_RT_ProtectFromGC gcStorageFile(*pThis); CLR_RT_ProtectFromGC gcContent(*content); // setup FileIO operation - FileOperation *fileIoOperation = (FileOperation *)malloc(sizeof(FileOperation)); + FileOperation *fileIoOperation = reinterpret_cast(malloc(sizeof(FileOperation))); fileIoOperation->FileName = filePath; fileIoOperation->Content = (char *)content->StringText(); @@ -315,7 +326,8 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteText___STATIC__V BaseType_t ret; ret = xTaskCreate(WriteTextWorkingThread, "WriteText", configMINIMAL_STACK_SIZE + 400, fileIoOperation, configMAX_PRIORITIES - 2, NULL); - if (ret != pdPASS) { + if (ret != pdPASS) + { NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); } @@ -323,29 +335,36 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteText___STATIC__V stack.m_customState = 2; } - while (eventResult) { + while (eventResult) + { // non-blocking wait allowing other threads to run while we wait for the write operation to complete NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents(stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult)); - if (eventResult) { + if (eventResult) + { // event occurred - - if (threadOperationResult == FR_DISK_ERR) { + if (threadOperationResult == FR_DISK_ERR) + { NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); - } else if (threadOperationResult == FR_NO_FILE) { + } + else if (threadOperationResult == FR_NO_FILE) + { NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); - } else if (threadOperationResult == FR_INVALID_DRIVE) { + } + else if (threadOperationResult == FR_INVALID_DRIVE) + { // failed to change drive NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); } // done here break; - } else { + } + else + { NANOCLR_SET_AND_LEAVE(CLR_E_TIMEOUT); } } - // pop timeout heap block from stack stack.PopValue(); @@ -362,9 +381,6 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___ST const TCHAR* filePath; - FIL* file; - FRESULT operationResult; - // get a pointer to the managed object instance and check that it's not NULL CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); @@ -378,23 +394,6 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___ST if(stack.m_customState == 1) { - // create file struct - file = (FIL*)malloc(sizeof(FIL)); - // check allocation - if(file == NULL) - { - NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); - } - - // open file (which is supposed to already exist) - // need to use FA_OPEN_EXISTING because we are reading an existing file content from start - operationResult = f_open(file, filePath, FA_OPEN_EXISTING | FA_READ); - - if(operationResult != FR_OK) - { - NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); - } - // get file details static FILINFO fileInfo; f_stat(filePath, &fileInfo); @@ -415,13 +414,13 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___ST // setup FileIO operation FileOperation *fileIoOperation = reinterpret_cast(malloc(sizeof(FileOperation))); - fileIoOperation->File = file; + fileIoOperation->FileName = filePath; fileIoOperation->Content = (char*)bufferArray->GetFirstElement(); fileIoOperation->ContentLength = bufferArray->m_numOfElements; // spawn working thread to perform the read transaction BaseType_t ret; - ret = xTaskCreate(ReadBinaryWorkingThread, "ReadBin", configMINIMAL_STACK_SIZE + 100, fileIoOperation, configMAX_PRIORITIES - 2, NULL); + ret = xTaskCreate(ReadBinaryWorkingThread, "ReadBin", configMINIMAL_STACK_SIZE + 600, fileIoOperation, configMAX_PRIORITIES - 2, NULL); if (ret != pdPASS) { @@ -455,7 +454,6 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___ST // failed to change drive NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); } - // done here break; } @@ -464,7 +462,6 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___ST NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); } } - // pop timeout heap block from stack stack.PopValue(); @@ -538,24 +535,30 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadTextNative___STAT if (eventResult) { // event occurred - if (threadOperationResult == FR_DISK_ERR) { + if (threadOperationResult == FR_DISK_ERR) + { NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); - } else if (threadOperationResult == FR_NO_FILE) { + } + else if (threadOperationResult == FR_NO_FILE) + { NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); - } else if (threadOperationResult == FR_INVALID_DRIVE) { + } + else if (threadOperationResult == FR_INVALID_DRIVE) + { // failed to change drive NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); } // done here break; - } else { + } + else + { NANOCLR_SET_AND_LEAVE(CLR_E_TIMEOUT); } } - // pop timeout heap block from stack stack.PopValue(); NANOCLR_NOCLEANUP(); -} \ No newline at end of file +} From 430f8d56f491a0f4eb1604fad7fb3c62dc8b4f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremi=20Jasi=C5=84ski?= Date: Wed, 18 Dec 2019 07:58:59 +0100 Subject: [PATCH 3/5] Fix two conditional ifs to set proper error flags --- .../win_storage_native_Windows_Storage_FileIO.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp b/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp index 7bc5c2f402..7656a09af2 100644 --- a/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp +++ b/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp @@ -49,9 +49,8 @@ static void ReadTextWorkingThread(void *arg) { } // read string - if (f_gets((TCHAR *)fileIoOperation->Content, readLength, &file)) { - threadOperationResult = FR_OK; - } else { + if (!(f_gets((TCHAR *)fileIoOperation->Content, readLength, &file))) + { threadOperationResult = (FRESULT)f_error(&file); } @@ -85,10 +84,10 @@ static void WriteTextWorkingThread(void *arg) { vTaskDelete(NULL); } - if (f_puts(fileIoOperation->Content, &file) == (int)fileIoOperation->ContentLength) { - // expected number of bytes written - threadOperationResult = FR_OK; - } + if (f_puts(fileIoOperation->Content, &file) != (int)fileIoOperation->ContentLength) + { + threadOperationResult = FR_DISK_ERR; + } // close file f_close(&file); From dbf229c50b256ccb623c3360bdb5003d5c8ffb59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremi=20Jasi=C5=84ski?= Date: Wed, 18 Dec 2019 11:20:28 +0100 Subject: [PATCH 4/5] Revert incorrect use of malloc --- .../win_storage_native_Windows_Storage_FileIO.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp b/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp index 7656a09af2..744a2ffa27 100644 --- a/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp +++ b/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp @@ -225,7 +225,7 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteBytes___STATIC__ CLR_RT_ProtectFromGC gcContent( *bufferArray ); // setup FileIO operation - FileOperation *fileIoOperation = reinterpret_cast(malloc(sizeof(FileOperation))); + FileOperation *fileIoOperation = reinterpret_cast(platform_malloc(sizeof(FileOperation))); //fileIoOperation->File = file; fileIoOperation->FileName = filePath; @@ -315,7 +315,7 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteText___STATIC__V CLR_RT_ProtectFromGC gcContent(*content); // setup FileIO operation - FileOperation *fileIoOperation = reinterpret_cast(malloc(sizeof(FileOperation))); + FileOperation *fileIoOperation = reinterpret_cast(platform_malloc(sizeof(FileOperation))); fileIoOperation->FileName = filePath; fileIoOperation->Content = (char *)content->StringText(); @@ -411,7 +411,7 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___ST CLR_RT_HeapBlock_Array* bufferArray = buffer.DereferenceArray(); // setup FileIO operation - FileOperation *fileIoOperation = reinterpret_cast(malloc(sizeof(FileOperation))); + FileOperation *fileIoOperation = reinterpret_cast(platform_malloc(sizeof(FileOperation))); fileIoOperation->FileName = filePath; fileIoOperation->Content = (char*)bufferArray->GetFirstElement(); @@ -509,7 +509,7 @@ HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadTextNative___STAT NANOCLR_CHECK_HRESULT(hbText.StoreToReference(stack.Arg1(), 0)); // setup FileIO operation - FileOperation *fileIoOperation = (FileOperation *)malloc(sizeof(FileOperation)); + FileOperation *fileIoOperation = (FileOperation *)platform_malloc(sizeof(FileOperation)); fileIoOperation->FileName = filePath; fileIoOperation->Content = (char *)textString->StringText(); From c42e42e28174488fed6524001cbab50c24feb15c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremi=20Jasi=C5=84ski?= Date: Wed, 18 Dec 2019 12:18:34 +0100 Subject: [PATCH 5/5] Replace free with platform_free --- ...win_storage_native_Windows_Storage_FileIO.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp b/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp index 744a2ffa27..5223466426 100644 --- a/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp +++ b/targets/FreeRTOS/NXP/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp @@ -43,7 +43,7 @@ static void ReadTextWorkingThread(void *arg) { if (threadOperationResult != FR_OK) { // free memory - free(fileIoOperation); + platform_free(fileIoOperation); Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); vTaskDelete(NULL); } @@ -58,7 +58,7 @@ static void ReadTextWorkingThread(void *arg) { f_close(&file); // free memory - free(fileIoOperation); + platform_free(fileIoOperation); // fire event for FileIO operation complete Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); @@ -79,7 +79,7 @@ static void WriteTextWorkingThread(void *arg) { if (threadOperationResult != FR_OK) { // free memory - free(fileIoOperation); + platform_free(fileIoOperation); Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); vTaskDelete(NULL); } @@ -93,7 +93,7 @@ static void WriteTextWorkingThread(void *arg) { f_close(&file); // free memory - free(fileIoOperation); + platform_free(fileIoOperation); // fire event for FileIO operation complete Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); @@ -115,7 +115,7 @@ static void WriteBinaryWorkingThread(void *arg) { if (threadOperationResult != FR_OK) { // free memory - free(fileIoOperation); + platform_free(fileIoOperation); Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); vTaskDelete(NULL); } @@ -129,7 +129,7 @@ static void WriteBinaryWorkingThread(void *arg) { f_close(&file); // free memory - free(fileIoOperation); + platform_free(fileIoOperation); // fire event for FileIO operation complete Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); @@ -153,7 +153,7 @@ static void ReadBinaryWorkingThread(void *arg) { if (threadOperationResult != FR_OK) { // free memory - free(fileIoOperation); + platform_free(fileIoOperation); Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); vTaskDelete(NULL); } @@ -167,7 +167,7 @@ static void ReadBinaryWorkingThread(void *arg) { // close file f_close(&file); - free(fileIoOperation); + platform_free(fileIoOperation); // fire event for FileIO operation complete Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO);