Cygwin: pipe, fifo: Release select_sem semaphore as much as needed.

- Currently, raw_read(), raw_write() and close() release select_sem
  unconditionally even if no waiter for select_sem exists. With this
  patch, only the minimum number of semaphores required is released.
This commit is contained in:
Takashi Yano 2021-09-14 18:50:49 +09:00 committed by Corinna Vinschen
parent f79a46112e
commit e4e4537979
3 changed files with 47 additions and 13 deletions

View File

@ -1177,6 +1177,7 @@ class fhandler_pipe_fifo: public fhandler_base
protected: protected:
size_t pipe_buf_size; size_t pipe_buf_size;
HANDLE query_hdl; HANDLE query_hdl;
virtual void release_select_sem (const char *) {};
public: public:
fhandler_pipe_fifo (); fhandler_pipe_fifo ();
@ -1201,6 +1202,7 @@ class fhandler_pipe: public fhandler_pipe_fifo
private: private:
HANDLE read_mtx; HANDLE read_mtx;
pid_t popen_pid; pid_t popen_pid;
void release_select_sem (const char *);
public: public:
fhandler_pipe (); fhandler_pipe ();
@ -1444,6 +1446,8 @@ class fhandler_fifo: public fhandler_pipe_fifo
void shared_fc_handler_updated (bool val) void shared_fc_handler_updated (bool val)
{ shmem->shared_fc_handler_updated (val); } { shmem->shared_fc_handler_updated (val); }
void release_select_sem (const char *);
public: public:
fhandler_fifo (); fhandler_fifo ();
~fhandler_fifo () ~fhandler_fifo ()

View File

@ -1185,6 +1185,22 @@ fhandler_fifo::take_ownership (DWORD timeout)
return ret; return ret;
} }
void
fhandler_fifo::release_select_sem (const char *from)
{
LONG n_release;
if (reader) /* Number of select() call. */
n_release = get_obj_handle_count (select_sem)
- get_obj_handle_count (read_ready);
else /* Number of select() and reader */
n_release = get_obj_handle_count (select_sem)
- get_obj_handle_count (get_handle ());
debug_printf("%s(%s) release %d", from,
reader ? "reader" : "writer", n_release);
if (n_release)
ReleaseSemaphore (select_sem, n_release, NULL);
}
void __reg3 void __reg3
fhandler_fifo::raw_read (void *in_ptr, size_t& len) fhandler_fifo::raw_read (void *in_ptr, size_t& len)
{ {
@ -1372,7 +1388,7 @@ out:
fifo_client_unlock (); fifo_client_unlock ();
reading_unlock (); reading_unlock ();
if (select_sem) if (select_sem)
ReleaseSemaphore (select_sem, get_obj_handle_count (select_sem), NULL); release_select_sem ("raw_read");
} }
int __reg2 int __reg2
@ -1483,6 +1499,11 @@ fhandler_fifo::cancel_reader_thread ()
int int
fhandler_fifo::close () fhandler_fifo::close ()
{ {
if (select_sem)
{
release_select_sem ("close");
NtClose (select_sem);
}
if (writer) if (writer)
{ {
nwriters_lock (); nwriters_lock ();
@ -1574,11 +1595,6 @@ fhandler_fifo::close ()
NtClose (write_ready); NtClose (write_ready);
if (writer_opening) if (writer_opening)
NtClose (writer_opening); NtClose (writer_opening);
if (select_sem)
{
ReleaseSemaphore (select_sem, get_obj_handle_count (select_sem), NULL);
NtClose (select_sem);
}
if (nohandle ()) if (nohandle ())
return 0; return 0;
else else

View File

@ -233,6 +233,22 @@ fhandler_pipe::get_proc_fd_name (char *buf)
return buf; return buf;
} }
void
fhandler_pipe::release_select_sem (const char *from)
{
LONG n_release;
if (get_dev () == FH_PIPER) /* Number of select() and writer */
n_release = get_obj_handle_count (select_sem)
- get_obj_handle_count (read_mtx);
else /* Number of select() call */
n_release = get_obj_handle_count (select_sem)
- get_obj_handle_count (query_hdl);
debug_printf("%s(%s) release %d", from,
get_dev () == FH_PIPER ? "PIPER" : "PIPEW", n_release);
if (n_release)
ReleaseSemaphore (select_sem, n_release, NULL);
}
void __reg3 void __reg3
fhandler_pipe::raw_read (void *ptr, size_t& len) fhandler_pipe::raw_read (void *ptr, size_t& len)
{ {
@ -324,8 +340,7 @@ fhandler_pipe::raw_read (void *ptr, size_t& len)
ptr = ((char *) ptr) + nbytes_now; ptr = ((char *) ptr) + nbytes_now;
nbytes += nbytes_now; nbytes += nbytes_now;
if (select_sem && nbytes_now > 0) if (select_sem && nbytes_now > 0)
ReleaseSemaphore (select_sem, release_select_sem ("raw_read");
get_obj_handle_count (select_sem), NULL);
} }
else else
{ {
@ -496,8 +511,7 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
ptr = ((char *) ptr) + nbytes_now; ptr = ((char *) ptr) + nbytes_now;
nbytes += nbytes_now; nbytes += nbytes_now;
if (select_sem && nbytes_now > 0) if (select_sem && nbytes_now > 0)
ReleaseSemaphore (select_sem, release_select_sem ("raw_write");
get_obj_handle_count (select_sem), NULL);
/* 0 bytes returned? EAGAIN. See above. */ /* 0 bytes returned? EAGAIN. See above. */
if (NT_SUCCESS (status) && nbytes == 0) if (NT_SUCCESS (status) && nbytes == 0)
set_errno (EAGAIN); set_errno (EAGAIN);
@ -591,13 +605,13 @@ fhandler_pipe::dup (fhandler_base *child, int flags)
int int
fhandler_pipe::close () fhandler_pipe::close ()
{ {
if (read_mtx)
CloseHandle (read_mtx);
if (select_sem) if (select_sem)
{ {
ReleaseSemaphore (select_sem, get_obj_handle_count (select_sem), NULL); release_select_sem ("close");
CloseHandle (select_sem); CloseHandle (select_sem);
} }
if (read_mtx)
CloseHandle (read_mtx);
if (query_hdl) if (query_hdl)
CloseHandle (query_hdl); CloseHandle (query_hdl);
return fhandler_base::close (); return fhandler_base::close ();