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.
This commit is contained in:
Jeff Johnston 2002-06-19 22:17:33 +00:00
parent 676a64b87d
commit ef467338e4
16 changed files with 1009 additions and 19 deletions

View 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.

View 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 \

View 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)

View File

@ -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;
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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__"

View 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