oskit/oskit-20020317/linux/shared/s_sched.c

192 lines
3.5 KiB
C
Executable File

/*
* Copyright (c) 1996-1999 The University of Utah and the Flux Group.
*
* This file is part of the OSKit Linux Glue Libraries, which are free
* software, also known as "open source;" you can redistribute them and/or
* modify them under the terms of the GNU General Public License (GPL),
* version 2, as published by the Free Software Foundation (FSF).
*
* The OSKit 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 GPL for more details. You should have
* received a copy of the GPL along with the OSKit; see the file COPYING. If
* not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
*/
/*
* Linux scheduler support.
*
* NOTE: These routines must carefully preserve the
* caller's interrupt flag.
*/
#include <linux/sched.h>
#include <asm/atomic.h>
#include "osenv.h"
/*
* Read the discussion in the linux source. Should the spinlock be under SMP?
*/
spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
void
__down(struct semaphore *sem)
{
struct task_struct *cur = current;
struct wait_queue wait = { cur, NULL };
unsigned long flags;
save_flags(flags);
cli();
__add_wait_queue(&sem->wait, &wait);
while (1) {
spin_lock(&semaphore_wake_lock);
if (sem->waking > 0) {
sem->waking--;
spin_unlock(&semaphore_wake_lock);
break;
}
spin_unlock(&semaphore_wake_lock);
osenv_sleep_init(&cur->sleeprec);
osenv_sleep(&cur->sleeprec);
}
__remove_wait_queue(&sem->wait, &wait);
current = cur;
restore_flags(flags);
}
void
__up(struct semaphore *sem)
{
unsigned long flags;
save_flags(flags);
cli();
spin_lock(&semaphore_wake_lock);
if (atomic_read(&sem->count) <= 0)
sem->waking++;
spin_unlock(&semaphore_wake_lock);
restore_flags(flags);
wake_up(&sem->wait);
}
static void
__sleep_on(struct wait_queue **q, int interruptible)
{
struct task_struct *cur = current;
struct wait_queue wait = { cur, NULL };
if (!q)
return;
osenv_sleep_init(&cur->sleeprec);
add_wait_queue(q, &wait);
osenv_sleep(&cur->sleeprec);
current = cur;
remove_wait_queue(q, &wait);
current = cur;
}
void
sleep_on(struct wait_queue **q)
{
__sleep_on(q, 0);
}
void
interruptible_sleep_on(struct wait_queue **q)
{
__sleep_on(q, 1);
}
long
interruptible_sleep_on_timeout(struct wait_queue **q, long timeo)
{
long residual;
/* XXX implement timeout */
residual = timeo;
__sleep_on(q, 1);
return residual;
}
void
__wake_up(struct wait_queue **q, unsigned int mode)
{
struct wait_queue *next;
struct wait_queue *head;
if (!q || !(next = *q))
return;
head = WAIT_QUEUE_HEAD(q);
while (next != head) {
struct task_struct *p = next->task;
next = next->next;
if (p != NULL) {
osenv_wakeup(&p->sleeprec, OSENV_SLEEP_WAKEUP);
}
if (!next)
panic("wait_queue is bad");
}
}
void
__wait_on_buffer(struct buffer_head *bh)
{
struct task_struct *cur = current;
struct wait_queue wait = { cur, NULL };
unsigned flags;
flags = linux_save_flags_cli();
__add_wait_queue(&bh->b_wait, &wait);
while (buffer_locked(bh)) {
osenv_sleep_init(&cur->sleeprec);
osenv_sleep(&cur->sleeprec);
}
current = cur;
__remove_wait_queue(&bh->b_wait, &wait);
linux_restore_flags(flags);
current = cur;
}
void
unlock_buffer(struct buffer_head *bh)
{
clear_bit (BH_Lock, &bh->b_state);
wake_up(&bh->b_wait);
}
/*
* schedule() should never be called in the oskit since we have
* no resource contention.
*/
void
schedule()
{
panic("SCHEDULE CALLED!\n");
}