public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] Cygwin: FIFO: add shared memory
@ 2020-05-08 11:29 Ken Brown
0 siblings, 0 replies; only message in thread
From: Ken Brown @ 2020-05-08 11:29 UTC (permalink / raw)
To: cygwin-cvs
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=878eb224622cd3bfc485fdf94a6c2f65e810fa19
commit 878eb224622cd3bfc485fdf94a6c2f65e810fa19
Author: Ken Brown <kbrown@cornell.edu>
Date: Tue Mar 17 12:29:56 2020 -0400
Cygwin: FIFO: add shared memory
Even though we currently allow a FIFO to be opened for reading only
once, we can still have more than one reader open because of dup and
fork. Add a named shared memory section accessible to all readers of
a given FIFO. In future commits we will add information needed by all
readers to this section
Add a class fifo_shmem_t that lets us access this information.
Add a method create_shmem that is called when a reader opens, and add
a method reopen_shmem that is called by dup, fork, and exec. (Each
new reader needs its own view of the shared memory.)
Diff:
---
winsup/cygwin/fhandler.h | 13 ++++++
winsup/cygwin/fhandler_fifo.cc | 97 ++++++++++++++++++++++++++++++++++++++++--
2 files changed, 106 insertions(+), 4 deletions(-)
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 5e6a1d1db..8d6b94021 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1300,6 +1300,11 @@ struct fifo_client_handler
int pipe_state ();
};
+/* Info needed by all readers of a FIFO, stored in named shared memory. */
+class fifo_shmem_t
+{
+};
+
class fhandler_fifo: public fhandler_base
{
/* Handles to named events shared by all fhandlers for a given FIFO. */
@@ -1319,6 +1324,10 @@ class fhandler_fifo: public fhandler_base
af_unix_spinlock_t _fifo_client_lock;
bool reader, writer, duplexer;
size_t max_atomic_write;
+
+ HANDLE shmem_handle;
+ fifo_shmem_t *shmem;
+
bool __reg2 wait (HANDLE);
static NTSTATUS npfs_handle (HANDLE &);
HANDLE create_pipe_instance (bool);
@@ -1330,6 +1339,9 @@ class fhandler_fifo: public fhandler_base
void record_connection (fifo_client_handler&,
fifo_client_connect_state = fc_connected);
+ int create_shmem ();
+ int reopen_shmem ();
+
public:
fhandler_fifo ();
bool hit_eof ();
@@ -1341,6 +1353,7 @@ public:
DWORD fifo_reader_thread_func ();
void fifo_client_lock () { _fifo_client_lock.lock (); }
void fifo_client_unlock () { _fifo_client_lock.unlock (); }
+
int open (int, mode_t);
off_t lseek (off_t offset, int whence);
int close ();
diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc
index 09a7eb321..9a0db3f33 100644
--- a/winsup/cygwin/fhandler_fifo.cc
+++ b/winsup/cygwin/fhandler_fifo.cc
@@ -70,7 +70,8 @@ fhandler_fifo::fhandler_fifo ():
read_ready (NULL), write_ready (NULL), writer_opening (NULL),
cancel_evt (NULL), thr_sync_evt (NULL), _maybe_eof (false), nhandlers (0),
reader (false), writer (false), duplexer (false),
- max_atomic_write (DEFAULT_PIPEBUFSIZE)
+ max_atomic_write (DEFAULT_PIPEBUFSIZE),
+ shmem_handle (NULL), shmem (NULL)
{
pipe_name_buf[0] = L'\0';
need_fork_fixup (true);
@@ -441,6 +442,67 @@ canceled:
return 0;
}
+int
+fhandler_fifo::create_shmem ()
+{
+ HANDLE sect;
+ OBJECT_ATTRIBUTES attr;
+ NTSTATUS status;
+ LARGE_INTEGER size = { .QuadPart = sizeof (fifo_shmem_t) };
+ SIZE_T viewsize = sizeof (fifo_shmem_t);
+ PVOID addr = NULL;
+ UNICODE_STRING uname;
+ WCHAR shmem_name[MAX_PATH];
+
+ __small_swprintf (shmem_name, L"fifo-shmem.%08x.%016X", get_dev (),
+ get_ino ());
+ RtlInitUnicodeString (&uname, shmem_name);
+ InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT,
+ get_shared_parent_dir (), NULL);
+ status = NtCreateSection (§, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY
+ | SECTION_MAP_READ | SECTION_MAP_WRITE,
+ &attr, &size, PAGE_READWRITE, SEC_COMMIT, NULL);
+ if (status == STATUS_OBJECT_NAME_COLLISION)
+ status = NtOpenSection (§, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY
+ | SECTION_MAP_READ | SECTION_MAP_WRITE, &attr);
+ if (!NT_SUCCESS (status))
+ {
+ __seterrno_from_nt_status (status);
+ return -1;
+ }
+ status = NtMapViewOfSection (sect, NtCurrentProcess (), &addr, 0, viewsize,
+ NULL, &viewsize, ViewShare, 0, PAGE_READWRITE);
+ if (!NT_SUCCESS (status))
+ {
+ NtClose (sect);
+ __seterrno_from_nt_status (status);
+ return -1;
+ }
+ shmem_handle = sect;
+ shmem = (fifo_shmem_t *) addr;
+ return 0;
+}
+
+/* shmem_handle must be valid when this is called. */
+int
+fhandler_fifo::reopen_shmem ()
+{
+ NTSTATUS status;
+ SIZE_T viewsize = sizeof (fifo_shmem_t);
+ PVOID addr = NULL;
+
+ status = NtMapViewOfSection (shmem_handle, NtCurrentProcess (), &addr,
+ 0, viewsize, NULL, &viewsize, ViewShare,
+ 0, PAGE_READWRITE);
+ if (!NT_SUCCESS (status))
+ {
+ __seterrno_from_nt_status (status);
+ return -1;
+ }
+ shmem = (fifo_shmem_t *) addr;
+ return 0;
+}
+
int
fhandler_fifo::open (int flags, mode_t)
{
@@ -501,12 +563,15 @@ fhandler_fifo::open (int flags, mode_t)
goto err_close_write_ready;
}
- /* If we're reading, signal read_ready and start the fifo_reader_thread. */
+ /* If we're reading, signal read_ready, create the shared memory,
+ and start the fifo_reader_thread. */
if (reader)
{
SetEvent (read_ready);
- if (!(cancel_evt = create_event ()))
+ if (create_shmem () < 0)
goto err_close_writer_opening;
+ if (!(cancel_evt = create_event ()))
+ goto err_close_shmem;
if (!(thr_sync_evt = create_event ()))
goto err_close_cancel_evt;
new cygthread (fifo_reader_thread, this, "fifo_reader", thr_sync_evt);
@@ -615,6 +680,9 @@ err_close_reader:
return 0;
err_close_cancel_evt:
NtClose (cancel_evt);
+err_close_shmem:
+ NtUnmapViewOfSection (NtCurrentProcess (), shmem);
+ NtClose (shmem_handle);
err_close_writer_opening:
NtClose (writer_opening);
err_close_write_ready:
@@ -944,6 +1012,10 @@ fhandler_fifo::close ()
dup/fork/exec; we should only reset read_ready when the last
one closes. */
ResetEvent (read_ready);
+ if (shmem)
+ NtUnmapViewOfSection (NtCurrentProcess (), shmem);
+ if (shmem_handle)
+ NtClose (shmem_handle);
}
if (read_ready)
NtClose (read_ready);
@@ -1014,6 +1086,15 @@ fhandler_fifo::dup (fhandler_base *child, int flags)
/* Make sure the child starts unlocked. */
fhf->fifo_client_unlock ();
+ if (!DuplicateHandle (GetCurrentProcess (), shmem_handle,
+ GetCurrentProcess (), &fhf->shmem_handle,
+ 0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
+ {
+ __seterrno ();
+ goto err_close_writer_opening;
+ }
+ if (fhf->reopen_shmem () < 0)
+ goto err_close_shmem_handle;
fifo_client_lock ();
for (i = 0; i < nhandlers; i++)
{
@@ -1044,7 +1125,10 @@ err_close_cancel_evt:
err_close_handlers:
for (int j = 0; j < i; j++)
fhf->fc_handler[j].close ();
-/* err_close_writer_opening: */
+ NtUnmapViewOfSection (GetCurrentProcess (), fhf->shmem);
+err_close_shmem_handle:
+ NtClose (fhf->shmem_handle);
+err_close_writer_opening:
NtClose (fhf->writer_opening);
err_close_write_ready:
NtClose (fhf->write_ready);
@@ -1066,6 +1150,9 @@ fhandler_fifo::fixup_after_fork (HANDLE parent)
/* Make sure the child starts unlocked. */
fifo_client_unlock ();
+ fork_fixup (parent, shmem_handle, "shmem_handle");
+ if (reopen_shmem () < 0)
+ api_fatal ("Can't reopen shared memory during fork, %E");
fifo_client_lock ();
for (int i = 0; i < nhandlers; i++)
fork_fixup (parent, fc_handler[i].h, "fc_handler[].h");
@@ -1087,6 +1174,8 @@ fhandler_fifo::fixup_after_exec ()
/* Make sure the child starts unlocked. */
fifo_client_unlock ();
+ if (reopen_shmem () < 0)
+ api_fatal ("Can't reopen shared memory during exec, %E");
if (!(cancel_evt = create_event ()))
api_fatal ("Can't create reader thread cancel event during exec, %E");
if (!(thr_sync_evt = create_event ()))
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-05-08 11:29 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-08 11:29 [newlib-cygwin] Cygwin: FIFO: add shared memory Ken Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).