]> sourceware.org Git - newlib-cygwin.git/blobdiff - winsup/cygwin/posix_ipc.cc
Cygwin: POSIX msg queues: implement open/mq_open entirely in fhandler
[newlib-cygwin.git] / winsup / cygwin / posix_ipc.cc
index ef05dbc1cd8538921ca3018a5283bc4d167f4056..772072d938ad71d4b2d03b861fa531ecff1b4508 100644 (file)
@@ -1,7 +1,5 @@
 /* posix_ipc.cc: POSIX IPC API for Cygwin.
 
-   Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2014, 2015 Red Hat, Inc.
-
 This file is part of Cygwin.
 
 This software is a copyrighted work licensed under the terms of the
@@ -18,6 +16,8 @@ details. */
 #include "cygheap.h"
 #include "sigproc.h"
 #include "ntdll.h"
+#include "tls_pbuf.h"
+#include <io.h>
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <stdlib.h>
@@ -25,7 +25,7 @@ details. */
 #include <mqueue.h>
 #include <semaphore.h>
 
-/* The prefix_len is the length of the path prefix ncluding trailing "/"
+/* The prefix_len is the length of the path prefix including trailing "/"
    (or "/sem." for semaphores) as well as the trailing NUL. */
 static struct
 {
@@ -66,22 +66,33 @@ check_path (char *res_name, ipc_type_t type, const char *name, size_t len)
       set_errno (EINVAL);
       return false;
     }
-  /* Name must not be empty, or just be a single slash, or start with more
-     than one slash.  Same for backslash.
-     Apart from handling backslash like slash, the naming rules are identical
+  /* Apart from handling backslash like slash, the naming rules are identical
      to Linux, including the names and requirements for subdirectories, if
      the name contains further slashes. */
-  if (!name || (strchr ("/\\", name[0])
-               && (!name[1] || strchr ("/\\", name[1]))))
+  /* Name must not be empty and has to start with a slash (or backslash) */
+  if (!name || !strchr ("/\\", name[0]))
     {
       debug_printf ("Invalid %s name '%s'", ipc_names[type].description, name);
       set_errno (EINVAL);
       return false;
     }
-  /* Skip leading (back-)slash. */
-  if (strchr ("/\\", name[0]))
-    ++name;
-  if (len > PATH_MAX - ipc_names[type].prefix_len)
+  /* Name must not consist of just a single slash (or backslash) */
+  if (!name[1])
+    {
+      debug_printf ("Invalid %s name '%s'", ipc_names[type].description, name);
+      set_errno (ENOENT);
+      return false;
+    }
+  /* Name must not contain slashes after the leading one */
+  if (strpbrk (name + 1, "/\\"))
+    {
+      debug_printf ("Invalid %s name '%s'", ipc_names[type].description, name);
+      set_errno (EACCES);
+      return false;
+    }
+  /* Length must be less than or equal to NAME_MAX, or NAME_MAX - 4 in
+     case of semaphores, due to the leading "sem." prefix */
+  if (len > NAME_MAX - (type == semaphore ? strlen ("sem.") : 0))
     {
       debug_printf ("%s name '%s' too long", ipc_names[type].description, name);
       set_errno (ENAMETOOLONG);
@@ -89,33 +100,10 @@ check_path (char *res_name, ipc_type_t type, const char *name, size_t len)
     }
   __small_sprintf (res_name, "%s/%s%s", ipc_names[type].prefix,
                                        type == semaphore ? "sem." : "",
-                                       name);
+                                       name + 1);
   return true;
 }
 
-static int
-ipc_mutex_init (HANDLE *pmtx, const char *name)
-{
-  WCHAR buf[MAX_PATH];
-  UNICODE_STRING uname;
-  OBJECT_ATTRIBUTES attr;
-  NTSTATUS status;
-
-  __small_swprintf (buf, L"mqueue/mtx_%s", name);
-  RtlInitUnicodeString (&uname, buf);
-  InitializeObjectAttributes (&attr, &uname,
-                             OBJ_INHERIT | OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
-                             get_shared_parent_dir (),
-                             everyone_sd (CYG_MUTANT_ACCESS));
-  status = NtCreateMutant (pmtx, CYG_MUTANT_ACCESS, &attr, FALSE);
-  if (!NT_SUCCESS (status))
-    {
-      debug_printf ("NtCreateMutant: %y", status);
-      return geterrno_from_win_error (RtlNtStatusToDosError (status));
-    }
-  return 0;
-}
-
 static int
 ipc_mutex_lock (HANDLE mtx, bool eintr)
 {
@@ -140,36 +128,6 @@ ipc_mutex_unlock (HANDLE mtx)
   return ReleaseMutex (mtx) ? 0 : geterrno_from_win_error ();
 }
 
-static inline int
-ipc_mutex_close (HANDLE mtx)
-{
-  return CloseHandle (mtx) ? 0 : geterrno_from_win_error ();
-}
-
-static int
-ipc_cond_init (HANDLE *pevt, const char *name, char sr)
-{
-  WCHAR buf[MAX_PATH];
-  UNICODE_STRING uname;
-  OBJECT_ATTRIBUTES attr;
-  NTSTATUS status;
-
-  __small_swprintf (buf, L"mqueue/evt_%s%c", name, sr);
-  RtlInitUnicodeString (&uname, buf);
-  InitializeObjectAttributes (&attr, &uname,
-                             OBJ_INHERIT | OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
-                             get_shared_parent_dir (),
-                             everyone_sd (CYG_EVENT_ACCESS));
-  status = NtCreateEvent (pevt, CYG_EVENT_ACCESS, &attr,
-                         NotificationEvent, FALSE);
-  if (!NT_SUCCESS (status))
-    {
-      debug_printf ("NtCreateEvent: %y", status);
-      return geterrno_from_win_error (RtlNtStatusToDosError (status));
-    }
-  return 0;
-}
-
 static int
 ipc_cond_timedwait (HANDLE evt, HANDLE mtx, const struct timespec *abstime)
 {
@@ -178,14 +136,12 @@ ipc_cond_timedwait (HANDLE evt, HANDLE mtx, const struct timespec *abstime)
   DWORD timer_idx = 0;
   int ret = 0;
 
-  set_signal_arrived here (w4[1]);
+  wait_signal_arrived here (w4[1]);
   if ((w4[cnt] = pthread::get_cancel_event ()) != NULL)
     ++cnt;
   if (abstime)
     {
-      if (abstime->tv_sec < 0
-              || abstime->tv_nsec < 0
-              || abstime->tv_nsec > 999999999)
+      if (!valid_timespec (*abstime))
        return EINVAL;
 
       /* If a timeout is set, we create a waitable timer to wait for.
@@ -225,7 +181,7 @@ restart1:
     case WAIT_OBJECT_0 + 2:
       if (timer_idx != 2)
        pthread::static_cancel_self ();
-      /*FALLTHRU*/
+      fallthrough;
     case WAIT_OBJECT_0 + 3:
       ret = ETIMEDOUT;
       break;
@@ -253,7 +209,7 @@ restart1:
        case WAIT_OBJECT_0 + 2:
          if (timer_idx != 2)
            pthread_testcancel ();
-         /*FALLTHRU*/
+         fallthrough;
        case WAIT_OBJECT_0 + 3:
          ret = ETIMEDOUT;
          break;
@@ -277,12 +233,6 @@ ipc_cond_signal (HANDLE evt)
   SetEvent (evt);
 }
 
-static inline void
-ipc_cond_close (HANDLE evt)
-{
-  CloseHandle (evt);
-}
-
 class ipc_flock
 {
   struct flock fl;
@@ -349,84 +299,13 @@ shm_unlink (const char *name)
    files are created under /dev/mqueue.  mq_timedsend and mq_timedreceive
    are implemented additionally. */
 
-/* The mq_attr structure is defined using long datatypes per POSIX.
-   For interoperability reasons between 32 and 64 bit processes, we have
-   to make sure to use a unified structure layout in the message queue file.
-   That's what the mq_fattr is, the in-file representation of the mq_attr
-   struct. */
-#pragma pack (push, 4)
-struct mq_fattr
-{
-  uint32_t mq_flags;
-  uint32_t mq_maxmsg;
-  uint32_t mq_msgsize;
-  uint32_t mq_curmsgs;
-};
-
-struct mq_hdr
-{
-  struct mq_fattr mqh_attr;     /* the queue's attributes */
-  int32_t         mqh_head;     /* index of first message */
-  int32_t         mqh_free;     /* index of first free message */
-  int32_t         mqh_nwait;    /* #threads blocked in mq_receive() */
-  pid_t           mqh_pid;      /* nonzero PID if mqh_event set */
-  char            mqh_uname[36]; /* unique name used to identify synchronization
-                                   objects connected to this queue */
-  union {
-    struct sigevent mqh_event;  /* for mq_notify() */
-    /* Make sure sigevent takes the same space on 32 and 64 bit systems.
-       Other than that, it doesn't need to be compatible since only
-       one process can be notified at a time. */
-    uint64_t        mqh_placeholder[8];
-  };
-  uint32_t        mqh_magic;   /* Expect MQI_MAGIC here, otherwise it's
-                                  an old-style message queue. */
-};
-
-struct msg_hdr
-{
-  int32_t         msg_next;     /* index of next on linked list */
-  int32_t         msg_len;      /* actual length */
-  unsigned int    msg_prio;     /* priority */
-};
-#pragma pack (pop)
-
-struct mq_info
-{
-  struct mq_hdr  *mqi_hdr;      /* start of mmap'ed region */
-  uint32_t        mqi_magic;    /* magic number if open */
-  int             mqi_flags;    /* flags for this process */
-  HANDLE          mqi_lock;     /* mutex lock */
-  HANDLE          mqi_waitsend;         /* and condition variable for full queue */
-  HANDLE          mqi_waitrecv;         /* and condition variable for empty queue */
-};
-
-#define MQI_MAGIC      0x98765432UL
-
-#define MSGSIZE(i)     roundup((i), sizeof(long))
-
-#define         MAX_TRIES      10      /* for waiting for initialization */
-
-struct mq_attr defattr = { 0, 10, 8192, 0 };   /* Linux defaults. */
-
-extern "C" off_t lseek64 (int, off_t, int);
-extern "C" void *mmap64 (void *, size_t, int, int, int, off_t);
-
 extern "C" mqd_t
 mq_open (const char *name, int oflag, ...)
 {
-  int i, fd = -1, nonblock, created = 0;
-  long msgsize, index;
-  off_t filesize = 0;
   va_list ap;
-  mode_t mode;
-  int8_t *mptr = (int8_t *) MAP_FAILED;
-  struct stat statbuff;
-  struct mq_hdr *mqhdr;
-  struct msg_hdr *msghdr;
-  struct mq_attr *attr;
-  struct mq_info *mqinfo = NULL;
-  LUID luid;
+  mode_t mode = 0;
+  fhandler_mqueue *fh = NULL;
+  struct mq_attr *attr = NULL;
 
   size_t len = strlen (name);
   char mqname[ipc_names[mqueue].prefix_len + len];
@@ -436,213 +315,50 @@ mq_open (const char *name, int oflag, ...)
 
   __try
     {
-      oflag &= (O_CREAT | O_EXCL | O_NONBLOCK);
-      nonblock = oflag & O_NONBLOCK;
-      oflag &= ~O_NONBLOCK;
-
-    again:
       if (oflag & O_CREAT)
        {
          va_start (ap, oflag);         /* init ap to final named argument */
          mode = va_arg (ap, mode_t) & ~S_IXUSR;
          attr = va_arg (ap, struct mq_attr *);
          va_end (ap);
-
-         /* Open and specify O_EXCL and user-execute */
-         fd = open (mqname, oflag | O_EXCL | O_RDWR | O_CLOEXEC,
-                    mode | S_IXUSR);
-         if (fd < 0)
-           {
-             if (errno == EEXIST && (oflag & O_EXCL) == 0)
-               goto exists;            /* already exists, OK */
-             return (mqd_t) -1;
-           }
-         created = 1;
-         /* First one to create the file initializes it */
-         if (attr == NULL)
-           attr = &defattr;
-         /* Check minimum and maximum values.  The max values are pretty much
-            arbitrary, taken from the linux mq_overview man page.  However,
-            these max values make sure that the internal mq_fattr structure
-            can use 32 bit types. */
-         else if (attr->mq_maxmsg <= 0 || attr->mq_maxmsg > 32768
-                  || attr->mq_msgsize <= 0 || attr->mq_msgsize > 1048576)
-           {
-             set_errno (EINVAL);
-             __leave;
-           }
-         /* Calculate and set the file size */
-         msgsize = MSGSIZE (attr->mq_msgsize);
-         filesize = sizeof (struct mq_hdr)
-                    + (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize));
-         if (lseek64 (fd, filesize - 1, SEEK_SET) == -1)
-           __leave;
-         if (write (fd, "", 1) == -1)
-           __leave;
-
-         /* Memory map the file */
-         mptr = (int8_t *) mmap64 (NULL, (size_t) filesize,
-                                   PROT_READ | PROT_WRITE,
-                                   MAP_SHARED, fd, 0);
-         if (mptr == (int8_t *) MAP_FAILED)
-           __leave;
-
-         /* Allocate one mq_info{} for the queue */
-         if (!(mqinfo = (struct mq_info *)
-                        calloc (1, sizeof (struct mq_info))))
-           __leave;
-         mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr;
-         mqinfo->mqi_magic = MQI_MAGIC;
-         mqinfo->mqi_flags = nonblock;
-
-         /* Initialize header at beginning of file */
-         /* Create free list with all messages on it */
-         mqhdr->mqh_attr.mq_flags = 0;
-         mqhdr->mqh_attr.mq_maxmsg = attr->mq_maxmsg;
-         mqhdr->mqh_attr.mq_msgsize = attr->mq_msgsize;
-         mqhdr->mqh_attr.mq_curmsgs = 0;
-         mqhdr->mqh_nwait = 0;
-         mqhdr->mqh_pid = 0;
-         NtAllocateLocallyUniqueId (&luid);
-         __small_sprintf (mqhdr->mqh_uname, "%016X%08x%08x",
-                          hash_path_name (0,mqname),
-                          luid.HighPart, luid.LowPart);
-         mqhdr->mqh_head = 0;
-         mqhdr->mqh_magic = MQI_MAGIC;
-         index = sizeof (struct mq_hdr);
-         mqhdr->mqh_free = index;
-         for (i = 0; i < attr->mq_maxmsg - 1; i++)
-           {
-             msghdr = (struct msg_hdr *) &mptr[index];
-             index += sizeof (struct msg_hdr) + msgsize;
-             msghdr->msg_next = index;
-           }
-         msghdr = (struct msg_hdr *) &mptr[index];
-         msghdr->msg_next = 0;         /* end of free list */
-
-         /* Initialize mutex & condition variables */
-         i = ipc_mutex_init (&mqinfo->mqi_lock, mqhdr->mqh_uname);
-         if (i != 0)
-           {
-             set_errno (i);
-             __leave;
-           }
-         i = ipc_cond_init (&mqinfo->mqi_waitsend, mqhdr->mqh_uname, 'S');
-         if (i != 0)
-           {
-             set_errno (i);
-             __leave;
-           }
-         i = ipc_cond_init (&mqinfo->mqi_waitrecv, mqhdr->mqh_uname, 'R');
-         if (i != 0)
-           {
-             set_errno (i);
-             __leave;
-           }
-         /* Initialization complete, turn off user-execute bit */
-         if (fchmod (fd, mode) == -1)
-           __leave;
-         close (fd);
-         return ((mqd_t) mqinfo);
        }
 
-    exists:
-      /* Open the file then memory map */
-      if ((fd = open (mqname, O_RDWR | O_CLOEXEC)) < 0)
-       {
-         if (errno == ENOENT && (oflag & O_CREAT))
-           goto again;
-         __leave;
-       }
-      /* Make certain initialization is complete */
-      for (i = 0; i < MAX_TRIES; i++)
-       {
-         if (stat64 (mqname, &statbuff) == -1)
-           {
-             if (errno == ENOENT && (oflag & O_CREAT))
-               {
-                 close (fd);
-                 fd = -1;
-                 goto again;
-               }
-             __leave;
-           }
-         if ((statbuff.st_mode & S_IXUSR) == 0)
-           break;
-         sleep (1);
-       }
-      if (i == MAX_TRIES)
-       {
-         set_errno (ETIMEDOUT);
-         __leave;
-       }
+      /* Create file descriptor for mqueue */
+      cygheap_fdnew fd;
 
-      filesize = statbuff.st_size;
-      mptr = (int8_t *) mmap64 (NULL, (size_t) filesize, PROT_READ | PROT_WRITE,
-                               MAP_SHARED, fd, 0);
-      if (mptr == (int8_t *) MAP_FAILED)
+      if (fd < 0)
        __leave;
-      close (fd);
-      fd = -1;
-
-      /* Allocate one mq_info{} for each open */
-      if (!(mqinfo = (struct mq_info *) calloc (1, sizeof (struct mq_info))))
+      fh = (fhandler_mqueue *) build_fh_name (mqname,
+                                             PC_OPEN | PC_POSIX
+                                             | PC_SYM_NOFOLLOW | PC_NULLEMPTY,
+                                             NULL);
+      if (!fh)
        __leave;
-      mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr;
-      if (mqhdr->mqh_magic != MQI_MAGIC)
-       {
-         system_printf (
-    "Old message queue \"%s\" detected!\n"
-    "This file is not usable as message queue anymore due to changes in the "
-    "internal file layout.  Please remove the file and try again.", mqname);
-         set_errno (EACCES);
-         __leave;
-       }
-      mqinfo->mqi_magic = MQI_MAGIC;
-      mqinfo->mqi_flags = nonblock;
 
-      /* Initialize mutex & condition variable */
-      i = ipc_mutex_init (&mqinfo->mqi_lock, mqhdr->mqh_uname);
-      if (i != 0)
-       {
-         set_errno (i);
-         __leave;
-       }
-      i = ipc_cond_init (&mqinfo->mqi_waitsend, mqhdr->mqh_uname, 'S');
-      if (i != 0)
+      if (fh->mq_open (oflag, mode, attr))
        {
-         set_errno (i);
-         __leave;
-       }
-      i = ipc_cond_init (&mqinfo->mqi_waitrecv, mqhdr->mqh_uname, 'R');
-      if (i != 0)
-       {
-         set_errno (i);
-         __leave;
+         fd = fh;
+         return (mqd_t) fd;
        }
-      return (mqd_t) mqinfo;
     }
   __except (EFAULT) {}
   __endtry
-  /* Don't let following function calls change errno */
-  save_errno save;
-  if (created)
-    unlink (mqname);
-  if (mptr != (int8_t *) MAP_FAILED)
-    munmap((void *) mptr, (size_t) filesize);
-  if (mqinfo)
+  if (fh)
+    delete fh;
+  return (mqd_t) -1;
+}
+
+static struct mq_info *
+get_mqinfo (cygheap_fdget &fd)
+{
+  if (fd >= 0)
     {
-      if (mqinfo->mqi_lock)
-       ipc_mutex_close (mqinfo->mqi_lock);
-      if (mqinfo->mqi_waitsend)
-       ipc_cond_close (mqinfo->mqi_waitsend);
-      if (mqinfo->mqi_waitrecv)
-       ipc_cond_close (mqinfo->mqi_waitrecv);
-      free (mqinfo);
+      fhandler_mqueue *fh = fd->is_mqueue ();
+      if (fh)
+       return fh->mqinfo ();
+      set_errno (EINVAL);
     }
-  if (fd >= 0)
-    close (fd);
-  return (mqd_t) -1;
+  return NULL;
 }
 
 extern "C" int
@@ -655,7 +371,8 @@ mq_getattr (mqd_t mqd, struct mq_attr *mqstat)
 
   __try
     {
-      mqinfo = (struct mq_info *) mqd;
+      cygheap_fdget fd ((int) mqd, true);
+      mqinfo = get_mqinfo (fd);
       if (mqinfo->mqi_magic != MQI_MAGIC)
        {
          set_errno (EBADF);
@@ -691,7 +408,8 @@ mq_setattr (mqd_t mqd, const struct mq_attr *mqstat, struct mq_attr *omqstat)
 
   __try
     {
-      mqinfo = (struct mq_info *) mqd;
+      cygheap_fdget fd ((int) mqd, true);
+      mqinfo = get_mqinfo (fd);
       if (mqinfo->mqi_magic != MQI_MAGIC)
        {
          set_errno (EBADF);
@@ -736,7 +454,8 @@ mq_notify (mqd_t mqd, const struct sigevent *notification)
 
   __try
     {
-      mqinfo = (struct mq_info *) mqd;
+      cygheap_fdget fd ((int) mqd, true);
+      mqinfo = get_mqinfo (fd);
       if (mqinfo->mqi_magic != MQI_MAGIC)
        {
          set_errno (EBADF);
@@ -796,13 +515,14 @@ _mq_send (mqd_t mqd, const char *ptr, size_t len, unsigned int prio,
 
   __try
     {
-      mqinfo = (struct mq_info *) mqd;
+      cygheap_fdget fd ((int) mqd);
+      mqinfo = get_mqinfo (fd);
       if (mqinfo->mqi_magic != MQI_MAGIC)
        {
          set_errno (EBADF);
          __leave;
        }
-      if (prio > MQ_PRIO_MAX)
+      if (prio >= MQ_PRIO_MAX)
        {
          set_errno (EINVAL);
          __leave;
@@ -890,7 +610,6 @@ _mq_send (mqd_t mqd, const char *ptr, size_t len, unsigned int prio,
        ipc_cond_signal (mqinfo->mqi_waitrecv);
       attr->mq_curmsgs++;
 
-      ipc_mutex_unlock (mqinfo->mqi_lock);
       ret = 0;
     }
   __except (EBADF) {}
@@ -924,13 +643,15 @@ _mq_receive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop,
   struct mq_hdr *mqhdr;
   struct mq_fattr *attr;
   struct msg_hdr *msghdr;
-  struct mq_info *mqinfo = (struct mq_info *) mqd;
+  struct mq_info *mqinfo;
   bool ipc_mutex_locked = false;
 
   pthread_testcancel ();
 
   __try
     {
+      cygheap_fdget fd ((int) mqd);
+      mqinfo = get_mqinfo (fd);
       if (mqinfo->mqi_magic != MQI_MAGIC)
        {
          set_errno (EBADF);
@@ -990,8 +711,6 @@ _mq_receive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop,
       if (attr->mq_curmsgs == attr->mq_maxmsg)
        ipc_cond_signal (mqinfo->mqi_waitsend);
       attr->mq_curmsgs--;
-
-      ipc_mutex_unlock (mqinfo->mqi_lock);
     }
   __except (EBADF) {}
   __endtry
@@ -1016,36 +735,21 @@ mq_timedreceive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop,
 extern "C" int
 mq_close (mqd_t mqd)
 {
-  long msgsize, filesize;
-  struct mq_hdr *mqhdr;
-  struct mq_fattr *attr;
-  struct mq_info *mqinfo;
-
   __try
     {
-      mqinfo = (struct mq_info *) mqd;
-      if (mqinfo->mqi_magic != MQI_MAGIC)
+      cygheap_fdget fd ((int) mqd, true);
+      if (!fd->is_mqueue ())
        {
          set_errno (EBADF);
          __leave;
        }
-      mqhdr = mqinfo->mqi_hdr;
-      attr = &mqhdr->mqh_attr;
 
       if (mq_notify (mqd, NULL))       /* unregister calling process */
        __leave;
 
-      msgsize = MSGSIZE (attr->mq_msgsize);
-      filesize = sizeof (struct mq_hdr)
-                + (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize));
-      if (munmap (mqinfo->mqi_hdr, filesize) == -1)
-       __leave;
-
-      mqinfo->mqi_magic = 0;          /* just in case */
-      ipc_cond_close (mqinfo->mqi_waitsend);
-      ipc_cond_close (mqinfo->mqi_waitrecv);
-      ipc_mutex_close (mqinfo->mqi_lock);
-      free (mqinfo);
+      fd->isclosed (true);
+      fd->close ();
+      fd.release ();
       return 0;
     }
   __except (EBADF) {}
@@ -1071,6 +775,8 @@ mq_unlink (const char *name)
    the already existing semaphore class in thread.cc.  Using a file backed
    solution allows to implement kernel persistent named semaphores.  */
 
+#define         MAX_TRIES      10      /* for waiting for initialization */
+
 struct sem_finfo
 {
   unsigned int       value;
@@ -1199,6 +905,8 @@ sem_open (const char *name, int oflag, ...)
   return SEM_FAILED;
 }
 
+extern "C" off_t lseek64 (int, off_t, int);
+
 int
 _sem_close (sem_t *sem, bool do_close)
 {
This page took 0.043881 seconds and 5 git commands to generate.