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.
This commit is contained in:
Sanchayan Maity 2016-03-22 15:57:53 +05:30
parent d84b3d9248
commit 55d341bc54
14 changed files with 188 additions and 17 deletions

View File

@ -853,6 +853,8 @@ 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},
{ NULL, 0 }
};

View File

@ -266,9 +266,11 @@
# 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 */
/* Total */
#define NR_SYS_CALLS 62 /* number of kernel calls */
#define NR_SYS_CALLS 64 /* number of kernel calls */
#define SYS_CALL_MASK_SIZE BITMAP_CHUNKS(NR_SYS_CALLS)

View File

@ -1264,6 +1264,15 @@ typedef struct {
} 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 {
void *vec_addr;
int vec_size;
@ -2285,6 +2294,7 @@ typedef struct noxfer_message {
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;
u8_t size[56]; /* message payload may have 56 bytes at most */
};

View File

@ -278,6 +278,8 @@ int copyfd(endpoint_t endpt, int fd, int what);
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_endpoint_from_pid(pid_t pid, endpoint_t *endpoint);

View File

@ -18,8 +18,11 @@ 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;
for (int i = 0; i < MAX_QUEUES; i++) {
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;
@ -31,7 +34,7 @@ int initialize_message_queues(void)
int deinitialize_message_queues(void)
{
mq.num_queues = -1;
for (int i = 0; i < MAX_QUEUES; i++) {
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;
@ -40,24 +43,48 @@ int deinitialize_message_queues(void)
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 >= MAX_QUEUES)
if (mq.num_queues >= number_of_queues)
return EMQUEUEFULL;
if (strlen(name) > NAME_SIZE)
return EINVAL;
for (int i = 0; i < MAX_QUEUES; i++)
for (int i = 0; i < number_of_queues; i++)
if (mq.queue_slot_empty[i] == NOT_EMPTY)
if (strcmp(mq.msg[i].name, name) == 0) {
mq.msg[i].num_users++;
return (mqd_t) i;
}
for (int i = 0; i < MAX_QUEUES; 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;
@ -65,7 +92,7 @@ int mq_open(const char *name, int oflag)
mq.msg[i].num_users++;
strncpy(mq.msg[i].name, name, strlen(name));
for (int j = 0; j < MAX_MESSAGES; j++) {
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++)
@ -80,7 +107,7 @@ int mq_open(const char *name, int oflag)
int mq_close(mqd_t mqdes)
{
if (mqdes < 0 || mqdes >= MAX_QUEUES)
if (mqdes < 0 || mqdes >= number_of_queues)
return EINVAL;
if (mq.queue_slot_empty[mqdes] == EMPTY)
@ -98,17 +125,17 @@ int mq_close(mqd_t mqdes)
int mq_send(mqd_t mqdes, const char *msg_ptr, unsigned int msg_prio, endpoint_t src, endpoint_t dst[])
{
if (mqdes < 0 || mqdes >= MAX_QUEUES)
if (mqdes < 0 || mqdes >= number_of_queues)
return EINVAL;
if (mq.queue_slot_empty[mqdes] == EMPTY)
return EMSGNOTFOUND;
if (mq.msg[mqdes].num_msgs > MAX_MESSAGES)
if (mq.msg[mqdes].num_msgs > number_of_messages)
return EMSGFULL;
int empty_slot_pos;
for (int i = 0; i < MAX_MESSAGES; i++)
for (int i = 0; i < number_of_messages; i++)
if (mq.msg[mqdes].msg_slot_empty[i] == EMPTY) {
empty_slot_pos = i;
break;
@ -132,7 +159,7 @@ int mq_send(mqd_t mqdes, const char *msg_ptr, unsigned int msg_prio, endpoint_t
size_t mq_receive(mqd_t mqdes, char *msg_ptr, unsigned int msg_prio, endpoint_t dst)
{
if (mqdes < 0 || mqdes >= MAX_QUEUES)
if (mqdes < 0 || mqdes >= number_of_queues)
return EINVAL;
if (mq.queue_slot_empty[mqdes] == EMPTY)
@ -163,7 +190,7 @@ int message_index_with_highprio(int mqdes, endpoint_t dst)
int max_prio = -1;
int index = -1;
for (int i = 0; i < MAX_MESSAGES; i++) {
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++) {
@ -187,7 +214,7 @@ int clean_message_queue(mqd_t mqdes)
{
int flag = 1;
for (int i = 0; i < MAX_MESSAGES; i++) {
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)

View File

@ -9,9 +9,16 @@
#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 16
#define MAX_QUEUES 16
#define MAX_MESSAGES MAX_LIMIT
#define MAX_QUEUES MAX_LIMIT
#define MAX_PAYLOAD 32
#define NAME_SIZE 32
#define DEFAULT_PRIO 0
@ -19,6 +26,9 @@
#define EMPTY -1
#define NOT_EMPTY 1
#define MQ_BLOCKING 0
#define MQ_NON_BLOCKING 1
typedef int mqd_t;
typedef struct message_entity {
@ -43,12 +53,18 @@ typedef struct message_queue {
int queue_slot_empty[MAX_QUEUES];
} message_queue;
int number_of_messages;
int number_of_queues;
int mq_blocking;
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 clean_message_queue(mqd_t mqdes);

View File

@ -273,6 +273,8 @@ 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 */
}
/*===========================================================================*

View File

@ -226,5 +226,15 @@ 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
#endif /* SYSTEM_H */

View File

@ -41,7 +41,9 @@ 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
.if ${MACHINE_ARCH} == "i386"
SRCS+= \

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_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

@ -92,6 +92,8 @@ SRCS+= \
sys_mq_close.c \
sys_mq_send.c \
sys_mq_receive.c \
sys_mq_set_attr.c \
sys_mq_get_attr.c \
sys_endpoint_from_pid.c \
taskcall.c \
tickdelay.c \

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,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));
}