259 lines
5.4 KiB
C
259 lines
5.4 KiB
C
#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;
|
|
}
|