/* * Copyright (C) 1997-2000 SpellCaster Telecommunications Inc. * $Id: msgq.h,v 1.1 2004/03/11 03:59:31 bcrl Exp $ * Released under the GNU Public License. See LICENSE file for details. */ #include #include #include #include #include #include #include "vercomp.h" struct qMsg { struct qMsg *next; struct qMsg *prev; void *data; int len; }; struct MsgQ { struct qMsg *msgQ; wait_queue_head_t wait; }; extern inline void initMsgQ(struct MsgQ *q) { init_waitqueue_head(&q->wait); } int queueMsg ( struct MsgQ *q, void *data, int len ) { struct qMsg *msg; unsigned long flags; msg = kmalloc(sizeof(struct qMsg) + len, GFP_ATOMIC); if (!msg) return -ENOMEM; msg->data = msg+1; msg->len = len; memcpy(msg->data, data, len); save_flags(flags); cli(); if (!q->msgQ) { msg->next = msg; msg->prev = msg; q->msgQ = msg; } else { msg->next = q->msgQ; msg->prev = q->msgQ->prev; msg->prev->next = msg; msg->next->prev = msg; } restore_flags(flags); wake_up_interruptible(&q->wait); return 0; } struct qMsg *getMsg (struct MsgQ *q) { struct qMsg *msg; cli(); msg = q->msgQ; if (msg) { if (q->msgQ == q->msgQ->next) q->msgQ = NULL; else { q->msgQ->prev->next = q->msgQ->next; q->msgQ->next->prev = q->msgQ->prev; q->msgQ = q->msgQ->next; } } sti(); return msg; } struct qMsg *waitMsg(struct MsgQ *q) { DECLARE_WAITQUEUE(wait, current); struct qMsg *msg = NULL; current->state = TASK_INTERRUPTIBLE; add_wait_queue(&q->wait, &wait); while (!q->msgQ || !(msg = getMsg(q))) { schedule(); if (signal_pending(current)) break; } current->state = TASK_RUNNING; remove_wait_queue(&q->wait, &wait); return msg; }