/* 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 libblockdriver (A. Welzel) */ #include #include #include #include "const.h" #include "mq.h" #define MQ_SIZE 128 struct mq_cell { message mess; int ipc_status; STAILQ_ENTRY(mq_cell) next; }; static struct mq_cell pool[MQ_SIZE]; static STAILQ_HEAD(queue, mq_cell) queue[MAX_DEVICES]; static STAILQ_HEAD(free_list, mq_cell) free_list; /*===========================================================================* * mq_init * *===========================================================================*/ void mq_init(void) { /* Initialize the message queues and message cells. */ int i; STAILQ_INIT(&free_list); for (i = 0; i < MAX_DEVICES; i++) STAILQ_INIT(&queue[i]); for (i = 0; i < MQ_SIZE; i++) STAILQ_INSERT_HEAD(&free_list, &pool[i], next); } /*===========================================================================* * mq_enqueue * *===========================================================================*/ int mq_enqueue(device_id_t device_id, const message *mess, int ipc_status) { /* Add a message, including its IPC status, to the message queue of a device. * Return TRUE iff the message was added successfully. */ struct mq_cell *cell; assert(device_id >= 0 && device_id < MAX_DEVICES); 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[device_id], cell, next); return TRUE; } /*===========================================================================* * mq_dequeue * *===========================================================================*/ int mq_dequeue(device_id_t device_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. */ struct mq_cell *cell; assert(device_id >= 0 && device_id < MAX_DEVICES); if (STAILQ_EMPTY(&queue[device_id])) return FALSE; cell = STAILQ_FIRST(&queue[device_id]); STAILQ_REMOVE_HEAD(&queue[device_id], next); *mess = cell->mess; *ipc_status = cell->ipc_status; STAILQ_INSERT_HEAD(&free_list, cell, next); return TRUE; }