diff --git a/fs/mmap/fs_mmap.c b/fs/mmap/fs_mmap.c index 36e710ad230..4f541fffe92 100644 --- a/fs/mmap/fs_mmap.c +++ b/fs/mmap/fs_mmap.c @@ -41,6 +41,46 @@ * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: unmap_anonymous + ****************************************************************************/ + +static int unmap_anonymous(FAR struct task_group_s *group, + FAR struct mm_map_entry_s *entry, + FAR void *start, + size_t length) +{ + int ret; + + /* De-allocate memory. + * NB: This is incomplete anounymous mapping implementation + * see file_mmap_ below + */ + + if (start == entry->vaddr && length == entry->length) + { + /* entry->priv marks allocation from kernel heap */ + + if (entry->priv.i) + { + kmm_free(start); + } + else + { + kumm_free(start); + } + + ret = mm_map_remove(group, &entry); + } + else + { + ret = -EINVAL; + ferr("ERROR: Unknown map type\n"); + } + + return ret; +} + /**************************************************************************** * Name: file_mmap_ ****************************************************************************/ @@ -51,6 +91,23 @@ static int file_mmap_(FAR struct file *filep, FAR void *start, { int ret; + /* Pass the information about the mapping in mm_map_entry_s structure. + * The driver may alter the structure, and if it supports unmap, it + * will also add it to the kernel maintained list of mappings. + */ + + struct mm_map_entry_s entry = + { + NULL, /* sq_entry_t */ + start, + length, + offset, + prot, + flags, + { NULL }, /* priv.p */ + NULL /* munmap */ + }; + /* Since only a tiny subset of mmap() functionality, we have to verify many * things. */ @@ -120,6 +177,11 @@ static int file_mmap_(FAR struct file *filep, FAR void *start, return -ENOMEM; } + entry.vaddr = *mapped; + entry.munmap = unmap_anonymous; + entry.priv.i = kernel; + mm_map_add(&entry); + return OK; } @@ -140,24 +202,10 @@ static int file_mmap_(FAR struct file *filep, FAR void *start, if (filep->f_inode && filep->f_inode->u.i_ops->mmap != NULL) { - /* Pass the information about the mapping in mm_map_entry_s structure. - * The driver may alter the structure, and if it supports unmap, it - * will also add it to the kernel maintained list of mappings. - */ - - struct mm_map_entry_s map = - { - NULL, /* sq_entry_t */ - start, length, offset, - prot, flags, - NULL, /* priv */ - NULL /* munmap */ - }; - - ret = filep->f_inode->u.i_ops->mmap(filep, &map); + ret = filep->f_inode->u.i_ops->mmap(filep, &entry); if (ret == OK) { - *mapped = (void *)map.vaddr; + *mapped = (void *)entry.vaddr; } } else diff --git a/fs/mmap/fs_munmap.c b/fs/mmap/fs_munmap.c index 7b8e57d4927..85ec132876f 100644 --- a/fs/mmap/fs_munmap.c +++ b/fs/mmap/fs_munmap.c @@ -23,6 +23,7 @@ ****************************************************************************/ #include +#include #include #include @@ -158,7 +159,32 @@ errout_with_lock: nxmutex_unlock(&g_rammaps.lock); return ret; #else - return OK; + + FAR struct tcb_s *tcb = nxsched_self(); + FAR struct task_group_s *group = tcb->group; + FAR struct mm_map_entry_s *entry = NULL; + int ret = OK; + + /* Iterate through all the mappings and call the underlying + * unmap for every mapping where "start" lies + * break loop on any errors. + * + * Get exclusive access to mm_map for this + */ + + ret = mm_map_lock(); + if (ret == OK) + { + while (ret == OK && (entry = mm_map_find(start, length))) + { + DEBUGASSERT(entry->munmap); + ret = entry->munmap(group, entry, start, length); + } + + mm_map_unlock(); + } + + return ret; #endif /* CONFIG_FS_RAMMAP */ }