Jump to content

Problem with gfileOpenFileList()


pur300

Recommended Posts

Hello,

I have a problem with a gfileOpenFileList() function. I have two threads. One is used to get names of all pictures from a gallery directory and the other one is used to get themes from a theme directory. A problem is that the function gfileOpenFileList() works only in the first thread and not in the second one. I've also tried to open and read name of files from the same directory(themes) and the function always returns a pointer to a gfileList struct in the first thread but NULL in the second thread. Where could be a problem?

Link to comment
Share on other sites

It sounds like there may two possible problems with this...

1. The gfile api is not thread safe. In other words you must not allow two different threads to be calling the api at the same time. If they are calling at different times and there is no overlap then everything will work.

2. Perhaps something has ended up in thread local storage rather than global storage. This would be something strange about the operating system you are using and it's use of memory (yyou didn't specify which).

Of the two, number 1 is the most likely problem. If you don't think it is that then you will need to debug to see what is going on.

Link to comment
Share on other sites

I disabled all threads except a thread which reads themes from a directory. I figured out that i have to open and close a random file on the sd card before i can use a gfileOpenFileList() function. If i don't do that then the function gfileOpenFileList() returns NULL.

Edited by Guest
Link to comment
Share on other sites

Does it mean that only gdisp api can be thread safe(if GDISP_NEED_MULTITHREAD is set TRUE)? So if i set GDISP_NEED_MULTITHREAD TRUE, gwin and other elements(container, widget and window) are also thread safe, right?

GDISP needs to be thread safe because it accesses hardware. GWIN itself on the other hand is a thread itself and does not access any hardware directly but through the GDISP module. Therefore only the GDISP module needs to be thread safe. The GFILE module (and the FatFS implementation) is not thread safe from our side.

I figured out that i have to open and close a random file on sd card before i can use a gfileOpenFileList() function.

That sounds very strange. I put that on my ToDo list to investigate. Can you please post a test-case that demonstrates how the problem occurs and how it can be work-arounded?

~ Tectu

Link to comment
Share on other sites

Thank you for an explanation. Here is my test code:

#include "testThrd.h"

char** files;

int numOfFiles;

threadreturn_t test_t(void* param){

GFILE* file;

gfileList* fileList;

const char* filename;

// Directory

char dir[] = "gallery";

// get number of files from the directory

numOfFiles = countFiles(dir);

if(numOfFiles){

int i = 0;

// Allocate space

files = chHeapAlloc(NULL, numOfFiles * sizeof(char*));

// !! Open file !!

/*file = gfileOpen("configuration/calibration.txt", "r");

gfileClose(file);*/

// Read file names in the directory

fileList = gfileOpenFileList('F', dir, FALSE);

if(fileList){

while((filename = gfileReadFileList(fileList)) != NULL){

// Allocate space

files[i] = chHeapAlloc(NULL, MAX_FILE_NAME_LENGTH * sizeof(char));

// Copy chars

strlcpy(files[i], filename, MAX_FILE_NAME_LENGTH);

i++;

}

}

}

for(;;

}

int countFiles(char* dir){

GFILE* file;

gfileList* fileList;

int i = 0;

// !! Open file !!

/*file = gfileOpen("configuration/calibration.txt", "r");

gfileClose(file);*/

// Read file names in the directory

fileList = gfileOpenFileList('F', dir, FALSE);

if(fileList){

while(gfileReadFileList(fileList) != NULL)
i++;

// Close fileList

gfileCloseFileList(fileList);

return i;

}

return 0;

}

If i comment out gfileOpen() and gfileClose() then this code doesn't work. numOfFiles is zero and a space for char** files is not allocated. If i uncomment gfileOpen() and gfileClose() then this code works well.

Link to comment
Share on other sites

To clarify, GDISP_NEED_MULTITHREAD makes gdisp thread safe. GWIN is thread safe because it has been written as thread safe code and talks to thread safe gdisp.

GTIMER is thread safe, GQUEUE is thread safe (eexcept for the "I" versions of the functions which designed to only be called at interrupt time. GMISC is thread safe as it has been written as thread safe code, GINPUT is not thread safe but doesn't need to be as event sending is thread safe and that is how you communicate at run time with input devices. GEVENT is thread safe. GDRIVER is not but is typically only called at init time and very seldom by application code. GAUDIO and GADC are thread safe but not multi-stream.

GFILE is not thread safe and neither are many of the underlying file system interfaces eg FATFS.

We should probably document this somewhere!

Making GFILE optionally thread safe is probably a good idea although locking granularity versus complexity will be an interesting design decision.

If you are finding that gfileopenfilelist fails if you don't make a open call first, this is likely a problem in the fatfs code itself (third party llibrary). I will investigate and see what I can find.

Link to comment
Share on other sites

  • 2 weeks later...

I reorganized my program and it seems to work now. I have one more question which is not related to the problem described above. Does gwinDestroy() free all resources if i destroy a container which has also other containers and widgets such as buttons and labels? Does gwinDestroy() free images which are used by buttons and a main container as a background? I analyzed a code and i found a function static void _destroy(GWindowObject *gh), but it is not called anywhere in my code. So i suppose i have to call gdispImageClose() for every background image used by a widget?

Link to comment
Share on other sites

gwinDestroy on a container will destroy all gwin objects in it.

It will not however close any gfiles' or gdispImage objects associated with buttons etc just as it does not automatically open them.

The reason for this is that the same gfile for an image can be used for multiple buttons. It would not be good if a destroyed button was to close the image gfile as then all the other still existing buttons using the image would fail.

So, images associated with gwin objects must be manually opened and also manually closed.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...