2011-11-02 17:31:38 +01:00
|
|
|
/* This file contains a simple message queue implementation to support both
|
|
|
|
* the singlethread and the multithreaded driver implementation.
|
|
|
|
*
|
|
|
|
* Changes:
|
|
|
|
* Oct 27, 2011 rewritten to use sys/queue.h (D.C. van Moolenbroek)
|
|
|
|
* Aug 27, 2011 integrated into libdriver (A. Welzel)
|
|
|
|
*/
|
2007-01-12 14:33:12 +01:00
|
|
|
|
2011-11-02 17:31:38 +01:00
|
|
|
#include <minix/driver_mt.h>
|
|
|
|
#include <sys/queue.h>
|
2007-01-12 14:33:12 +01:00
|
|
|
#include <assert.h>
|
|
|
|
|
2011-11-02 17:31:38 +01:00
|
|
|
#include "mq.h"
|
2007-01-12 14:33:12 +01:00
|
|
|
|
|
|
|
#define MQ_SIZE 128
|
|
|
|
|
2011-11-02 17:31:38 +01:00
|
|
|
struct mq_cell {
|
|
|
|
message mess;
|
|
|
|
int ipc_status;
|
|
|
|
STAILQ_ENTRY(mq_cell) next;
|
|
|
|
};
|
2007-01-12 14:33:12 +01:00
|
|
|
|
2011-11-02 17:31:38 +01:00
|
|
|
PRIVATE struct mq_cell pool[MQ_SIZE];
|
|
|
|
|
|
|
|
PRIVATE STAILQ_HEAD(queue, mq_cell) queue[DRIVER_MT_MAX_WORKERS];
|
|
|
|
PRIVATE STAILQ_HEAD(free_list, mq_cell) free_list;
|
2007-01-12 14:33:12 +01:00
|
|
|
|
2011-11-02 17:31:38 +01:00
|
|
|
/*===========================================================================*
|
|
|
|
* driver_mq_init *
|
|
|
|
*===========================================================================*/
|
|
|
|
PUBLIC void driver_mq_init(void)
|
2007-01-12 14:33:12 +01:00
|
|
|
{
|
2011-11-02 17:31:38 +01:00
|
|
|
/* Initialize the message queues and message cells.
|
|
|
|
*/
|
|
|
|
int i;
|
|
|
|
|
|
|
|
STAILQ_INIT(&free_list);
|
2007-01-12 14:33:12 +01:00
|
|
|
|
2011-11-02 17:31:38 +01:00
|
|
|
for (i = 0; i < DRIVER_MT_MAX_WORKERS; i++)
|
|
|
|
STAILQ_INIT(&queue[i]);
|
2007-01-12 14:33:12 +01:00
|
|
|
|
2011-11-02 17:31:38 +01:00
|
|
|
for (i = 0; i < MQ_SIZE; i++)
|
|
|
|
STAILQ_INSERT_HEAD(&free_list, &pool[i], next);
|
2007-01-12 14:33:12 +01:00
|
|
|
}
|
|
|
|
|
2011-11-02 17:31:38 +01:00
|
|
|
/*===========================================================================*
|
|
|
|
* driver_mq_enqueue *
|
|
|
|
*===========================================================================*/
|
|
|
|
PUBLIC int driver_mq_enqueue(thread_id_t thread_id, const message *mess,
|
|
|
|
int ipc_status)
|
2007-01-12 14:33:12 +01:00
|
|
|
{
|
2011-11-02 17:31:38 +01:00
|
|
|
/* Add a message, including its IPC status, to the message queue of a thread.
|
|
|
|
* Return TRUE iff the message was added successfully.
|
|
|
|
*/
|
|
|
|
struct mq_cell *cell;
|
|
|
|
|
|
|
|
assert(thread_id >= 0 && thread_id < DRIVER_MT_MAX_WORKERS);
|
|
|
|
|
|
|
|
if (STAILQ_EMPTY(&free_list))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
cell = STAILQ_FIRST(&free_list);
|
|
|
|
STAILQ_REMOVE_HEAD(&free_list, next);
|
|
|
|
|
|
|
|
cell->mess = *mess;
|
|
|
|
cell->ipc_status = ipc_status;
|
|
|
|
|
|
|
|
STAILQ_INSERT_TAIL(&queue[thread_id], cell, next);
|
|
|
|
|
|
|
|
return TRUE;
|
2007-01-12 14:33:12 +01:00
|
|
|
}
|
|
|
|
|
2011-11-02 17:31:38 +01:00
|
|
|
/*===========================================================================*
|
|
|
|
* driver_mq_dequeue *
|
|
|
|
*===========================================================================*/
|
|
|
|
PUBLIC int driver_mq_dequeue(thread_id_t thread_id, message *mess,
|
|
|
|
int *ipc_status)
|
|
|
|
{
|
|
|
|
/* Return and remove a message, including its IPC status, from the message
|
|
|
|
* queue of a thread. Return TRUE iff a message was available.
|
2007-01-12 14:33:12 +01:00
|
|
|
*/
|
2011-11-02 17:31:38 +01:00
|
|
|
struct mq_cell *cell;
|
|
|
|
|
|
|
|
assert(thread_id >= 0 && thread_id < DRIVER_MT_MAX_WORKERS);
|
|
|
|
|
|
|
|
if (STAILQ_EMPTY(&queue[thread_id]))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
cell = STAILQ_FIRST(&queue[thread_id]);
|
|
|
|
STAILQ_REMOVE_HEAD(&queue[thread_id], next);
|
|
|
|
|
|
|
|
*mess = cell->mess;
|
|
|
|
*ipc_status = cell->ipc_status;
|
|
|
|
|
|
|
|
STAILQ_INSERT_HEAD(&free_list, cell, next);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|