/* IPC message queues. Copyright 1999, 2000, 2001 Johan Rydberg, jrydberg@opencores.org. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "tm.h" #include "ipc-mqueue.h" #include "ipc-kmsg.h" #include "vm-slab.h" #include "trace.h" /* Cache for ipc mqueue structures. */ static struct kmem_cache *mqueue_cache; /* Initialize the message queue system. */ void ipc_mqueue_init (void) { mqueue_cache = kmem_cache_create ("ipc mqueue cache", sizeof (struct ipc_mqueue), 0); assert (mqueue_cache); } /* Create a new message queue for a port. Returns a new queue with default queue limit, NULL if we can not allocate memory. */ struct ipc_mqueue * ipc_mqueue_create (void) { struct ipc_mqueue *imq; imq = (struct ipc_mqueue *) kmem_cache_alloc (mqueue_cache); if (imq == 0) return (struct ipc_mqueue *) 0; queue_init (&imq->queue); imq->qlimit = RTMK_PORT_QLIMIT_DEFAULT; imq->msgcount = 0; return imq; } /* Destroy message queue, releasing all messages on it. */ void ipc_mqueue_destroy (struct ipc_mqueue *imq) { struct ipc_kmsg *ikm, *next; /* First of all we free all messages in the queue. That is, if we have any. */ if (imq->msgcount > 0) { for (ikm = (struct ipc_kmsg *) queue_first (&imq->queue); !queue_end (&imq->queue, &ikm->link);) { next = (struct ipc_kmsg *) queue_next (&ikm->link); ipc_kmsg_free (ikm); ikm = next; } } kmem_cache_free (mqueue_cache, imq); } /* This function tries to enqueue a kernel message on the message queue. It returns false on success. If it failes (the queue has reaced its limit), it returns true (the message is NOT queued). If OVERRUN_P is true we enqueue the message anyway. */ bool ipc_mqueue_enqueue (struct ipc_mqueue *imq, struct ipc_kmsg *ikm, bool overrun_p) { if (overrun_p == false && imq->msgcount == (imq->qlimit - 1)) return true; imq->msgcount++; enqueue_tail (&imq->queue, &ikm->link); return false; } /* Dequeue a kernel message from IMQ. */ struct ipc_kmsg * ipc_mqueue_dequeue (struct ipc_mqueue *imq) { struct ipc_kmsg *ikm; if (imq->msgcount == 0) return (struct ipc_kmsg *) 0; imq->msgcount--; ikm = (struct ipc_kmsg *) dequeue_head (&imq->queue); return ikm; } /* Move all messages from SRC to message queue IMQ. */ void ipc_mqueue_move (struct ipc_mqueue *imq, struct ipc_mqueue *src) { struct ipc_kmsg *ikm; while (src->msgcount) { ikm = (struct ipc_kmsg *) dequeue_head (&src->queue); src->msgcount--; enqueue_tail (&imq->queue, &ikm->link); imq->msgcount++; } }