Compare commits

...

10 commits

Author SHA1 Message Date
Sanchayan Maity 368b5fc155 Initialise the "name" variable properly and compare all 32 bytes
Without this patch, calling sys_mq_open() with same names specified
results in two separate queues being opened and their descriptors
returned instead of the same descriptor being returned for both.

Do the initialisation and comparison properly, so that when the
same name is specified to sys_mq_open multiple times in same
process or different process, the same opened queue descriptor is
returned.
2016-03-23 11:11:30 +05:30
Sanchayan Maity 8501cb7ed8 Allow users to request a asynchronous notification
This patch adds functionality to request an asynchronous notification
if some other process has send a message to it. We currently send a
SIGALRM to avoid any changes to core infrastructure of signal handling.
Ideally we should implement a separate signal for this. Currently there
is an obvious disadvantage of not being able to use SIGALRM with alarm,
if we are using this functionality.
2016-03-22 17:51:09 +05:30
Sanchayan Maity 55d341bc54 Allow users to get and set attributes
Currently we only allow users to get and set number of queues. The
operation is always non blocking. There is no provision for non
blocking operation at the moment.

The queue sizes are set to MAX 256 by default. If a user changes the
attributes and sets the queue size or number of messages in a queue
to less than 256, it is the responsibility of the user to close any
queues which were opened with a descriptor greater than the value
currently set.

For example, by default queue sizes are 256. If 150 queues are opened
and then the user sets the number of queues to 32, all open descriptors
and queues from 32 to 150 must be closed. Note that descriptor number
allocation starts with zero and not one.
2016-03-22 15:57:53 +05:30
Sanchayan Maity d84b3d9248 Miscellaneous cleanup 2016-03-19 17:42:29 +05:30
Sanchayan Maity 0cc443d3c2 Fix message priority implementation
Functional specification mandates returning a message with a higher
timestamp in case two messages have the same priority. Somehow we
missed this in the implementation. This also introduced a bug where
all messages with same priority could cause problems.
2016-03-19 16:54:26 +05:30
Sanchayan Maity fe71ea4bc1 First round of assorted bug fixes
Fixed the following bugs:
1. Message priority was not set at all at two places
2. Limits check was not correct while returning error values
3. We are suppose to allow multiple users operate on the same queue
using a named descriptor. However any one user calling close before
the other would result in closing the queue even when other users
might be using it. Track number of users and close only if number of
users is zero. Yet to do functional tests for this, so this is untested,
but introduce it anyway at this juncture.
2016-03-19 11:49:48 +05:30
Sanchayan Maity d2fb3a4b8a Allow user processes to send messages to kernel
This patch allows user processes to send messages to kernel. Without
this change, trying to do a system call for using message queues like
sys_mq_open will fail with ECALLDENIED error number -210.
2016-03-16 23:30:06 +05:30
Sanchayan Maity 58ce9ca12b Fix return values used in mq_open 2016-03-15 19:51:08 +05:30
Sanchayan Maity df5a0e339c Limit the number of queues to 16 2016-03-15 19:39:03 +05:30
Sanchayan Maity 63062e7e15 Add message queue support for Minix
Implement message queues support for Minix.

Pending tasks:
Blocking or non blocking for send receive?
Sort by priority and time?
Test codes?
Bug fixes?
2016-03-07 17:41:07 +05:30
28 changed files with 893 additions and 9 deletions

View file

@ -853,6 +853,9 @@ struct
{ "MQ_CLOSE", SYS_MQ_CLOSE},
{ "MQ_SEND", SYS_MQ_SEND},
{ "MQ_REC", SYS_MQ_REC},
{ "MQ_SET_ATTR", SYS_MQ_SET_ATTR},
{ "MQ_GET_ATTR", SYS_MQ_GET_ATTR},
{ "MQ_REQ_NOTIFY", SYS_MQ_REQ_NOTIFY},
{ NULL, 0 }
};

View file

@ -266,9 +266,12 @@
# define SYS_MQ_CLOSE (KERNEL_CALL + 59) /* sys_mq_close */
# define SYS_MQ_SEND (KERNEL_CALL + 60) /* sys_mq_send */
# define SYS_MQ_REC (KERNEL_CALL + 61) /* sys_mq_rec */
# define SYS_MQ_SET_ATTR (KERNEL_CALL + 62) /* sys_mq_set_attributes */
# define SYS_MQ_GET_ATTR (KERNEL_CALL + 63) /* sys_mq_get_attributes */
# define SYS_MQ_REQ_NOTIFY (KERNEL_CALL + 64) /* sys_mq_request_notify */
/* Total */
#define NR_SYS_CALLS 62 /* number of kernel calls */
#define NR_SYS_CALLS 65 /* number of kernel calls */
#define SYS_CALL_MASK_SIZE BITMAP_CHUNKS(NR_SYS_CALLS)

View file

@ -1231,6 +1231,55 @@ typedef struct {
} mess_lsys_krn_sys_vumap;
_ASSERT_MSG_SIZE(mess_lsys_krn_sys_vumap);
typedef struct {
char name[32];
int oflag;
uint8_t padding[20];
} mess_lsys_krn_sys_mqueue_open;
_ASSERT_MSG_SIZE(mess_lsys_krn_sys_mqueue_open);
typedef struct {
int mqdes;
uint8_t padding[52];
} mess_lsys_krn_sys_mqueue_close;
_ASSERT_MSG_SIZE(mess_lsys_krn_sys_mqueue_close);
typedef struct {
int mqdes;
char msg[32];
unsigned int msg_prio;
endpoint_t dst[4];
} mess_lsys_krn_sys_mqueue_send;
_ASSERT_MSG_SIZE(mess_lsys_krn_sys_mqueue_send);
typedef struct {
int mqdes;
char msg[32];
unsigned int msg_prio;
endpoint_t dst;
uint8_t padding[12];
} mess_lsys_krn_sys_mqueue_receive;
_ASSERT_MSG_SIZE(mess_lsys_krn_sys_mqueue_receive);
typedef struct {
int no_of_messages;
int no_of_queues;
int blocking;
uint8_t padding[44];
} mess_lsys_krn_sys_mqueue_attribute;
_ASSERT_MSG_SIZE(mess_lsys_krn_sys_mqueue_attribute);
typedef struct {
int notify_on_off;
uint8_t padding[52];
} mess_lsys_krn_sys_mqueue_notify;
_ASSERT_MSG_SIZE(mess_lsys_krn_sys_mqueue_notify);
typedef struct {
void *vec_addr;
int vec_size;
@ -2248,6 +2297,12 @@ typedef struct noxfer_message {
mess_vm_vfs_mmap m_vm_vfs_mmap;
mess_vmmcp m_vmmcp;
mess_vmmcp_reply m_vmmcp_reply;
mess_lsys_krn_sys_mqueue_open m_lsys_krn_sys_mqueue_open;
mess_lsys_krn_sys_mqueue_close m_lsys_krn_sys_mqueue_close;
mess_lsys_krn_sys_mqueue_send m_lsys_krn_sys_mqueue_send;
mess_lsys_krn_sys_mqueue_receive m_lsys_krn_sys_mqueue_receive;
mess_lsys_krn_sys_mqueue_attribute m_lsys_krn_sys_mqueue_attribute;
mess_lsys_krn_sys_mqueue_notify m_lsys_krn_sys_mqueue_notify;
u8_t size[56]; /* message payload may have 56 bytes at most */
};

View file

@ -275,5 +275,14 @@ int copyfd(endpoint_t endpt, int fd, int what);
#define COPYFD_TO 1 /* copy file descriptor to remote process */
#define COPYFD_CLOSE 2 /* close file descriptor in remote process */
int sys_mq_open(const char *name, int oflag);
int sys_mq_send(int mqdes, const char *msg_ptr, pid_t dst[], unsigned int msg_prio);
int sys_mq_receive(int mqdes, char *msg_ptr, unsigned int msg_prio);
int sys_mq_get_attr(int *no_of_messages, int *no_of_queues, int *blocking);
int sys_mq_set_attr(int no_of_messages, int no_of_queues, int blocking);
int sys_mq_close(int mqdes);
int sys_mq_request_notify(int notify_on_off);
int sys_endpoint_from_pid(pid_t pid, endpoint_t *endpoint);
#endif /* _SYSLIB_H */

View file

@ -13,7 +13,7 @@ DBG=-O0
.include "arch/${MACHINE_ARCH}/Makefile.inc"
SRCS+= clock.c cpulocals.c interrupt.c main.c proc.c system.c \
table.c utility.c usermapped_data.c
table.c utility.c usermapped_data.c mqueue.c
LDADD+= -ltimers -lsys -lexec

View file

@ -23,6 +23,7 @@
#include "direct_utils.h"
#include "hw_intr.h"
#include "arch_proto.h"
#include "mqueue.h"
#ifdef CONFIG_SMP
#include "smp.h"
@ -304,6 +305,8 @@ void kmain(kinfo_t *local_cbi)
*/
add_memmap(&kinfo, kinfo.bootstrap_start, kinfo.bootstrap_len);
initialize_message_queues();
#ifdef CONFIG_SMP
if (config_no_apic) {
DEBUGBASIC(("APIC disabled, disables SMP, using legacy PIC\n"));
@ -376,6 +379,8 @@ void minix_shutdown(minix_timer_t *tp)
*/
int how;
deinitialize_message_queues();
#ifdef CONFIG_SMP
/*
* FIXME

258
minix/kernel/mqueue.c Normal file
View file

@ -0,0 +1,258 @@
#include <string.h>
#include <sys/errno.h>
#include <minix/sysutil.h>
#include "mqueue.h"
#include "kernel/kernel.h"
#include <minix/endpoint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "clock.h"
#include "proto.h"
message_queue mq;
int initialize_message_queues(void)
{
mq.num_queues = 0;
number_of_queues = MAX_QUEUES;
number_of_messages = MAX_MESSAGES;
mq_blocking = MQ_NON_BLOCKING;
notify = NOTIFY_OFF;
for (int i = 0; i < number_of_queues; i++) {
mq.queue_slot_empty[i] = EMPTY;
mq.msg[i].num_users = 0;
mq.msg[i].num_msgs = 0;
}
return 0;
}
int deinitialize_message_queues(void)
{
mq.num_queues = -1;
for (int i = 0; i < number_of_queues; i++) {
mq.msg[i].num_msgs = -1;
mq.msg[i].num_users = -1;
mq.queue_slot_empty[i] = EMPTY;
}
return 0;
}
int mq_get_attributes(int *no_of_msgs, int *no_of_queues, int *blocking)
{
*no_of_msgs = number_of_messages;
*no_of_queues = number_of_queues;
*blocking = MQ_NON_BLOCKING;
return 0;
}
int mq_set_attributes(int no_of_msgs, int no_of_queues, int blocking)
{
if (no_of_msgs <= MIN_LIMIT || no_of_msgs > MAX_LIMIT)
return EINVAL;
if (no_of_queues <= MIN_LIMIT || no_of_queues > MAX_LIMIT)
return EINVAL;
number_of_messages = no_of_msgs;
number_of_queues = no_of_queues;
mq_blocking = NON_BLOCKING;
return 0;
}
int mq_open(const char *name, int oflag)
{
mqd_t mqd;
if (mq.num_queues >= number_of_queues)
return EMQUEUEFULL;
if (strlen(name) > NAME_SIZE)
return EINVAL;
for (int i = 0; i < number_of_queues; i++)
if (mq.queue_slot_empty[i] == NOT_EMPTY)
if (strncmp(mq.msg[i].name, name, NAME_SIZE) == 0) {
mq.msg[i].num_users++;
return (mqd_t) i;
}
for (int i = 0; i < number_of_queues; i++) {
if (mq.queue_slot_empty[i] == EMPTY) {
mqd = i;
mq.queue_slot_empty[i] = NOT_EMPTY;
mq.num_queues++;
mq.msg[i].num_users++;
memset(mq.msg[i].name, '\0', NAME_SIZE);
strncpy(mq.msg[i].name, name, strlen(name));
for (int j = 0; j < number_of_messages; j++) {
mq.msg[i].msg_slot_empty[j] = EMPTY;
mq.msg[i].msge[j].priority = DEFAULT_PRIO;
for (int k = 0; k < MAX_RECEIVERS; k++)
mq.msg[i].msge[j].dst[k] = EMPTY;
}
break;
}
}
return mqd;
}
int mq_close(mqd_t mqdes)
{
if (mqdes < 0 || mqdes >= number_of_queues)
return EINVAL;
if (mq.queue_slot_empty[mqdes] == EMPTY)
return EMSGNOTFOUND;
mq.msg[mqdes].num_users--;
if (mq.msg[mqdes].num_users == 0) {
mq.msg[mqdes].num_msgs = 0;
mq.queue_slot_empty[mqdes] = EMPTY;
mq.num_queues--;
}
return 0;
}
int mq_send(mqd_t mqdes, const char *msg_ptr, unsigned int msg_prio, endpoint_t src, endpoint_t dst[])
{
if (mqdes < 0 || mqdes >= number_of_queues)
return EINVAL;
if (mq.queue_slot_empty[mqdes] == EMPTY)
return EMSGNOTFOUND;
if (mq.msg[mqdes].num_msgs > number_of_messages)
return EMSGFULL;
int empty_slot_pos;
for (int i = 0; i < number_of_messages; i++)
if (mq.msg[mqdes].msg_slot_empty[i] == EMPTY) {
empty_slot_pos = i;
break;
}
memset(mq.msg[mqdes].msge[empty_slot_pos].msg, 0, MAX_PAYLOAD);
memcpy(mq.msg[mqdes].msge[empty_slot_pos].msg,
msg_ptr, MAX_PAYLOAD);
mq.msg[mqdes].msge[empty_slot_pos].src = src;
mq.msg[mqdes].msge[empty_slot_pos].priority = msg_prio;
mq.msg[mqdes].msg_slot_empty[empty_slot_pos] = NOT_EMPTY;
for (int i = 0; i < MAX_RECEIVERS; i++)
mq.msg[mqdes].msge[empty_slot_pos].dst[i] = dst[i];
mq.msg[mqdes].msge[empty_slot_pos].timestamp = get_monotonic();
mq.msg[mqdes].num_msgs++;
if (notify) {
proc_nr_t proc_nr;
for (int i = 0; i < MAX_RECEIVERS; i++) {
if (dst[i] != -1) {
/* Translate endpoint to process number */
if (!isokendpt(dst[i], &proc_nr))
goto exit;
else
cause_sig(proc_nr, SIGALRM);
}
}
}
exit:
return 0;
}
size_t mq_receive(mqd_t mqdes, char *msg_ptr, unsigned int msg_prio, endpoint_t dst)
{
if (mqdes < 0 || mqdes >= number_of_queues)
return EINVAL;
if (mq.queue_slot_empty[mqdes] == EMPTY)
return EMSGNOTFOUND;
if (mq.msg[mqdes].num_msgs == 0)
return EMSGEMPTY;
int index = message_index_with_highprio(mqdes, dst);
if (index == -1)
return EMSGEMPTY;
for (int i = 0; i < MAX_RECEIVERS; i++) {
if (mq.msg[mqdes].msge[index].dst[i] == dst) {
memcpy(msg_ptr, mq.msg[mqdes].msge[index].msg, MAX_PAYLOAD);
mq.msg[mqdes].msge[index].dst[i] = EMPTY;
clean_message_queue(mqdes);
}
}
return 0;
}
int message_index_with_highprio(int mqdes, endpoint_t dst)
{
int prio;
int max_prio = -1;
int index = -1;
for (int i = 0; i < number_of_messages; i++) {
if (mq.msg[mqdes].msg_slot_empty[i] == NOT_EMPTY) {
prio = mq.msg[mqdes].msge[i].priority;
for (int j = 0; j < MAX_RECEIVERS; j++) {
if (mq.msg[mqdes].msge[i].dst[j] == dst) {
if (max_prio == prio) {
if (mq.msg[mqdes].msge[i].timestamp > mq.msg[mqdes].msge[index].timestamp)
index = i;
} else if (max_prio < MAX(max_prio, prio)) {
index = i;
max_prio = MAX(max_prio, prio);
}
}
}
}
}
return index;
}
int clean_message_queue(mqd_t mqdes)
{
int flag = 1;
for (int i = 0; i < number_of_messages; i++) {
if (mq.msg[mqdes].msg_slot_empty[i] == NOT_EMPTY) {
for (int j = 0; j < MAX_RECEIVERS; j++)
if (mq.msg[mqdes].msge[i].dst[j] != EMPTY)
flag = 0;
}
if (flag) {
mq.msg[mqdes].msg_slot_empty[i] = EMPTY;
mq.msg[mqdes].num_msgs--;
}
}
return 0;
}
int mq_notify(int notify_on_off)
{
if (notify_on_off)
notify = NOTIFY_ON;
else
notify = NOTIFY_OFF;
return 0;
}

78
minix/kernel/mqueue.h Normal file
View file

@ -0,0 +1,78 @@
#ifndef MQUEUE_H
#define MQUEUE_H
/*
* This header file defines constants and function declarations used for
* MINIX interprocess message queues. These are used primarily in file
* mqueue.c
*/
#include <minix/type.h>
/*
* This provides a maximum limit beyond which we do not allow changing
* number of queues or number of messages in queue.
*/
#define MAX_LIMIT 256
#define MIN_LIMIT 16
#define MAX_RECEIVERS 4
#define MAX_MESSAGES MAX_LIMIT
#define MAX_QUEUES MAX_LIMIT
#define MAX_PAYLOAD 32
#define NAME_SIZE 32
#define DEFAULT_PRIO 0
#define EMPTY -1
#define NOT_EMPTY 1
#define MQ_BLOCKING 0
#define MQ_NON_BLOCKING 1
#define NOTIFY_ON 1
#define NOTIFY_OFF 0
typedef int mqd_t;
typedef struct message_entity {
u64_t timestamp;
char msg[MAX_PAYLOAD];
endpoint_t src;
endpoint_t dst[MAX_RECEIVERS];
unsigned int priority;
} message_entity;
typedef struct messageq {
char name[NAME_SIZE];
int num_msgs;
int num_users;
message_entity msge[MAX_MESSAGES];
int msg_slot_empty[MAX_MESSAGES];
} messageq;
typedef struct message_queue {
int num_queues;
messageq msg[MAX_QUEUES];
int queue_slot_empty[MAX_QUEUES];
} message_queue;
int number_of_messages;
int number_of_queues;
int mq_blocking;
int notify;
int initialize_message_queues(void);
int deinitialize_message_queues(void);
mqd_t mq_open(const char *name, int oflag);
int mq_send(mqd_t mqdes, const char *msg_ptr, unsigned int msg_prio, endpoint_t src, endpoint_t dst[]);
size_t mq_receive(mqd_t mqdes, char *msg_ptr, unsigned int msg_prio, endpoint_t dst);
int mq_get_attributes(int *no_of_msgs, int *no_of_queues, int *blocking);
int mq_set_attributes(int no_of_msgs, int no_of_queues, int blocking);
int mq_close(mqd_t mqdes);
int mq_notify(int notify_on_off);
int clean_message_queue(mqd_t mqdes);
int message_index_with_highprio(mqd_t mqdes, endpoint_t dst);
#endif /* MQUEUE_H */

View file

@ -108,11 +108,11 @@ static int kernel_call_dispatch(struct proc * caller, message *msg)
printf("SYSTEM: illegal request %d from %d.\n",
call_nr,msg->m_source);
result = EBADREQUEST; /* illegal message type */
}
else if (!GET_BIT(priv(caller)->s_k_call_mask, call_nr)) {
printf("SYSTEM: denied request %d from %d.\n",
call_nr,msg->m_source);
result = ECALLDENIED; /* illegal message type */
// } /* We have to allow user processes to send messages to kernel */
// else if (!GET_BIT(priv(caller)->s_k_call_mask, call_nr)) {
// printf("SYSTEM: denied request %d from %d.\n",
// call_nr,msg->m_source);
// result = ECALLDENIED; /* illegal message type */
} else {
/* handle the system call */
if (call_vec[call_nr])
@ -273,6 +273,9 @@ void system_init(void)
map(SYS_MQ_CLOSE, do_mq_close); /* close a message queue */
map(SYS_MQ_SEND, do_mq_send); /* send to a message queue */
map(SYS_MQ_REC, do_mq_rec); /* receive from a message queue */
map(SYS_MQ_SET_ATTR, do_mq_set_attr); /* set message queue attributes */
map(SYS_MQ_GET_ATTR, do_mq_get_attr); /* get message queue attributes */
map(SYS_MQ_REQ_NOTIFY, do_mq_request_notify); /* request notification for receive */
}
/*===========================================================================*

View file

@ -226,5 +226,20 @@ int do_mq_rec(struct proc * caller, message *m_ptr);
#define do_mq_rec NULL
#endif
int do_mq_set_attr(struct proc * caller, message *m_ptr);
#if ! USE_MQ_IPC
#define do_mq_set_attr NULL
#endif
int do_mq_get_attr(struct proc * caller, message *m_ptr);
#if ! USE_MQ_IPC
#define do_mq_get_attr NULL
#endif
int do_mq_request_notify(struct proc * caller, message *m_ptr);
#if ! USE_MQ_IPC
#define do_mq_request_notify NULL
#endif
#endif /* SYSTEM_H */

View file

@ -41,7 +41,10 @@ SRCS+= \
do_mq_open.c \
do_mq_close.c \
do_mq_send.c \
do_mq_rec.c
do_mq_rec.c \
do_mq_set_attribute.c \
do_mq_get_attribute.c \
do_mq_request_notify.c
.if ${MACHINE_ARCH} == "i386"
SRCS+= \

View file

@ -0,0 +1,26 @@
/* The kernel call implemented in this file:
* m_type: SYS_MQ_CLOSE
*
*/
#include "kernel/mqueue.h"
#include "kernel/system.h"
#include "kernel/vm.h"
#include <signal.h>
#include <string.h>
#include <assert.h>
#include <minix/endpoint.h>
#include <minix/u64.h>
#if USE_MQ_IPC
/*===========================================================================*
* do_mq_close *
*===========================================================================*/
int do_mq_close(struct proc * caller, message * m_ptr)
{
return mq_close(m_ptr->m_lsys_krn_sys_mqueue_close.mqdes);
}
#endif /* USE_MQ_IPC */

View file

@ -0,0 +1,28 @@
/* The kernel call implemented in this file:
* m_type: SYS_MQ_GET_ATTRIBUTE
*
*/
#include "kernel/mqueue.h"
#include "kernel/system.h"
#include "kernel/vm.h"
#include <signal.h>
#include <string.h>
#include <assert.h>
#include <minix/endpoint.h>
#include <minix/u64.h>
#if USE_MQ_IPC
/*===========================================================================*
* do_mq_get_attribute *
*===========================================================================*/
int do_mq_get_attr(struct proc *caller, message * m_ptr)
{
return mq_get_attributes(&m_ptr->m_lsys_krn_sys_mqueue_attribute.no_of_messages,
&m_ptr->m_lsys_krn_sys_mqueue_attribute.no_of_queues,
&m_ptr->m_lsys_krn_sys_mqueue_attribute.blocking);
}
#endif /* USE_MQ_IPC */

View file

@ -0,0 +1,28 @@
/* The kernel call implemented in this file:
* m_type: SYS_MQ_OPEN
*
*/
#include "kernel/mqueue.h"
#include "kernel/system.h"
#include "kernel/vm.h"
#include <signal.h>
#include <string.h>
#include <assert.h>
#include <minix/endpoint.h>
#include <minix/u64.h>
#if USE_MQ_IPC
/*===========================================================================*
* do_mq_open *
*===========================================================================*/
int do_mq_open(struct proc * caller, message * m_ptr)
{
return mq_open(m_ptr->m_lsys_krn_sys_mqueue_open.name,
m_ptr->m_lsys_krn_sys_mqueue_open.oflag);
}
#endif /* USE_MQ_IPC */

View file

@ -0,0 +1,29 @@
/* The kernel call implemented in this file:
* m_type: SYS_MQ_REC
*
*/
#include "kernel/mqueue.h"
#include "kernel/system.h"
#include "kernel/vm.h"
#include <signal.h>
#include <string.h>
#include <assert.h>
#include <minix/endpoint.h>
#include <minix/u64.h>
#if USE_MQ_IPC
/*===========================================================================*
* do_mq_rec *
*===========================================================================*/
int do_mq_rec(struct proc * caller, message * m_ptr)
{
return mq_receive(m_ptr->m_lsys_krn_sys_mqueue_receive.mqdes,
m_ptr->m_lsys_krn_sys_mqueue_receive.msg,
m_ptr->m_lsys_krn_sys_mqueue_receive.msg_prio,
caller->p_endpoint);
}
#endif /* USE_MQ_IPC */

View file

@ -0,0 +1,26 @@
/* The kernel call implemented in this file:
* m_type: SYS_MQ_REQUEST_NOTIFY
*
*/
#include "kernel/mqueue.h"
#include "kernel/system.h"
#include "kernel/vm.h"
#include <signal.h>
#include <string.h>
#include <assert.h>
#include <minix/endpoint.h>
#include <minix/u64.h>
#if USE_MQ_IPC
/*===========================================================================*
* do_mq_request_notify *
*===========================================================================*/
int do_mq_request_notify(struct proc * caller, message * m_ptr)
{
return mq_notify(m_ptr->m_lsys_krn_sys_mqueue_notify.notify_on_off);
}
#endif /* USE_MQ_IPC */

View file

@ -0,0 +1,30 @@
/* The kernel call implemented in this file:
* m_type: SYS_MQ_SEND
*
*/
#include "kernel/mqueue.h"
#include "kernel/system.h"
#include "kernel/vm.h"
#include <signal.h>
#include <string.h>
#include <assert.h>
#include <minix/endpoint.h>
#include <minix/u64.h>
#if USE_MQ_IPC
/*===========================================================================*
* do_mq_send *
*===========================================================================*/
int do_mq_send(struct proc * caller, message * m_ptr)
{
return mq_send(m_ptr->m_lsys_krn_sys_mqueue_send.mqdes,
m_ptr->m_lsys_krn_sys_mqueue_send.msg,
m_ptr->m_lsys_krn_sys_mqueue_send.msg_prio,
caller->p_endpoint,
m_ptr->m_lsys_krn_sys_mqueue_send.dst);
}
#endif /* USE_MQ_IPC */

View file

@ -0,0 +1,28 @@
/* The kernel call implemented in this file:
* m_type: SYS_MQ_SET_ATTRIBUTE
*
*/
#include "kernel/mqueue.h"
#include "kernel/system.h"
#include "kernel/vm.h"
#include <signal.h>
#include <string.h>
#include <assert.h>
#include <minix/endpoint.h>
#include <minix/u64.h>
#if USE_MQ_IPC
/*===========================================================================*
* do_mq_set_attribute *
*===========================================================================*/
int do_mq_set_attr(struct proc *caller, message * m_ptr)
{
return mq_set_attributes(m_ptr->m_lsys_krn_sys_mqueue_attribute.no_of_messages,
m_ptr->m_lsys_krn_sys_mqueue_attribute.no_of_queues,
m_ptr->m_lsys_krn_sys_mqueue_attribute.blocking);
}
#endif /* USE_MQ_IPC */

View file

@ -88,6 +88,14 @@ SRCS+= \
sys_vsafecopy.c \
sys_vtimer.c \
sys_vumap.c \
sys_mq_open.c \
sys_mq_close.c \
sys_mq_send.c \
sys_mq_receive.c \
sys_mq_set_attr.c \
sys_mq_get_attr.c \
sys_mq_request_notify.c \
sys_endpoint_from_pid.c \
taskcall.c \
tickdelay.c \
timers.c \

View file

@ -0,0 +1,108 @@
#include <minix/procfs.h>
#include <string.h>
#include "syslib.h"
struct pstat { /* structure filled by pstat() */
struct pstat *ps_next; /* next in process list */
int ps_task; /* is this process a task or not? */
int ps_endpt; /* process endpoint (NONE means unused slot) */
dev_t ps_dev; /* major/minor of controlling tty */
uid_t ps_ruid; /* real uid */
uid_t ps_euid; /* effective uid */
pid_t ps_pid; /* process id */
pid_t ps_ppid; /* parent process id */
int ps_pgrp; /* process group id */
char ps_state; /* process state */
char ps_pstate; /* sleep state */
char ps_fstate; /* VFS block state */
int ps_ftask; /* VFS suspend task (endpoint) */
vir_bytes ps_memory; /* memory usage */
int ps_recv; /* process number to receive from (endpoint) */
unsigned int ps_utime; /* accumulated user time */
unsigned int ps_stime; /* accumulated system time */
char ps_name[PROC_NAME_LEN + 1];/* process name */
char *ps_args; /* concatenated argument string */
};
int pstat(struct pstat *ps, pid_t pid);
int sys_endpoint_from_pid(pid_t pid, endpoint_t *endpoint) {
struct pstat ps;
int ret = pstat(&ps, pid);
if(!ret)
*endpoint = ps.ps_endpt;
return ret;
}
/* Taken from minix/commands/ps/ps.c */
int pstat(struct pstat *ps, pid_t pid) {
FILE *fp;
int version, ruid, euid, dev;
char type, path[PATH_MAX], name[256];
ps->ps_pid = pid;
ps->ps_next = NULL;
sprintf(path, "/proc/%d/psinfo", pid);
if ((fp = fopen(path, "r")) == NULL)
return -1;
if (fscanf(fp, "%d", &version) != 1) {
fclose(fp);
return -1;
}
/* The psinfo file's version must match what we expect. */
if (version != PSINFO_VERSION) {
fputs("procfs version mismatch!\n", stderr);
return -1;
}
if (fscanf(fp, " %c %d %255s %c %d %*d %u %u %*u %*u", &type, &ps->ps_endpt,
name, &ps->ps_state, &ps->ps_recv, &ps->ps_utime, &ps->ps_stime)
!= 7) {
fclose(fp);
return -1;
}
strncpy(ps->ps_name, name, sizeof(ps->ps_name) - 1);
ps->ps_name[sizeof(ps->ps_name) - 1] = 0;
ps->ps_task = type == TYPE_TASK;
if (!ps->ps_task) {
if (fscanf(fp, " %lu %*u %*u %c %d %u %u %u %*d %c %d %u",
&ps->ps_memory, &ps->ps_pstate, &ps->ps_ppid, &ruid, &euid,
&ps->ps_pgrp, &ps->ps_fstate, &ps->ps_ftask, &dev) != 9) {
fclose(fp);
return -1;
}
ps->ps_ruid = ruid;
ps->ps_euid = euid;
ps->ps_dev = dev;
} else {
ps->ps_memory = 0L;
ps->ps_pstate = PSTATE_NONE;
ps->ps_ppid = 0;
ps->ps_ruid = 0;
ps->ps_euid = 0;
ps->ps_pgrp = 0;
ps->ps_fstate = FSTATE_NONE;
ps->ps_ftask = NONE;
ps->ps_dev = NO_DEV;
}
fclose(fp);
if (ps->ps_state == STATE_ZOMBIE)
strncpy(ps->ps_args, "<defunct>", 9);
else
ps->ps_args = NULL;
return OK;
}

View file

@ -0,0 +1,10 @@
#include "syslib.h"
int sys_mq_close(int mqdes)
{
message m;
m.m_lsys_krn_sys_mqueue_close.mqdes = mqdes;
return _kernel_call(SYS_MQ_CLOSE, &m);
}

View file

@ -0,0 +1,23 @@
#include "syslib.h"
#include <string.h>
#include <machine/archtypes.h>
#include <minix/timers.h>
#include <minix/sysutil.h>
#include <minix/vm.h>
int sys_mq_get_attr(int *no_of_messages, int *no_of_queues, int *blocking)
{
message m;
m.m_lsys_krn_sys_mqueue_attribute.no_of_messages = 0;
m.m_lsys_krn_sys_mqueue_attribute.no_of_queues = 0;
m.m_lsys_krn_sys_mqueue_attribute.blocking = 0;
_kernel_call(SYS_MQ_GET_ATTR, &m);
*no_of_messages = m.m_lsys_krn_sys_mqueue_attribute.no_of_messages;
*no_of_queues = m.m_lsys_krn_sys_mqueue_attribute.no_of_queues;
*blocking = m.m_lsys_krn_sys_mqueue_attribute.blocking;
return 0;
}

View file

@ -0,0 +1,14 @@
# include "syslib.h"
# include <string.h>
#define MAX_PAYLOAD 32
int sys_mq_open(const char *name, int oflag)
{
message m;
m.m_lsys_krn_sys_mqueue_open.oflag = oflag;
strncpy(m.m_lsys_krn_sys_mqueue_open.name, name, MAX_PAYLOAD);
return _kernel_call(SYS_MQ_OPEN, &m);
}

View file

@ -0,0 +1,24 @@
#include "syslib.h"
#include <string.h>
#include <machine/archtypes.h>
#include <minix/timers.h>
#include <minix/sysutil.h>
#include <minix/vm.h>
#define MAX_PAYLOAD 32
int sys_mq_receive(int mqdes, char *msg_ptr, unsigned int msg_prio)
{
int ret;
message m;
m.m_lsys_krn_sys_mqueue_receive.mqdes = mqdes;
m.m_lsys_krn_sys_mqueue_receive.msg_prio = msg_prio;
ret = _kernel_call(SYS_MQ_REC, &m);
if (ret == 0)
memcpy(msg_ptr, m.m_lsys_krn_sys_mqueue_receive.msg, MAX_PAYLOAD);
return ret;
}

View file

@ -0,0 +1,15 @@
#include "syslib.h"
#include <string.h>
#include <machine/archtypes.h>
#include <minix/timers.h>
#include <minix/sysutil.h>
#include <minix/vm.h>
int sys_mq_request_notify(int notify_on_off)
{
message m;
m.m_lsys_krn_sys_mqueue_notify.notify_on_off = notify_on_off;
return (_kernel_call(SYS_MQ_REQ_NOTIFY, &m));
}

View file

@ -0,0 +1,32 @@
#include "syslib.h"
#include <string.h>
#include <machine/archtypes.h>
#include <minix/timers.h>
#include <minix/sysutil.h>
#include <minix/vm.h>
#define MAX_RECEIVERS 4
#define MAX_PAYLOAD 32
int sys_mq_send(int mqdes, const char *msg_ptr, pid_t dst[], unsigned int msg_prio)
{
message m;
m.m_lsys_krn_sys_mqueue_send.mqdes = mqdes;
m.m_lsys_krn_sys_mqueue_send.msg_prio = msg_prio;
for (int i = 0; i < MAX_RECEIVERS; i++) {
if (dst[i] == -1) {
m.m_lsys_krn_sys_mqueue_send.dst[i] = dst[i];
break;
}
endpoint_t endpoint;
int ret = sys_endpoint_from_pid(dst[i], &endpoint);
if (ret != 0)
endpoint = -1;
m.m_lsys_krn_sys_mqueue_send.dst[i] = endpoint;
}
memcpy(m.m_lsys_krn_sys_mqueue_send.msg, msg_ptr, MAX_PAYLOAD);
return (_kernel_call(SYS_MQ_SEND, &m));
}

View file

@ -0,0 +1,17 @@
#include "syslib.h"
#include <string.h>
#include <machine/archtypes.h>
#include <minix/timers.h>
#include <minix/sysutil.h>
#include <minix/vm.h>
int sys_mq_set_attr(int no_of_messages, int no_of_queues, int blocking)
{
message m;
m.m_lsys_krn_sys_mqueue_attribute.no_of_messages = no_of_messages;
m.m_lsys_krn_sys_mqueue_attribute.no_of_queues = no_of_queues;
m.m_lsys_krn_sys_mqueue_attribute.blocking = blocking;
return (_kernel_call(SYS_MQ_SET_ATTR, &m));
}

View file

@ -172,7 +172,13 @@
#define ENOLINK (_SIGN 95 ) /* Link has been severed */
#define EPROTO (_SIGN 96 ) /* Protocol error */
#define ELAST (_SIGN 96 ) /* Must equal largest errno */
#define EMQUEUEFULL (_SIGN 97 ) /* Message queue is full */
#define EMSGNOTFOUND (_SIGN 98 ) /* Message queue descriptor does not exist */
#define EMSGFULL (_SIGN 99 ) /* Message queue with given descriptor is full */
#define EMSGNONE (_SIGN 100 ) /* No message for process to retrieve */
#define EMSGEMPTY (_SIGN 101 ) /* Message queue empty */
#define ELAST (_SIGN 101 ) /* Must equal largest errno */
#if defined(_KERNEL) || defined(_KMEMUSER)
/* pseudo-errors returned inside kernel to modify return to process */