Skip to contentSkip to conversation

State of Posix compliance in v2.2/v2.4 kernel?

DISCUSSION [email protected] 7 participants 9 messages Nov 13, 2000 – Nov 19, 2000 Documentation

lore
Share & tools
lore
#0 lore raw

Hello.

Sorry if this is a FAQ, but I've searched the archives for this list
(http://www.uwsg.iu.edu/hypermail/linux/kernel/) and only come with references from 1996!

What is the state of Posix-compliant services (threads, semaphores, timers, etc.) in the current (v2.2/v2.4) Linux kernels?

Thank you.

PLANET PROJECT will connect millions of people worldwide through the combined technology of 3Com and the Internet. Find out more and register now at
http://www.planetproject.com

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/

#1 lore raw
Quoted 6 lines · [email protected] wrote:

Sorry if this is a FAQ, but I've searched the archives for this list
(http://www.uwsg.iu.edu/hypermail/linux/kernel/) and only come with references from 1996!

What is the state of Posix-compliant services (threads, semaphores, timers, etc.) in the current (v2.2/v2.4) Linux kernels?

IMHO this is a question better asked of glibc people, not kernel people.

The kernel does its best to facilitate POSIX compliances, but in some cases the kernel developers have said "POSIX is braindead here!" and solved a particular problem in a non-POSIX way. [and leaves glibc to pick up the pieces, and enforce POSIX compliancy]

Also, from what I've seen lately on IRC and lkml, the Single Unix Specification ("SuS") is generally held in higher regard than POSIX; and when spec questions arise, kernel developers tend to check SuS before POSIX (if POSIX is checked at all).

Jeff

Signature · 7 lines
Jeff Garzik             |
Building 1024           | The chief enemy of creativity is "good" sense
MandrakeSoft            |          -- Picasso
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/
#2 lore raw
In reply to [email protected]
Quoted 11 lines · Jeff Garzik
Quoted 6 lines · [email protected] wrote:

Sorry if this is a FAQ, but I've searched the archives for this list
(http://www.uwsg.iu.edu/hypermail/linux/kernel/) and only come with references from 1996!

What is the state of Posix-compliant services (threads, semaphores, timers, etc.) in the current (v2.2/v2.4) Linux kernels?

IMHO this is a question better asked of glibc people, not kernel people.

The kernel does its best to facilitate POSIX compliances,

Well, it does not do its best. There are several areas where kernel should help, things like POSIX semaphores would be much faster with kernel support, likewise threads if some things Ulrich stated here a couple of months ago were done in the kernel, POSIX message queue passing is not doable in userland without kernel help either (I have a message queue filesystem kernel patch for this, but it is a 2.5 thing).

Jakub
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/

#3 lore raw

At Mon, 13 Nov 2000 11:13:19 -0500,

Quoted 3 lines · Jakub Jelinek

ago were done in the kernel, POSIX message queue passing is not doable in userland without kernel help either (I have a message queue filesystem kernel patch for this, but it is a 2.5 thing).

Interesting. Is yours ready for?
(I'm also working with it. I agree it's for 2.5)

Regards,
-- GOTO Masanori
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/

#4 lore raw
In reply to [email protected]
Quoted 4 lines · Jakub Jelinek

Well, it does not do its best. There are several areas where kernel should help, things like POSIX semaphores would be much faster with kernel support, likewise threads if some things Ulrich stated here a couple of months ago were done in the kernel,

Would it be reasonable to have these needs documented in a central location, with patches attached where possible?

Making people other than Linus aware of the technical issues can only benefit the cause of POSIX compliancy, IMHO...

Quoted 3 lines

POSIX message queue passing is not doable in
userland without kernel help either (I have a message queue filesystem kernel patch for this, but it is a 2.5 thing).

If its small and standalone and doesn't touch existing infrastructure...

Regards,

Jeff

Signature · 7 lines
Jeff Garzik             |
Building 1024           | The chief enemy of creativity is "good" sense
MandrakeSoft            |          -- Picasso
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/
#5 lore raw
In reply to [email protected]
Quoted 4 lines · Jeff Garzik

Also, from what I've seen lately on IRC and lkml, the Single Unix Specification ("SuS") is generally held in higher regard than POSIX; and when spec questions arise, kernel developers tend to check SuS before POSIX (if POSIX is checked at all).

POSIX is the law, but many things are not covered.
SUSv2 is a large collection of random stuff.
The Austin group now prepares a joint revision of POSIX.1 and POSIX.2 and SUSv2. This is to be the next version of all standards involved.
See also http://www.opengroup.org/austin/
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/

#6 lore raw
In reply to [email protected]
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"J" == Jeff Garzik <[email protected]> writes:

J> Would it be reasonable to have these needs documented in a J> central location, with patches attached where possible?

http://kernelbook.sourceforge.net:80/wiki/?LinuxAndPosixCompliance

The lead-in discussion has been snipped and inserted under the more general topic http://kernelbook.sourceforge.net:80/wiki/?LinuxVsUnix

Signature · 8 lines
Gary Lawrence Murphy <[email protected]>: office voice/fax: 01 519 4222723
T(!c)Inc Business Innovation through Open Source http://www.teledyn.com
M:I-3 - Documenting the Linux kernel: http://kernelbook.sourceforge.net
"You don't play what you know; you play what you hear." --- Miles Davis
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/
#7 lore raw
In reply to [email protected]
Quoted 4 lines · Jeff Garzik

Also, from what I've seen lately on IRC and lkml, the Single Unix Specification ("SuS") is generally held in higher regard than POSIX; and when spec questions arise, kernel developers tend to check SuS before POSIX (if POSIX is checked at all).

One reason for this: You can read SuS online from the net, but you have to buy your copy of the POSIX standards before you could look into it.

But POSIX compliance is fortunatly noted in the man pages ;-)

Regards

Ingo Oeser

Signature · 7 lines
To the systems programmer, users and applications
serve only to provide a test load.
<esc>:x
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/
#8 lore raw

POSIX message queue passing (was Re: State of Posix compliance in v2.2/v2.4 kernel?)

In reply to [email protected]
Quoted 8 lines · GOTO Masanori

At Mon, 13 Nov 2000 11:13:19 -0500,

Quoted 3 lines · Jakub Jelinek

ago were done in the kernel, POSIX message queue passing is not doable in userland without kernel help either (I have a message queue filesystem kernel patch for this, but it is a 2.5 thing).

Interesting. Is yours ready for?
(I'm also working with it. I agree it's for 2.5)

Below is my preliminary version from Sep, 16th if you're interested. I haven't had time for it since then, so it most probably will not apply cleanly to current kernel.
Things still to do:
- clean it up
- implement poll on message queues
- handle __SI_RT in architectural copy_siginfo_to_user routines
- test much more than I have done so far
- fix mq_notify - see below
- avoid doing linear searches - see below

Message queues are presented as a new filesystem, mounted usually on /dev/msg. The objects in that filesystems are fifos with special MQ semantics.
One can use normal open/read/write on fifos in /dev/msg, which means mq_open with mq_attr NULL, mq_receive which does not tell the priority and mq_send with default priority.
Then there are a few ioctls which allow to open with special queue attributes, send with priority and receive so that you get priority back, etc.
Things I'm not sure about is mq_notify, because it states the signal should be sent to the process (ie. I'd think it is tgid, not pid in 2.4.0-test8, but then I don't know which close/exit should cause the notification registration to be freed).
Also, I wonder how many pending messages typical message queues have pending, if not too many, then the current linear search is fine, otherwise I should put the messages into some heap which would allow O(1) mq_receive. If you find any races/problems, please let me know.

I've coded mqueue.h public glibc userland header and mqueue.c which has hacks on top and then basically what could end up in glibc's mq_*.c (after shm_open.c code for locating mount points is copied in).

Jakub

Documentation/ioctl-number.txt renamed from Documentation/ioctl-number.txt.jj +1 -0
@@ -183,5 +183,6 @@ Code	Seq#	Include File		Comments
 0xB0	all	RATIO devices		in development:
 					<mailto:[email protected]>
 0xB1	00-1F	PPPoX			<mailto:[email protected]>
+0xB2	00-1F	linux/mqueue.h
 0xCB	00-1F	CBM serial IEC bus	in development:
 					<mailto:[email protected]>
include/asm-alpha/siginfo.h renamed from include/asm-alpha/siginfo.h.jj +1 -1
@@ -104,7 +104,7 @@ typedef struct siginfo {
 #define SI_KERNEL	0x80		/* sent by the kernel from somewhere */
 #define SI_QUEUE	-1		/* sent by sigqueue */
 #define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
-#define SI_MESGQ	-3		/* sent by real time mesq state change */
+#define SI_MESGQ __SI_CODE(__SI_RT,-3)	/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
 
include/asm-arm/siginfo.h renamed from include/asm-arm/siginfo.h.jj +1 -1
@@ -104,7 +104,7 @@ typedef struct siginfo {
 #define SI_KERNEL	0x80		/* sent by the kernel from somewhere */
 #define SI_QUEUE	-1		/* sent by sigqueue */
 #define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
-#define SI_MESGQ	-3		/* sent by real time mesq state change */
+#define SI_MESGQ __SI_CODE(__SI_RT,-3)	/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
 
include/asm-i386/siginfo.h renamed from include/asm-i386/siginfo.h.jj +1 -1
@@ -104,7 +104,7 @@ typedef struct siginfo {
 #define SI_KERNEL	0x80		/* sent by the kernel from somewhere */
 #define SI_QUEUE	-1		/* sent by sigqueue */
 #define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
-#define SI_MESGQ	-3		/* sent by real time mesq state change */
+#define SI_MESGQ __SI_CODE(__SI_RT,-3)	/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
 
include/asm-ia64/siginfo.h renamed from include/asm-ia64/siginfo.h.jj +1 -1
@@ -113,7 +113,7 @@ typedef struct siginfo {
 #define SI_KERNEL	0x80		/* sent by the kernel from somewhere */
 #define SI_QUEUE	-1		/* sent by sigqueue */
 #define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
-#define SI_MESGQ	-3		/* sent by real time mesq state change */
+#define SI_MESGQ __SI_CODE(__SI_RT,-3)	/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
 
include/asm-m68k/siginfo.h renamed from include/asm-m68k/siginfo.h.jj +1 -1
@@ -104,7 +104,7 @@ typedef struct siginfo {
 #define SI_KERNEL	0x80		/* sent by the kernel from somewhere */
 #define SI_QUEUE	-1		/* sent by sigqueue */
 #define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
-#define SI_MESGQ	-3		/* sent by real time mesq state change */
+#define SI_MESGQ __SI_CODE(__SI_RT,-3)	/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
 
include/asm-mips/siginfo.h renamed from include/asm-mips/siginfo.h.jj +1 -1
@@ -125,7 +125,7 @@ typedef struct siginfo {
 #define SI_QUEUE	-1	/* sent by sigqueue */
 #define SI_ASYNCIO	-2	/* sent by AIO completion */
 #define SI_TIMER __SI_CODE(__SI_TIMER,-3) /* sent by timer expiration */
-#define SI_MESGQ	-4	/* sent by real time mesq state change */
+#define SI_MESGQ __SI_CODE(__SI_RT,-4)	/* sent by real time mesq state change */
 #define SI_SIGIO	-5	/* sent by queued SIGIO */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
include/asm-mips64/siginfo.h renamed from include/asm-mips64/siginfo.h.jj +1 -1
@@ -125,7 +125,7 @@ typedef struct siginfo {
 #define SI_QUEUE	-1	/* sent by sigqueue */
 #define SI_ASYNCIO	-2	/* sent by AIO completion */
 #define SI_TIMER __SI_CODE(__SI_TIMER,-3) /* sent by timer expiration */
-#define SI_MESGQ	-4	/* sent by real time mesq state change */
+#define SI_MESGQ __SI_CODE(__SI_RT,-4)	/* sent by real time mesq state change */
 #define SI_SIGIO	-5	/* sent by queued SIGIO */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
include/asm-ppc/siginfo.h renamed from include/asm-ppc/siginfo.h.jj +1 -1
@@ -104,7 +104,7 @@ typedef struct siginfo {
 #define SI_KERNEL	0x80		/* sent by the kernel from somewhere */
 #define SI_QUEUE	-1		/* sent by sigqueue */
 #define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
-#define SI_MESGQ	-3		/* sent by real time mesq state change */
+#define SI_MESGQ __SI_CODE(__SI_RT,-3)	/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
 
include/asm-sh/siginfo.h renamed from include/asm-sh/siginfo.h.jj +1 -1
@@ -104,7 +104,7 @@ typedef struct siginfo {
 #define SI_KERNEL	0x80		/* sent by the kernel from somewhere */
 #define SI_QUEUE	-1		/* sent by sigqueue */
 #define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
-#define SI_MESGQ	-3		/* sent by real time mesq state change */
+#define SI_MESGQ __SI_CODE(__SI_RT,-3)	/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
 
include/asm-sparc/siginfo.h renamed from include/asm-sparc/siginfo.h.jj +1 -1
@@ -109,7 +109,7 @@ typedef struct siginfo {
 #define SI_KERNEL	0x80		/* sent by the kernel from somewhere */
 #define SI_QUEUE	-1		/* sent by sigqueue */
 #define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
-#define SI_MESGQ	-3		/* sent by real time mesq state change */
+#define SI_MESGQ __SI_CODE(__SI_RT,-3)	/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
 
include/asm-sparc64/siginfo.h renamed from include/asm-sparc64/siginfo.h.jj +1 -1
@@ -169,7 +169,7 @@ typedef struct siginfo32 {
 #define SI_KERNEL	0x80		/* sent by the kernel from somewhere */
 #define SI_QUEUE	-1		/* sent by sigqueue */
 #define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
-#define SI_MESGQ	-3		/* sent by real time mesq state change */
+#define SI_MESGQ __SI_CODE(__SI_RT,-3)	/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
 
include/linux/mqueue.h renamed from include/linux/mqueue.h.jj +37 -0
@@ -0,0 +1,37 @@
+#ifndef _LINUX_MQUEUE_H
+#define _LINUX_MQUEUE_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <asm/siginfo.h>
+
+struct mq_attr {
+	long		mq_flags;	/* O_NONBLOCK or 0 */
+	long		mq_maxmsg;	/* Maximum number of messages in the queue */
+	long		mq_msgsize;	/* Maximum size of one message in bytes */
+	long		mq_curmsgs;	/* Current number of messages in the queue */
+	long		__pad[2];
+};
+
+struct mq_open {
+	char		*mq_name;	/* pathname */
+	int		mq_oflag;	/* flags */
+	mode_t		mq_mode;	/* mode */
+	struct mq_attr	mq_attr;	/* attributes */
+};
+
+struct mq_sndrcv {
+	size_t		mq_len;		/* message length */
+	long		mq_type;	/* message type */
+	char		*mq_buf;	/* message buffer */
+};
+
+#define MQ_OPEN		_IOW(0xB2, 0, struct mq_open)
+#define MQ_GETATTR	_IOR(0xB2, 1, struct mq_attr)
+#define MQ_SEND		_IOW(0xB2, 2, struct mq_sndrcv)
+#define MQ_RECEIVE	_IOWR(0xB2, 3, struct mq_sndrcv)
+#define MQ_NOTIFY	_IOW(0xB2, 4, struct sigevent)
+
+#define MQ_DEFAULT_TYPE	0x7FFFFFFE
+
+#endif /* _LINUX_MQUEUE_H */
ipc/msg.c renamed from ipc/msg.c.jj +954 -177

1,343 lines not on this page · raw message

#ifndef _MQUEUE_H
#define _MQUEUE_H

#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>

typedef int mqd_t;

struct mq_attr {

  long  mq_flags;	/* O_NONBLOCK or 0 */
  long  mq_maxmsg;	/* Maximum number of messages in the queue */
  long  mq_msgsize;	/* Maximum size of one message in bytes */
  long  mq_curmsgs;	/* Current number of messages in the queue */
  long  __pad[2];

};

#define MQ_PRIO_MAX 0x7FFFFFFE

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 *);
int mq_unlink (const char *);

#endif /* mqueue.h */

#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <alloca.h>

struct mq_attr {
long mq_flags; /* O_NONBLOCK or 0 */
long mq_maxmsg; /* Maximum number of messages in the queue */
long mq_msgsize; /* Maximum size of one message in bytes */
long mq_curmsgs; /* Current number of messages in the queue */
long __pad[2];
};

struct mq_open {
	char		*mq_name;	/* pathname */
	int		mq_oflag;	/* flags */
	unsigned short	mq_mode;	/* mode */
	struct mq_attr	mq_attr;	/* attributes */
};
struct mq_sndrcv {
	size_t		mq_len;		/* message length */
	long		mq_type;	/* message type */
	char		*mq_buf;	/* message buffer */
};

#define MQ_OPEN _IOW(0xB2, 0, struct mq_open)
#define MQ_GETATTR _IOR(0xB2, 1, struct mq_attr)
#define MQ_SEND _IOW(0xB2, 2, struct mq_sndrcv)
#define MQ_RECEIVE _IOWR(0xB2, 3, struct mq_sndrcv)
#define MQ_NOTIFY _IOW(0xB2, 4, struct sigevent)

#define MQ_PRIO_MAX 0x7FFFFFFE

typedef int mqd_t;

/* *********** */
#ifndef __set_errno
#define __set_errno(x) errno = x
#endif
#ifndef __memcpy
#define __memcpy(x,y,z) memcpy(x,y,z)
#endif
#ifndef __mempcpy
#define __mempcpy(x,y,z) mempcpy(x,y,z)
#endif
#ifndef __ioctl
#define __ioctl(x,y,z) ioctl(x,y,z)
#endif
#undef __libc_once
#define __libc_once(x,y) do { } while (0)
/* *********** */

/* Mount point of the shared memory filesystem. */ static struct
{
char *dir;
size_t dirlen;
} mountpoint
= { "/dev/msg/", 9 };

mqd_t mq_open (const char *name, int oflag, ...)
{
size_t namelen;
char *fname, *p;
int fd;
mqd_t ret;
mode_t mode = 0;
struct mq_attr *attr = NULL;
struct mq_open open_arg;

/* Determine where the msgfs is mounted. */
__libc_once (once, where_is_msgfs);

  /* If we don't know the mount points there is nothing we can do.  Ever.  */
  if (mountpoint.dir == NULL)
    {
      __set_errno (ENOSYS);
      return -1;
    }

/* Construct the filename. */
while (name[0] == '/')

    ++name;
  if (name[0] == '\0')
    {
      /* The name "/" is not supported.  */
      __set_errno (EINVAL);
      return -1;
    }
                                                                      
  namelen = strlen (name);
  fname = (char *) alloca (mountpoint.dirlen + namelen + 1);
  p = __mempcpy (fname, mountpoint.dir, mountpoint.dirlen);

  if (oflag & O_CREAT)
    {
      va_list ap;
      va_start (ap, oflag);
      /* Get the arguments.  */
      mode = va_arg (ap, mode_t);
      attr = va_arg (ap, struct mq_attr *);
      va_end (ap);

      if (attr != NULL)
	{
	  p[0] = '.';
	  p[1] = '\0';
	  fd = open (fname, O_RDONLY);

	  if (fd < 0)
	    {
	      __set_errno (ENOSYS);
	      return -1;
	    }

	  __memcpy (p, name, namelen + 1);
	  open_arg.mq_name = fname;
	  open_arg.mq_oflag = oflag;
	  open_arg.mq_mode = mode;
	  open_arg.mq_attr = *attr;

	  ret = __ioctl (fd, MQ_OPEN, &open_arg);
	  if (ret < 0 && errno == ENOTTY)
	    __set_errno (ENOSYS);

	  close (fd);
	  return ret;
	}
    }

__memcpy (p, name, namelen + 1);
return open (fname, oflag, mode);
}

int mq_close (mqd_t mqdes)
{
return close (mqdes);
}

int mq_send (mqd_t mqdes, const char *buf, size_t len, unsigned int prio) {
struct mq_sndrcv send_req;

  if (prio > MQ_PRIO_MAX)
    {
      __set_errno (EINVAL);
      return -1;
    }

  send_req.mq_buf = (char *)buf;
  send_req.mq_len = len;
  send_req.mq_type = MQ_PRIO_MAX - prio;

return __ioctl (mqdes, MQ_SEND, &send_req);
}

ssize_t mq_receive (mqd_t mqdes, char *buf, size_t len, unsigned int *prio) {
struct mq_sndrcv recv_req;
ssize_t ret;

  recv_req.mq_buf = buf;
  recv_req.mq_len = len;
  recv_req.mq_type = -MQ_PRIO_MAX;

  ret = __ioctl (mqdes, MQ_RECEIVE, &recv_req);

  if (!ret && prio != NULL)
    *prio = MQ_PRIO_MAX - recv_req.mq_type;

return ret;
}

int mq_unlink (const char *name)
{
size_t namelen;
char *fname;

/* Determine where the msgfs is mounted. */
__libc_once (once, where_is_msgfs);

if (mountpoint.dir == NULL)

    {
      /* We cannot find the shmfs.  If `name' is really a message
         queue object it must have been created by another process
         and we have no idea where that process found the mountpoint.  */
      __set_errno (ENOENT);
      return -1;
    }

/* Construct the filename. */
while (name[0] == '/')

    ++name;
  if (name[0] == '\0')
    {
      /* The name "/" is not supported.  */
      __set_errno (ENOENT);
      return -1;
    }

  namelen = strlen (name);
  fname = (char *) alloca (mountpoint.dirlen + namelen + 1);
  __mempcpy (__mempcpy (fname, mountpoint.dir, mountpoint.dirlen),
             name, namelen + 1);

/* And get the file descriptor. */
return unlink (fname);
}

int mq_getattr (mqd_t mqdes, const struct mq_attr *mqstat) {
return __ioctl (mqdes, MQ_GETATTR, mqstat);
}

int mq_setattr (mqd_t mqdes, const struct mq_attr *mqstat,
struct mq_attr *omqstat)
{
int ret;

if (omqstat != NULL)

    {
      ret = __ioctl (mqdes, MQ_GETATTR, omqstat);
      if (ret)
	return ret;
    }
  ret = fcntl (mqdes, F_GETFL);
  if (ret == -1)
    return ret;

if ((ret ^ mqstat->mq_flags) & O_NONBLOCK)

    {
      ret = fcntl (mqdes, F_SETFL, (ret & ~O_NONBLOCK)
				   | (mqstat->mq_flags & O_NONBLOCK));
      if (ret == -1)
	return ret;
    }

return 0;
}

int mq_notify (mqd_t mqdes, const struct sigevent *notification) {
struct sigevent null_notify, *n;

n = (struct sigevent *)notification;
if (notification == NULL)

    {
      null_notify.sigev_notify = SIGEV_NONE;
      n = &null_notify;
    }
  else if (notification->sigev_notify != SIGEV_NONE
	   && notification->sigev_notify != SIGEV_SIGNAL)
    {
      __set_errno (EINVAL);
      return -1;
    }

return __ioctl (mqdes, MQ_NOTIFY, notification);
}