203 lines
4.0 KiB
C
203 lines
4.0 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;
|
|
|
|
for (int i = 0; i < MAX_QUEUES; i++) {
|
|
mq.queue_slot_empty[i] = EMPTY;
|
|
mq.msg[i].num_msgs = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int deinitialize_message_queues(void)
|
|
{
|
|
mq.num_queues = -1;
|
|
for (int i = 0; i < MAX_QUEUES; i++) {
|
|
mq.msg[i].num_msgs = -1;
|
|
mq.queue_slot_empty[i] = -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mq_open(const char *name, int oflag)
|
|
{
|
|
mqd_t mqd;
|
|
|
|
if (mq.num_queues == MAX_QUEUES)
|
|
return (mqd_t) -1;
|
|
|
|
if (strlen(name) > NAME_SIZE)
|
|
return (mqd_t) -1;
|
|
|
|
for (int i = 0; i < MAX_QUEUES; i++)
|
|
if (mq.queue_slot_empty[i] == NOT_EMPTY)
|
|
if (strcmp(mq.msg[i].name, name) == 0)
|
|
return (mqd_t) i;
|
|
|
|
for (int i = 0; i < MAX_QUEUES; i++) {
|
|
if (mq.queue_slot_empty[i] == EMPTY) {
|
|
mqd = i;
|
|
mq.queue_slot_empty[i] = NOT_EMPTY;
|
|
mq.num_queues++;
|
|
strncpy(mq.msg[i].name, name, strlen(name));
|
|
|
|
for (int j = 0; j < MAX_MESSAGES; j++) {
|
|
mq.msg[i].msg_slot_empty[j] = NOT_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 >= MAX_QUEUES)
|
|
return EINVAL;
|
|
|
|
if (mq.queue_slot_empty[mqdes] == EMPTY)
|
|
return EMSGNOTFOUND;
|
|
|
|
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 >= MAX_QUEUES)
|
|
return EINVAL;
|
|
|
|
if (mq.queue_slot_empty[mqdes] == EMPTY)
|
|
return EMSGNOTFOUND;
|
|
|
|
if (mq.msg[mqdes].num_msgs >= MAX_MESSAGES)
|
|
return EMSGFULL;
|
|
|
|
int empty_slot_pos;
|
|
for (int i = 0; i < MAX_MESSAGES; i++)
|
|
if (mq.msg[mqdes].msg_slot_empty[i] == EMPTY) {
|
|
empty_slot_pos = i;
|
|
break;
|
|
}
|
|
|
|
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].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++;
|
|
|
|
return 0;
|
|
}
|
|
|
|
size_t mq_receive(mqd_t mqdes, char *msg_ptr, unsigned int msg_prio, endpoint_t dst)
|
|
{
|
|
if (mqdes < 0 || mqdes >= MAX_QUEUES)
|
|
return EINVAL;
|
|
|
|
if (mq.queue_slot_empty[mqdes] == EMPTY)
|
|
return EMSGNOTFOUND;
|
|
|
|
if (mq.msg[mqdes].num_msgs >= MAX_MESSAGES)
|
|
return EMSGFULL;
|
|
|
|
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 find_max(int n1, int n2)
|
|
{
|
|
if (n1 > n2)
|
|
return n1;
|
|
|
|
return n2;
|
|
}
|
|
|
|
int message_index_with_highprio(mqdes, dst)
|
|
{
|
|
int prio;
|
|
int max_prio = -1;
|
|
int index = -1;
|
|
|
|
for (int i = 0; i < MAX_MESSAGES; i++) {
|
|
prio = mq.msg[mqdes].msge[i].priority;
|
|
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] == dst) {
|
|
if (max_prio < find_max(max_prio, prio)) {
|
|
index = i;
|
|
max_prio = find_max(max_prio, prio);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
int clean_message_queue(mqd_t mqdes)
|
|
{
|
|
int flag = 1;
|
|
|
|
for (int i = 0; i < MAX_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 == 1) {
|
|
mq.msg[mqdes].msg_slot_empty[i] = EMPTY;
|
|
mq.msg[mqdes].num_msgs--;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|