All of lore.kernel.org
 help / color / mirror / Atom feed
From: Manfred Spraul <manfred@colorfullife.com>
To: "David S. Miller" <davem@redhat.com>
Cc: akpm@osdl.org, linux-arch@vger.kernel.org
Subject: Re: posix message queues
Date: Sat, 10 Apr 2004 13:19:45 +0200	[thread overview]
Message-ID: <4077D851.7000008@colorfullife.com> (raw)
In-Reply-To: <20040409164506.0611846a.davem@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 1169 bytes --]

David S. Miller wrote:

>On Wed, 07 Apr 2004 21:15:44 +0200
>Manfred Spraul <manfred@colorfullife.com> wrote:
>
>  
>
>>No. The unix spec mandates 'long' for the final C-library api. Using u32 
>>would mean that glibc would have to add an emulation layer in user space 
>>for 64-bit archs. In the long run, 64-bit kernels running 64-bit apps 
>>will be the common case. I don't want to add an emulation layer to the 
>>common case.
>>    
>>
>
>We need to support this stuff when running 32-bit apps, you cannot
>avoid this Manfred.
>
Of course. But the compat stuff is only used if a 32-bit app runs on a 
64-bit kernel. If I'd use u32 for the kernel interface, then a compat 
wrappers would be necessary if a 64-bit app runs on a 64-bit kernel, and 
that would be the wrong thing.

>  So we'll need kernel compat layer code to
>translate these structures containing 'long'.  Please code up the
>necessary compat.c code for this posix message queues feature.
>  
>
Arndt did 90% of the coding, it's already in 2.6.5-mm3. The only missing 
part was the SIGEV_THREAD handling, I've attached a patch that adds 
this, together a small user space test app.

--
    Manfred

[-- Attachment #2: mq_test.c --]
[-- Type: text/x-csrc, Size: 9849 bytes --]

/*
 * Test app for Linux Kernel posix message queues.
 *
 * Copyright (C) 2004 Manfred Spraul
 *
 * Redistribution of this file is permitted under the terms of the GNU 
 * Public License (GPL)
 * $Header: /home/manfred/cvs-tree/mq/mq_test.c,v 1.3 2004/04/10 11:17:31 manfred Exp $
 */
#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <string.h>
#include <limits.h>


/*
 * Kernel-interface based on the Mqueue library:
 *
 * Copyright (C) 2003 Krzysztof Benedyczak & Michal Wronski

   This program 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.

   It 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 this software; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.
 */

/****************** implementation *****************/

#define __NR_mq_open		277

#define __NR_mq_unlink		(__NR_mq_open+1)
#define __NR_mq_timedsend	(__NR_mq_open+2)
#define __NR_mq_timedreceive	(__NR_mq_open+3)
#define __NR_mq_notify		(__NR_mq_open+4)
#define __NR_mq_getsetattr	(__NR_mq_open+5)


#define MQ_PRIO_MAX 	32768

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	*/
	long	__reserved[4];	/* unused */
};

#include <signal.h>
#include <fcntl.h>
#include <time.h>
#include <stdarg.h>

mqd_t mq_open(const char *name, int oflag, /* mode_t mode, struct mq_attr *attr */ ...);
int mq_close(mqd_t mqdes);
int mq_unlink(const char *name);
int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio);
int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout);
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);
ssize_t mq_timedreceive(mqd_t mqdes, char *__restrict msg_ptr, size_t msg_len, unsigned int *__restrict msg_prio, const struct timespec *__restrict abs_timeout);
int mq_notify(mqd_t mqdes, const struct sigevent *notification);
int mq_getattr(mqd_t mqdes, struct mq_attr *mqstat);
int mq_setattr(mqd_t mqdes, const struct mq_attr *__restrict mqstat, struct mq_attr *__restrict omqstat);

/*
 * kernel interfaces.  We use glibc's syscall(3) instead of the macros
 * _syscall1, _syscall2, etc, as the macros generate compilation errors
 * when mqueue.c is built as a dynamic shared library.
 */
static inline mqd_t __mq_open(const char  *name,
				int oflag, mode_t mode, struct mq_attr* attr)
{
	return syscall(__NR_mq_open, name, oflag, mode, attr);
}

static inline int __mq_unlink(const char *name)
{
	return syscall(__NR_mq_unlink, name);
}

static inline int __mq_notify(mqd_t mqdes, const struct sigevent *notification)
{
	return syscall(__NR_mq_notify, mqdes, notification);
}

static inline int __mq_getsetattr(mqd_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat)
{
	return syscall(__NR_mq_getsetattr, mqdes, mqstat, omqstat);
}

static inline int __mq_timedsend(mqd_t mqdes, const char *msg_ptr,
				size_t msg_len, unsigned int msg_prio,
				const struct timespec *abs_timeout)
{
	return syscall(__NR_mq_timedsend, mqdes, msg_ptr, msg_len,
		msg_prio, abs_timeout);
}

static inline ssize_t __mq_timedreceive(mqd_t mqdes, char *msg_ptr,
				size_t msg_len, unsigned int *msg_prio,
				const struct timespec *abs_timeout)
{
	return syscall(__NR_mq_timedreceive, mqdes, msg_ptr, msg_len,
		msg_prio, abs_timeout);
}

static inline int is_valid_path(const char *name)
{
	if (name[0] != '/') {
		errno = EINVAL;
		return -1;
	}
	return 0;
}
/*
 * application-visible wrappers around the kernel interfaces
 */

mqd_t mq_open(const char *name, int oflag, ...)
{
	unsigned long 	mode;
	struct mq_attr 	*attr;
	va_list 	ap;

	va_start(ap, oflag);
	mode = va_arg(ap, unsigned long);
	attr = va_arg(ap, struct mq_attr *);
	va_end(ap);

	if (is_valid_path(name) < 0)
		return (mqd_t)-1;

	/* omit leading slash */
	return __mq_open(name + 1, oflag, mode, attr);
}

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

int mq_unlink(const char *name)
{
	if (is_valid_path(name) < 0)
		return -1;
	
	return __mq_unlink(name+1);
}

int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
					unsigned int msg_prio)
{
	return __mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, NULL);
}

ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len,
					unsigned int *msg_prio)
{
	return __mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, NULL);
}

int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
					unsigned int msg_prio,
					const struct timespec *abs_timeout)
{
	return __mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, abs_timeout);
}

ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len,
					unsigned int *msg_prio,
					const struct timespec *abs_timeout)
{
	return __mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio,
		abs_timeout);
}

int mq_getattr(mqd_t mqdes, struct mq_attr *mqstat)
{
	return __mq_getsetattr(mqdes, NULL, mqstat);
}

int mq_setattr( mqd_t mqdes, const struct mq_attr *mqstat,
					struct mq_attr *omqstat)
{
	return __mq_getsetattr(mqdes, mqstat, omqstat);
}

int mq_notify(mqd_t mqdes, const struct sigevent *notification)
{
	return __mq_notify(mqdes, notification);
}

int got_signal = 0;
void usr1_handler(int unused)
{
	printf("usr1 signal caught.\n");
	got_signal = 1;
}

char buffer[131072];

int main(int argc, char **argv)
{
static const char qname[] = "/test_123";
        int err;
        mqd_t m, m2;
	struct mq_attr ma;

	printf("Test 1: mq_open()\n");
	m = mq_open(qname, O_CREAT|O_RDWR, S_IRUSR | S_IWUSR, NULL);
	if (m == -1) {
	        printf("mq_open() failed,  errno %d.\n", errno);
		return 1;
	}

	printf("Test 2: check exclusive open()\n");
	m2 = mq_open(qname, O_EXCL|O_CREAT|O_RDWR, S_IRUSR | S_IWUSR, NULL);
	if (m2 != -1 || errno != EEXIST) {
	        printf("mq_open() succeeded or wrong errno (%d).\n", errno);
		return 1;
	}

	printf("Test 3: close handle\n");
	err = mq_close(m);

	if (err) {
		printf("mq_close() failed.\n");
	}

	printf("Test 4: mq_unlink\n");
	err = mq_unlink(qname);
	if (err) {
	        printf("mq_unlink() failed,  errno %d.\n", errno);
		return 1;
	}

	printf("Test 4: mq_unlink on nonexisting file\n");
	err = mq_unlink(qname);
	if (err != -1 || errno != ENOENT) {
	        printf("mq_unlink() failed,  errno %d.\n", errno);
		return 1;
	}

	printf("Test 5: mq_open()\n");
	m = mq_open(qname, O_CREAT|O_EXCL|O_RDWR, S_IRUSR | S_IWUSR, NULL);
	if (m == -1) {
	        printf("mq_open() failed,  errno %d.\n", errno);
		return 1;
	}

	printf("Test 6: mq_getattr()\n");
	err = mq_getattr(m, &ma);
	if (err || ma.mq_curmsgs != 0) {
	        printf("mq_getattr() failed,  errno %d, curmsg %ld.\n", errno, ma.mq_curmsgs);
		return 1;
	}

	printf("Test 7: setup signal based notify().\n");

	signal (SIGUSR1,usr1_handler);

	struct sigevent event;
	event.sigev_notify = SIGEV_SIGNAL;
	event.sigev_signo = SIGUSR1;
	err = mq_notify(m, &event);
	if (err) {
	        printf("mq_notify() failed,  errno %d.\n", errno);
		return 1;
	}

	printf("Test 8: mq_send()\n");
	err = mq_send(m, qname, strlen(qname), 1);
	if (err) {
	        printf("mq_send() failed,  errno %d.\n", errno);
		return 1;
	}
	if (!got_signal) {
		printf("No signal received.\n");
		return 1;
	}

	printf("Test 9: mq_getattr() with one pending message\n");
	err = mq_getattr(m, &ma);
	if (err || ma.mq_curmsgs != 1) {
	        printf("mq_getattr() failed,  errno %d, curmsg %ld.\n", errno, ma.mq_curmsgs);
		return 1;
	}

	printf("Test 10: mq_receive()\n");
	err = mq_receive(m, buffer, sizeof(buffer), NULL);
	if (err < 0) {
	        printf("mq_receive() failed,  errno %d.\n", errno);
		return 1;
	}

	printf("Test 11: data comparison\n");
	if (strcmp(qname, buffer)) {
		printf("Data mismatch!!!.\n");
		return 1;
	}

	printf("Test 12: request notification cookie.\n");
	{
		int fd, i;
		char inc[32], outc[64];


		fd = socket(PF_NETLINK, SOCK_RAW, 0);
		if (fd == -1) {
			printf("opening netlink socket failed, errno %d.\n", errno);
			return 1;
		}

		for (i=0;i<32;i++)
			inc[i] = 64+2*i;

		event.sigev_notify = SIGEV_THREAD;
		event.sigev_signo = fd;
		event.sigev_value.sival_ptr = inc;
		err = mq_notify(m, &event);
		if (err < 0) {
			 printf("mq_notify() failed,  errno %d.\n", errno);
			return 1;
		}
		err = mq_send(m, qname, strlen(qname), 1);
		if (err) {
		        printf("mq_send() failed,  errno %d.\n", errno);
			return 1;
		}
		err = recv(fd, outc, sizeof(outc), MSG_NOSIGNAL|MSG_DONTWAIT);
		if (err != 32) {
			printf("recv unexpected result %d, errno %d.\n", err, errno);
			return 1;
		}
		for (i=0;i<31;i++) {
			if (outc[i] != 64+2*i) {
				printf("Data mismatch in cookie at offset %d: %d.\n",
						i, outc[i]);
				return 1;
			}
		}
		if (outc[31] != 1) {
			printf("state mismatch in cookie: got %d.\n", outc[31]);
		}
	}

	printf("Test 13: another mq_unlink\n");
	err = mq_unlink(qname);
	if (err) {
	        printf("mq_unlink() failed,  errno %d.\n", errno);
		return 1;
	}

	printf("Test 14: mq_close()\n");
	err = mq_close(m);
	if (err) {
		printf("mq_close() failed, errno %d.\n", errno);
		return 1;
	}
	return 0;
}

[-- Attachment #3: patch-mqueue-compat --]
[-- Type: text/plain, Size: 793 bytes --]

// $Header$
// Kernel Version:
//  VERSION = 2
//  PATCHLEVEL = 6
//  SUBLEVEL = 5
//  EXTRAVERSION = -mm3
--- 2.6/ipc/compat_mq.c	2004-04-10 09:59:40.000000000 +0200
+++ build-2.6/ipc/compat_mq.c	2004-04-10 13:15:40.414231437 +0200
@@ -139,6 +139,7 @@
 {
 	mm_segment_t oldfs;
 	struct sigevent notification;
+	char cookie[NOTIFY_COOKIE_LEN];
 	long ret;
 
 	if (!u_notification)
@@ -147,6 +148,14 @@
 	if (get_compat_sigevent(&notification, u_notification))
 		return -EFAULT;
 
+	if (notification.sigev_notify == SIGEV_THREAD) {
+		if (copy_from_user(cookie, u_notification.sigev_value.sival_ptr,
+					NOTIFY_COOKIE_LEN)) {
+			return -EFAULT;
+		}
+		notification.sigev_value.sival_ptr = cookie;
+	}
+
 	oldfs = get_fs();
 	set_fs(KERNEL_DS);
 	ret = sys_mq_notify(mqdes, &notification);

  reply	other threads:[~2004-04-10 11:45 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-04-07 19:07 posix message queues Andrew Morton
2004-04-07 19:15 ` Manfred Spraul
2004-04-08  8:17   ` Arnd Bergmann
2004-04-08  8:49     ` Andrew Morton
2004-04-08 14:08     ` Manfred Spraul
2004-04-08 20:24     ` Andrew Morton
2004-04-09 23:45   ` David S. Miller
2004-04-10 11:19     ` Manfred Spraul [this message]
2004-04-10 11:53       ` Manfred Spraul
2004-04-10 20:43         ` Arnd Bergmann
  -- strict thread matches above, loose matches on Subject: below --
2010-09-02  9:51 POSIX Message Queues Ardhan Madras
2010-06-15  3:34 Ardhan Madras
2010-06-15 15:33 ` Glynn Clements
2010-06-12  9:10 Ardhan Madras
2010-06-12 13:40 ` Glynn Clements
2004-04-08 22:22 posix message queues Arnd Bergmann
2003-10-07  7:50 POSIX " Peter Waechtler
2003-10-07  8:11 ` Jakub Jelinek
2003-10-05  9:13 Krzysztof Benedyczak
2003-10-05 10:11 ` Manfred Spraul
2003-10-06 19:04   ` Krzysztof Benedyczak
2003-10-05 16:35 ` Ulrich Drepper
2003-10-05 18:16   ` Jamie Lokier
2003-10-05 18:32     ` Jakub Jelinek
2003-10-05 19:18       ` Jamie Lokier
2003-10-05 21:52         ` Ulrich Drepper
2002-10-02 10:35 Krzysztof Benedyczak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4077D851.7000008@colorfullife.com \
    --to=manfred@colorfullife.com \
    --cc=akpm@osdl.org \
    --cc=davem@redhat.com \
    --cc=linux-arch@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.