Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Johnston <jjohnstn@redhat.com>2002-06-20 02:17:33 +0400
committerJeff Johnston <jjohnstn@redhat.com>2002-06-20 02:17:33 +0400
commitef467338e4a290b0f8978a0701b404e17c5bb048 (patch)
tree94570e7616b92bab0db3acef31bcf53dd6ce7a24 /newlib/libc/sys/linux
parent676a64b87d76d8c0a518dbcb2e03d8ae4c59ced4 (diff)
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.
Diffstat (limited to 'newlib/libc/sys/linux')
-rw-r--r--newlib/libc/sys/linux/Makefile.am10
-rw-r--r--newlib/libc/sys/linux/Makefile.in51
-rw-r--r--newlib/libc/sys/linux/ftok.c41
-rw-r--r--newlib/libc/sys/linux/include/mqueue.h34
-rw-r--r--newlib/libc/sys/linux/ipc.c87
-rw-r--r--newlib/libc/sys/linux/mq_close.c48
-rw-r--r--newlib/libc/sys/linux/mq_getattr.c52
-rw-r--r--newlib/libc/sys/linux/mq_notify.c22
-rw-r--r--newlib/libc/sys/linux/mq_open.c340
-rw-r--r--newlib/libc/sys/linux/mq_receive.c67
-rw-r--r--newlib/libc/sys/linux/mq_send.c72
-rw-r--r--newlib/libc/sys/linux/mq_setattr.c59
-rw-r--r--newlib/libc/sys/linux/mq_unlink.c73
-rw-r--r--newlib/libc/sys/linux/mqlocal.h47
-rw-r--r--newlib/libc/sys/linux/sys/types.h2
15 files changed, 989 insertions, 16 deletions
diff --git a/newlib/libc/sys/linux/Makefile.am b/newlib/libc/sys/linux/Makefile.am
index fccb24dc3..861340d22 100644
--- a/newlib/libc/sys/linux/Makefile.am
+++ b/newlib/libc/sys/linux/Makefile.am
@@ -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 \
diff --git a/newlib/libc/sys/linux/Makefile.in b/newlib/libc/sys/linux/Makefile.in
index a89736059..9f8459e65 100644
--- a/newlib/libc/sys/linux/Makefile.in
+++ b/newlib/libc/sys/linux/Makefile.in
@@ -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
index 000000000..497754bdb
--- /dev/null
+++ b/newlib/libc/sys/linux/ftok.c
@@ -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
index 000000000..10e81e72f
--- /dev/null
+++ b/newlib/libc/sys/linux/include/mqueue.h
@@ -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
index 000000000..31e225255
--- /dev/null
+++ b/newlib/libc/sys/linux/ipc.c
@@ -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
index 000000000..f80744327
--- /dev/null
+++ b/newlib/libc/sys/linux/mq_close.c
@@ -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
index 000000000..b82906013
--- /dev/null
+++ b/newlib/libc/sys/linux/mq_getattr.c
@@ -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
index 000000000..fd4606bd4
--- /dev/null
+++ b/newlib/libc/sys/linux/mq_notify.c
@@ -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
index 000000000..b8da2144d
--- /dev/null
+++ b/newlib/libc/sys/linux/mq_open.c
@@ -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
index 000000000..1aa7b9fb3
--- /dev/null
+++ b/newlib/libc/sys/linux/mq_receive.c
@@ -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
index 000000000..92710c2f2
--- /dev/null
+++ b/newlib/libc/sys/linux/mq_send.c
@@ -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
index 000000000..ecc32e931
--- /dev/null
+++ b/newlib/libc/sys/linux/mq_setattr.c
@@ -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
index 000000000..93902cd59
--- /dev/null
+++ b/newlib/libc/sys/linux/mq_unlink.c
@@ -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
index 000000000..56fd66c2d
--- /dev/null
+++ b/newlib/libc/sys/linux/mqlocal.h
@@ -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__"
+
diff --git a/newlib/libc/sys/linux/sys/types.h b/newlib/libc/sys/linux/sys/types.h
index 05e313d10..bbc23167e 100644
--- a/newlib/libc/sys/linux/sys/types.h
+++ b/newlib/libc/sys/linux/sys/types.h
@@ -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