Hi Ken,

On Thu, 26 Dec 2024 11:56:00 -0500
Ken Brown wrote:
> diff --git a/winsup/cygwin/mm/mmap.cc b/winsup/cygwin/mm/mmap.cc
> index 13418d782baf..10e3f5bdc2b3 100644
> --- a/winsup/cygwin/mm/mmap.cc
> +++ b/winsup/cygwin/mm/mmap.cc
> @@ -580,18 +580,61 @@ mmap_record::free_fh (fhandler_base *fh)
>      delete fh;
>  }
>  
> +/* Keep the list of anonymous mappings sorted as follows: All attached
> +   records come first, then those that are noreserve but not attached,
> +   then those that are not noreserve.  Those that are noreserve but
> +   not attached are sorted by address.  This order of the mappings is
> +   used in mmap_is_attached_or_noreserve.  Note: The code that follows
> +   makes implicit use of the fact that attached maps are also
> +   noreserve. */
>  mmap_record *
>  mmap_list::add_record (mmap_record &r)
>  {
> -  mmap_record *rec = (mmap_record *) ccalloc (HEAP_MMAP,
> -                   sizeof (mmap_record)
> -                   + MAPSIZE (PAGE_CNT (r.get_len ())) * sizeof (DWORD), 1);
> -  if (!rec)
> +  mmap_record *new_rec = (mmap_record *) ccalloc (HEAP_MMAP,
> +                      sizeof (mmap_record)
> +                      + MAPSIZE (PAGE_CNT (r.get_len ()))
> +                      * sizeof (DWORD), 1);
> +  if (!new_rec)
>      return NULL;
> -  rec->init_page_map (r);
> +  new_rec->init_page_map (r);
> +
> +  bool new_attached = new_rec->attached ();
> +  bool new_noreserve = new_rec->noreserve ();
> +  caddr_t new_addr = new_rec->get_address ();
> +
> +  LIST_WRITE_LOCK ();

This patch atempt to acquire lock despite the lock has been
already acquired. I think this is the cause of deadlock.

> +  if (fd != -1 || LIST_EMPTY (&recs))
> +    {
> +      LIST_INSERT_HEAD (&recs, new_rec, mr_next);
> +      goto out;
> +    }
>  
> -  LIST_INSERT_HEAD (&recs, rec, mr_next);
> -  return rec;
> +  /* Now we're working on the anonymous list, which is non-empty. */
> +  mmap_record *rec, *prev;
> +  LIST_FOREACH (rec, &recs, mr_next)
> +    {
> +      prev = rec;
> +      if (new_attached)
> +     {
> +       LIST_INSERT_HEAD (&recs, new_rec, mr_next);
> +       goto out;
> +     }
> +      if (new_noreserve && (rec->attached ()
> +                         || (rec->noreserve ()
> +                             && new_addr > rec->get_address ())))
> +     continue;
> +      if (!new_noreserve && rec->noreserve ())
> +     continue;
> +      LIST_INSERT_BEFORE (rec, new_rec, mr_next);
> +      goto out;
> +    }
> +
> +  /* If we get here, new_rec should be inserted at the end of the
> +     list, and prev points to the last record. */
> +  LIST_INSERT_AFTER (prev, new_rec, mr_next);
> +out:
> +  LIST_WRITE_UNLOCK ();
> +  return new_rec;
>  }
>  
>  void

-- 
Takashi Yano <takashi.y...@nifty.ne.jp>

Reply via email to