This is the mail archive of the cygwin-cvs@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[newlib-cygwin] ctype: align size of category bit fields to small targets needs


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=e98d3eb3eb9b6abd897e102031a14b7057641a65

commit e98d3eb3eb9b6abd897e102031a14b7057641a65
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Wed Mar 14 10:36:34 2018 +0100

    ctype: align size of category bit fields to small targets needs
    
    E.g. arm ABI requires -fshort-enums for bare-metal toolchains.
    Given there are only 29 category enums, the compiler chooses an
    8 bit enum type, so a size of 11 bits for the bitfield leads to
    a compile time error:
    
      error: width of 'cat' exceeds its type
        enum category cat: 11;
                      ^~~
    
    Fix this by aligning the size of the category members to byte
    borders.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 newlib/libc/ctype/categories.c        |   4 +-
 winsup/cygwin/fhandler.h              | 117 +++++++++++------
 winsup/cygwin/fhandler_socket_unix.cc | 229 ++++++++++++++++++++--------------
 3 files changed, 214 insertions(+), 136 deletions(-)

diff --git a/newlib/libc/ctype/categories.c b/newlib/libc/ctype/categories.c
index db285d7..c237324 100644
--- a/newlib/libc/ctype/categories.c
+++ b/newlib/libc/ctype/categories.c
@@ -2,8 +2,8 @@
 #include "categories.h"
 
 struct _category {
-  enum category cat: 11;
-  unsigned int first: 21;
+  enum category cat: 8;
+  unsigned int first: 24;
   unsigned short delta;
 } __attribute__((packed));
 
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 2e50208..2d11030 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -579,8 +579,8 @@ class fhandler_socket: public fhandler_base
 
   void set_addr_family (int af) {addr_family = af;}
   int get_addr_family () {return addr_family;}
-  void set_socket_type (int st) { type = st;}
-  int get_socket_type () {return type;}
+  virtual void set_socket_type (int st) { type = st;}
+  virtual int get_socket_type () {return type;}
 
   /* select.cc */
   virtual select_record *select_read (select_stuff *) = 0;
@@ -825,6 +825,38 @@ class fhandler_socket_local: public fhandler_socket_wsock
   }
 };
 
+/* Sharable spinlock with low CPU profile and massively better
+   performance than OS mutex or event solutions. */
+class af_unix_spinlock_t
+{
+  LONG  locked;          /* 0 oder 1 */
+
+public:
+  void lock ()
+  {
+    LONG ret = InterlockedExchange (&locked, 1);
+    if (ret)
+      {
+        for (DWORD i = 0; ret; ++i)
+          {
+            Sleep ((i % 1024) >> 8);
+            ret = InterlockedExchange (&locked, 1);
+          }
+      }
+  }
+  void unlock ()
+  {
+    InterlockedExchange (&locked, 0);
+  }
+};
+
+/* Internal representation of shutdown states */
+enum shut_state {
+  _SHUT_RECV	= 1,
+  _SHUT_SEND	= 2,
+  _SHUT_MASK	= 3
+};
+
 class sun_name_t
 {
  public:
@@ -835,19 +867,10 @@ class sun_name_t
       /* Allows 108 bytes sun_path plus trailing NUL */
       char _nul[sizeof (struct sockaddr_un) + 1];
     };
-  sun_name_t ();
-  sun_name_t (const struct sockaddr *name, __socklen_t namelen);
-
-  void *operator new (size_t) __attribute__ ((nothrow))
-    { return cmalloc_abort (HEAP_FHANDLER, sizeof (sun_name_t)); }
-  void operator delete (void *p) {cfree (p);}
-};
-
-/* Internal representation of shutdown states */
-enum shut_state {
-  _SHUT_READ	= 1,
-  _SHUT_WRITE	= 2,
-  _SHUT_RW	= 3
+  sun_name_t () { set (NULL, 0); }
+  sun_name_t (const struct sockaddr *name, __socklen_t namelen)
+    { set ((const struct sockaddr_un *) name, namelen); }
+  void set (const struct sockaddr_un *name, __socklen_t namelen);
 };
 
 /* For each AF_UNIX socket, we need to maintain socket-wide data,
@@ -855,30 +878,29 @@ enum shut_state {
    in socket, socketpair or accept4 and reopened by dup, fork or exec. */
 class af_unix_shmem_t
 {
-  SRWLOCK _bind_lock;
-  SRWLOCK _conn_lock;
-  SRWLOCK _io_lock;
+  /* Don't use SRWLOCKs here.  They are not sharable. */
+  af_unix_spinlock_t _bind_lock;
+  af_unix_spinlock_t _conn_lock;
+  af_unix_spinlock_t _state_lock;
+  af_unix_spinlock_t _io_lock;
   LONG _connection_state;	/* conn_state */
   LONG _binding_state;		/* bind_state */
   LONG _shutdown;		/* shut_state */
   LONG _so_error;		/* SO_ERROR */
   LONG _reuseaddr;		/* dummy */
+  int  _type;			/* socket type */
+  sun_name_t sun_path;
+  sun_name_t peer_sun_path;
 
  public:
-  af_unix_shmem_t ()
-  : _connection_state (unconnected), _binding_state (unbound),
-    _shutdown (0), _so_error (0)
-  {
-    InitializeSRWLock (&_bind_lock);
-    InitializeSRWLock (&_conn_lock);
-    InitializeSRWLock (&_io_lock);
-  }
-  void bind_lock () { AcquireSRWLockExclusive (&_bind_lock); }
-  void bind_unlock () { ReleaseSRWLockExclusive (&_bind_lock); }
-  void conn_lock () { AcquireSRWLockExclusive (&_conn_lock); }
-  void conn_unlock () { ReleaseSRWLockExclusive (&_conn_lock); }
-  void io_lock () { AcquireSRWLockExclusive (&_io_lock); }
-  void io_unlock () { ReleaseSRWLockExclusive (&_io_lock); }
+  void bind_lock () { _bind_lock.lock (); }
+  void bind_unlock () { _bind_lock.unlock (); }
+  void conn_lock () { _conn_lock.lock (); }
+  void conn_unlock () { _conn_lock.unlock (); }
+  void state_lock () { _state_lock.lock (); }
+  void state_unlock () { _state_lock.unlock (); }
+  void io_lock () { _io_lock.lock (); }
+  void io_unlock () { _io_lock.unlock (); }
 
   conn_state connect_state (conn_state val)
     { return (conn_state) InterlockedExchange (&_connection_state, val); }
@@ -899,8 +921,20 @@ class af_unix_shmem_t
   int reuseaddr (int val)
     { return (int) InterlockedExchange (&_reuseaddr, val); }
   int reuseaddr () const { return _reuseaddr; }
+
+  void set_socket_type (int val) { _type = val; }
+  int get_socket_type () const { return _type; }
+
+  sun_name_t *get_sun_path () {return &sun_path;}
+  sun_name_t *get_peer_sun_path () {return &peer_sun_path;}
+  void set_sun_path (struct sockaddr_un *un, __socklen_t unlen)
+    { sun_path.set (un, unlen); }
+  void set_peer_sun_path (struct sockaddr_un *un, __socklen_t unlen)
+    { peer_sun_path.set (un, unlen); }
 };
 
+class af_unix_pkt_hdr_t;
+
 class fhandler_socket_unix : public fhandler_socket
 {
  protected:
@@ -913,14 +947,14 @@ class fhandler_socket_unix : public fhandler_socket
   HANDLE connect_wait_thr;
   HANDLE cwt_termination_evt;
   PVOID cwt_param;
-  sun_name_t *sun_path;
-  sun_name_t *peer_sun_path;
   struct ucred peer_cred;
 
   void bind_lock () { shmem->bind_lock (); }
   void bind_unlock () { shmem->bind_unlock (); }
   void conn_lock () { shmem->conn_lock (); }
   void conn_unlock () { shmem->conn_unlock (); }
+  void state_lock () { shmem->state_lock (); }
+  void state_unlock () { shmem->state_unlock (); }
   void io_lock () { shmem->io_lock (); }
   void io_unlock () { shmem->io_unlock (); }
   conn_state connect_state (conn_state val)
@@ -935,6 +969,8 @@ class fhandler_socket_unix : public fhandler_socket
   int so_error () const { return shmem->so_error (); }
   int reuseaddr (int err) { return shmem->reuseaddr (err); }
   int reuseaddr () const { return shmem->reuseaddr (); }
+  void set_socket_type (int val) { shmem->set_socket_type (val); }
+  int get_socket_type () const { return shmem->get_socket_type (); }
 
   int create_shmem ();
   int reopen_shmem ();
@@ -960,12 +996,14 @@ class fhandler_socket_unix : public fhandler_socket
   int connect_pipe (PUNICODE_STRING pipe_name);
   int listen_pipe ();
   int disconnect_pipe (HANDLE ph);
-  sun_name_t *get_sun_path () {return sun_path;}
-  sun_name_t *get_peer_sun_path () {return peer_sun_path;}
-  void set_sun_path (struct sockaddr_un *un, __socklen_t unlen);
+  sun_name_t *get_sun_path () {return shmem->get_sun_path ();}
+  sun_name_t *get_peer_sun_path () {return shmem->get_peer_sun_path ();}
+  void set_sun_path (struct sockaddr_un *un, __socklen_t unlen)
+    { shmem->set_sun_path (un, unlen); }
   void set_sun_path (sun_name_t *snt)
     { snt ? set_sun_path (&snt->un, snt->un_len) : set_sun_path (NULL, 0); }
-  void set_peer_sun_path (struct sockaddr_un *un, __socklen_t unlen);
+  void set_peer_sun_path (struct sockaddr_un *un, __socklen_t unlen)
+    { shmem->set_peer_sun_path (un, unlen); }
   void set_peer_sun_path (sun_name_t *snt)
     { snt ? set_peer_sun_path (&snt->un, snt->un_len)
 	  : set_peer_sun_path (NULL, 0); }
@@ -973,6 +1011,9 @@ class fhandler_socket_unix : public fhandler_socket
   void fixup_after_fork (HANDLE parent);
   void fixup_after_exec ();
   void set_close_on_exec (bool val);
+  ssize_t recv_dgram (af_unix_pkt_hdr_t *packet, int flags);
+  ssize_t recv_stream (af_unix_pkt_hdr_t *packet, int flags);
+  ssize_t recv_eval (af_unix_pkt_hdr_t *packet, struct msghdr *msg, int flags);
 
  public:
   fhandler_socket_unix ();
diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc
index 79fc4bc..1bceaaf 100644
--- a/winsup/cygwin/fhandler_socket_unix.cc
+++ b/winsup/cygwin/fhandler_socket_unix.cc
@@ -88,6 +88,8 @@ class af_unix_pkt_hdr_t
   uint16_t	cmsg_len;	/* size of ancillary data block		*/
   uint16_t	data_len;	/* size of user data			*/
 
+  af_unix_pkt_hdr_t (uint8_t s, uint8_t n, uint16_t c, uint16_t d)
+    { init (s, n, c, d); }
   void init (uint8_t s, uint8_t n, uint16_t c, uint16_t d)
     {
       shut_info = s;
@@ -157,19 +159,14 @@ GUID __cygwin_socket_guid = {
 /* Default timeout value of connect: 20 secs, as on Linux. */
 #define AF_UNIX_CONNECT_TIMEOUT (-20 * NS100PERSEC)
 
-sun_name_t::sun_name_t ()
-{
-  un_len = sizeof (sa_family_t);
-  un.sun_family = AF_UNIX;
-  _nul[sizeof (struct sockaddr_un)] = '\0';
-}
-
-sun_name_t::sun_name_t (const struct sockaddr *name, socklen_t namelen)
+void
+sun_name_t::set (const struct sockaddr_un *name, socklen_t namelen)
 {
   if (namelen < 0)
     namelen = 0;
   un_len = namelen < (__socklen_t) sizeof un ? namelen : sizeof un;
-  if (name)
+  un.sun_family = AF_UNIX;
+  if (name && un_len)
     memcpy (&un, name, un_len);
   _nul[sizeof (struct sockaddr_un)] = '\0';
 }
@@ -622,20 +619,18 @@ int
 fhandler_socket_unix::send_my_name ()
 {
   sun_name_t *sun;
-  size_t name_len = 0;
   af_unix_pkt_hdr_t *packet;
   NTSTATUS status;
   IO_STATUS_BLOCK io;
 
   bind_lock ();
   sun = get_sun_path ();
-  name_len = sun ? sun->un_len : 0;
-  packet = (af_unix_pkt_hdr_t *) alloca (sizeof *packet + name_len);
+  packet = (af_unix_pkt_hdr_t *) alloca (sizeof *packet + sun->un_len);
   if (sun)
-    memcpy (AF_UNIX_PKT_NAME (packet), &sun->un, name_len);
-  bind_unlock ();
+    memcpy (AF_UNIX_PKT_NAME (packet), &sun->un, sun->un_len);
 
-  packet->init (0, name_len, 0, 0);
+  packet->init (0, sun->un_len, 0, 0);
+  bind_unlock ();
 
   /* The theory: Fire and forget. */
   io_lock ();
@@ -1009,27 +1004,6 @@ fhandler_socket_unix::disconnect_pipe (HANDLE ph)
 }
 
 void
-fhandler_socket_unix::set_sun_path (struct sockaddr_un *un, socklen_t unlen)
-{
-  if (peer_sun_path)
-    delete peer_sun_path;
-  if (!un)
-    sun_path = NULL;
-  sun_path = new sun_name_t ((const struct sockaddr *) un, unlen);
-}
-
-void
-fhandler_socket_unix::set_peer_sun_path (struct sockaddr_un *un,
-					 socklen_t unlen)
-{
-  if (peer_sun_path)
-    delete peer_sun_path;
-  if (!un)
-    peer_sun_path = NULL;
-  peer_sun_path = new sun_name_t ((const struct sockaddr *) un, unlen);
-}
-
-void
 fhandler_socket_unix::set_cred ()
 {
   peer_cred.pid = (pid_t) 0;
@@ -1079,10 +1053,6 @@ fhandler_socket_unix::fhandler_socket_unix ()
 
 fhandler_socket_unix::~fhandler_socket_unix ()
 {
-  if (sun_path)
-    delete sun_path;
-  if (peer_sun_path)
-    delete peer_sun_path;
 }
 
 int
@@ -1094,6 +1064,12 @@ fhandler_socket_unix::dup (fhandler_base *child, int flags)
       return -1;
     }
   fhandler_socket_unix *fhs = (fhandler_socket_unix *) child;
+  if (reopen_shmem () < 0)
+    {
+      __seterrno ();
+      fhs->close ();
+      return -1;
+    }
   if (backing_file_handle && backing_file_handle != INVALID_HANDLE_VALUE
       && !DuplicateHandle (GetCurrentProcess (), backing_file_handle,
 			    GetCurrentProcess (), &fhs->backing_file_handle,
@@ -1111,12 +1087,6 @@ fhandler_socket_unix::dup (fhandler_base *child, int flags)
       fhs->close ();
       return -1;
     }
-  if (reopen_shmem () < 0)
-    {
-      __seterrno ();
-      fhs->close ();
-      return -1;
-    }
   fhs->set_sun_path (get_sun_path ());
   fhs->set_peer_sun_path (get_peer_sun_path ());
   fhs->connect_wait_thr = NULL;
@@ -1248,7 +1218,7 @@ fhandler_socket_unix::socket (int af, int type, int protocol, int flags)
     return -1;
   rmem (262144);
   wmem (262144);
-  set_addr_family (af);
+  set_addr_family (AF_UNIX);
   set_socket_type (type);
   if (flags & SOCK_NONBLOCK)
     set_nonblocking (true);
@@ -1279,13 +1249,17 @@ fhandler_socket_unix::socketpair (int af, int type, int protocol, int flags,
       return -1;
     }
 
+  if (create_shmem () < 0)
+    return -1;
+  if (fh->create_shmem () < 0)
+    goto fh_shmem_failed;
   /* socket() on both sockets */
   rmem (262144);
   fh->rmem (262144);
   wmem (262144);
   fh->wmem (262144);
-  set_addr_family (af);
-  fh->set_addr_family (af);
+  set_addr_family (AF_UNIX);
+  fh->set_addr_family (AF_UNIX);
   set_socket_type (type);
   fh->set_socket_type (type);
   set_unique_id ();
@@ -1294,31 +1268,15 @@ fhandler_socket_unix::socketpair (int af, int type, int protocol, int flags,
   gen_pipe_name ();
   pipe = create_pipe (true);
   if (!pipe)
-    return -1;
+    goto create_pipe_failed;
   set_io_handle (pipe);
   set_sun_path (&sun);
   fh->set_peer_sun_path (&sun);
-  if (create_shmem () < 0)
-    {
-      NtClose (pipe);
-      return -1;
-    }
-  binding_state (bound);
   connect_state (listener);
-  /* connect 2nd socket */
-  if (type != SOCK_DGRAM
-      && fh->open_pipe (pc.get_nt_native_path (), false) < 0)
-    {
-      NtClose (shmem_handle);
-      NtClose (pipe);
-      return -1;
-    }
-  if (fh->create_shmem () < 0)
-    {
-      NtClose (fh->get_handle ());
-      NtClose (shmem_handle);
-      NtClose (pipe);
-    }
+  /* connect 2nd socket, even for DGRAM.  There's no difference as far
+     as socketpairs are concerned. */
+  if (fh->open_pipe (pc.get_nt_native_path (), false) < 0)
+    goto fh_open_pipe_failed;
   fh->connect_state (connected);
   if (flags & SOCK_NONBLOCK)
     {
@@ -1331,6 +1289,16 @@ fhandler_socket_unix::socketpair (int af, int type, int protocol, int flags,
       fh->set_close_on_exec (true);
     }
   return 0;
+
+fh_open_pipe_failed:
+  NtClose (pipe);
+create_pipe_failed:
+  NtUnmapViewOfSection (GetCurrentProcess (), fh->shmem);
+  NtClose (fh->shmem_handle);
+fh_shmem_failed:
+  NtUnmapViewOfSection (GetCurrentProcess (), shmem);
+  NtClose (shmem_handle);
+  return -1;
 }
 
 /* Bind creates the backing file, generates the pipe name and sets
@@ -1471,7 +1439,7 @@ fhandler_socket_unix::accept4 (struct sockaddr *peer, int *len, int flags)
 		  if (sock->create_shmem () < 0)
 		    goto create_shmem_failed;
 
-		  sock->set_addr_family (get_addr_family ());
+		  sock->set_addr_family (AF_UNIX);
 		  sock->set_socket_type (get_socket_type ());
 		  if (flags & SOCK_NONBLOCK)
 		    sock->set_nonblocking (true);
@@ -1609,36 +1577,60 @@ fhandler_socket_unix::connect (const struct sockaddr *name, int namelen)
 int
 fhandler_socket_unix::getsockname (struct sockaddr *name, int *namelen)
 {
-  sun_name_t sun;
+  sun_name_t *sun = get_sun_path ();
 
-  if (get_sun_path ())
-    memcpy (&sun, &get_sun_path ()->un, get_sun_path ()->un_len);
-  else
-    sun.un_len = 0;
-  memcpy (name, &sun, MIN (*namelen, sun.un_len));
-  *namelen = sun.un_len;
+  memcpy (name, sun, MIN (*namelen, sun->un_len));
+  *namelen = sun->un_len;
   return 0;
 }
 
 int
 fhandler_socket_unix::getpeername (struct sockaddr *name, int *namelen)
 {
-  sun_name_t sun;
-
-  if (get_peer_sun_path ())
-    memcpy (&sun, &get_peer_sun_path ()->un, get_peer_sun_path ()->un_len);
-  else
-    sun.un_len = 0;
-  memcpy (name, &sun, MIN (*namelen, sun.un_len));
-  *namelen = sun.un_len;
+  sun_name_t *sun = get_peer_sun_path ();
+  memcpy (name, sun, MIN (*namelen, sun->un_len));
+  *namelen = sun->un_len;
   return 0;
 }
 
 int
 fhandler_socket_unix::shutdown (int how)
 {
-  set_errno (EAFNOSUPPORT);
-  return -1;
+  NTSTATUS status = STATUS_SUCCESS;
+  IO_STATUS_BLOCK io;
+
+  if (how < SHUT_RD || how > SHUT_RDWR)
+    {
+      set_errno (EINVAL);
+      return -1;
+    }
+  /* Convert SHUT_RD/SHUT_WR/SHUT_RDWR to _SHUT_RECV/_SHUT_SEND bits. */
+  ++how;
+  state_lock ();
+  int old_shutdown_mask = saw_shutdown ();
+  int new_shutdown_mask = old_shutdown_mask | how;
+  if (new_shutdown_mask != old_shutdown_mask)
+    saw_shutdown (new_shutdown_mask);
+  state_unlock ();
+  if (new_shutdown_mask != old_shutdown_mask)
+    {
+      /* Send shutdown info to peer.  Note that it's not necessarily fatal
+	 if the info isn't sent here.  The info will be reproduced by any
+	 followup package sent to the peer. */
+      af_unix_pkt_hdr_t packet (new_shutdown_mask, 0, 0, 0);
+      io_lock ();
+      set_pipe_non_blocking (true);
+      status = NtWriteFile (get_handle (), NULL, NULL, NULL, &io, &packet,
+			    packet.pckt_len, NULL, NULL);
+      set_pipe_non_blocking (is_nonblocking ());
+      io_unlock ();
+    }
+  if (!NT_SUCCESS (status))
+    {
+      debug_printf ("Couldn't send shutdown info: NtWriteFile: %y", status);
+      return -1;
+    }
+  return 0;
 }
 
 int
@@ -1658,16 +1650,17 @@ fhandler_socket_unix::close ()
   PVOID param = InterlockedExchangePointer (&cwt_param, NULL);
   if (param)
     cfree (param);
+  HANDLE hdl = InterlockedExchangePointer (&get_handle (), NULL);
+  if (hdl)
+    NtClose (hdl);
+  if (backing_file_handle && backing_file_handle != INVALID_HANDLE_VALUE)
+    NtClose (backing_file_handle);
   HANDLE shm = InterlockedExchangePointer (&shmem_handle, NULL);
   if (shm)
     NtClose (shm);
   param = InterlockedExchangePointer ((PVOID *) &shmem, NULL);
   if (param)
     NtUnmapViewOfSection (GetCurrentProcess (), param);
-  if (get_handle ())
-    NtClose (get_handle ());
-  if (backing_file_handle && backing_file_handle != INVALID_HANDLE_VALUE)
-    NtClose (backing_file_handle);
   return 0;
 }
 
@@ -1681,33 +1674,77 @@ fhandler_socket_unix::getpeereid (pid_t *pid, uid_t *euid, gid_t *egid)
       set_errno (EINVAL);
       return -1;
     }
-  conn_lock ();
   if (connect_state () != connected)
     set_errno (ENOTCONN);
   else
     {
       __try
 	{
+	  state_lock ();
 	  if (pid)
 	    *pid = peer_cred.pid;
 	  if (euid)
 	    *euid = peer_cred.uid;
 	  if (egid)
 	    *egid = peer_cred.gid;
+	  state_unlock ();
 	  ret = 0;
 	}
       __except (EFAULT) {}
       __endtry
     }
-  conn_unlock ();
   return ret;
 }
 
 ssize_t
+fhandler_socket_unix::recv_dgram (af_unix_pkt_hdr_t *packet, int flags)
+{
+  /* socketpair sockets already have a valid pipe handle! */
+  return 0;
+}
+
+ssize_t
+fhandler_socket_unix::recv_stream (af_unix_pkt_hdr_t *packet, int flags)
+{
+
+  io_lock ();
+  io_unlock ();
+  return 0;
+}
+
+ssize_t
+fhandler_socket_unix::recv_eval (af_unix_pkt_hdr_t *packet, struct msghdr *msg,
+				 int flags)
+{
+  return 0;
+}
+
+ssize_t
 fhandler_socket_unix::recvmsg (struct msghdr *msg, int flags)
 {
-  set_errno (EAFNOSUPPORT);
-  return -1;
+  tmp_pathbuf tp;
+  af_unix_pkt_hdr_t *packet;
+  ssize_t ret;
+
+  if ((flags & ~(MSG_CMSG_CLOEXEC | MSG_DONTWAIT | MSG_OOB | MSG_PEEK
+		 | MSG_TRUNC | MSG_WAITALL)) != 0)
+    {
+      set_errno (EINVAL);
+      return -1;
+    }
+  if (flags & MSG_OOB)
+    {
+      set_errno (EOPNOTSUPP);
+      return -1;
+    }
+  if (saw_shutdown () & _SHUT_RECV)
+    return 0; /* EOF */
+  packet = (af_unix_pkt_hdr_t *) tp.t_get ();
+  ret = (get_socket_type () == SOCK_DGRAM) ? recv_dgram (packet, flags)
+					   : recv_stream (packet, flags);
+  if (ret > 0)
+    ret = recv_eval (packet, msg, flags);
+  return ret;
 }
 
 ssize_t


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]