1*433d6423SLionel Sambuc #include <minix/mthread.h>
2*433d6423SLionel Sambuc #include "global.h"
3*433d6423SLionel Sambuc #include "proto.h"
4*433d6423SLionel Sambuc
5*433d6423SLionel Sambuc /*===========================================================================*
6*433d6423SLionel Sambuc * mthread_queue_add *
7*433d6423SLionel Sambuc *===========================================================================*/
mthread_queue_add(queue,thread)8*433d6423SLionel Sambuc void mthread_queue_add(queue, thread)
9*433d6423SLionel Sambuc mthread_queue_t *queue; /* Queue we want thread to append to */
10*433d6423SLionel Sambuc mthread_thread_t thread;
11*433d6423SLionel Sambuc {
12*433d6423SLionel Sambuc /* Append a thread to the tail of the queue. As a process can be present on
13*433d6423SLionel Sambuc * only one queue at the same time, we can use the threads array's 'next'
14*433d6423SLionel Sambuc * pointer to point to the next thread on the queue.
15*433d6423SLionel Sambuc */
16*433d6423SLionel Sambuc mthread_tcb_t *last;
17*433d6423SLionel Sambuc
18*433d6423SLionel Sambuc if (!isokthreadid(thread))
19*433d6423SLionel Sambuc mthread_panic("Can't append invalid thread ID to a queue");
20*433d6423SLionel Sambuc
21*433d6423SLionel Sambuc last = mthread_find_tcb(thread);
22*433d6423SLionel Sambuc
23*433d6423SLionel Sambuc if (mthread_queue_isempty(queue)) {
24*433d6423SLionel Sambuc queue->mq_head = queue->mq_tail = last;
25*433d6423SLionel Sambuc } else {
26*433d6423SLionel Sambuc queue->mq_tail->m_next = last;
27*433d6423SLionel Sambuc queue->mq_tail = last; /* 'last' is the new last in line */
28*433d6423SLionel Sambuc }
29*433d6423SLionel Sambuc }
30*433d6423SLionel Sambuc
31*433d6423SLionel Sambuc
32*433d6423SLionel Sambuc /*===========================================================================*
33*433d6423SLionel Sambuc * mthread_queue_init *
34*433d6423SLionel Sambuc *===========================================================================*/
mthread_queue_init(queue)35*433d6423SLionel Sambuc void mthread_queue_init(queue)
36*433d6423SLionel Sambuc mthread_queue_t *queue; /* Queue that has to be initialized */
37*433d6423SLionel Sambuc {
38*433d6423SLionel Sambuc /* Initialize queue to a known state */
39*433d6423SLionel Sambuc
40*433d6423SLionel Sambuc queue->mq_head = queue->mq_tail = NULL;
41*433d6423SLionel Sambuc }
42*433d6423SLionel Sambuc
43*433d6423SLionel Sambuc
44*433d6423SLionel Sambuc /*===========================================================================*
45*433d6423SLionel Sambuc * mthread_queue_isempty *
46*433d6423SLionel Sambuc *===========================================================================*/
mthread_queue_isempty(queue)47*433d6423SLionel Sambuc int mthread_queue_isempty(queue)
48*433d6423SLionel Sambuc mthread_queue_t *queue;
49*433d6423SLionel Sambuc {
50*433d6423SLionel Sambuc return(queue->mq_head == NULL);
51*433d6423SLionel Sambuc }
52*433d6423SLionel Sambuc
53*433d6423SLionel Sambuc
54*433d6423SLionel Sambuc /*===========================================================================*
55*433d6423SLionel Sambuc * mthread_dump_queue *
56*433d6423SLionel Sambuc *===========================================================================*/
57*433d6423SLionel Sambuc #ifdef MDEBUG
mthread_dump_queue(queue)58*433d6423SLionel Sambuc void mthread_dump_queue(queue)
59*433d6423SLionel Sambuc mthread_queue_t *queue;
60*433d6423SLionel Sambuc {
61*433d6423SLionel Sambuc int threshold, count = 0;
62*433d6423SLionel Sambuc mthread_tcb_t *t;
63*433d6423SLionel Sambuc mthread_thread_t tid;
64*433d6423SLionel Sambuc threshold = no_threads;
65*433d6423SLionel Sambuc printf("Dumping queue: ");
66*433d6423SLionel Sambuc
67*433d6423SLionel Sambuc if(queue->mq_head != NULL) {
68*433d6423SLionel Sambuc t = queue->mq_head;
69*433d6423SLionel Sambuc if (t == &mainthread) tid = MAIN_THREAD;
70*433d6423SLionel Sambuc else tid = t->m_tid;
71*433d6423SLionel Sambuc printf("%d ", tid);
72*433d6423SLionel Sambuc count++;
73*433d6423SLionel Sambuc t = t->m_next;
74*433d6423SLionel Sambuc while (t != NULL) {
75*433d6423SLionel Sambuc if (t == &mainthread) tid = MAIN_THREAD;
76*433d6423SLionel Sambuc else tid = t->m_tid;
77*433d6423SLionel Sambuc printf("%d ", tid);
78*433d6423SLionel Sambuc t = t->m_next;
79*433d6423SLionel Sambuc count++;
80*433d6423SLionel Sambuc if (count > threshold) break;
81*433d6423SLionel Sambuc }
82*433d6423SLionel Sambuc } else {
83*433d6423SLionel Sambuc printf("[empty]");
84*433d6423SLionel Sambuc }
85*433d6423SLionel Sambuc
86*433d6423SLionel Sambuc printf("\n");
87*433d6423SLionel Sambuc }
88*433d6423SLionel Sambuc #endif
89*433d6423SLionel Sambuc
90*433d6423SLionel Sambuc /*===========================================================================*
91*433d6423SLionel Sambuc * mthread_queue_remove *
92*433d6423SLionel Sambuc *===========================================================================*/
mthread_queue_remove(queue)93*433d6423SLionel Sambuc mthread_thread_t mthread_queue_remove(queue)
94*433d6423SLionel Sambuc mthread_queue_t *queue; /* Queue we want a thread from */
95*433d6423SLionel Sambuc {
96*433d6423SLionel Sambuc /* Get the first thread in this queue, if there is one. */
97*433d6423SLionel Sambuc mthread_thread_t thread;
98*433d6423SLionel Sambuc mthread_tcb_t *tcb, *random_tcb, *prev;
99*433d6423SLionel Sambuc int count = 0, offset_id = 0, picked_random = 0;
100*433d6423SLionel Sambuc
101*433d6423SLionel Sambuc tcb = queue->mq_head;
102*433d6423SLionel Sambuc
103*433d6423SLionel Sambuc if (MTHREAD_RND_SCHED) {
104*433d6423SLionel Sambuc /* Count items on queue */
105*433d6423SLionel Sambuc random_tcb = queue->mq_head;
106*433d6423SLionel Sambuc if (random_tcb != NULL) {
107*433d6423SLionel Sambuc do {
108*433d6423SLionel Sambuc count++;
109*433d6423SLionel Sambuc random_tcb = random_tcb->m_next;
110*433d6423SLionel Sambuc } while (random_tcb != NULL);
111*433d6423SLionel Sambuc }
112*433d6423SLionel Sambuc
113*433d6423SLionel Sambuc if (count > 1) {
114*433d6423SLionel Sambuc picked_random = 1;
115*433d6423SLionel Sambuc
116*433d6423SLionel Sambuc /* Get random offset */
117*433d6423SLionel Sambuc offset_id = random() % count;
118*433d6423SLionel Sambuc
119*433d6423SLionel Sambuc /* Find offset in queue */
120*433d6423SLionel Sambuc random_tcb = queue->mq_head;
121*433d6423SLionel Sambuc prev = random_tcb;
122*433d6423SLionel Sambuc while (--offset_id > 0) {
123*433d6423SLionel Sambuc prev = random_tcb;
124*433d6423SLionel Sambuc random_tcb = random_tcb->m_next;
125*433d6423SLionel Sambuc }
126*433d6423SLionel Sambuc
127*433d6423SLionel Sambuc /* Stitch head and tail together */
128*433d6423SLionel Sambuc prev->m_next = random_tcb->m_next;
129*433d6423SLionel Sambuc
130*433d6423SLionel Sambuc /* Fix head and tail */
131*433d6423SLionel Sambuc if (queue->mq_head == random_tcb)
132*433d6423SLionel Sambuc queue->mq_head = random_tcb->m_next;
133*433d6423SLionel Sambuc if (queue->mq_tail == random_tcb)
134*433d6423SLionel Sambuc queue->mq_tail = prev;
135*433d6423SLionel Sambuc
136*433d6423SLionel Sambuc tcb = random_tcb;
137*433d6423SLionel Sambuc }
138*433d6423SLionel Sambuc }
139*433d6423SLionel Sambuc
140*433d6423SLionel Sambuc /* Retrieve thread id from tcb */
141*433d6423SLionel Sambuc if (tcb == NULL) thread = NO_THREAD;
142*433d6423SLionel Sambuc else if (tcb == &mainthread) thread = MAIN_THREAD;
143*433d6423SLionel Sambuc else thread = (tcb->m_tid);
144*433d6423SLionel Sambuc
145*433d6423SLionel Sambuc /* If we didn't pick a random thread and queue is not empty... */
146*433d6423SLionel Sambuc if (!picked_random && thread != NO_THREAD) {
147*433d6423SLionel Sambuc tcb = queue->mq_head;
148*433d6423SLionel Sambuc if (queue->mq_head == queue->mq_tail) {
149*433d6423SLionel Sambuc /* Queue holds only one thread */
150*433d6423SLionel Sambuc queue->mq_head = queue->mq_tail = NULL; /* So mark thread empty */
151*433d6423SLionel Sambuc } else {
152*433d6423SLionel Sambuc /* Second thread in line is the new first */
153*433d6423SLionel Sambuc queue->mq_head = queue->mq_head->m_next;
154*433d6423SLionel Sambuc }
155*433d6423SLionel Sambuc }
156*433d6423SLionel Sambuc
157*433d6423SLionel Sambuc if (tcb != NULL)
158*433d6423SLionel Sambuc tcb->m_next = NULL; /* This thread is no longer part of a queue */
159*433d6423SLionel Sambuc
160*433d6423SLionel Sambuc return(thread);
161*433d6423SLionel Sambuc }
162*433d6423SLionel Sambuc
163