OSDN Git Service

2002-06-19 Jeff Johnston <jjohnstn@redhat.com>
authorjjohnstn <jjohnstn>
Wed, 19 Jun 2002 22:17:27 +0000 (22:17 +0000)
committerjjohnstn <jjohnstn>
Wed, 19 Jun 2002 22:17:27 +0000 (22:17 +0000)
        * libc/sys/linux/Makefile.am: Add support for message queue routines,
        ipc routines, and ftok.
        * libc/sys/linux/Makefile.in: Regenerated.
        * libc/sys/linux/ftok.c: New file.
        * libc/sys/linux/ipc.c: Ditto.
        * libc/sys/linux/mq_close.c: Ditto.
        * libc/sys/linux/mq_getattr.c: Ditto.
        * libc/sys/linux/mq_notify.c: Ditto.
        * libc/sys/linux/mq_open.c: Ditto.
        * libc/sys/linux/mq_receive.c: Ditto.
        * libc/sys/linux/mq_send.c: Ditto.
        * libc/sys/linux/mq_setattr.c: Ditto.
        * libc/sys/linux/mq_unlink.c: Ditto.
        * libc/sys/linux/mqlocal.h: Ditto.
        * libc/sys/linux/include/mqueue.h: Ditto.
        * libc/sys/linux/sys/types.h: Define __gid_t_defined and
        __uid_t_defined.

16 files changed:
newlib/ChangeLog
newlib/libc/sys/linux/Makefile.am
newlib/libc/sys/linux/Makefile.in
newlib/libc/sys/linux/ftok.c [new file with mode: 0644]
newlib/libc/sys/linux/include/mqueue.h [new file with mode: 0644]
newlib/libc/sys/linux/ipc.c [new file with mode: 0644]
newlib/libc/sys/linux/mq_close.c [new file with mode: 0644]
newlib/libc/sys/linux/mq_getattr.c [new file with mode: 0644]
newlib/libc/sys/linux/mq_notify.c [new file with mode: 0644]
newlib/libc/sys/linux/mq_open.c [new file with mode: 0644]
newlib/libc/sys/linux/mq_receive.c [new file with mode: 0644]
newlib/libc/sys/linux/mq_send.c [new file with mode: 0644]
newlib/libc/sys/linux/mq_setattr.c [new file with mode: 0644]
newlib/libc/sys/linux/mq_unlink.c [new file with mode: 0644]
newlib/libc/sys/linux/mqlocal.h [new file with mode: 0644]
newlib/libc/sys/linux/sys/types.h

index 8d0b6df..e6df2dc 100644 (file)
@@ -1,3 +1,23 @@
+2002-06-19  Jeff Johnston  <jjohnstn@redhat.com>
+
+        * libc/sys/linux/Makefile.am: Add support for message queue routines,
+        ipc routines, and ftok.
+        * libc/sys/linux/Makefile.in: Regenerated.
+        * libc/sys/linux/ftok.c: New file.
+        * libc/sys/linux/ipc.c: Ditto.
+        * libc/sys/linux/mq_close.c: Ditto.
+        * libc/sys/linux/mq_getattr.c: Ditto.
+        * libc/sys/linux/mq_notify.c: Ditto.
+        * libc/sys/linux/mq_open.c: Ditto.
+        * libc/sys/linux/mq_receive.c: Ditto.
+        * libc/sys/linux/mq_send.c: Ditto.
+        * libc/sys/linux/mq_setattr.c: Ditto.
+        * libc/sys/linux/mq_unlink.c: Ditto.
+        * libc/sys/linux/mqlocal.h: Ditto.
+        * libc/sys/linux/include/mqueue.h: Ditto.
+        * libc/sys/linux/sys/types.h: Define __gid_t_defined and
+        __uid_t_defined.
+
 2002-06-19  J"orn Rennecke <joern.rennecke@superh.com>
 
        * libm/common/sf_lround.c (round): Change name to: (lround).
@@ -186,9 +206,6 @@ Thu Jun 13 19:23:40 2002  J"orn Rennecke <joern.rennecke@superh.com>
         * libc/sys/linux/sigaction.c: New file.
         * libc/sys/linux/signal.c: Changed to be linux signal() function
         so as to override regular newlib default signal.c.
-        * libc/sys/linux/linuxthreads/config.h: Add __ASSUME_REALTIME_SIGNALS
-        definition.
-        * libc/sys/linux/linuxthreads/testrtsig.h: New file.
         * libc/sys/linux/machine/i386/Makefile.am: Remove sigset.c.
         * libc/sys/linux/machine/i386/Makefile.in: Regenerated.
         * libc/sys/linux/machine/i386/sigset.c: Moved to linux main directory.
index fccb24d..861340d 100644 (file)
@@ -13,6 +13,7 @@ LIB_SOURCES = \
        brk.c \
        cfspeed.c \
        flockfile.c \
+       ftok.c \
        funlockfile.c \
        gethostname.c \
        getoptlong.c \
@@ -21,8 +22,17 @@ LIB_SOURCES = \
        inode.c \
        io.c \
        io64.c \
+       ipc.c \
        linux.c \
        mmap.c \
+       mq_close.c \
+       mq_getattr.c \
+       mq_notify.c \
+       mq_open.c \
+       mq_receive.c \
+       mq_send.c \
+       mq_setattr.c \
+       mq_unlink.c \
        pread.c \
        pread64.c \
        process.c \
index a897360..9f8459e 100644 (file)
@@ -110,6 +110,7 @@ LIB_SOURCES = \
        brk.c \
        cfspeed.c \
        flockfile.c \
+       ftok.c \
        funlockfile.c \
        gethostname.c \
        getoptlong.c \
@@ -118,8 +119,17 @@ LIB_SOURCES = \
        inode.c \
        io.c \
        io64.c \
+       ipc.c \
        linux.c \
        mmap.c \
+       mq_close.c \
+       mq_getattr.c \
+       mq_notify.c \
+       mq_open.c \
+       mq_receive.c \
+       mq_send.c \
+       mq_setattr.c \
+       mq_unlink.c \
        pread.c \
        pread64.c \
        process.c \
@@ -186,12 +196,18 @@ DEFS = @DEFS@ -I. -I$(srcdir)
 CPPFLAGS = @CPPFLAGS@
 LIBS = @LIBS@
 @USE_LIBTOOL_FALSE@lib_a_OBJECTS =  brk.$(OBJEXT) cfspeed.$(OBJEXT) \
-@USE_LIBTOOL_FALSE@flockfile.$(OBJEXT) funlockfile.$(OBJEXT) \
-@USE_LIBTOOL_FALSE@gethostname.$(OBJEXT) getoptlong.$(OBJEXT) \
-@USE_LIBTOOL_FALSE@getreent.$(OBJEXT) ids.$(OBJEXT) inode.$(OBJEXT) \
-@USE_LIBTOOL_FALSE@io.$(OBJEXT) io64.$(OBJEXT) linux.$(OBJEXT) \
-@USE_LIBTOOL_FALSE@mmap.$(OBJEXT) pread.$(OBJEXT) pread64.$(OBJEXT) \
-@USE_LIBTOOL_FALSE@process.$(OBJEXT) psignal.$(OBJEXT) pwrite.$(OBJEXT) \
+@USE_LIBTOOL_FALSE@flockfile.$(OBJEXT) ftok.$(OBJEXT) \
+@USE_LIBTOOL_FALSE@funlockfile.$(OBJEXT) gethostname.$(OBJEXT) \
+@USE_LIBTOOL_FALSE@getoptlong.$(OBJEXT) getreent.$(OBJEXT) \
+@USE_LIBTOOL_FALSE@ids.$(OBJEXT) inode.$(OBJEXT) io.$(OBJEXT) \
+@USE_LIBTOOL_FALSE@io64.$(OBJEXT) ipc.$(OBJEXT) linux.$(OBJEXT) \
+@USE_LIBTOOL_FALSE@mmap.$(OBJEXT) mq_close.$(OBJEXT) \
+@USE_LIBTOOL_FALSE@mq_getattr.$(OBJEXT) mq_notify.$(OBJEXT) \
+@USE_LIBTOOL_FALSE@mq_open.$(OBJEXT) mq_receive.$(OBJEXT) \
+@USE_LIBTOOL_FALSE@mq_send.$(OBJEXT) mq_setattr.$(OBJEXT) \
+@USE_LIBTOOL_FALSE@mq_unlink.$(OBJEXT) pread.$(OBJEXT) \
+@USE_LIBTOOL_FALSE@pread64.$(OBJEXT) process.$(OBJEXT) \
+@USE_LIBTOOL_FALSE@psignal.$(OBJEXT) pwrite.$(OBJEXT) \
 @USE_LIBTOOL_FALSE@pwrite64.$(OBJEXT) raise.$(OBJEXT) \
 @USE_LIBTOOL_FALSE@realpath.$(OBJEXT) rename.$(OBJEXT) \
 @USE_LIBTOOL_FALSE@resource.$(OBJEXT) sched.$(OBJEXT) select.$(OBJEXT) \
@@ -209,16 +225,19 @@ LTLIBRARIES =  $(noinst_LTLIBRARIES)
 
 @USE_LIBTOOL_TRUE@liblinux_la_DEPENDENCIES = 
 @USE_LIBTOOL_TRUE@liblinux_la_OBJECTS =  brk.lo cfspeed.lo flockfile.lo \
-@USE_LIBTOOL_TRUE@funlockfile.lo gethostname.lo getoptlong.lo \
-@USE_LIBTOOL_TRUE@getreent.lo ids.lo inode.lo io.lo io64.lo linux.lo \
-@USE_LIBTOOL_TRUE@mmap.lo pread.lo pread64.lo process.lo psignal.lo \
-@USE_LIBTOOL_TRUE@pwrite.lo pwrite64.lo raise.lo realpath.lo rename.lo \
-@USE_LIBTOOL_TRUE@resource.lo sched.lo select.lo seteuid.lo shm_open.lo \
-@USE_LIBTOOL_TRUE@shm_unlink.lo sig.lo sigaction.lo sigqueue.lo \
-@USE_LIBTOOL_TRUE@signal.lo siglongjmp.lo sigset.lo sigwait.lo \
-@USE_LIBTOOL_TRUE@socket.lo sleep.lo stack.lo strsignal.lo sysconf.lo \
-@USE_LIBTOOL_TRUE@sysctl.lo systat.lo system.lo tcdrain.lo tcsendbrk.lo \
-@USE_LIBTOOL_TRUE@termios.lo time.lo usleep.lo wait.lo
+@USE_LIBTOOL_TRUE@ftok.lo funlockfile.lo gethostname.lo getoptlong.lo \
+@USE_LIBTOOL_TRUE@getreent.lo ids.lo inode.lo io.lo io64.lo ipc.lo \
+@USE_LIBTOOL_TRUE@linux.lo mmap.lo mq_close.lo mq_getattr.lo \
+@USE_LIBTOOL_TRUE@mq_notify.lo mq_open.lo mq_receive.lo mq_send.lo \
+@USE_LIBTOOL_TRUE@mq_setattr.lo mq_unlink.lo pread.lo pread64.lo \
+@USE_LIBTOOL_TRUE@process.lo psignal.lo pwrite.lo pwrite64.lo raise.lo \
+@USE_LIBTOOL_TRUE@realpath.lo rename.lo resource.lo sched.lo select.lo \
+@USE_LIBTOOL_TRUE@seteuid.lo shm_open.lo shm_unlink.lo sig.lo \
+@USE_LIBTOOL_TRUE@sigaction.lo sigqueue.lo signal.lo siglongjmp.lo \
+@USE_LIBTOOL_TRUE@sigset.lo sigwait.lo socket.lo sleep.lo stack.lo \
+@USE_LIBTOOL_TRUE@strsignal.lo sysconf.lo sysctl.lo systat.lo system.lo \
+@USE_LIBTOOL_TRUE@tcdrain.lo tcsendbrk.lo termios.lo time.lo usleep.lo \
+@USE_LIBTOOL_TRUE@wait.lo
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
diff --git a/newlib/libc/sys/linux/ftok.c b/newlib/libc/sys/linux/ftok.c
new file mode 100644 (file)
index 0000000..497754b
--- /dev/null
@@ -0,0 +1,41 @@
+/* Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Modified for newlib by Jeff Johnston, June 10/2002 */
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/stat.h>
+
+key_t
+ftok (pathname, proj_id)
+     const char *pathname;
+     int proj_id;
+{
+  struct stat64 st;
+  key_t key;
+
+  if (stat64 (pathname, &st) < 0)
+    return (key_t) -1;
+
+  key = ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16)
+        | ((proj_id & 0xff) << 24));
+
+  return key;
+}
diff --git a/newlib/libc/sys/linux/include/mqueue.h b/newlib/libc/sys/linux/include/mqueue.h
new file mode 100644 (file)
index 0000000..10e81e7
--- /dev/null
@@ -0,0 +1,34 @@
+/* libc/sys/linux/include/mqueue.h - message queue functions */
+
+/* Copyright 2002, Red Hat Inc. - all rights reserved */
+
+#ifndef __MQUEUE_H
+#define __MQUEUE_H
+
+#include <sys/types.h>
+#define __need_sigevent_t 1
+#include <asm/siginfo.h>
+
+/* message queue types */
+typedef int mqd_t;
+
+struct mq_attr {
+  long mq_flags;    /* message queue flags */
+  long mq_maxmsg;   /* maximum number of messages */
+  long mq_msgsize;  /* maximum message size */
+  long mq_curmsgs;  /* number of messages currently queued */
+};
+
+#define MQ_PRIO_MAX 16
+
+/* prototypes */
+mqd_t mq_open (const char *__name, int __oflag, ...);
+int mq_close (mqd_t __msgid);
+int mq_send (mqd_t __msgid, const char *__msg, size_t __msg_len, unsigned int __msg_prio);
+ssize_t mq_receive (mqd_t __msgid, char *__msg, size_t __msg_len, unsigned int *__msg_prio);
+int mq_notify (mqd_t __msgid, const struct sigevent *__notification);
+int mq_unlink (const char *__name);
+int mq_getattr (mqd_t __msgid, struct mq_attr *__mqstat);
+int mq_setattr (mqd_t __msgid, const struct mq_attr *__mqstat, struct mq_attr *__omqattr);
+
+#endif /* __MQUEUE_H */
diff --git a/newlib/libc/sys/linux/ipc.c b/newlib/libc/sys/linux/ipc.c
new file mode 100644 (file)
index 0000000..31e2252
--- /dev/null
@@ -0,0 +1,87 @@
+/* libc/sys/linux/ipc.c - IPC semaphore and message queue functions */
+
+/* Copyright 2002, Red Hat Inc. */
+
+#include <sys/types.h>
+#include <sys/sem.h>
+#include <sys/msg.h>
+#include <stdarg.h>
+
+#include <machine/syscall.h>
+
+#define IPC_64 0x100
+
+#define IPCOP_semop    1
+#define IPCOP_semget   2
+#define IPCOP_semctl   3
+#define IPCOP_msgsnd   11
+#define IPCOP_msgrcv   12
+#define IPCOP_msgget   13
+#define IPCOP_msgctl   14
+
+static _syscall5(int,ipc,int,op,int,arg1,int,arg2,int,arg3,void *,arg4);
+
+int
+semget (key_t key, int nsems, int semflgs)
+{
+  return __libc_ipc(IPCOP_semget, (int)key, nsems, semflgs, NULL);
+}
+
+int
+semctl (int semid, int semnum, int cmd, ...)
+{
+  va_list va;
+  union semun {
+    int val;
+    struct semid_ds *buf;
+    unsigned short  *array;
+  } arg;
+
+  va_start (va, cmd);
+
+  arg = va_arg (va, union semun);
+
+  va_end (va);
+
+  return __libc_ipc(IPCOP_semctl, semid, semnum, cmd | IPC_64, &arg);
+}
+
+int
+semop (int semid, struct sembuf *sops, size_t nsems)
+{
+  return __libc_ipc(IPCOP_semop, semid, (int)nsems, 0, sops);
+}
+
+int
+msgget (key_t key, int msgflg)
+{
+  return __libc_ipc(IPCOP_msgget, (int)key, msgflg, 0, NULL);
+}
+
+int
+msgctl (int msqid, int cmd, struct msqid_ds *buf)
+{
+  return __libc_ipc(IPCOP_msgctl, msqid, cmd | IPC_64, 0, buf);
+}
+
+int
+msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg)
+{
+  return __libc_ipc(IPCOP_msgsnd, msqid, (int)msgsz, msgflg, (void *)msgp);
+}
+
+int
+msgrcv (int msqid, void *msgp, size_t msgsz, long int msgtyp, int msgflg)
+{
+  /* last argument must contain multiple args */
+  struct {
+    void *msgp;
+    long int msgtyp;
+  } args;
+
+  args.msgp = msgp;
+  args.msgtyp = msgtyp;
+
+  return (ssize_t)__libc_ipc(IPCOP_msgrcv, msqid, (int)msgsz, msgflg, &args);
+}
+
diff --git a/newlib/libc/sys/linux/mq_close.c b/newlib/libc/sys/linux/mq_close.c
new file mode 100644 (file)
index 0000000..f807443
--- /dev/null
@@ -0,0 +1,48 @@
+/* Copyright 2002, Red Hat Inc. */
+
+#include <mqueue.h>
+#include <errno.h>
+#include <sys/sem.h>
+#define _LIBC
+#include <sys/lock.h>
+#undef _LIBC
+
+#include "mqlocal.h"
+
+int
+mq_close (mqd_t msgid)
+{
+  struct libc_mq *info;
+  struct sembuf sb0 = {0, -1, 0};
+  int rc;
+  int semid;
+
+  info = __find_mq (msgid);
+
+  if (info == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  /* lock message queue */
+  semid = info->semid;
+  rc = semop (semid, &sb0, 1);
+
+  if (rc == 0)
+    {
+      __cleanup_mq (msgid);
+      
+      /* unlock message queue */
+      sb0.sem_op = 1;
+      semop (semid, &sb0, 1);
+    }
+
+  return rc;
+}
+      
+
+
+
+
+
diff --git a/newlib/libc/sys/linux/mq_getattr.c b/newlib/libc/sys/linux/mq_getattr.c
new file mode 100644 (file)
index 0000000..b829060
--- /dev/null
@@ -0,0 +1,52 @@
+/* Copyright 2002, Red Hat Inc. */
+
+#include <mqueue.h>
+#include <errno.h>
+#include <sys/sem.h>
+#include <string.h>
+#define _LIBC
+#include <sys/lock.h>
+#undef _LIBC
+
+#include "mqlocal.h"
+
+int
+mq_getattr (mqd_t msgid, struct mq_attr *mqstat)
+{
+  struct libc_mq *info;
+  struct sembuf sb0 = {0, -1, 0};
+  int num_msgs;
+  int rc = 0;
+
+  info = __find_mq (msgid);
+
+  if (info == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  /* temporarily lock message queue */
+  semop (info->semid, &sb0, 1);
+
+  num_msgs = semctl (info->semid, 3, GETVAL);
+  if (num_msgs >= 0)
+    {
+      memcpy (mqstat, info->attr, sizeof(struct mq_attr));
+      mqstat->mq_curmsgs = num_msgs;
+    }
+  else
+    rc = -1;
+
+  /* release message queue */
+  sb0.sem_op = 1;
+  semop (info->semid, &sb0, 1);
+
+  return rc;
+}
+      
+
+
+
+
+
diff --git a/newlib/libc/sys/linux/mq_notify.c b/newlib/libc/sys/linux/mq_notify.c
new file mode 100644 (file)
index 0000000..fd4606b
--- /dev/null
@@ -0,0 +1,22 @@
+/* Copyright 2002, Red Hat Inc. */
+
+#include <mqueue.h>
+#include <errno.h>
+#include <machine/weakalias.h>
+
+#include "mqlocal.h"
+
+int
+__libc_mq_notify (mqd_t msgid, const struct sigevent *notification)
+{
+  errno = ENOSYS;
+  return -1;
+}
+weak_alias (__libc_mq_notify, mq_notify)
+
+      
+
+
+
+
+
diff --git a/newlib/libc/sys/linux/mq_open.c b/newlib/libc/sys/linux/mq_open.c
new file mode 100644 (file)
index 0000000..b8da214
--- /dev/null
@@ -0,0 +1,340 @@
+/* Copyright 2002, Red Hat Inc. */
+
+#include <mqueue.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <stdarg.h>
+#include <machine/weakalias.h>
+#define _LIBC
+#include <sys/lock.h>
+#undef _LIBC
+
+#include "mqlocal.h"
+
+#define        NHASH   32                /* Num of hash lists, must be a power of 2 */
+#define        LOCHASH(i)      ((i)&(NHASH-1))
+
+static long    mq_index;       /* Index of next entry */
+static struct  libc_mq *mq_hash[NHASH];   /* Hash list heads for mqopen_infos */
+
+__LOCK_INIT(static, mq_hash_lock);
+
+mqd_t
+mq_open (const char *name, int oflag, ...)
+{
+  MSG *wrbuf = NULL;
+  MSG *rdbuf = NULL;
+  int msgqid = -1;
+  int rc = -1;
+  int fd = -1;
+  int semid = -1;
+  int created = 0;
+  key_t key = (key_t)-1;
+  struct mq_attr *attr = (struct mq_attr *)MAP_FAILED;
+  struct sembuf sb = {0, 0, 0};
+  mode_t mode = 0;
+  int size;
+  int i, index, saved_errno;
+  char *real_name;
+  char *ptr;
+  struct mq_attr *user_attr = NULL;
+  struct libc_mq *info;
+  union semun arg;
+  
+  /* ignore opening slash if present */
+  if (*name == '/')
+    ++name;  
+  size = strlen(name);
+
+  if ((real_name = (char *)malloc (size + sizeof(MSGQ_PREFIX))) == NULL ||
+      (info = (struct libc_mq *)malloc (sizeof(struct libc_mq))) == NULL)
+    {
+      errno = ENOSPC;
+      if (real_name)
+       free (real_name);
+      return (mqd_t)-1;
+    }
+  
+  /* use given name to create shared memory file name - we convert any
+     slashes to underscores so we don't have to create directories */
+  memcpy (real_name, MSGQ_PREFIX, sizeof(MSGQ_PREFIX) - 1);
+  memcpy (real_name + sizeof(MSGQ_PREFIX) - 1, name, size + 1);
+  ptr = real_name + sizeof(MSGQ_PREFIX) - 1;
+  for (i = 0; i < size; ++i)
+    {
+      if (*ptr == '/')
+       *ptr = '_';
+      ++ptr;
+    }
+
+  /* open shared memory file based on msg queue open flags and then use memory
+     file to create a unique key to use for semaphores, etc.. */
+  if (oflag & O_CREAT)
+    {
+      va_list list;
+      va_start (list, oflag);
+
+      saved_errno = errno;
+      mode = (mode_t)va_arg (list, int);
+      user_attr = va_arg(list,struct mq_attr *);
+      va_end (list);
+
+      /* attempt to open the shared memory file for exclusive create so we know
+        whether we are the owners or not */
+      fd = open (real_name, O_RDWR | O_CREAT | O_EXCL, mode);
+      if (fd < 0 && (oflag & O_EXCL))
+       {
+         /* we failed and the user wanted exclusive create */
+         free (real_name);
+         free (info);
+         return (mqd_t)-1;
+       }
+      errno = saved_errno;
+      created = 1;
+    }
+         
+  if (fd < 0)
+    fd = open (real_name, O_RDWR, 0);
+
+  if (fd >= 0)
+    key = ftok(real_name, 255);
+
+  if (key != (key_t)-1)
+    /* memory map the shared memory file so we have a global shared data area to use */
+    attr = (struct mq_attr *)mmap (0, sizeof(struct mq_attr), PROT_READ | PROT_WRITE,
+                                  MAP_SHARED, fd, 0);
+  
+  if (attr != (struct mq_attr *)MAP_FAILED)
+    {
+      /* we need semaphores to prevent multi-process race conditions on the
+        shared storage which contains a shared structure.  The following
+        are the ones we need.
+        
+        0 = open semaphore
+        1 = number of opens
+        2 = number of writes left until queue is full
+        3 = number of reads available in queue
+        4 = notify semaphore 
+        5 = number of readers */
+      arg.val = 0;
+      /* make sure the creator of the shared memory file also is the creator of the
+        semaphores...this will ensure that it also creates the message queue */
+      if (created)
+       {
+         saved_errno = errno;
+         semid = semget (key, 6, IPC_CREAT | IPC_EXCL | mode);
+         errno = saved_errno;
+         /* now that we have created the semaphore, we should initialize it */
+         if (semid != -1)
+           semctl (semid, 0, SETVAL, arg);
+       }
+      else
+       {
+         /* if we didn't create the shared memory file but have gotten to here, we want
+            to ensure we haven't gotten ahead of the creator temporarily so we will
+            loop until the semaphore exists.  This ensures that the creator will be the
+            one to create the message queue with the correct mode and we will be blocked
+            by the open semaphore 0.  We impose a time limit to ensure something terrible
+            hasn't gone wrong. */
+         struct timespec tms;
+         int i;
+
+         tms.tv_sec = 0;
+         tms.tv_nsec = 10000; /* 10 microseconds */
+         for (i = 0; i < 100; ++i)
+           {
+             if ((semid = semget (key, 6, 0)) != -1)
+               break;
+             /* sleep in case we our a higher priority process */
+             nanosleep (&tms, NULL);
+           }
+       }
+    }
+
+  if (semid != -1)
+    {
+      /* acquire main open semaphore if we didn't create it */
+      if (!created)
+       {
+         sb.sem_op = -1;
+         rc = semop (semid, &sb, 1);
+       }
+      else
+       rc = 0; /* need this to continue below */
+    }
+      
+  if (rc == 0)
+    {
+      if (created)
+       {
+         /* the creator must get here first so the message queue will be created */
+         msgqid = msgget (key, IPC_CREAT | mode); 
+         if (msgqid >= 0)
+           {
+             /* we have created the message queue so check and set the attributes */
+             if ((wrbuf = (MSG *)malloc (user_attr->mq_msgsize + sizeof(int))) == NULL ||
+                 (rdbuf = (MSG *)malloc (user_attr->mq_msgsize + sizeof(int))) == NULL ||
+                 user_attr == NULL || user_attr->mq_msgsize <= 0 || user_attr->mq_maxmsg <= 0)
+               {
+                 /* we're out of space and we created the message queue so we should
+                    try to remove it */
+                 msgctl (msgqid, IPC_RMID, NULL);
+                 msgqid = -1; /* allow clean up to occur below */
+                 if (wrbuf && rdbuf)
+                   errno = EINVAL;
+                 else
+                   errno = ENOSPC;
+               }
+             else /* valid attributes */
+               {
+                 write (fd, user_attr, sizeof(struct mq_attr));
+                 attr->mq_curmsgs = 0;
+                 attr->mq_flags = oflag & O_NONBLOCK;
+                 arg.val = 0;
+                 semctl (semid, 1, SETVAL, arg); /* number of opens starts at 0 */
+                 semctl (semid, 3, SETVAL, arg); /* number of reads available starts at 0 */
+                 semctl (semid, 5, SETVAL, arg); /* number of readers starts at 0 */
+                 arg.val = 1;
+                 semctl (semid, 4, SETVAL, arg); /* notify semaphore */
+                 arg.val = user_attr->mq_maxmsg;
+                 semctl (semid, 2, SETVAL, arg); /* number of writes left starts at mq_maxmsg */
+               }
+           }
+       }
+      else /* just open it */
+       msgqid = msgget (key, 0);
+      
+      /* release semaphore acquired earlier */
+      sb.sem_op = 1;
+      semop (semid, &sb, 1);
+    }
+
+  /* if we get here and we haven't got a message queue id, then we need to clean up 
+     our mess and return failure */
+  if (msgqid < 0)
+    {
+      if (fd >= 0)
+       close (fd);
+      if (attr != (struct mq_attr *)MAP_FAILED)
+       munmap (attr, sizeof(struct mq_attr));
+      if (created)
+       {
+         unlink (real_name);
+         if (semid != -1)
+           semctl (semid, 0, IPC_RMID);
+       }
+      free (real_name);
+      free (info);
+      if (wrbuf)
+       free (wrbuf);
+      if (rdbuf)
+       free (rdbuf);
+      return (mqd_t)-1;
+    }
+
+  /* we are successful so register the message queue */
+
+  /* up the count of msg queue opens */
+  sb.sem_op = 1;
+  sb.sem_num = 1;
+  semop (semid, &sb, 1);
+
+  /* success, translate into index into mq_info array */  
+  __lock_acquire(mq_hash_lock);
+  index = mq_index++;
+  info->index = index;
+  info->msgqid = msgqid;
+  info->name = real_name;
+  info->semid = semid;
+  info->fd = fd;
+  info->oflag = oflag;
+  info->wrbuf = wrbuf;
+  info->rdbuf = rdbuf;
+  info->cleanup_notify = NULL;
+  info->next = mq_hash[LOCHASH(index)];
+  info->attr = attr;
+  mq_hash[LOCHASH(index)] = info;
+  __lock_release(mq_hash_lock);
+
+  return (mqd_t)index;
+}
+
+struct libc_mq *
+__find_mq (mqd_t mq)
+{
+  struct libc_mq *ptr;
+
+  __lock_acquire(mq_hash_lock);
+
+  ptr = mq_hash[LOCHASH((int)mq)];
+
+  while (ptr)
+    {
+      if (ptr->index == (int)mq)
+        break;
+      ptr = ptr->next;
+    }
+
+  __lock_release(mq_hash_lock);
+
+  return ptr;
+}
+      
+void
+__cleanup_mq (mqd_t mq)
+{
+  struct libc_mq *ptr;
+  struct libc_mq *prev;
+  int semid;
+  struct sembuf sb = {0, 0, 0};
+
+  __lock_acquire(mq_hash_lock);
+
+  ptr = mq_hash[LOCHASH((int)mq)];
+  prev = NULL;
+
+  while (ptr)
+    {
+      if (ptr->index == (int)mq)
+        break;
+      prev = ptr;
+      ptr = ptr->next;
+    }
+
+  if (ptr != NULL)
+    {
+      if (ptr->cleanup_notify != NULL)
+       ptr->cleanup_notify (ptr);
+      if (prev != NULL)
+       prev->next = ptr->next;
+      else
+       mq_hash[LOCHASH((int)mq)] = NULL;
+      munmap (ptr->attr, sizeof(struct mq_attr));
+      close (ptr->fd);
+      free (ptr->name);
+      free (ptr->wrbuf);
+      free (ptr->rdbuf);
+      semid = ptr->semid;
+      free (ptr);
+      /* lower the count of msg queue opens */
+      sb.sem_op = -1;
+      sb.sem_num = 1;
+      sb.sem_flg = IPC_NOWAIT;
+      semop (semid, &sb, 1);
+    }
+
+  __lock_release(mq_hash_lock);
+}
+
+
+
+
+
diff --git a/newlib/libc/sys/linux/mq_receive.c b/newlib/libc/sys/linux/mq_receive.c
new file mode 100644 (file)
index 0000000..1aa7b9f
--- /dev/null
@@ -0,0 +1,67 @@
+/* Copyright 2002, Red Hat Inc. */
+
+#include <mqueue.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <string.h>
+#define _LIBC
+#include <sys/lock.h>
+#undef _LIBC
+
+#include "mqlocal.h"
+
+__LOCK_INIT(static, mq_rdbuf_lock);
+
+ssize_t
+mq_receive (mqd_t msgid, char *msg, size_t msg_len, unsigned int *msg_prio)
+{
+  struct libc_mq *info;
+  struct sembuf sb2 = {2, 1, 0};
+  struct sembuf sb3 = {3, -1, IPC_NOWAIT};
+  struct sembuf sb5 = {5, 1, IPC_NOWAIT};
+  ssize_t num_bytes;
+  int ipcflag;
+
+  info = __find_mq (msgid);
+
+  if (info == NULL || (info->oflag & O_ACCMODE) == O_WRONLY)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  if (msg_len < info->attr->mq_msgsize)
+    {
+      errno = EMSGSIZE;
+      return -1;
+    }
+
+  __lock_acquire (mq_rdbuf_lock);
+
+  ipcflag = (info->attr->mq_flags & O_NONBLOCK) ? IPC_NOWAIT : 0;
+
+  semop (info->semid, &sb5, 1); /* increase number of readers */
+  num_bytes = msgrcv (info->msgqid, info->rdbuf, msg_len, -MQ_PRIO_MAX, ipcflag);
+  sb5.sem_op = -1;
+  semop (info->semid, &sb5, 1); /* decrease number of readers */
+
+  if (num_bytes != (ssize_t)-1)
+    {
+      semop (info->semid, &sb2, 1); /* add one to messages left to write */
+      semop (info->semid, &sb3, 1); /* subtract one from messages to read */
+      memcpy (msg, info->rdbuf->text, num_bytes);
+      if (msg_prio != NULL)
+       *msg_prio = MQ_PRIO_MAX - info->rdbuf->type;
+    }
+  
+  __lock_release (mq_rdbuf_lock);
+  return num_bytes;
+}
+      
+
+
+
+
+
diff --git a/newlib/libc/sys/linux/mq_send.c b/newlib/libc/sys/linux/mq_send.c
new file mode 100644 (file)
index 0000000..92710c2
--- /dev/null
@@ -0,0 +1,72 @@
+/* Copyright 2002, Red Hat Inc. */
+
+#include <mqueue.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <string.h>
+#include <stdlib.h>
+#define _LIBC
+#include <sys/lock.h>
+#undef _LIBC
+
+#include "mqlocal.h"
+
+__LOCK_INIT(static, mq_wrbuf_lock);
+
+int
+mq_send (mqd_t msgid, const char *msg, size_t msg_len, unsigned int msg_prio)
+{
+  struct libc_mq *info;
+  struct sembuf sb2 = {2, -1, 0};
+  struct sembuf sb3 = {3, 1, 0};
+  int rc;
+  int ipcflag;
+
+  info = __find_mq (msgid);
+
+  if (info == NULL || (info->oflag & O_ACCMODE) == O_RDONLY)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  if (msg_len > info->attr->mq_msgsize)
+    {
+      errno = EMSGSIZE;
+      return -1;
+    }
+
+  if (msg_prio > MQ_PRIO_MAX)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  __lock_acquire (mq_wrbuf_lock);
+
+  memcpy (info->wrbuf->text, msg, msg_len);
+  info->wrbuf->type = (MQ_PRIO_MAX - msg_prio);
+
+  ipcflag = (info->attr->mq_flags & O_NONBLOCK) ? IPC_NOWAIT : 0;
+  sb2.sem_flg = ipcflag;
+
+  /* check to see if max msgs are on queue */
+  rc = semop (info->semid, &sb2, 1);
+
+  if (rc == 0)
+    rc = msgsnd (info->msgqid, info->wrbuf, msg_len, ipcflag);
+
+  if (rc == 0)
+    semop (info->semid, &sb3, 1);  /* increment number of reads */
+
+  __lock_release (mq_wrbuf_lock);
+  return rc;
+}
+      
+
+
+
+
+
diff --git a/newlib/libc/sys/linux/mq_setattr.c b/newlib/libc/sys/linux/mq_setattr.c
new file mode 100644 (file)
index 0000000..ecc32e9
--- /dev/null
@@ -0,0 +1,59 @@
+/* Copyright 2002, Red Hat Inc. */
+
+#include <mqueue.h>
+#include <errno.h>
+#include <sys/sem.h>
+#include <string.h>
+#define _LIBC
+#include <sys/lock.h>
+#undef _LIBC
+
+#include "mqlocal.h"
+
+int
+mq_setattr (mqd_t msgid, const struct mq_attr *mqstat, struct mq_attr *omqstat)
+{
+  struct libc_mq *info;
+  struct sembuf sb0 = {0, -1, 0};
+  int num_msgs;
+  int rc = 0;
+
+  info = __find_mq (msgid);
+
+  if (info == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  /* temporarily lock message queue */
+  semop (info->semid, &sb0, 1);
+
+  /* make copy of old structure */
+  if (omqstat != NULL)
+    {
+      num_msgs = semctl (info->semid, 3, GETVAL);
+      if (num_msgs >= 0)
+       {
+         memcpy (omqstat, info->attr, sizeof(struct mq_attr));
+         omqstat->mq_curmsgs = num_msgs;
+       }
+      else
+       rc = -1;
+    }
+  
+  /* only the mq_flags field can be changed */
+  info->attr->mq_flags = mqstat->mq_flags;
+
+  /* release message queue */
+  sb0.sem_op = 1;
+  semop (info->semid, &sb0, 1);
+
+  return rc;
+}
+      
+
+
+
+
+
diff --git a/newlib/libc/sys/linux/mq_unlink.c b/newlib/libc/sys/linux/mq_unlink.c
new file mode 100644 (file)
index 0000000..93902cd
--- /dev/null
@@ -0,0 +1,73 @@
+/* Copyright 2002, Red Hat Inc. */
+
+#include <mqueue.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <string.h>
+#include <stdlib.h>
+#include <machine/weakalias.h>
+#define _LIBC
+#include <sys/lock.h>
+#undef _LIBC
+
+#include "mqlocal.h"
+
+int
+mq_unlink (const char *name)
+{
+  int size;
+  int saved_errno;
+  char *real_name;
+  char *ptr;
+  int i, rc;
+  int semid, msgqid;
+  key_t key;
+  
+  /* ignore opening slash if present */
+  if (*name == '/')
+    ++name;  
+  size = strlen(name);
+
+  if ((real_name = (char *)malloc (size + sizeof(MSGQ_PREFIX))) == NULL)
+    {
+      errno = ENOSPC;
+      return -1;
+    }
+  
+  /* use given name to create shared memory file name - we convert any
+     slashes to underscores so we don't have to create directories */
+  memcpy (real_name, MSGQ_PREFIX, sizeof(MSGQ_PREFIX) - 1);
+  memcpy (real_name + sizeof(MSGQ_PREFIX) - 1, name, size + 1);
+  ptr = real_name + sizeof(MSGQ_PREFIX) - 1;
+  for (i = 0; i < size; ++i)
+    {
+      if (*ptr == '/')
+       *ptr = '_';
+      ++ptr;
+    }
+
+  /* get key and then unlink shared memory file */
+  if ((key = ftok(real_name, 255)) == (key_t)-1)
+    return -1;
+
+  rc = unlink (real_name);
+
+  if (rc == 0)
+    {
+      /* try to remove semaphore and msg queues associated with shared memory file */
+      saved_errno = errno;
+      semid = semget (key, 6, 0);
+      if (semid != -1)
+       semctl (semid, 0, IPC_RMID);
+      msgqid = msgget (key, 0);
+      if (msgqid != -1)
+       msgctl (msgqid, IPC_RMID, NULL);
+      errno = saved_errno;
+    }
+
+  return rc;
+}
diff --git a/newlib/libc/sys/linux/mqlocal.h b/newlib/libc/sys/linux/mqlocal.h
new file mode 100644 (file)
index 0000000..56fd66c
--- /dev/null
@@ -0,0 +1,47 @@
+/* local definitions needed by mq routines */
+
+#include <sys/msg.h>
+#include <signal.h>
+
+/* a message */
+typedef struct
+{
+  unsigned int type;
+  char text[1];
+} MSG; 
+
+union semun {
+  int val;
+  struct semid_ds *buf;
+  unsigned short  *array;
+} arg;
+
+/*
+ * One of these structures is malloced to describe any open message queue
+ * each time mq_open is called. 
+ */
+
+struct libc_mq;
+
+struct libc_mq {
+  int              index;          /* index of this message queue */
+  int              msgqid;         /* value returned by msgget */
+  int              semid;          /* semaphore id */
+  int              fd;             /* fd of shared memory file */
+  int              oflag;          /* original open flag used */
+  int              th;             /* thread id for mq_notify */
+  char            *name;           /* name used */
+  MSG             *wrbuf;          /* msg write buffer */
+  MSG             *rdbuf;          /* msg read buffer */
+  struct mq_attr  *attr;           /* pointer to attribute structure */
+  struct sigevent *sigevent;       /* used for mq_notify */
+  void (*cleanup_notify)(struct libc_mq *); /* also used for mq_notify */
+  struct libc_mq  *next;           /* next info struct in hash table */
+};
+
+extern struct libc_mq *__find_mq (mqd_t mq);
+extern void __cleanup_mq (mqd_t mq);
+extern void __cleanup_mq_notify (struct libc_mq *ptr);
+
+#define MSGQ_PREFIX "/dev/shm/__MSGQ__"
+
index 05e313d..bbc2316 100644 (file)
@@ -150,5 +150,7 @@ typedef     long    fd_mask;
 #include <linux/types.h>
 #include <bits/types.h>
 #define __mode_t_defined
+#define __gid_t_defined
+#define __uid_t_defined
 
 #endif