163 lines
4.2 KiB
C
163 lines
4.2 KiB
C
|
#include <minix/mthread.h>
|
||
|
#include "global.h"
|
||
|
#include "proto.h"
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* mthread_queue_add *
|
||
|
*===========================================================================*/
|
||
|
void mthread_queue_add(queue, thread)
|
||
|
mthread_queue_t *queue; /* Queue we want thread to append to */
|
||
|
mthread_thread_t thread;
|
||
|
{
|
||
|
/* Append a thread to the tail of the queue. As a process can be present on
|
||
|
* only one queue at the same time, we can use the threads array's 'next'
|
||
|
* pointer to point to the next thread on the queue.
|
||
|
*/
|
||
|
mthread_tcb_t *last;
|
||
|
|
||
|
if (!isokthreadid(thread))
|
||
|
mthread_panic("Can't append invalid thread ID to a queue");
|
||
|
|
||
|
last = mthread_find_tcb(thread);
|
||
|
|
||
|
if (mthread_queue_isempty(queue)) {
|
||
|
queue->mq_head = queue->mq_tail = last;
|
||
|
} else {
|
||
|
queue->mq_tail->m_next = last;
|
||
|
queue->mq_tail = last; /* 'last' is the new last in line */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* mthread_queue_init *
|
||
|
*===========================================================================*/
|
||
|
void mthread_queue_init(queue)
|
||
|
mthread_queue_t *queue; /* Queue that has to be initialized */
|
||
|
{
|
||
|
/* Initialize queue to a known state */
|
||
|
|
||
|
queue->mq_head = queue->mq_tail = NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* mthread_queue_isempty *
|
||
|
*===========================================================================*/
|
||
|
int mthread_queue_isempty(queue)
|
||
|
mthread_queue_t *queue;
|
||
|
{
|
||
|
return(queue->mq_head == NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* mthread_dump_queue *
|
||
|
*===========================================================================*/
|
||
|
#ifdef MDEBUG
|
||
|
void mthread_dump_queue(queue)
|
||
|
mthread_queue_t *queue;
|
||
|
{
|
||
|
int threshold, count = 0;
|
||
|
mthread_tcb_t *t;
|
||
|
mthread_thread_t tid;
|
||
|
threshold = no_threads;
|
||
|
printf("Dumping queue: ");
|
||
|
|
||
|
if(queue->mq_head != NULL) {
|
||
|
t = queue->mq_head;
|
||
|
if (t == &mainthread) tid = MAIN_THREAD;
|
||
|
else tid = t->m_tid;
|
||
|
printf("%d ", tid);
|
||
|
count++;
|
||
|
t = t->m_next;
|
||
|
while (t != NULL) {
|
||
|
if (t == &mainthread) tid = MAIN_THREAD;
|
||
|
else tid = t->m_tid;
|
||
|
printf("%d ", tid);
|
||
|
t = t->m_next;
|
||
|
count++;
|
||
|
if (count > threshold) break;
|
||
|
}
|
||
|
} else {
|
||
|
printf("[empty]");
|
||
|
}
|
||
|
|
||
|
printf("\n");
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* mthread_queue_remove *
|
||
|
*===========================================================================*/
|
||
|
mthread_thread_t mthread_queue_remove(queue)
|
||
|
mthread_queue_t *queue; /* Queue we want a thread from */
|
||
|
{
|
||
|
/* Get the first thread in this queue, if there is one. */
|
||
|
mthread_thread_t thread;
|
||
|
mthread_tcb_t *tcb, *random_tcb, *prev;
|
||
|
int count = 0, offset_id = 0, picked_random = 0;
|
||
|
|
||
|
tcb = queue->mq_head;
|
||
|
|
||
|
if (MTHREAD_RND_SCHED) {
|
||
|
/* Count items on queue */
|
||
|
random_tcb = queue->mq_head;
|
||
|
if (random_tcb != NULL) {
|
||
|
do {
|
||
|
count++;
|
||
|
random_tcb = random_tcb->m_next;
|
||
|
} while (random_tcb != NULL);
|
||
|
}
|
||
|
|
||
|
if (count > 1) {
|
||
|
picked_random = 1;
|
||
|
|
||
|
/* Get random offset */
|
||
|
offset_id = random() % count;
|
||
|
|
||
|
/* Find offset in queue */
|
||
|
random_tcb = queue->mq_head;
|
||
|
prev = random_tcb;
|
||
|
while (--offset_id > 0) {
|
||
|
prev = random_tcb;
|
||
|
random_tcb = random_tcb->m_next;
|
||
|
}
|
||
|
|
||
|
/* Stitch head and tail together */
|
||
|
prev->m_next = random_tcb->m_next;
|
||
|
|
||
|
/* Fix head and tail */
|
||
|
if (queue->mq_head == random_tcb)
|
||
|
queue->mq_head = random_tcb->m_next;
|
||
|
if (queue->mq_tail == random_tcb)
|
||
|
queue->mq_tail = prev;
|
||
|
|
||
|
tcb = random_tcb;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Retrieve thread id from tcb */
|
||
|
if (tcb == NULL) thread = NO_THREAD;
|
||
|
else if (tcb == &mainthread) thread = MAIN_THREAD;
|
||
|
else thread = (tcb->m_tid);
|
||
|
|
||
|
/* If we didn't pick a random thread and queue is not empty... */
|
||
|
if (!picked_random && thread != NO_THREAD) {
|
||
|
tcb = queue->mq_head;
|
||
|
if (queue->mq_head == queue->mq_tail) {
|
||
|
/* Queue holds only one thread */
|
||
|
queue->mq_head = queue->mq_tail = NULL; /* So mark thread empty */
|
||
|
} else {
|
||
|
/* Second thread in line is the new first */
|
||
|
queue->mq_head = queue->mq_head->m_next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (tcb != NULL)
|
||
|
tcb->m_next = NULL; /* This thread is no longer part of a queue */
|
||
|
|
||
|
return(thread);
|
||
|
}
|
||
|
|