Skip to content

Commit 3d8d441

Browse files
committed
Make FAT filesystem thread safe
Add lock and unlock calls to the FAT filesystem so it is thread safe.
1 parent b174d6a commit 3d8d441

File tree

7 files changed

+179
-18
lines changed

7 files changed

+179
-18
lines changed

libraries/fs/fat/FATDirHandle.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,22 @@
2525

2626
using namespace mbed;
2727

28-
FATDirHandle::FATDirHandle(const FATFS_DIR &the_dir) {
28+
FATDirHandle::FATDirHandle(const FATFS_DIR &the_dir, PlatformMutex * mutex): _mutex(mutex) {
2929
dir = the_dir;
3030
}
3131

3232
int FATDirHandle::closedir() {
33+
lock();
3334
int retval = f_closedir(&dir);
35+
unlock();
3436
delete this;
3537
return retval;
3638
}
3739

3840
struct dirent *FATDirHandle::readdir() {
3941
FILINFO finfo;
4042

43+
lock();
4144
#if _USE_LFN
4245
finfo.lfname = cur_entry.d_name;
4346
finfo.lfsize = sizeof(cur_entry.d_name);
@@ -47,33 +50,52 @@ struct dirent *FATDirHandle::readdir() {
4750

4851
#if _USE_LFN
4952
if(res != 0 || finfo.fname[0]==0) {
53+
unlock();
5054
return NULL;
5155
} else {
5256
if(cur_entry.d_name[0]==0) {
5357
// No long filename so use short filename.
5458
memcpy(cur_entry.d_name, finfo.fname, sizeof(finfo.fname));
5559
}
60+
unlock();
5661
return &cur_entry;
5762
}
5863
#else
5964
if(res != 0 || finfo.fname[0]==0) {
65+
unlock();
6066
return NULL;
6167
} else {
6268
memcpy(cur_entry.d_name, finfo.fname, sizeof(finfo.fname));
69+
unlock();
6370
return &cur_entry;
6471
}
6572
#endif /* _USE_LFN */
6673
}
6774

6875
void FATDirHandle::rewinddir() {
76+
lock();
6977
dir.index = 0;
78+
unlock();
7079
}
7180

7281
off_t FATDirHandle::telldir() {
73-
return dir.index;
82+
lock();
83+
off_t offset = dir.index;
84+
unlock();
85+
return offset;
7486
}
7587

7688
void FATDirHandle::seekdir(off_t location) {
89+
lock();
7790
dir.index = location;
91+
unlock();
92+
}
93+
94+
void FATDirHandle::lock() {
95+
_mutex->lock();
96+
}
97+
98+
void FATDirHandle::unlock() {
99+
_mutex->unlock();
78100
}
79101

libraries/fs/fat/FATDirHandle.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,27 @@
2323
#define MBED_FATDIRHANDLE_H
2424

2525
#include "DirHandle.h"
26+
#include "platform.h"
2627

2728
using namespace mbed;
2829

2930
class FATDirHandle : public DirHandle {
3031

3132
public:
32-
FATDirHandle(const FATFS_DIR &the_dir);
33+
FATDirHandle(const FATFS_DIR &the_dir, PlatformMutex * mutex);
3334
virtual int closedir();
3435
virtual struct dirent *readdir();
3536
virtual void rewinddir();
3637
virtual off_t telldir();
3738
virtual void seekdir(off_t location);
3839

40+
protected:
41+
42+
virtual void lock();
43+
virtual void unlock();
44+
45+
PlatformMutex * _mutex;
46+
3947
private:
4048
FATFS_DIR dir;
4149
struct dirent cur_entry;

libraries/fs/fat/FATFileHandle.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,34 +25,42 @@
2525

2626
#include "FATFileHandle.h"
2727

28-
FATFileHandle::FATFileHandle(FIL fh) {
28+
FATFileHandle::FATFileHandle(FIL fh, PlatformMutex * mutex): _mutex(mutex) {
2929
_fh = fh;
3030
}
3131

3232
int FATFileHandle::close() {
33+
lock();
3334
int retval = f_close(&_fh);
35+
unlock();
3436
delete this;
3537
return retval;
3638
}
3739

3840
ssize_t FATFileHandle::write(const void* buffer, size_t length) {
41+
lock();
3942
UINT n;
4043
FRESULT res = f_write(&_fh, buffer, length, &n);
4144
if (res) {
4245
debug_if(FFS_DBG, "f_write() failed: %d", res);
46+
unlock();
4347
return -1;
4448
}
49+
unlock();
4550
return n;
4651
}
4752

4853
ssize_t FATFileHandle::read(void* buffer, size_t length) {
54+
lock();
4955
debug_if(FFS_DBG, "read(%d)\n", length);
5056
UINT n;
5157
FRESULT res = f_read(&_fh, buffer, length, &n);
5258
if (res) {
5359
debug_if(FFS_DBG, "f_read() failed: %d\n", res);
60+
unlock();
5461
return -1;
5562
}
63+
unlock();
5664
return n;
5765
}
5866

@@ -61,6 +69,7 @@ int FATFileHandle::isatty() {
6169
}
6270

6371
off_t FATFileHandle::lseek(off_t position, int whence) {
72+
lock();
6473
if (whence == SEEK_END) {
6574
position += _fh.fsize;
6675
} else if(whence==SEEK_CUR) {
@@ -69,22 +78,38 @@ off_t FATFileHandle::lseek(off_t position, int whence) {
6978
FRESULT res = f_lseek(&_fh, position);
7079
if (res) {
7180
debug_if(FFS_DBG, "lseek failed: %d\n", res);
81+
unlock();
7282
return -1;
7383
} else {
7484
debug_if(FFS_DBG, "lseek OK, returning %i\n", _fh.fptr);
85+
unlock();
7586
return _fh.fptr;
7687
}
7788
}
7889

7990
int FATFileHandle::fsync() {
91+
lock();
8092
FRESULT res = f_sync(&_fh);
8193
if (res) {
8294
debug_if(FFS_DBG, "f_sync() failed: %d\n", res);
95+
unlock();
8396
return -1;
8497
}
98+
unlock();
8599
return 0;
86100
}
87101

88102
off_t FATFileHandle::flen() {
89-
return _fh.fsize;
103+
lock();
104+
off_t size = _fh.fsize;
105+
unlock();
106+
return size;
107+
}
108+
109+
void FATFileHandle::lock() {
110+
_mutex->lock();
111+
}
112+
113+
void FATFileHandle::unlock() {
114+
_mutex->unlock();
90115
}

libraries/fs/fat/FATFileHandle.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@
2323
#define MBED_FATFILEHANDLE_H
2424

2525
#include "FileHandle.h"
26+
#include "platform.h"
2627

2728
using namespace mbed;
2829

2930
class FATFileHandle : public FileHandle {
3031
public:
3132

32-
FATFileHandle(FIL fh);
33+
FATFileHandle(FIL fh, PlatformMutex * mutex);
3334
virtual int close();
3435
virtual ssize_t write(const void* buffer, size_t length);
3536
virtual ssize_t read(void* buffer, size_t length);
@@ -40,7 +41,11 @@ class FATFileHandle : public FileHandle {
4041

4142
protected:
4243

44+
virtual void lock();
45+
virtual void unlock();
46+
4347
FIL _fh;
48+
PlatformMutex * _mutex;
4449

4550
};
4651

libraries/fs/fat/FATFileSystem.cpp

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "FATFileSystem.h"
2828
#include "FATFileHandle.h"
2929
#include "FATDirHandle.h"
30+
#include "critical.h"
3031

3132
DWORD get_fattime(void) {
3233
time_t rawtime;
@@ -41,33 +42,55 @@ DWORD get_fattime(void) {
4142
}
4243

4344
FATFileSystem *FATFileSystem::_ffs[_VOLUMES] = {0};
45+
static PlatformMutex * mutex = NULL;
4446

45-
FATFileSystem::FATFileSystem(const char* n) : FileSystemLike(n) {
47+
PlatformMutex * get_fat_mutex() {
48+
PlatformMutex * new_mutex = new PlatformMutex;
49+
50+
core_util_critical_section_enter();
51+
if (NULL == mutex) {
52+
mutex = new_mutex;
53+
}
54+
core_util_critical_section_exit();
55+
56+
if (mutex != new_mutex) {
57+
delete new_mutex;
58+
}
59+
return mutex;
60+
}
61+
62+
FATFileSystem::FATFileSystem(const char* n) : FileSystemLike(n), _mutex(get_fat_mutex()) {
63+
lock();
4664
debug_if(FFS_DBG, "FATFileSystem(%s)\n", n);
4765
for(int i=0; i<_VOLUMES; i++) {
4866
if(_ffs[i] == 0) {
4967
_ffs[i] = this;
5068
_fsid[0] = '0' + i;
5169
_fsid[1] = '\0';
52-
debug_if(FFS_DBG, "Mounting [%s] on ffs drive [%s]\n", _name, _fsid);
70+
debug_if(FFS_DBG, "Mounting [%s] on ffs drive [%s]\n", getName(), _fsid);
5371
f_mount(&_fs, _fsid, 0);
72+
unlock();
5473
return;
5574
}
5675
}
5776
error("Couldn't create %s in FATFileSystem::FATFileSystem\n", n);
77+
unlock();
5878
}
5979

6080
FATFileSystem::~FATFileSystem() {
81+
lock();
6182
for (int i=0; i<_VOLUMES; i++) {
6283
if (_ffs[i] == this) {
6384
_ffs[i] = 0;
6485
f_mount(NULL, _fsid, 0);
6586
}
6687
}
88+
unlock();
6789
}
6890

6991
FileHandle *FATFileSystem::open(const char* name, int flags) {
70-
debug_if(FFS_DBG, "open(%s) on filesystem [%s], drv [%s]\n", name, _name, _fsid);
92+
lock();
93+
debug_if(FFS_DBG, "open(%s) on filesystem [%s], drv [%s]\n", name, getName(), _fsid);
7194
char n[64];
7295
sprintf(n, "%s:/%s", _fsid, name);
7396

@@ -92,63 +115,95 @@ FileHandle *FATFileSystem::open(const char* name, int flags) {
92115
FRESULT res = f_open(&fh, n, openmode);
93116
if (res) {
94117
debug_if(FFS_DBG, "f_open('w') failed: %d\n", res);
118+
unlock();
95119
return NULL;
96120
}
97121
if (flags & O_APPEND) {
98122
f_lseek(&fh, fh.fsize);
99123
}
100-
return new FATFileHandle(fh);
124+
FATFileHandle * handle = new FATFileHandle(fh, _mutex);
125+
unlock();
126+
return handle;
101127
}
102128

103129
int FATFileSystem::remove(const char *filename) {
130+
lock();
104131
FRESULT res = f_unlink(filename);
105132
if (res) {
106133
debug_if(FFS_DBG, "f_unlink() failed: %d\n", res);
134+
unlock();
107135
return -1;
108136
}
137+
unlock();
109138
return 0;
110139
}
111140

112141
int FATFileSystem::rename(const char *oldname, const char *newname) {
142+
lock();
113143
FRESULT res = f_rename(oldname, newname);
114144
if (res) {
115145
debug_if(FFS_DBG, "f_rename() failed: %d\n", res);
146+
unlock();
116147
return -1;
117148
}
149+
unlock();
118150
return 0;
119151
}
120152

121153
int FATFileSystem::format() {
154+
lock();
122155
FRESULT res = f_mkfs(_fsid, 0, 512); // Logical drive number, Partitioning rule, Allocation unit size (bytes per cluster)
123156
if (res) {
124157
debug_if(FFS_DBG, "f_mkfs() failed: %d\n", res);
158+
unlock();
125159
return -1;
126160
}
161+
unlock();
127162
return 0;
128163
}
129164

130165
DirHandle *FATFileSystem::opendir(const char *name) {
166+
lock();
131167
FATFS_DIR dir;
132168
FRESULT res = f_opendir(&dir, name);
133169
if (res != 0) {
170+
unlock();
134171
return NULL;
135172
}
136-
return new FATDirHandle(dir);
173+
FATDirHandle *handle = new FATDirHandle(dir, _mutex);
174+
unlock();
175+
return handle;
137176
}
138177

139178
int FATFileSystem::mkdir(const char *name, mode_t mode) {
179+
lock();
140180
FRESULT res = f_mkdir(name);
181+
unlock();
141182
return res == 0 ? 0 : -1;
142183
}
143184

144185
int FATFileSystem::mount() {
186+
lock();
145187
FRESULT res = f_mount(&_fs, _fsid, 1);
188+
unlock();
146189
return res == 0 ? 0 : -1;
147190
}
148191

149192
int FATFileSystem::unmount() {
150-
if (disk_sync())
193+
lock();
194+
if (disk_sync()) {
195+
unlock();
151196
return -1;
197+
}
152198
FRESULT res = f_mount(NULL, _fsid, 0);
199+
unlock();
153200
return res == 0 ? 0 : -1;
154201
}
202+
203+
void FATFileSystem::lock() {
204+
_mutex->lock();
205+
}
206+
207+
void FATFileSystem::unlock() {
208+
_mutex->unlock();
209+
}

0 commit comments

Comments
 (0)