include ../FrameworkRules.mk
+C_FLAGS += -DCONFIG_YAFFS_USE_PTHREADS
yaffs_test: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
- gcc $(CFLLAG) -o $@ $(YAFFS_TEST_OBJS)
+ gcc $(CFLLAG) -o $@ $(YAFFS_TEST_OBJS) -lpthread
fuzzer: $(FUZZER_OBJS)
gcc $(CFLAGS) -o $@ $<
* published by the Free Software Foundation.
*/
-/*
+/*
* Example OS glue functions for running on a Linux/POSIX system.
*/
#include <assert.h>
#include <errno.h>
+#include <unistd.h>
/*
* yaffsfs_SetError() and yaffsfs_GetError()
* yaffsfs_Unlock()
* A single mechanism to lock and unlock yaffs. Hook up to a mutex or whatever.
* Here are two examples, one using POSIX pthreads, the other doing nothing.
+ *
+ * If we use pthreads then we also start a background gc thread.
*/
-#ifdef CONFIG_YAFFS_USE_PTHREADS
+#if 1
+
#include <pthread.h>
-static pthread_mutex_t mutex1;
+static pthread_mutex_t mutex1;
+static pthread_t bc_gc_thread;
void yaffsfs_Lock(void)
{
pthread_mutex_unlock( &mutex1 );
}
+static void *bg_gc_func(void *dummy)
+{
+ struct yaffs_dev *dev;
+ int urgent = 0;
+ int result;
+ int next_urgent;
+
+ /* Sleep for a bit to allow start up */
+ sleep(2);
+
+
+ while (1) {
+ /* Iterate through devices, do bg gc updating ungency */
+ yaffs_dev_rewind();
+ next_urgent = 0;
+
+ while ((dev = yaffs_next_dev()) != NULL) {
+ result = yaffs_do_background_gc_reldev(dev, urgent);
+ if (result > 0)
+ next_urgent = 1;
+ }
+
+ urgent = next_urgent;
+
+ if (next_urgent)
+ sleep(1);
+ else
+ sleep(5);
+ }
+
+ /* Don't ever return. */
+ return NULL;
+}
+
void yaffsfs_LockInit(void)
{
- pthread_mutex_init( &mutex1, NULL);
+ /* Initialise lock */
+ pthread_mutex_init(&mutex1, NULL);
+
+ /* Sneak in starting a background gc thread too */
+ pthread_create(&bc_gc_thread, NULL, bg_gc_func, NULL);
}
#else
/*
* yaffsfs_CurrentTime() retrns a 32-bit timestamp.
- *
+ *
* Can return 0 if your system does not care about time.
*/
-
+
u32 yaffsfs_CurrentTime(void)
{
return time(NULL);
*
* Functions to allocate and free memory.
*/
-
+
#ifdef CONFIG_YAFFS_TEST_MALLOC
static int yaffs_kill_alloc = 0;
* yaffs_bug_fn()
* Function to report a bug.
*/
-
+
void yaffs_bug_fn(const char *file_name, int line_no)
{
printf("yaffs bug detected %s:%d\n",
return yaffs_sync_common(NULL, path);
}
+
+static int yaffsfs_bg_gc_common(struct yaffs_dev *dev,
+ const YCHAR *path,
+ int urgency)
+{
+ int retVal = -1;
+ YCHAR *dummy;
+
+ if (!dev) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
+ yaffsfs_SetError(-EFAULT);
+ return -1;
+ }
+
+ if (yaffsfs_CheckPath(path) < 0) {
+ yaffsfs_SetError(-ENAMETOOLONG);
+ return -1;
+ }
+ }
+
+ yaffsfs_Lock();
+ if (!dev)
+ dev = yaffsfs_FindDevice(path, &dummy);
+
+ if (dev) {
+ if (!dev->is_mounted)
+ yaffsfs_SetError(-EINVAL);
+ else
+ retVal = yaffs_bg_gc(dev, urgency);
+ } else
+ yaffsfs_SetError(-ENODEV);
+
+ yaffsfs_Unlock();
+ return retVal;
+}
+
+/* Background gc functions.
+ * These return 0 when bg done or greater than 0 when gc has been
+ * done and there is still a lot of garbage to be cleaned up.
+ */
+
+int yaffs_do_background_gc(const YCHAR *path, int urgency)
+{
+ return yaffsfs_bg_gc_common(NULL, path, urgency);
+}
+
+int yaffs_do_background_gc_reldev(struct yaffs_dev *dev, int urgency)
+{
+ return yaffsfs_bg_gc_common(dev, NULL, urgency);
+}
+
static int yaffsfs_IsDevBusy(struct yaffs_dev *dev)
{
int i;
struct yaffs_dirent *yaffs_readdir_fd(int fd);
void yaffs_rewinddir_fd(int fd);
+/* Non-standard functions to pump garbage collection. */
+int yaffs_do_background_gc(const YCHAR *path, int urgency);
+int yaffs_do_background_gc_reldev(struct yaffs_dev *dev, int urgency);
+/* Non-standard functions to get usage info */
int yaffs_inodecount(const YCHAR *path);
int yaffs_n_handles(const YCHAR *path);
int yaffs_n_handles_reldev(struct yaffs_dev *dev, const YCHAR *path);
int yaffs_dump_dev_reldev(struct yaffs_dev *dev, const YCHAR *path);
-
#ifdef CONFIG_YAFFS_WINCE
int yaffs_set_wince_times(int fd,
const unsigned *wctime,