Module Name: src Committed By: rmind Date: Sun Jul 19 02:26:49 UTC 2009
Modified Files: src/sys/kern: sys_mqueue.c src/sys/sys: mqueue.h Log Message: Fix previous, so that it actually works, correctly. To generate a diff of this commit: cvs rdiff -u -r1.22 -r1.23 src/sys/kern/sys_mqueue.c cvs rdiff -u -r1.8 -r1.9 src/sys/sys/mqueue.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/sys_mqueue.c diff -u src/sys/kern/sys_mqueue.c:1.22 src/sys/kern/sys_mqueue.c:1.23 --- src/sys/kern/sys_mqueue.c:1.22 Mon Jul 13 02:37:12 2009 +++ src/sys/kern/sys_mqueue.c Sun Jul 19 02:26:49 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: sys_mqueue.c,v 1.22 2009/07/13 02:37:12 rmind Exp $ */ +/* $NetBSD: sys_mqueue.c,v 1.23 2009/07/19 02:26:49 rmind Exp $ */ /* * Copyright (c) 2007-2009 Mindaugas Rasiukevicius <rmind at NetBSD org> @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.22 2009/07/13 02:37:12 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.23 2009/07/19 02:26:49 rmind Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -136,7 +136,8 @@ size_t msz; u_int i; - for (i = 0; i < (MQ_PQSIZE + 1); i++) { + /* Note MQ_PQSIZE + 1. */ + for (i = 0; i <= MQ_PQSIZE; i++) { while ((msg = TAILQ_FIRST(&mq->mq_head[i])) != NULL) { TAILQ_REMOVE(&mq->mq_head[i], msg, msg_queue); msz = sizeof(struct mq_msg) + msg->msg_len; @@ -199,20 +200,20 @@ /* * mqueue_linear_insert: perform linear insert according to the message - * priority into the reserved queue (note MQ_PQSIZE + 1). Reserved queue - * is a sorted list used only when mq_prio_max is increased via sysctl. + * priority into the reserved queue (MQ_PQRESQ). Reserved queue is a + * sorted list used only when mq_prio_max is increased via sysctl. */ static inline void mqueue_linear_insert(struct mqueue *mq, struct mq_msg *msg) { struct mq_msg *mit; - TAILQ_FOREACH(mit, &mq->mq_head[MQ_PQSIZE], msg_queue) { + TAILQ_FOREACH(mit, &mq->mq_head[MQ_PQRESQ], msg_queue) { if (msg->msg_prio > mit->msg_prio) break; } if (mit == NULL) { - TAILQ_INSERT_TAIL(&mq->mq_head[MQ_PQSIZE], msg, msg_queue); + TAILQ_INSERT_TAIL(&mq->mq_head[MQ_PQRESQ], msg, msg_queue); } else { TAILQ_INSERT_BEFORE(mit, msg, msg_queue); } @@ -543,7 +544,7 @@ struct mqueue *mq; struct mq_msg *msg = NULL; struct mq_attr *mqattr; - u_int prio; + u_int idx; int error; /* Get the message queue */ @@ -588,22 +589,24 @@ } } - /* Find the highest priority message */ - prio = ffs(mq->mq_bitmap); - if (__predict_false(prio == 0)) { - /* Must be in reserved queue then */ - prio = MQ_PQSIZE; - } - - /* Remove it from the queue */ - msg = TAILQ_FIRST(&mq->mq_head[prio]); - KASSERT(msg != NULL); - TAILQ_REMOVE(&mq->mq_head[prio], msg, msg_queue); - - /* Unmark the bit, if last message */ - if (__predict_true(prio != MQ_PQSIZE) && - TAILQ_EMPTY(&mq->mq_head[prio])) { - mq->mq_bitmap &= ~(MQ_PQMSB >> prio); + /* + * Find the highest priority message, and remove it from the queue. + * At first, reserved queue is checked, bitmap is next. + */ + msg = TAILQ_FIRST(&mq->mq_head[MQ_PQRESQ]); + if (__predict_true(msg == NULL)) { + idx = ffs(mq->mq_bitmap); + msg = TAILQ_FIRST(&mq->mq_head[idx]); + KASSERT(msg != NULL); + } else { + idx = MQ_PQRESQ; + } + TAILQ_REMOVE(&mq->mq_head[idx], msg, msg_queue); + + /* Unmark the bit, if last message. */ + if (__predict_true(idx) && TAILQ_EMPTY(&mq->mq_head[idx])) { + KASSERT((MQ_PQSIZE - idx) == msg->msg_prio); + mq->mq_bitmap &= ~(1 << --idx); } /* Decrement the counter and signal waiter, if any */ @@ -767,10 +770,16 @@ } KASSERT(mqattr->mq_curmsgs < mqattr->mq_maxmsg); - /* Insert message into the queue, according to the priority */ + /* + * Insert message into the queue, according to the priority. + * Note the difference between index and priority. + */ if (__predict_true(msg_prio < MQ_PQSIZE)) { - TAILQ_INSERT_TAIL(&mq->mq_head[msg_prio], msg, msg_queue); - mq->mq_bitmap |= (MQ_PQMSB >> msg_prio); + u_int idx = MQ_PQSIZE - msg_prio; + + KASSERT(idx != MQ_PQRESQ); + TAILQ_INSERT_TAIL(&mq->mq_head[idx], msg, msg_queue); + mq->mq_bitmap |= (1 << --idx); } else { mqueue_linear_insert(mq, msg); } Index: src/sys/sys/mqueue.h diff -u src/sys/sys/mqueue.h:1.8 src/sys/sys/mqueue.h:1.9 --- src/sys/sys/mqueue.h:1.8 Mon Jul 13 02:37:13 2009 +++ src/sys/sys/mqueue.h Sun Jul 19 02:26:49 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: mqueue.h,v 1.8 2009/07/13 02:37:13 rmind Exp $ */ +/* $NetBSD: mqueue.h,v 1.9 2009/07/19 02:26:49 rmind Exp $ */ /* * Copyright (c) 2007-2009 Mindaugas Rasiukevicius <rmind at NetBSD org> @@ -67,9 +67,9 @@ /* Default size of the message */ #define MQ_DEF_MSGSIZE 1024 -/* Size/bits and MSB for the queue array */ +/* Size/bits and index of reserved queue */ #define MQ_PQSIZE 32 -#define MQ_PQMSB 0x80000000U +#define MQ_PQRESQ 0 /* Structure of the message queue */ struct mqueue { @@ -89,7 +89,7 @@ gid_t mq_egid; /* Reference counter, queue array and bitmap */ u_int mq_refcnt; - TAILQ_HEAD(, mq_msg) mq_head[MQ_PQSIZE + 1]; + TAILQ_HEAD(, mq_msg) mq_head[1 + MQ_PQSIZE]; uint32_t mq_bitmap; /* Entry of the global list */ LIST_ENTRY(mqueue) mq_list;