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:
parent
676a64b87d
commit
ef467338e4
|
@ -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.
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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__"
|
||||
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue