2 ** GNU Pth - The GNU Portable Threads
3 ** Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com>
5 ** This file is part of GNU Pth, a non-preemptive thread scheduling
6 ** library which can be found at http://www.gnu.org/software/pth/.
8 ** This library is free software; you can redistribute it and/or
9 ** modify it under the terms of the GNU Lesser General Public
10 ** License as published by the Free Software Foundation; either
11 ** version 2.1 of the License, or (at your option) any later version.
13 ** This library is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ** Lesser General Public License for more details.
18 ** You should have received a copy of the GNU Lesser General Public
19 ** License along with this library; if not, write to the Free Software
20 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 ** USA, or contact Ralf S. Engelschall <rse@engelschall.com>.
23 ** pth_pqueue.c: Pth thread priority queues
25 /* ``Real hackers can write assembly
26 code in any language''
32 /* thread priority queue */
33 struct pth_pqueue_st {
37 typedef struct pth_pqueue_st pth_pqueue_t;
41 /* initialize a priority queue; O(1) */
42 intern void pth_pqueue_init(pth_pqueue_t *q)
51 /* insert thread into priority queue; O(n) */
52 intern void pth_pqueue_insert(pth_pqueue_t *q, int prio, pth_t t)
59 if (q->q_head == NULL || q->q_num == 0) {
60 /* add as first element */
66 else if (q->q_head->q_prio < prio) {
67 /* add as new head of queue */
68 t->q_prev = q->q_head->q_prev;
69 t->q_next = q->q_head;
70 t->q_prev->q_next = t;
71 t->q_next->q_prev = t;
73 t->q_next->q_prio = prio - t->q_next->q_prio;
77 /* insert after elements with greater or equal priority */
80 while ((p - c->q_next->q_prio) >= prio && c->q_next != q->q_head) {
85 t->q_next = c->q_next;
86 t->q_prev->q_next = t;
87 t->q_next->q_prev = t;
89 if (t->q_next != q->q_head)
90 t->q_next->q_prio -= t->q_prio;
96 /* remove thread with maximum priority from priority queue; O(1) */
97 intern pth_t pth_pqueue_delmax(pth_pqueue_t *q)
103 if (q->q_head == NULL)
105 else if (q->q_head->q_next == q->q_head) {
106 /* remove the last element and make queue empty */
115 /* remove head of queue */
117 t->q_prev->q_next = t->q_next;
118 t->q_next->q_prev = t->q_prev;
119 t->q_next->q_prio = t->q_prio - t->q_next->q_prio;
121 q->q_head = t->q_next;
127 /* remove thread from priority queue; O(n) */
128 intern void pth_pqueue_delete(pth_pqueue_t *q, pth_t t)
132 if (q->q_head == NULL)
134 else if (q->q_head == t) {
135 if (t->q_next == t) {
136 /* remove the last element and make queue empty */
144 /* remove head of queue */
145 t->q_prev->q_next = t->q_next;
146 t->q_next->q_prev = t->q_prev;
147 t->q_next->q_prio = t->q_prio - t->q_next->q_prio;
149 q->q_head = t->q_next;
154 t->q_prev->q_next = t->q_next;
155 t->q_next->q_prev = t->q_prev;
156 if (t->q_next != q->q_head)
157 t->q_next->q_prio += t->q_prio;
164 /* determine priority required to favorite a thread; O(1) */
166 #define pth_pqueue_favorite_prio(q) \
167 ((q)->q_head != NULL ? (q)->q_head->q_prio + 1 : PTH_PRIO_MAX)
170 /* move a thread inside queue to the top; O(n) */
171 intern int pth_pqueue_favorite(pth_pqueue_t *q, pth_t t)
175 if (q->q_head == NULL || q->q_num == 0)
177 /* element is already at top */
181 pth_pqueue_delete(q, t);
182 pth_pqueue_insert(q, pth_pqueue_favorite_prio(q), t);
186 /* increase priority of all(!) threads in queue; O(1) */
187 intern void pth_pqueue_increase(pth_pqueue_t *q)
191 if (q->q_head == NULL)
193 /* <grin> yes, that's all ;-) */
194 q->q_head->q_prio += 1;
198 /* return number of elements in priority queue: O(1) */
200 #define pth_pqueue_elements(q) \
201 ((q) == NULL ? (-1) : (q)->q_num)
204 /* walk to first thread in queue; O(1) */
206 #define pth_pqueue_head(q) \
207 ((q) == NULL ? NULL : (q)->q_head)
210 /* walk to last thread in queue */
211 intern pth_t pth_pqueue_tail(pth_pqueue_t *q)
215 if (q->q_head == NULL)
217 return q->q_head->q_prev;
220 /* walk to next or previous thread in queue; O(1) */
221 intern pth_t pth_pqueue_walk(pth_pqueue_t *q, pth_t t, int direction)
225 if (q == NULL || t == NULL)
228 if (direction == PTH_WALK_PREV) {
232 else if (direction == PTH_WALK_NEXT) {
240 /* check whether a thread is in a queue; O(n) */
241 intern int pth_pqueue_contains(pth_pqueue_t *q, pth_t t)
247 for (tc = pth_pqueue_head(q); tc != NULL;
248 tc = pth_pqueue_walk(q, tc, PTH_WALK_NEXT)) {