1 /* This file contains a simple message queue implementation to support both 2 * the singlethread and the multithreaded driver implementation. 3 * 4 * Changes: 5 * Oct 27, 2011 rewritten to use sys/queue.h (D.C. van Moolenbroek) 6 * Aug 27, 2011 integrated into libblockdriver (A. Welzel) 7 */ 8 9 #include <minix/blockdriver_mt.h> 10 #include <sys/queue.h> 11 #include <assert.h> 12 13 #include "const.h" 14 #include "mq.h" 15 16 #define MQ_SIZE 128 17 18 struct mq_cell { 19 message mess; 20 int ipc_status; 21 STAILQ_ENTRY(mq_cell) next; 22 }; 23 24 static struct mq_cell pool[MQ_SIZE]; 25 static STAILQ_HEAD(queue, mq_cell) queue[MAX_DEVICES]; 26 static STAILQ_HEAD(free_list, mq_cell) free_list; 27 28 /*===========================================================================* 29 * mq_init * 30 *===========================================================================*/ 31 void mq_init(void) 32 { 33 /* Initialize the message queues and message cells. 34 */ 35 int i; 36 37 STAILQ_INIT(&free_list); 38 39 for (i = 0; i < MAX_DEVICES; i++) 40 STAILQ_INIT(&queue[i]); 41 42 for (i = 0; i < MQ_SIZE; i++) 43 STAILQ_INSERT_HEAD(&free_list, &pool[i], next); 44 } 45 46 /*===========================================================================* 47 * mq_enqueue * 48 *===========================================================================*/ 49 int mq_enqueue(device_id_t device_id, const message *mess, 50 int ipc_status) 51 { 52 /* Add a message, including its IPC status, to the message queue of a device. 53 * Return TRUE iff the message was added successfully. 54 */ 55 struct mq_cell *cell; 56 57 assert(device_id >= 0 && device_id < MAX_DEVICES); 58 59 if (STAILQ_EMPTY(&free_list)) 60 return FALSE; 61 62 cell = STAILQ_FIRST(&free_list); 63 STAILQ_REMOVE_HEAD(&free_list, next); 64 65 cell->mess = *mess; 66 cell->ipc_status = ipc_status; 67 68 STAILQ_INSERT_TAIL(&queue[device_id], cell, next); 69 70 return TRUE; 71 } 72 73 /*===========================================================================* 74 * mq_dequeue * 75 *===========================================================================*/ 76 int mq_dequeue(device_id_t device_id, message *mess, int *ipc_status) 77 { 78 /* Return and remove a message, including its IPC status, from the message 79 * queue of a thread. Return TRUE iff a message was available. 80 */ 81 struct mq_cell *cell; 82 83 assert(device_id >= 0 && device_id < MAX_DEVICES); 84 85 if (STAILQ_EMPTY(&queue[device_id])) 86 return FALSE; 87 88 cell = STAILQ_FIRST(&queue[device_id]); 89 STAILQ_REMOVE_HEAD(&queue[device_id], next); 90 91 *mess = cell->mess; 92 *ipc_status = cell->ipc_status; 93 94 STAILQ_INSERT_HEAD(&free_list, cell, next); 95 96 return TRUE; 97 } 98