Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do you implement thread saftey? #20

Closed
MSmithDev opened this issue Feb 23, 2021 · 11 comments
Closed

How do you implement thread saftey? #20

MSmithDev opened this issue Feb 23, 2021 · 11 comments

Comments

@MSmithDev
Copy link

I saw that Thread Safety was added back in December, Is there any documentation on this? how do you implement it?

@lorol
Copy link
Owner

lorol commented Feb 23, 2021

Not implemented. I see what do you mean ...

This is a wrapper of the wrapper. Perhaps @BrianPugh can take a look in future.

@MSmithDev
Copy link
Author

Dang, I guess I misinterpreted that. Thanks anyway!

@BrianPugh
Copy link
Collaborator

@MSmithDev if you're curious, basically upon filesystem initialization, I just allocate a FreeRTOS xSemaphoreCreateRecursiveMutex() and acquire/release it around most commands. For example:

https://github.com/joltwallet/esp_littlefs/blob/d268e18d774431fb6f0e444feef4e97a2dfaaa29/src/esp_littlefs.c#L1153

I didn't know that littlefs added thread safety internally; we could migrate to that, but I don't really see a benefit at the moment.

@MSmithDev
Copy link
Author

@BrianPugh Thanks, I will definitely look into that, I personally haven't done much with Mutex and Semaphores so I need to read up on that first.

@johnnytolengo
Copy link

Did anyone solve the Thread Safe issue?
I still have crashes and sometimes the FS is corrupted after that, of course using boths cores with parallel tasks.

@MSmithDev
Copy link
Author

There is no thread safety built in currently. You have to handle the tasks in your code and make sure it can't happen.

@BrianPugh
Copy link
Collaborator

All actions are guarded by mutexs, I implemented this before upstream littlefs had support. What exact use case is causing errors?

@johnnytolengo
Copy link

@BrianPugh I don't know exactly where is the colision but I seems to be when some task is writing or reading in Core0 and ESPAsyncWebServer request on Core1 accessing to some datafile.

@johnnytolengo
Copy link

johnnytolengo commented Jul 27, 2021

I am currently writting a wrapper for LITTLEFS using SemaphoreHandle_t at open() and close() functions my header file:

#ifndef _FILESYS_H_
#define _FILESYS_H_

#include "LITTLEFS.h"

namespace fs
{
class FILESYSSYS : public LITTLEFSFS {
public:
    FILESYSSYS();
    ~FILESYSSYS();
    bool begin(bool formatOnFail=false, const char * basePath="/littlefs", uint8_t maxOpenFiles=10, const char * partitionLabel="spiffs");
    bool exists(const char* path);
    bool mkdir(const char *path);
    bool remove(const char *path);
    bool rmdir(const char *path);
    File open(const char* path, const char* mode);
    void close();
private:
    SemaphoreHandle_t  _fsmux; 
    File fileh;
    bool fs_lock();
    void fs_unlock();
};

}

extern fs::FILESYSSYS FILESYS;
#endif

Cpp file:

FILESYSSYS::FILESYSSYS() : LITTLEFSFS()
{
  if ((_fsmux = xSemaphoreCreateBinary()) == NULL) { ESP_LOGI(MODULE_NAME, "_fsmux FAILED"); }
	xSemaphoreGive( _fsmux );
}

File FILESYSSYS::open(const char* path, const char* mode){
               fs_lock();
		fileh = LITTLEFS.open(path, mode);
		return fileh;
}


//this function is very nasty and I don't know how to capture the close() to trigger the fs_unlock()
void FILESYSSYS::close(){
  fileh.close();
	fs_unlock();
}

bool FILESYSSYS::fs_lock(){
  if(xSemaphoreTake(_fsmux, portMAX_DELAY) == pdTRUE ){
    return true;
  }
  else{
    return false;
  }
}

void FILESYSSYS::fs_unlock(){
  xSemaphoreGive(_fsmux);
}

Now I have an issue with the wrapper I don't know how to handle the close() function using/capturing the "File" pointer at close action to trigger the fs_unlock()

Any idea? I am not a .cpp expert

@BrianPugh
Copy link
Collaborator

I think you might be misguided, this is already builtin:

https://github.com/lorol/LITTLEFS/blob/master/src/esp_littlefs.c#L662

Is your issue related to this? joltwallet/esp_littlefs#18 Basically its an upstream issue that having two filedescriptors open for the same file will run into issues.

@johnnytolengo
Copy link

johnnytolengo commented Jul 28, 2021

@BrianPugh @lorol
OMG! I didn't know that "sem_take()" but after looking the code (esp_littlefs.c) and enabling the log with LOG_LOCAL_LEVEL=5
I see that the sem_take() is not executed using the example code: https://raw.githubusercontent.com/lorol/LITTLEFS/master/examples/LITTLEFS_PlatformIO/src/main.cpp

It seems that esp_littlefs.c is not used everything is linked to FS.cpp so now I am fully misunderstanding how LITTLEFS is working.
Please if any one can tell me how I can trace and enable debugging.

Regarding the two filedescriptors open is possible that that is my problem, to make the code thread safe will be enough to put the sem_take() before the File pointer is linked to LITTLEFS library, is it?

Reminder, my scenario: core0 working on readwrite stuff and core1 used by ESPAsyncWebServer to server and return written data by core0. It can occur that one file can be reading by core1 while core0 is already writing/reading on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants