From 835c91b03a8f7d68d017254923314d07687962c1 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 23 Sep 2014 16:04:39 -0600 Subject: [PATCH] Add support for a per-process virtual page allocator. This is a new member of the task_group_s structure. The allocaor must be initialized when a new user process is started and uninitialize when the process group is finally destroyed. It is used by shmat() and shmdt() to pick the virtual address onto which to map the shared physical memory. --- binfmt/binfmt_execmodule.c | 15 ++++++++- include/nuttx/sched.h | 14 ++++++-- include/nuttx/shm.h | 58 ++++++++++++++++++++++++++++++++ mm/shm/shm_initialize.c | 69 ++++++++++++++++++++++++++++++++++++++ sched/group/group_leave.c | 8 ++++- 5 files changed, 159 insertions(+), 5 deletions(-) mode change 100755 => 100644 mm/shm/shm_initialize.c diff --git a/binfmt/binfmt_execmodule.c b/binfmt/binfmt_execmodule.c index babd5f1f7d..e4ef0b7854 100644 --- a/binfmt/binfmt_execmodule.c +++ b/binfmt/binfmt_execmodule.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include "sched/sched.h" @@ -229,6 +230,18 @@ int exec_module(FAR const struct binary_s *binp) } #endif +#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_SHM) + /* Initialize the shared memory virtual page allocator */ + + ret = shm_group_initialize(&tcb->cmn.group); + if (ret < 0) + { + bdbg("ERROR: shm_group_initialize() failed: %d\n", ret); + err = -ret; + goto errout_with_tcbinit; + } +#endif + #ifdef CONFIG_PIC /* Add the D-Space address as the PIC base address. By convention, this * must be the first allocated address space. @@ -244,7 +257,7 @@ int exec_module(FAR const struct binary_s *binp) #ifdef CONFIG_ARCH_ADDRENV /* Assign the address environment to the new task group */ - ret = up_addrenv_clone(&binp->addrenv, &tcb->cmn.group->addrenv); + ret = up_addrenv_clone(&binp->addrenv, &tcb->cmn.group->tg_addrenv); if (ret < 0) { err = -ret; diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 9d1cfbe945..321449f6cd 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -52,6 +52,7 @@ #include #include +#include #include #include @@ -103,6 +104,8 @@ # define HAVE_TASK_GROUP 1 /* Message queues */ # elif defined(CONFIG_ARCH_ADDRENV) # define HAVE_TASK_GROUP 1 /* Address environment */ +# elif defined(CONFIG_MM_SHM) +# define HAVE_TASK_GROUP 1 /* Shared memory */ # endif #endif @@ -418,10 +421,15 @@ struct task_group_s #endif #ifdef CONFIG_ARCH_ADDRENV - /* POSIX Named Message Queue Fields *******************************************/ - /* POSIX Named Message Queue Fields *******************************************/ + /* Address Environment ********************************************************/ - group_addrenv_t addrenv; /* Task group address environment */ + group_addrenv_t tg_addrenv; /* Task group address environment */ +#endif + +#ifdef CONFIG_MM_SHM + /* Shared Memory **************************************************************/ + + struct group_shm_s tg_shm; /* Task shared memory logic */ #endif }; #endif diff --git a/include/nuttx/shm.h b/include/nuttx/shm.h index baff3df9e4..2bd0a7e275 100644 --- a/include/nuttx/shm.h +++ b/include/nuttx/shm.h @@ -44,6 +44,8 @@ #include +#include + #ifdef CONFIG_MM_SHM /**************************************************************************** @@ -95,6 +97,26 @@ * Public Types ****************************************************************************/ +/* This structure describes the virtual page allocator that is use to manage + * the mapping of shared memory into the group/process address space. + */ + +struct group_shm_s +{ + /* Handle returned by gran_initialize() when the virtual page allocator + * was created. + */ + + GRAN_HANDLE gs_handle; + + /* This array is used to do a reverse lookup: Give the virtual address + * of a shared memory region, find the region index that performs that + * mapping. + */ + + uintptr_t gs_vaddr[CONFIG_ARCH_SHM_MAXREGIONS]; +}; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -119,5 +141,41 @@ void shm_initialize(void); +/**************************************************************************** + * Name: shm_group_initialize + * + * Description: + * Initialize the group shared memory data structures when a new task + * group is initialized. + * + * Input Parameters: + * group - A reference to the new group structure to be initialized. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +struct task_group_s; /* Forward reference */ +int shm_group_initialize(FAR struct task_group_s *group); + +/**************************************************************************** + * Name: shm_group_release + * + * Description: + * Release resources used by the group shared memory logic. This function + * is called at the time at the group is destroyed. + * + * Input Parameters: + * group - A reference to the group structure to be un-initialized. + * + * Returned Value: + * None + * + ****************************************************************************/ + +struct task_group_s; /* Forward reference */ +void shm_group_release(FAR struct task_group_s *group); + #endif /* CONFIG_MM_SHM */ #endif /* __INCLUDE_NUTTX_SHM_H */ diff --git a/mm/shm/shm_initialize.c b/mm/shm/shm_initialize.c old mode 100755 new mode 100644 index 2b7d7d406e..de942793c9 --- a/mm/shm/shm_initialize.c +++ b/mm/shm/shm_initialize.c @@ -39,6 +39,15 @@ #include +#include +#include + +#include +#include +#include +#include +#include + #include "shm/shm.h" #ifdef CONFIG_MM_SHM @@ -104,4 +113,64 @@ void shm_initialize(void) #endif } +/**************************************************************************** + * Name: shm_group_initialize + * + * Description: + * Initialize the group shared memory data structures when a new task + * group is initialized. + * + * Input Parameters: + * group - A reference to the new group structure to be initialized. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int shm_group_initialize(FAR struct task_group_s *group) +{ + DEBUGASSERT(group && !group->tg_shm.gs_handle); + + group->tg_shm.gs_handle = + gran_initialize((FAR void *)CONFIG_ARCH_SHM_VBASE, + ARCH_SHM_MAXPAGES << MM_PGSHIFT, + MM_PGSHIFT, MM_PGSHIFT); + + if (!group->tg_shm.gs_handle) + { + shmdbg("gran_initialize() failed\n"); + return -ENOMEM; + } + + return OK; +} + +/**************************************************************************** + * Name: shm_group_release + * + * Description: + * Release resources used by the group shared memory logic. This function + * is called at the time at the group is destroyed. + * + * Input Parameters: + * group - A reference to the group structure to be un-initialized. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void shm_group_release(FAR struct task_group_s *group) +{ + GRAN_HANDLE handle; + DEBUGASSERT(group) + + handle = group->tg_shm.gs_handle; + if (handle) + { + gran_release(handle); + } +} + #endif /* CONFIG_MM_SHM */ diff --git a/sched/group/group_leave.c b/sched/group/group_leave.c index 6b44ba68a0..7fadb31fc4 100644 --- a/sched/group/group_leave.c +++ b/sched/group/group_leave.c @@ -204,10 +204,16 @@ static inline void group_release(FAR struct task_group_s *group) mq_release(group); #endif +#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_SHM) + /* Release any resource held by shared memory virtual page allocator */ + + (void)shm_group_release(group); +#endif + #ifdef CONFIG_ARCH_ADDRENV /* Destroy the group address environment */ - (void)up_addrenv_destroy(&group->addrenv); + (void)up_addrenv_destroy(&group->tg_addrenv); /* Mark no address environment */