* Makefile.in (DLL_OFILES): Add posix_ipc.o.
* cygwin.din (mq_close): Export. (mq_getattr): Export. (mq_notify): Export. (mq_open): Export. (mq_receive): Export. (mq_send): Export. (mq_setattr): Export. (mq_timedreceive): Export. (mq_timedsend): Export. (mq_unlink): Export. * posix_ipc.cc: New file implementing the above functions. Move shm_open and shm_unlink from syscalls.cc here. * sysconf.cc (sca): Set value of _SC_MQ_OPEN_MAX to MQ_OPEN_MAX, _SC_MQ_PRIO_MAX to MQ_PRIO_MAX, _SC_MESSAGE_PASSING to _POSIX_MESSAGE_PASSING. * include/limits.h (MQ_OPEN_MAX): Define. (MQ_PRIO_MAX): Define. * include/mqueue.h: New file. * include/cygwin/version.h: Bump API minor number.
This commit is contained in:
parent
77da924b40
commit
7b487ba942
|
@ -1,3 +1,26 @@
|
||||||
|
2007-02-14 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* Makefile.in (DLL_OFILES): Add posix_ipc.o.
|
||||||
|
* cygwin.din (mq_close): Export.
|
||||||
|
(mq_getattr): Export.
|
||||||
|
(mq_notify): Export.
|
||||||
|
(mq_open): Export.
|
||||||
|
(mq_receive): Export.
|
||||||
|
(mq_send): Export.
|
||||||
|
(mq_setattr): Export.
|
||||||
|
(mq_timedreceive): Export.
|
||||||
|
(mq_timedsend): Export.
|
||||||
|
(mq_unlink): Export.
|
||||||
|
* posix_ipc.cc: New file implementing the above functions. Move
|
||||||
|
shm_open and shm_unlink from syscalls.cc here.
|
||||||
|
* sysconf.cc (sca): Set value of _SC_MQ_OPEN_MAX to MQ_OPEN_MAX,
|
||||||
|
_SC_MQ_PRIO_MAX to MQ_PRIO_MAX, _SC_MESSAGE_PASSING to
|
||||||
|
_POSIX_MESSAGE_PASSING.
|
||||||
|
* include/limits.h (MQ_OPEN_MAX): Define.
|
||||||
|
(MQ_PRIO_MAX): Define.
|
||||||
|
* include/mqueue.h: New file.
|
||||||
|
* include/cygwin/version.h: Bump API minor number.
|
||||||
|
|
||||||
2007-02-13 Corinna Vinschen <corinna@vinschen.de>
|
2007-02-13 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* include/cygwin/stdlib.h (valloc): Declare.
|
* include/cygwin/stdlib.h (valloc): Declare.
|
||||||
|
|
|
@ -137,13 +137,13 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o cygthread.o \
|
||||||
grp.o heap.o hookapi.o inet_addr.o inet_network.o init.o ioctl.o ipc.o \
|
grp.o heap.o hookapi.o inet_addr.o inet_network.o init.o ioctl.o ipc.o \
|
||||||
localtime.o lsearch.o malloc_wrapper.o memmem.o minires-os-if.o \
|
localtime.o lsearch.o malloc_wrapper.o memmem.o minires-os-if.o \
|
||||||
minires.o miscfuncs.o mktemp.o mmap.o msg.o net.o netdb.o nftw.o ntea.o \
|
minires.o miscfuncs.o mktemp.o mmap.o msg.o net.o netdb.o nftw.o ntea.o \
|
||||||
passwd.o path.o pinfo.o pipe.o poll.o pthread.o regcomp.o regerror.o \
|
passwd.o path.o pinfo.o pipe.o poll.o posix_ipc.o pthread.o regcomp.o \
|
||||||
regexec.o regfree.o registry.o resource.o rexec.o rcmd.o scandir.o \
|
regerror.o regexec.o regfree.o registry.o resource.o rexec.o rcmd.o \
|
||||||
sched.o sec_acl.o sec_helper.o security.o select.o sem.o shared.o shm.o \
|
scandir.o sched.o sec_acl.o sec_helper.o security.o select.o sem.o \
|
||||||
sigfe.o signal.o sigproc.o smallprint.o spawn.o strace.o strptime.o \
|
shared.o shm.o sigfe.o signal.o sigproc.o smallprint.o spawn.o strace.o \
|
||||||
strsep.o strsig.o sync.o syscalls.o sysconf.o syslog.o termios.o \
|
strptime.o strsep.o strsig.o sync.o syscalls.o sysconf.o syslog.o \
|
||||||
thread.o timelocal.o timer.o times.o tty.o uinfo.o uname.o v8_regexp.o \
|
termios.o thread.o timelocal.o timer.o times.o tty.o uinfo.o uname.o \
|
||||||
v8_regerror.o v8_regsub.o wait.o wincap.o window.o winf.o \
|
v8_regexp.o v8_regerror.o v8_regsub.o wait.o wincap.o window.o winf.o \
|
||||||
$(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS)
|
$(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS)
|
||||||
|
|
||||||
GMON_OFILES:=gmon.o mcount.o profil.o
|
GMON_OFILES:=gmon.o mcount.o profil.o
|
||||||
|
|
|
@ -933,6 +933,16 @@ _modff = modff NOSIGFE
|
||||||
mount SIGFE
|
mount SIGFE
|
||||||
_mount = mount SIGFE
|
_mount = mount SIGFE
|
||||||
mprotect SIGFE
|
mprotect SIGFE
|
||||||
|
mq_close SIGFE
|
||||||
|
mq_getattr SIGFE
|
||||||
|
mq_notify SIGFE
|
||||||
|
mq_open SIGFE
|
||||||
|
mq_receive SIGFE
|
||||||
|
mq_send SIGFE
|
||||||
|
mq_setattr SIGFE
|
||||||
|
mq_timedreceive SIGFE
|
||||||
|
mq_timedsend SIGFE
|
||||||
|
mq_unlink SIGFE
|
||||||
mrand48 NOSIGFE
|
mrand48 NOSIGFE
|
||||||
msgctl SIGFE
|
msgctl SIGFE
|
||||||
msgget SIGFE
|
msgget SIGFE
|
||||||
|
|
|
@ -303,12 +303,14 @@ details. */
|
||||||
if_nameindex, if_freenameindex.
|
if_nameindex, if_freenameindex.
|
||||||
163: Export posix_madvise, posix_memalign.
|
163: Export posix_madvise, posix_memalign.
|
||||||
164: Export shm_open, shm_unlink.
|
164: Export shm_open, shm_unlink.
|
||||||
|
165: Export mq_close, mq_getattr, mq_notify, mq_open, mq_receive,
|
||||||
|
mq_send, mq_setattr, mq_timedreceive, mq_timedsend, mq_unlink.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
|
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
|
||||||
|
|
||||||
#define CYGWIN_VERSION_API_MAJOR 0
|
#define CYGWIN_VERSION_API_MAJOR 0
|
||||||
#define CYGWIN_VERSION_API_MINOR 164
|
#define CYGWIN_VERSION_API_MINOR 165
|
||||||
|
|
||||||
/* There is also a compatibity version number associated with the
|
/* There is also a compatibity version number associated with the
|
||||||
shared memory regions. It is incremented when incompatible
|
shared memory regions. It is incremented when incompatible
|
||||||
|
|
|
@ -179,15 +179,13 @@ details. */
|
||||||
#undef LOGIN_NAME_MAX
|
#undef LOGIN_NAME_MAX
|
||||||
#define LOGIN_NAME_MAX 256 /* equal to UNLEN defined in w32api/lmcons.h */
|
#define LOGIN_NAME_MAX 256 /* equal to UNLEN defined in w32api/lmcons.h */
|
||||||
|
|
||||||
/* The maximum number of open message queue descriptors a process may hold.
|
/* The maximum number of open message queue descriptors a process may hold. */
|
||||||
Not yet implemented. */
|
|
||||||
#undef MQ_OPEN_MAX
|
#undef MQ_OPEN_MAX
|
||||||
/* #define MQ_OPEN_MAX >= _POSIX_MQ_OPEN_MAX */
|
#define MQ_OPEN_MAX OPEN_MAX
|
||||||
|
|
||||||
/* The maximum number of message priorities supported by the implementation.
|
/* The maximum number of message priorities supported by the implementation. */
|
||||||
Not yet implemented. */
|
|
||||||
#undef MQ_PRIO_MAX
|
#undef MQ_PRIO_MAX
|
||||||
/* #define MQ_PRIO_MAX >= _POSIX_MQ_PRIO_MAX */
|
#define MQ_PRIO_MAX INT_MAX
|
||||||
|
|
||||||
/* # of open files per process. Actually it can be more since Cygwin
|
/* # of open files per process. Actually it can be more since Cygwin
|
||||||
grows the dtable as necessary. We define a reasonable limit here
|
grows the dtable as necessary. We define a reasonable limit here
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/* mqueue.h: POSIX message queue interface
|
||||||
|
|
||||||
|
Copyright 2007 Red Hat, Inc.
|
||||||
|
|
||||||
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
This software is a copyrighted work licensed under the terms of the
|
||||||
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/signal.h>
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
#ifndef _MQUEUE_H
|
||||||
|
#define _MQUEUE_H
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef void *mqd_t;
|
||||||
|
|
||||||
|
struct mq_attr {
|
||||||
|
long mq_flags; /* Message queue flags */
|
||||||
|
long mq_maxmsg; /* Max number of messages in queue */
|
||||||
|
long mq_msgsize; /* Max message size */
|
||||||
|
long mq_curmsgs; /* Current number of messages in queue */
|
||||||
|
};
|
||||||
|
|
||||||
|
int mq_close (mqd_t);
|
||||||
|
int mq_getattr (mqd_t, struct mq_attr *);
|
||||||
|
int mq_notify (mqd_t, const struct sigevent *);
|
||||||
|
mqd_t mq_open (const char *, int, ...);
|
||||||
|
ssize_t mq_receive (mqd_t, char *, size_t, unsigned int *);
|
||||||
|
int mq_send (mqd_t, const char *, size_t, unsigned int);
|
||||||
|
int mq_setattr (mqd_t, const struct mq_attr *, struct mq_attr *);
|
||||||
|
ssize_t mq_timedreceive (mqd_t, char *, size_t, unsigned int *,
|
||||||
|
const struct timespec *);
|
||||||
|
int mq_timedsend (mqd_t, const char *, size_t, unsigned int,
|
||||||
|
const struct timespec *);
|
||||||
|
int mq_unlink (const char *name);
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif /* _MQUEUE_H */
|
|
@ -0,0 +1,849 @@
|
||||||
|
/* posix_ipc.cc: POSIX IPC API for Cygwin.
|
||||||
|
|
||||||
|
Copyright 2007 Red Hat, Inc.
|
||||||
|
|
||||||
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
This software is a copyrighted work licensed under the terms of the
|
||||||
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
/* TODO: POSIX semaphores are implemented in thread.cc right now. The
|
||||||
|
implementation in thread.cc disallows implementing kernel
|
||||||
|
persistent semaphores, so in the long run we should move the
|
||||||
|
implementation here, using file based shared memory instead. */
|
||||||
|
|
||||||
|
#include "winsup.h"
|
||||||
|
#include "path.h"
|
||||||
|
#include "cygerrno.h"
|
||||||
|
#include "cygtls.h"
|
||||||
|
#include "security.h"
|
||||||
|
#include "sigproc.h"
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <mqueue.h>
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
const char *prefix;
|
||||||
|
const char *description;
|
||||||
|
} ipc_names[] = {
|
||||||
|
{ "/dev/shm", "POSIX shared memory object" },
|
||||||
|
{ "/dev/mqueue", "POSIX message queue" },
|
||||||
|
{ "/dev/sem", "POSIX semaphore" }
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ipc_type_t
|
||||||
|
{
|
||||||
|
shmem,
|
||||||
|
mqueue,
|
||||||
|
sem
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
check_path (char *res_name, ipc_type_t type, const char *name)
|
||||||
|
{
|
||||||
|
/* Note that we require the existance of the apprpriate /dev subdirectories
|
||||||
|
for POSIX IPC object support, similar to Linux (which supports the
|
||||||
|
directories, but doesn't require to mount them). We don't create
|
||||||
|
these directory here, that's the task of the installer. But we check
|
||||||
|
for existance and give ample warning. */
|
||||||
|
path_conv path (ipc_names[type].prefix, PC_SYM_NOFOLLOW);
|
||||||
|
if (path.error || !path.exists () || !path.isdir ())
|
||||||
|
{
|
||||||
|
small_printf (
|
||||||
|
"Warning: '%s' does not exists or is not a directory.\n\n"
|
||||||
|
"%ss require the existance of this directory.\n"
|
||||||
|
"Create the directory '%s' and set the permissions to 01777.\n"
|
||||||
|
"For instance on the command line: mkdir -m 01777 %s\n",
|
||||||
|
ipc_names[type].prefix, ipc_names[type].description,
|
||||||
|
ipc_names[type].prefix, ipc_names[type].prefix);
|
||||||
|
set_errno (EINVAL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Name must start with a single slash. */
|
||||||
|
if (!name || name[0] != '/' || name[1] == '/')
|
||||||
|
{
|
||||||
|
debug_printf ("Invalid %s name '%s'", ipc_names[type].description, name);
|
||||||
|
set_errno (EINVAL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (strlen (name) > CYG_MAX_PATH - sizeof (ipc_names[type].prefix))
|
||||||
|
{
|
||||||
|
debug_printf ("%s name '%s' too long", ipc_names[type].description, name);
|
||||||
|
set_errno (ENAMETOOLONG);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
strcpy (res_name, ipc_names[type].prefix);
|
||||||
|
strcat (res_name, name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ipc_mutex_init (HANDLE *pmtx, const char *name)
|
||||||
|
{
|
||||||
|
char buf[CYG_MAX_PATH];
|
||||||
|
strcpy (buf, "cyg_pmtx");
|
||||||
|
strcat (buf, name);
|
||||||
|
for (char *c = buf; c = strchr (c + 1, '\\'); ++c)
|
||||||
|
*c = '/';
|
||||||
|
*pmtx = CreateMutex (&sec_all, FALSE, buf);
|
||||||
|
if (!*pmtx)
|
||||||
|
debug_printf ("failed: %E\n");
|
||||||
|
return *pmtx ? 0 : geterrno_from_win_error ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ipc_mutex_lock (HANDLE mtx)
|
||||||
|
{
|
||||||
|
HANDLE h[2] = { mtx, signal_arrived };
|
||||||
|
|
||||||
|
switch (WaitForMultipleObjects (2, h, FALSE, INFINITE))
|
||||||
|
{
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
case WAIT_ABANDONED_0:
|
||||||
|
return 0;
|
||||||
|
case WAIT_OBJECT_0 + 1:
|
||||||
|
set_errno (EINTR);
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return geterrno_from_win_error ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ipc_mutex_unlock (HANDLE mtx)
|
||||||
|
{
|
||||||
|
return ReleaseMutex (mtx) ? 0 : geterrno_from_win_error ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ipc_mutex_close (HANDLE mtx)
|
||||||
|
{
|
||||||
|
return CloseHandle (mtx) ? 0 : geterrno_from_win_error ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ipc_cond_init (HANDLE *pevt, const char *name)
|
||||||
|
{
|
||||||
|
char buf[CYG_MAX_PATH];
|
||||||
|
strcpy (buf, "cyg_pevt");
|
||||||
|
strcat (buf, name);
|
||||||
|
for (char *c = buf; c = strchr (c + 1, '\\'); ++c)
|
||||||
|
*c = '/';
|
||||||
|
*pevt = CreateEvent (&sec_all, TRUE, FALSE, buf);
|
||||||
|
if (!*pevt)
|
||||||
|
debug_printf ("failed: %E\n");
|
||||||
|
return *pevt ? 0 : geterrno_from_win_error ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ipc_cond_timedwait (HANDLE evt, HANDLE mtx, const struct timespec *abstime)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
DWORD timeout;
|
||||||
|
HANDLE h[2] = { mtx, evt };
|
||||||
|
|
||||||
|
if (!abstime)
|
||||||
|
timeout = INFINITE;
|
||||||
|
else if (abstime->tv_sec < 0
|
||||||
|
|| abstime->tv_nsec < 0
|
||||||
|
|| abstime->tv_nsec > 999999999)
|
||||||
|
return EINVAL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gettimeofday (&tv, NULL);
|
||||||
|
/* Check for immediate timeout. */
|
||||||
|
if (tv.tv_sec > abstime->tv_sec
|
||||||
|
|| (tv.tv_sec == abstime->tv_sec
|
||||||
|
&& tv.tv_usec > abstime->tv_nsec / 1000))
|
||||||
|
return ETIMEDOUT;
|
||||||
|
timeout = (abstime->tv_sec - tv.tv_sec) * 1000;
|
||||||
|
timeout += (abstime->tv_nsec / 1000 - tv.tv_usec) / 1000;
|
||||||
|
}
|
||||||
|
if (ipc_mutex_unlock (mtx))
|
||||||
|
return -1;
|
||||||
|
switch (WaitForMultipleObjects (2, h, TRUE, timeout))
|
||||||
|
{
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
case WAIT_ABANDONED_0:
|
||||||
|
ResetEvent (evt);
|
||||||
|
return 0;
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
ipc_mutex_lock (mtx);
|
||||||
|
return ETIMEDOUT;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return geterrno_from_win_error ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ipc_cond_signal (HANDLE evt)
|
||||||
|
{
|
||||||
|
return SetEvent (evt) ? 0 : geterrno_from_win_error ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ipc_cond_close (HANDLE evt)
|
||||||
|
{
|
||||||
|
return CloseHandle (evt) ? 0 : geterrno_from_win_error ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* POSIX shared memory object implementation. */
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
shm_open (const char *name, int oflag, mode_t mode)
|
||||||
|
{
|
||||||
|
char shmname[CYG_MAX_PATH];
|
||||||
|
|
||||||
|
if (!check_path (shmname, shmem, name))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Check for valid flags. */
|
||||||
|
if (((oflag & O_ACCMODE) != O_RDONLY && (oflag & O_ACCMODE) != O_RDWR)
|
||||||
|
|| (oflag & ~(O_ACCMODE | O_CREAT | O_EXCL | O_TRUNC)))
|
||||||
|
{
|
||||||
|
debug_printf ("Invalid oflag 0%o", oflag);
|
||||||
|
set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return open (shmname, oflag, mode & 0777);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
shm_unlink (const char *name)
|
||||||
|
{
|
||||||
|
char shmname[CYG_MAX_PATH];
|
||||||
|
|
||||||
|
if (!check_path (shmname, shmem, name))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return unlink (shmname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The POSIX message queue implementation is based on W. Richard STEVENS
|
||||||
|
implementation, just tweaked for Cygwin. The main change is
|
||||||
|
the usage of Windows mutexes and events instead of using the pthread
|
||||||
|
synchronization objects. The pathname is massaged so that the
|
||||||
|
files are created under /dev/mqueue. mq_timedsend and mq_timedreceive
|
||||||
|
are implemented additionally. */
|
||||||
|
|
||||||
|
struct mq_hdr
|
||||||
|
{
|
||||||
|
struct mq_attr mqh_attr; /* the queue's attributes */
|
||||||
|
long mqh_head; /* index of first message */
|
||||||
|
long mqh_free; /* index of first free message */
|
||||||
|
long mqh_nwait; /* #threads blocked in mq_receive() */
|
||||||
|
pid_t mqh_pid; /* nonzero PID if mqh_event set */
|
||||||
|
struct sigevent mqh_event; /* for mq_notify() */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msg_hdr
|
||||||
|
{
|
||||||
|
long msg_next; /* index of next on linked list */
|
||||||
|
ssize_t msg_len; /* actual length */
|
||||||
|
unsigned int msg_prio; /* priority */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mq_info
|
||||||
|
{
|
||||||
|
struct mq_hdr *mqi_hdr; /* start of mmap'ed region */
|
||||||
|
unsigned long mqi_magic; /* magic number if open */
|
||||||
|
int mqi_flags; /* flags for this process */
|
||||||
|
HANDLE mqi_lock; /* mutex lock */
|
||||||
|
HANDLE mqi_wait; /* and condition variable */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MQI_MAGIC 0x98765432UL
|
||||||
|
|
||||||
|
#define MSGSIZE(i) roundup((i), sizeof(long))
|
||||||
|
|
||||||
|
#define MAX_TRIES 10 /* for waiting for initialization */
|
||||||
|
|
||||||
|
struct mq_attr defattr = { 0, 10, 8192, 0 }; /* Linux defaults. */
|
||||||
|
|
||||||
|
extern "C" _off64_t lseek64 (int, _off64_t, int);
|
||||||
|
extern "C" void *mmap64 (void *, size_t, int, int, int, _off64_t);
|
||||||
|
|
||||||
|
extern "C" mqd_t
|
||||||
|
mq_open (const char *name, int oflag, ...)
|
||||||
|
{
|
||||||
|
int i, fd, nonblock, created;
|
||||||
|
long msgsize, index;
|
||||||
|
_off64_t filesize;
|
||||||
|
va_list ap;
|
||||||
|
mode_t mode;
|
||||||
|
int8_t *mptr;
|
||||||
|
struct __stat64 statbuff;
|
||||||
|
struct mq_hdr *mqhdr;
|
||||||
|
struct msg_hdr *msghdr;
|
||||||
|
struct mq_attr *attr;
|
||||||
|
struct mq_info *mqinfo;
|
||||||
|
char mqname[CYG_MAX_PATH];
|
||||||
|
|
||||||
|
if (!check_path (mqname, mqueue, name))
|
||||||
|
return (mqd_t) -1;
|
||||||
|
|
||||||
|
myfault efault;
|
||||||
|
if (efault.faulted (EFAULT))
|
||||||
|
return (mqd_t) -1;
|
||||||
|
|
||||||
|
created = 0;
|
||||||
|
nonblock = oflag & O_NONBLOCK;
|
||||||
|
oflag &= ~O_NONBLOCK;
|
||||||
|
mptr = (int8_t *) MAP_FAILED;
|
||||||
|
mqinfo = NULL;
|
||||||
|
|
||||||
|
again:
|
||||||
|
if (oflag & O_CREAT)
|
||||||
|
{
|
||||||
|
va_start (ap, oflag); /* init ap to final named argument */
|
||||||
|
mode = va_arg (ap, mode_t) & ~S_IXUSR;
|
||||||
|
attr = va_arg (ap, struct mq_attr *);
|
||||||
|
va_end (ap);
|
||||||
|
|
||||||
|
/* Open and specify O_EXCL and user-execute */
|
||||||
|
fd = open (mqname, oflag | O_EXCL | O_RDWR, mode | S_IXUSR);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
if (errno == EEXIST && (oflag & O_EXCL) == 0)
|
||||||
|
goto exists; /* already exists, OK */
|
||||||
|
return (mqd_t) -1;
|
||||||
|
}
|
||||||
|
created = 1;
|
||||||
|
/* First one to create the file initializes it */
|
||||||
|
if (attr == NULL)
|
||||||
|
attr = &defattr;
|
||||||
|
else if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0)
|
||||||
|
{
|
||||||
|
set_errno (EINVAL);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/* Calculate and set the file size */
|
||||||
|
msgsize = MSGSIZE (attr->mq_msgsize);
|
||||||
|
filesize = sizeof (struct mq_hdr)
|
||||||
|
+ (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize));
|
||||||
|
if (lseek64 (fd, filesize - 1, SEEK_SET) == -1)
|
||||||
|
goto err;
|
||||||
|
if (write (fd, "", 1) == -1)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* Memory map the file */
|
||||||
|
mptr = (int8_t *) mmap64 (NULL, (size_t) filesize, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_SHARED, fd, 0);
|
||||||
|
if (mptr == (int8_t *) MAP_FAILED)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* Allocate one mq_info{} for the queue */
|
||||||
|
if (!(mqinfo = (struct mq_info *) malloc (sizeof (struct mq_info))))
|
||||||
|
goto err;
|
||||||
|
mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr;
|
||||||
|
mqinfo->mqi_magic = MQI_MAGIC;
|
||||||
|
mqinfo->mqi_flags = nonblock;
|
||||||
|
|
||||||
|
/* Initialize header at beginning of file */
|
||||||
|
/* Create free list with all messages on it */
|
||||||
|
mqhdr->mqh_attr.mq_flags = 0;
|
||||||
|
mqhdr->mqh_attr.mq_maxmsg = attr->mq_maxmsg;
|
||||||
|
mqhdr->mqh_attr.mq_msgsize = attr->mq_msgsize;
|
||||||
|
mqhdr->mqh_attr.mq_curmsgs = 0;
|
||||||
|
mqhdr->mqh_nwait = 0;
|
||||||
|
mqhdr->mqh_pid = 0;
|
||||||
|
mqhdr->mqh_head = 0;
|
||||||
|
index = sizeof (struct mq_hdr);
|
||||||
|
mqhdr->mqh_free = index;
|
||||||
|
for (i = 0; i < attr->mq_maxmsg - 1; i++)
|
||||||
|
{
|
||||||
|
msghdr = (struct msg_hdr *) &mptr[index];
|
||||||
|
index += sizeof (struct msg_hdr) + msgsize;
|
||||||
|
msghdr->msg_next = index;
|
||||||
|
}
|
||||||
|
msghdr = (struct msg_hdr *) &mptr[index];
|
||||||
|
msghdr->msg_next = 0; /* end of free list */
|
||||||
|
|
||||||
|
/* Initialize mutex & condition variable */
|
||||||
|
i = ipc_mutex_init (&mqinfo->mqi_lock, mqname);
|
||||||
|
if (i != 0)
|
||||||
|
goto pthreaderr;
|
||||||
|
|
||||||
|
i = ipc_cond_init (&mqinfo->mqi_wait, mqname);
|
||||||
|
if (i != 0)
|
||||||
|
goto pthreaderr;
|
||||||
|
|
||||||
|
/* Initialization complete, turn off user-execute bit */
|
||||||
|
if (fchmod (fd, mode) == -1)
|
||||||
|
goto err;
|
||||||
|
close (fd);
|
||||||
|
return ((mqd_t) mqinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
exists:
|
||||||
|
/* Open the file then memory map */
|
||||||
|
if ((fd = open (mqname, O_RDWR)) < 0)
|
||||||
|
{
|
||||||
|
if (errno == ENOENT && (oflag & O_CREAT))
|
||||||
|
goto again;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/* Make certain initialization is complete */
|
||||||
|
for (i = 0; i < MAX_TRIES; i++)
|
||||||
|
{
|
||||||
|
if (stat64 (mqname, &statbuff) == -1)
|
||||||
|
{
|
||||||
|
if (errno == ENOENT && (oflag & O_CREAT))
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if ((statbuff.st_mode & S_IXUSR) == 0)
|
||||||
|
break;
|
||||||
|
sleep (1);
|
||||||
|
}
|
||||||
|
if (i == MAX_TRIES)
|
||||||
|
{
|
||||||
|
set_errno (ETIMEDOUT);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
filesize = statbuff.st_size;
|
||||||
|
mptr = (int8_t *) mmap64 (NULL, (size_t) filesize, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_SHARED, fd, 0);
|
||||||
|
if (mptr == (int8_t *) MAP_FAILED)
|
||||||
|
goto err;
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
/* Allocate one mq_info{} for each open */
|
||||||
|
if (!(mqinfo = (struct mq_info *) malloc (sizeof (struct mq_info))))
|
||||||
|
goto err;
|
||||||
|
mqinfo->mqi_hdr = (struct mq_hdr *) mptr;
|
||||||
|
mqinfo->mqi_magic = MQI_MAGIC;
|
||||||
|
mqinfo->mqi_flags = nonblock;
|
||||||
|
|
||||||
|
/* Initialize mutex & condition variable */
|
||||||
|
i = ipc_mutex_init (&mqinfo->mqi_lock, mqname);
|
||||||
|
if (i != 0)
|
||||||
|
goto pthreaderr;
|
||||||
|
|
||||||
|
i = ipc_cond_init (&mqinfo->mqi_wait, mqname);
|
||||||
|
if (i != 0)
|
||||||
|
goto pthreaderr;
|
||||||
|
|
||||||
|
return (mqd_t) mqinfo;
|
||||||
|
|
||||||
|
pthreaderr:
|
||||||
|
errno = i;
|
||||||
|
err:
|
||||||
|
/* Don't let following function calls change errno */
|
||||||
|
save_errno save;
|
||||||
|
|
||||||
|
if (created)
|
||||||
|
unlink (mqname);
|
||||||
|
if (mptr != (int8_t *) MAP_FAILED)
|
||||||
|
munmap((void *) mptr, (size_t) filesize);
|
||||||
|
if (mqinfo)
|
||||||
|
free (mqinfo);
|
||||||
|
close (fd);
|
||||||
|
return (mqd_t) -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
mq_getattr (mqd_t mqd, struct mq_attr *mqstat)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
struct mq_hdr *mqhdr;
|
||||||
|
struct mq_attr *attr;
|
||||||
|
struct mq_info *mqinfo;
|
||||||
|
|
||||||
|
myfault efault;
|
||||||
|
if (efault.faulted (EBADF))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mqinfo = (struct mq_info *) mqd;
|
||||||
|
if (mqinfo->mqi_magic != MQI_MAGIC)
|
||||||
|
{
|
||||||
|
set_errno (EBADF);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mqhdr = mqinfo->mqi_hdr;
|
||||||
|
attr = &mqhdr->mqh_attr;
|
||||||
|
if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
|
||||||
|
{
|
||||||
|
errno = n;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mqstat->mq_flags = mqinfo->mqi_flags; /* per-open */
|
||||||
|
mqstat->mq_maxmsg = attr->mq_maxmsg; /* remaining three per-queue */
|
||||||
|
mqstat->mq_msgsize = attr->mq_msgsize;
|
||||||
|
mqstat->mq_curmsgs = attr->mq_curmsgs;
|
||||||
|
|
||||||
|
ipc_mutex_unlock (mqinfo->mqi_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
mq_setattr (mqd_t mqd, const struct mq_attr *mqstat, struct mq_attr *omqstat)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
struct mq_hdr *mqhdr;
|
||||||
|
struct mq_attr *attr;
|
||||||
|
struct mq_info *mqinfo;
|
||||||
|
|
||||||
|
myfault efault;
|
||||||
|
if (efault.faulted (EBADF))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mqinfo = (struct mq_info *) mqd;
|
||||||
|
if (mqinfo->mqi_magic != MQI_MAGIC)
|
||||||
|
{
|
||||||
|
set_errno (EBADF);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mqhdr = mqinfo->mqi_hdr;
|
||||||
|
attr = &mqhdr->mqh_attr;
|
||||||
|
if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
|
||||||
|
{
|
||||||
|
errno = n;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (omqstat != NULL)
|
||||||
|
{
|
||||||
|
omqstat->mq_flags = mqinfo->mqi_flags; /* previous attributes */
|
||||||
|
omqstat->mq_maxmsg = attr->mq_maxmsg;
|
||||||
|
omqstat->mq_msgsize = attr->mq_msgsize;
|
||||||
|
omqstat->mq_curmsgs = attr->mq_curmsgs; /* and current status */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mqstat->mq_flags & O_NONBLOCK)
|
||||||
|
mqinfo->mqi_flags |= O_NONBLOCK;
|
||||||
|
else
|
||||||
|
mqinfo->mqi_flags &= ~O_NONBLOCK;
|
||||||
|
|
||||||
|
ipc_mutex_unlock (mqinfo->mqi_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
mq_notify (mqd_t mqd, const struct sigevent *notification)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
pid_t pid;
|
||||||
|
struct mq_hdr *mqhdr;
|
||||||
|
struct mq_info *mqinfo;
|
||||||
|
|
||||||
|
myfault efault;
|
||||||
|
if (efault.faulted (EBADF))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mqinfo = (struct mq_info *) mqd;
|
||||||
|
if (mqinfo->mqi_magic != MQI_MAGIC)
|
||||||
|
{
|
||||||
|
set_errno (EBADF);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mqhdr = mqinfo->mqi_hdr;
|
||||||
|
if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
|
||||||
|
{
|
||||||
|
errno = n;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = getpid ();
|
||||||
|
if (!notification)
|
||||||
|
{
|
||||||
|
if (mqhdr->mqh_pid == pid)
|
||||||
|
mqhdr->mqh_pid = 0; /* unregister calling process */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mqhdr->mqh_pid != 0)
|
||||||
|
{
|
||||||
|
if (kill (mqhdr->mqh_pid, 0) != -1 || errno != ESRCH)
|
||||||
|
{
|
||||||
|
set_errno (EBUSY);
|
||||||
|
ipc_mutex_unlock (mqinfo->mqi_lock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mqhdr->mqh_pid = pid;
|
||||||
|
mqhdr->mqh_event = *notification;
|
||||||
|
}
|
||||||
|
ipc_mutex_unlock (mqinfo->mqi_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_mq_send (mqd_t mqd, const char *ptr, size_t len, unsigned int prio,
|
||||||
|
const struct timespec *abstime)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
long index, freeindex;
|
||||||
|
int8_t *mptr;
|
||||||
|
struct sigevent *sigev;
|
||||||
|
struct mq_hdr *mqhdr;
|
||||||
|
struct mq_attr *attr;
|
||||||
|
struct msg_hdr *msghdr, *nmsghdr, *pmsghdr;
|
||||||
|
struct mq_info *mqinfo;
|
||||||
|
|
||||||
|
myfault efault;
|
||||||
|
if (efault.faulted (EBADF))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mqinfo = (struct mq_info *) mqd;
|
||||||
|
if (mqinfo->mqi_magic != MQI_MAGIC)
|
||||||
|
{
|
||||||
|
set_errno (EBADF);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (prio > MQ_PRIO_MAX)
|
||||||
|
{
|
||||||
|
set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mqhdr = mqinfo->mqi_hdr; /* struct pointer */
|
||||||
|
mptr = (int8_t *) mqhdr; /* byte pointer */
|
||||||
|
attr = &mqhdr->mqh_attr;
|
||||||
|
if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
|
||||||
|
{
|
||||||
|
errno = n;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > (size_t) attr->mq_msgsize)
|
||||||
|
{
|
||||||
|
set_errno (EMSGSIZE);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (attr->mq_curmsgs == 0)
|
||||||
|
{
|
||||||
|
if (mqhdr->mqh_pid != 0 && mqhdr->mqh_nwait == 0)
|
||||||
|
{
|
||||||
|
sigev = &mqhdr->mqh_event;
|
||||||
|
if (sigev->sigev_notify == SIGEV_SIGNAL)
|
||||||
|
sigqueue (mqhdr->mqh_pid, sigev->sigev_signo, sigev->sigev_value);
|
||||||
|
mqhdr->mqh_pid = 0; /* unregister */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (attr->mq_curmsgs >= attr->mq_maxmsg)
|
||||||
|
{
|
||||||
|
/* Queue is full */
|
||||||
|
if (mqinfo->mqi_flags & O_NONBLOCK)
|
||||||
|
{
|
||||||
|
set_errno (EAGAIN);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/* Wait for room for one message on the queue */
|
||||||
|
while (attr->mq_curmsgs >= attr->mq_maxmsg)
|
||||||
|
ipc_cond_timedwait (mqinfo->mqi_wait, mqinfo->mqi_lock, abstime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nmsghdr will point to new message */
|
||||||
|
if ((freeindex = mqhdr->mqh_free) == 0)
|
||||||
|
api_fatal ("mq_send: curmsgs = %ld; free = 0", attr->mq_curmsgs);
|
||||||
|
|
||||||
|
nmsghdr = (struct msg_hdr *) &mptr[freeindex];
|
||||||
|
nmsghdr->msg_prio = prio;
|
||||||
|
nmsghdr->msg_len = len;
|
||||||
|
memcpy (nmsghdr + 1, ptr, len); /* copy message from caller */
|
||||||
|
mqhdr->mqh_free = nmsghdr->msg_next; /* new freelist head */
|
||||||
|
|
||||||
|
/* Find right place for message in linked list */
|
||||||
|
index = mqhdr->mqh_head;
|
||||||
|
pmsghdr = (struct msg_hdr *) &(mqhdr->mqh_head);
|
||||||
|
while (index)
|
||||||
|
{
|
||||||
|
msghdr = (struct msg_hdr *) &mptr[index];
|
||||||
|
if (prio > msghdr->msg_prio)
|
||||||
|
{
|
||||||
|
nmsghdr->msg_next = index;
|
||||||
|
pmsghdr->msg_next = freeindex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index = msghdr->msg_next;
|
||||||
|
pmsghdr = msghdr;
|
||||||
|
}
|
||||||
|
if (index == 0)
|
||||||
|
{
|
||||||
|
/* Queue was empty or new goes at end of list */
|
||||||
|
pmsghdr->msg_next = freeindex;
|
||||||
|
nmsghdr->msg_next = 0;
|
||||||
|
}
|
||||||
|
/* Wake up anyone blocked in mq_receive waiting for a message */
|
||||||
|
if (attr->mq_curmsgs == 0)
|
||||||
|
ipc_cond_signal (mqinfo->mqi_wait);
|
||||||
|
attr->mq_curmsgs++;
|
||||||
|
|
||||||
|
ipc_mutex_unlock (mqinfo->mqi_lock);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
ipc_mutex_unlock (mqinfo->mqi_lock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
mq_send (mqd_t mqd, const char *ptr, size_t len, unsigned int prio)
|
||||||
|
{
|
||||||
|
return _mq_send (mqd, ptr, len, prio, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
mq_timedsend (mqd_t mqd, const char *ptr, size_t len, unsigned int prio,
|
||||||
|
const struct timespec *abstime)
|
||||||
|
{
|
||||||
|
return _mq_send (mqd, ptr, len, prio, abstime);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
_mq_receive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop,
|
||||||
|
const struct timespec *abstime)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
long index;
|
||||||
|
int8_t *mptr;
|
||||||
|
ssize_t len;
|
||||||
|
struct mq_hdr *mqhdr;
|
||||||
|
struct mq_attr *attr;
|
||||||
|
struct msg_hdr *msghdr;
|
||||||
|
struct mq_info *mqinfo;
|
||||||
|
|
||||||
|
myfault efault;
|
||||||
|
if (efault.faulted (EBADF))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mqinfo = (struct mq_info *) mqd;
|
||||||
|
if (mqinfo->mqi_magic != MQI_MAGIC)
|
||||||
|
{
|
||||||
|
set_errno (EBADF);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mqhdr = mqinfo->mqi_hdr; /* struct pointer */
|
||||||
|
mptr = (int8_t *) mqhdr; /* byte pointer */
|
||||||
|
attr = &mqhdr->mqh_attr;
|
||||||
|
if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
|
||||||
|
{
|
||||||
|
errno = n;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxlen < (size_t) attr->mq_msgsize)
|
||||||
|
{
|
||||||
|
set_errno (EMSGSIZE);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (attr->mq_curmsgs == 0) /* queue is empty */
|
||||||
|
{
|
||||||
|
if (mqinfo->mqi_flags & O_NONBLOCK)
|
||||||
|
{
|
||||||
|
set_errno (EAGAIN);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/* Wait for a message to be placed onto queue */
|
||||||
|
mqhdr->mqh_nwait++;
|
||||||
|
while (attr->mq_curmsgs == 0)
|
||||||
|
ipc_cond_timedwait (mqinfo->mqi_wait, mqinfo->mqi_lock, abstime);
|
||||||
|
mqhdr->mqh_nwait--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((index = mqhdr->mqh_head) == 0)
|
||||||
|
api_fatal ("mq_receive: curmsgs = %ld; head = 0", attr->mq_curmsgs);
|
||||||
|
|
||||||
|
msghdr = (struct msg_hdr *) &mptr[index];
|
||||||
|
mqhdr->mqh_head = msghdr->msg_next; /* new head of list */
|
||||||
|
len = msghdr->msg_len;
|
||||||
|
memcpy(ptr, msghdr + 1, len); /* copy the message itself */
|
||||||
|
if (priop != NULL)
|
||||||
|
*priop = msghdr->msg_prio;
|
||||||
|
|
||||||
|
/* Just-read message goes to front of free list */
|
||||||
|
msghdr->msg_next = mqhdr->mqh_free;
|
||||||
|
mqhdr->mqh_free = index;
|
||||||
|
|
||||||
|
/* Wake up anyone blocked in mq_send waiting for room */
|
||||||
|
if (attr->mq_curmsgs == attr->mq_maxmsg)
|
||||||
|
ipc_cond_signal (mqinfo->mqi_wait);
|
||||||
|
attr->mq_curmsgs--;
|
||||||
|
|
||||||
|
ipc_mutex_unlock (mqinfo->mqi_lock);
|
||||||
|
return len;
|
||||||
|
|
||||||
|
err:
|
||||||
|
ipc_mutex_unlock (mqinfo->mqi_lock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" ssize_t
|
||||||
|
mq_receive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop)
|
||||||
|
{
|
||||||
|
return _mq_receive (mqd, ptr, maxlen, priop, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" ssize_t
|
||||||
|
mq_timedreceive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop,
|
||||||
|
const struct timespec *abstime)
|
||||||
|
{
|
||||||
|
return _mq_receive (mqd, ptr, maxlen, priop, abstime);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
mq_close (mqd_t mqd)
|
||||||
|
{
|
||||||
|
long msgsize, filesize;
|
||||||
|
struct mq_hdr *mqhdr;
|
||||||
|
struct mq_attr *attr;
|
||||||
|
struct mq_info *mqinfo;
|
||||||
|
|
||||||
|
myfault efault;
|
||||||
|
if (efault.faulted (EBADF))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mqinfo = (struct mq_info *) mqd;
|
||||||
|
if (mqinfo->mqi_magic != MQI_MAGIC)
|
||||||
|
{
|
||||||
|
set_errno (EBADF);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mqhdr = mqinfo->mqi_hdr;
|
||||||
|
attr = &mqhdr->mqh_attr;
|
||||||
|
|
||||||
|
if (mq_notify (mqd, NULL)) /* unregister calling process */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
msgsize = MSGSIZE (attr->mq_msgsize);
|
||||||
|
filesize = sizeof (struct mq_hdr)
|
||||||
|
+ (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize));
|
||||||
|
if (munmap (mqinfo->mqi_hdr, filesize) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mqinfo->mqi_magic = 0; /* just in case */
|
||||||
|
ipc_cond_close (mqinfo->mqi_wait);
|
||||||
|
ipc_mutex_close (mqinfo->mqi_lock);
|
||||||
|
free (mqinfo);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
mq_unlink (const char *name)
|
||||||
|
{
|
||||||
|
char mqname[CYG_MAX_PATH];
|
||||||
|
|
||||||
|
if (!check_path (mqname, mqueue, name))
|
||||||
|
return -1;
|
||||||
|
if (unlink (mqname) == -1)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -3346,73 +3346,3 @@ pclose (FILE *fp)
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SHM_STORAGE "/dev/shm"
|
|
||||||
|
|
||||||
static bool
|
|
||||||
check_shm (const char *name)
|
|
||||||
{
|
|
||||||
/* Note that we require the existance of /dev/shm for shared memory
|
|
||||||
object support, same as on Linux. We don't create this directory
|
|
||||||
here, that's the task of the installer. But we check for existance
|
|
||||||
and give ample warning. */
|
|
||||||
path_conv dev_shm (SHM_STORAGE, PC_SYM_NOFOLLOW);
|
|
||||||
if (dev_shm.error || !dev_shm.exists () || !dev_shm.isdir ())
|
|
||||||
{
|
|
||||||
small_printf (
|
|
||||||
"Warning: '%s' does not exists or is not a directory.\n\n"
|
|
||||||
"Shared memory objects require the existance of this directory.\n"
|
|
||||||
"Create the directory '%s' and set the permissions to 01777.\n"
|
|
||||||
"For instance on the command line: mkdir -m 01777 %s\n",
|
|
||||||
SHM_STORAGE, SHM_STORAGE, SHM_STORAGE);
|
|
||||||
set_errno (EINVAL);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* Name must start with a single slash. */
|
|
||||||
if (!name || name[0] != '/' || name[1] == '/')
|
|
||||||
{
|
|
||||||
debug_printf ("Invalid shared memory object name '%s'", name);
|
|
||||||
set_errno (EINVAL);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (strlen (name) > CYG_MAX_PATH - sizeof (SHM_STORAGE))
|
|
||||||
{
|
|
||||||
debug_printf ("shared memory object name '%s' too long", name);
|
|
||||||
set_errno (ENAMETOOLONG);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" int
|
|
||||||
shm_open (const char *name, int oflag, mode_t mode)
|
|
||||||
{
|
|
||||||
if (!check_shm (name))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Check for valid flags. */
|
|
||||||
if (((oflag & O_ACCMODE) != O_RDONLY && (oflag & O_ACCMODE) != O_RDWR)
|
|
||||||
|| (oflag & ~(O_ACCMODE | O_CREAT | O_EXCL | O_TRUNC)))
|
|
||||||
{
|
|
||||||
debug_printf ("Invalid oflag 0%o", oflag);
|
|
||||||
set_errno (EINVAL);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char shmname[CYG_MAX_PATH];
|
|
||||||
strcpy (shmname, SHM_STORAGE);
|
|
||||||
strcat (shmname, name);
|
|
||||||
return open (shmname, oflag, mode & 0777);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" int
|
|
||||||
shm_unlink (const char *name)
|
|
||||||
{
|
|
||||||
if (!check_shm (name))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
char shmname[CYG_MAX_PATH];
|
|
||||||
strcpy (shmname, SHM_STORAGE);
|
|
||||||
strcat (shmname, name);
|
|
||||||
return unlink (shmname);
|
|
||||||
}
|
|
||||||
|
|
|
@ -131,8 +131,8 @@ static struct
|
||||||
{func, {f:get_nproc_values}}, /* 10, _SC_NPROCESSORS_ONLN */
|
{func, {f:get_nproc_values}}, /* 10, _SC_NPROCESSORS_ONLN */
|
||||||
{func, {f:get_nproc_values}}, /* 11, _SC_PHYS_PAGES */
|
{func, {f:get_nproc_values}}, /* 11, _SC_PHYS_PAGES */
|
||||||
{func, {f:get_avphys}}, /* 12, _SC_AVPHYS_PAGES */
|
{func, {f:get_avphys}}, /* 12, _SC_AVPHYS_PAGES */
|
||||||
{nsup, {c:0}}, /* 13, _SC_MQ_OPEN_MAX */
|
{cons, {c:MQ_OPEN_MAX}}, /* 13, _SC_MQ_OPEN_MAX */
|
||||||
{nsup, {c:0}}, /* 14, _SC_MQ_PRIO_MAX */
|
{cons, {c:MQ_PRIO_MAX}}, /* 14, _SC_MQ_PRIO_MAX */
|
||||||
{cons, {c:RTSIG_MAX}}, /* 15, _SC_RTSIG_MAX */
|
{cons, {c:RTSIG_MAX}}, /* 15, _SC_RTSIG_MAX */
|
||||||
{cons, {c:-1L}}, /* 16, _SC_SEM_NSEMS_MAX */
|
{cons, {c:-1L}}, /* 16, _SC_SEM_NSEMS_MAX */
|
||||||
{cons, {c:SEM_VALUE_MAX}}, /* 17, _SC_SEM_VALUE_MAX */
|
{cons, {c:SEM_VALUE_MAX}}, /* 17, _SC_SEM_VALUE_MAX */
|
||||||
|
@ -145,7 +145,7 @@ static struct
|
||||||
{cons, {c:-1L}}, /* 24, _SC_MEMLOCK */
|
{cons, {c:-1L}}, /* 24, _SC_MEMLOCK */
|
||||||
{cons, {c:_POSIX_MEMLOCK_RANGE}}, /* 25, _SC_MEMLOCK_RANGE */
|
{cons, {c:_POSIX_MEMLOCK_RANGE}}, /* 25, _SC_MEMLOCK_RANGE */
|
||||||
{cons, {c:_POSIX_MEMORY_PROTECTION}}, /* 26, _SC_MEMORY_PROTECTION */
|
{cons, {c:_POSIX_MEMORY_PROTECTION}}, /* 26, _SC_MEMORY_PROTECTION */
|
||||||
{cons, {c:-1L}}, /* 27, _SC_MESSAGE_PASSING */
|
{cons, {c:_POSIX_MESSAGE_PASSING}}, /* 27, _SC_MESSAGE_PASSING */
|
||||||
{cons, {c:-1L}}, /* 28, _SC_PRIORITIZED_IO */
|
{cons, {c:-1L}}, /* 28, _SC_PRIORITIZED_IO */
|
||||||
{cons, {c:_POSIX_REALTIME_SIGNALS}}, /* 29, _SC_REALTIME_SIGNALS */
|
{cons, {c:_POSIX_REALTIME_SIGNALS}}, /* 29, _SC_REALTIME_SIGNALS */
|
||||||
{cons, {c:_POSIX_SEMAPHORES}}, /* 30, _SC_SEMAPHORES */
|
{cons, {c:_POSIX_SEMAPHORES}}, /* 30, _SC_SEMAPHORES */
|
||||||
|
|
Loading…
Reference in New Issue