Hi,

> -----Original Message-----
> From: [email protected] [mailto:linux-omap-
> [email protected]] On Behalf Of Ameya Palande
> Sent: Wednesday, August 05, 2009 8:25 AM
> To: [email protected]
> Cc: [email protected]; Guzman Lugo, Fernando; Ramirez Luna, Omar;
> [email protected]; Moogi, Suyog
> Subject: [PATCH 2/3] DSPBRIDGE: Move resource cleanup to bridge_release
> 
> Instead of doing lazy resource cleanup in bridge_open, this patch will
> move
> it to bridge_release. This way the resources allocated will be cleaned up
> when that instance of the open is closed and will not wait till the next
> instance of open happens.
> 
> Signed-off-by: Fernando Guzman Lugo <[email protected]>
> Signed-off-by: Ameya Palande <[email protected]>
> ---
>  drivers/dsp/bridge/rmgr/drv_interface.c |  132 ++++++++++++--------------
> -----
>  1 files changed, 52 insertions(+), 80 deletions(-)
> 
> diff --git a/drivers/dsp/bridge/rmgr/drv_interface.c
> b/drivers/dsp/bridge/rmgr/drv_interface.c
> index 8cbdeee..2fcd6f9 100644
> --- a/drivers/dsp/bridge/rmgr/drv_interface.c
> +++ b/drivers/dsp/bridge/rmgr/drv_interface.c
> @@ -562,102 +562,74 @@ static void __exit bridge_exit(void)
>       platform_driver_unregister(&bridge_driver);
>  }
> 
> -/* This function is called when an application opens handle to the
> - * bridge driver. */
> -
> +/*
> + * This function is called when an application opens handle to the
> + * bridge driver.
> + */
>  static int bridge_open(struct inode *ip, struct file *filp)
>  {
>       int status = 0;
> -#ifndef RES_CLEANUP_DISABLE
> -       u32     hProcess;
> -     DSP_STATUS dsp_status = DSP_SOK;
> -     HANDLE       hDrvObject = NULL;
> -     struct PROCESS_CONTEXT    *pPctxt = NULL;
> -     struct PROCESS_CONTEXT  *next_node = NULL;
> -     struct PROCESS_CONTEXT    *pCtxtclosed = NULL;
> -     struct PROCESS_CONTEXT    *pCtxttraverse = NULL;
> -     struct task_struct *tsk = NULL;
> -     GT_0trace(driverTrace, GT_ENTER, "-> driver_open\n");
> -     dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
> +     DSP_STATUS dsp_status;
> +     HANDLE hDrvObject;
> +     struct PROCESS_CONTEXT *pr_ctxt = NULL;
> 
> -     /* Checking weather task structure for all process existing
> -      * in the process context list If not removing those processes*/
> -     if (DSP_FAILED(dsp_status))
> -             goto func_cont;
> +     GT_0trace(driverTrace, GT_ENTER, "-> bridge_open\n");
> 
> -     DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
> -     while (pCtxtclosed != NULL) {
> -             tsk = find_task_by_vpid(pCtxtclosed->pid);
> -             next_node = pCtxtclosed->next;
> -
> -             if ((tsk == NULL) || (tsk->exit_state == EXIT_ZOMBIE)) {
> -
> -                     GT_1trace(driverTrace, GT_5CLASS,
> -                              "***Task structure not existing for "
> -                              "process***%d\n", pCtxtclosed->pid);
> -                     DRV_RemoveAllResources(pCtxtclosed);
> -                     if (pCtxtclosed->hProcessor != NULL) {
> -                             DRV_GetProcCtxtList(&pCtxttraverse,
> -                                         (struct DRV_OBJECT *)hDrvObject);
> -                             if (pCtxttraverse->next == NULL) {
> -                                     PROC_Detach(pCtxtclosed->hProcessor);
> -                             } else {
> -                                     if ((pCtxtclosed->pid ==
> -                                       pCtxttraverse->pid) &&
> -                                       (pCtxttraverse->next != NULL)) {
> -                                             pCtxttraverse =
> -                                                     pCtxttraverse->next;
> -                                     }
> -                                     while ((pCtxttraverse != NULL) &&
> -                                          (pCtxtclosed->hProcessor
> -                                          != pCtxttraverse->hProcessor)) {
> -                                             pCtxttraverse =
> -                                                     pCtxttraverse->next;
> -                                             if ((pCtxttraverse != NULL) &&
> -                                               (pCtxtclosed->pid ==
> -                                               pCtxttraverse->pid)) {
> -                                                     pCtxttraverse =
> -                                                        pCtxttraverse->next;
> -                                             }
> -                                     }
> -                                     if (pCtxttraverse == NULL) {
> -                                             PROC_Detach
> -                                                  (pCtxtclosed->hProcessor);
> -                                     }
> -                             }
> -                     }
> -                     DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
> -                                          pCtxtclosed,
> -                                          (void *)pCtxtclosed->pid);
> +     dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
> +     if (DSP_SUCCEEDED(dsp_status)) {
> +             /*
> +              * Allocate a new process context and insert it into global
> +              * process context list.
> +              */
> +             DRV_InsertProcContext(hDrvObject, &pr_ctxt);
> +             if (pr_ctxt) {
> +                     DRV_ProcUpdatestate(pr_ctxt, PROC_RES_ALLOCATED);
> +                     DRV_ProcSetPID(pr_ctxt, current->pid);
> +             } else {
> +                     status = -ENOMEM;
>               }
> -             pCtxtclosed = next_node;
> +     } else {
> +             status = -EIO;
>       }
> -func_cont:
> -     dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
> -     if (DSP_SUCCEEDED(dsp_status))
> -             dsp_status = DRV_InsertProcContext(
> -                             (struct DRV_OBJECT *)hDrvObject, &pPctxt);
> 
> -     if (pPctxt != NULL) {
> -                     /* Return PID instead of process handle */
> -                     hProcess = current->pid;
> +     filp->private_data = pr_ctxt;
> 
> -             DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
> -                     DRV_ProcSetPID(pPctxt, hProcess);
> -     }
> -#endif
> -
> -     GT_0trace(driverTrace, GT_ENTER, " <- driver_open\n");
> +     GT_0trace(driverTrace, GT_ENTER, "<- bridge_open\n");
>       return status;
>  }
> 
> -/* This function is called when an application closes handle to the
> bridge
> - * driver. */
> +/*
> + * This function is called when an application closes handle to the
> bridge
> + * driver.
> + */
>  static int bridge_release(struct inode *ip, struct file *filp)
>  {
> +     int status = 0;
> +     DSP_STATUS dsp_status;
> +     HANDLE hDrvObject;
> +     struct PROCESS_CONTEXT *pr_ctxt;
> +
>       GT_0trace(driverTrace, GT_ENTER, "-> bridge_release\n");
> +
> +     if (!filp->private_data) {
> +             status = -EIO;
> +     } else {
> +             pr_ctxt = filp->private_data;
> +             dsp_status = CFG_GetObject((u32 *)&hDrvObject,
> REG_DRV_OBJECT);
> +             if (DSP_SUCCEEDED(dsp_status)) {
> +                     flush_signals(current);
> +                     DRV_RemoveAllResources(pr_ctxt);
> +                     PROC_Detach(pr_ctxt->hProcessor);
> +                     DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
> +                                     pr_ctxt, (void *)pr_ctxt->pid);
> +             } else {
> +                     status = -EIO;
> +             }
> +             filp->private_data = NULL;
> +     }
> +
>       GT_0trace(driverTrace, GT_ENTER, "<- bridge_release\n");
> -     return 0;
> +     return status;
>  }
> 
>  /* This function provides IO interface to the bridge driver. */
> --
> 1.6.2.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to [email protected]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

We have detected a use case where if an application creates a child process 
using fork call, and then the child and father processes call 
DSPProcessor_Attach() and create a new process context with new tgid; when the 
processes are terminated, only the last process calls bridge_release cleaning 
only the resources in the father process, leaving the child resources 
unreleased.

One solution we have seen is to perform goes through the entire process context 
list, clean up all the resources for all terminated processes or in "zombie" 
state, as below,

DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
while (pCtxtclosed != NULL) {
        printk("pCtxtclosed->pid = %d\n",pCtxtclosed->pid);
        tsk = find_task_by_pid(pCtxtclosed->pid);

        if ((tsk == NULL) || (tsk->exit_state == EXIT_ZOMBIE)) {
        
                GT_1trace(driverTrace, GT_5CLASS,
                        "***Task structure not existing for "
                         "process***%d\n", pCtxtclosed->pid);
                DRV_RemoveAllResources(pCtxtclosed);
                if (pCtxtclosed->hProcessor != NULL) {
                                        PROC_Detach
                                                 (pCtxtclosed->hProcessor);
                }
                pTmp = pCtxtclosed->next;
                DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
                                         pCtxtclosed,
                                         (void *)pCtxtclosed->pid);
        } else {
                pTmp = pCtxtclosed->next;
        }
        pCtxtclosed = pTmp;
}

Please let me know your comments.

/Ernesto
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to