244 lines
7.0 KiB
C
244 lines
7.0 KiB
C
/* Copyright (C) 1986 Sun Microsystems Inc. */
|
|
/*
|
|
* This source code is a product of Sun Microsystems, Inc. and is provided
|
|
* for unrestricted use provided that this legend is included on all tape
|
|
* media and as a part of the software program in whole or part. Users
|
|
* may copy or modify this source code without charge, but are not authorized
|
|
* to license or distribute it to anyone else except as part of a product or
|
|
* program developed by the user.
|
|
*
|
|
* THIS PROGRAM CONTAINS SOURCE CODE COPYRIGHTED BY SUN MICROSYSTEMS, INC.
|
|
* AND IS LICENSED TO SUNSOFT, INC., A SUBSIDIARY OF SUN MICROSYSTEMS, INC.
|
|
* SUN MICROSYSTEMS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABLITY
|
|
* OF SUCH SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT
|
|
* EXPRESS OR IMPLIED WARRANTY OF ANY KIND. SUN MICROSYSTEMS, INC. DISCLAIMS
|
|
* ALL WARRANTIES WITH REGARD TO SUCH SOURCE CODE, INCLUDING ALL IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN
|
|
* NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT,
|
|
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
|
* FROM USE OF SUCH SOURCE CODE, REGARDLESS OF THE THEORY OF LIABILITY.
|
|
*
|
|
* This source code is provided with no support and without any obligation on
|
|
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
|
* modification or enhancement.
|
|
*
|
|
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
|
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS
|
|
* SOURCE CODE OR ANY PART THEREOF.
|
|
*
|
|
* Sun Microsystems, Inc.
|
|
* 2550 Garcia Avenue
|
|
* Mountain View, California 94043
|
|
*/
|
|
#include <lwp/common.h>
|
|
#include <lwp/queue.h>
|
|
#include <lwp/asynch.h>
|
|
#include <machlwp/machsig.h>
|
|
#include <machlwp/machdep.h>
|
|
#include <lwp/cntxt.h>
|
|
#include <lwp/lwperror.h>
|
|
#include <lwp/schedule.h>
|
|
#include <lwp/alloc.h>
|
|
#include <lwp/agent.h>
|
|
#include <lwp/clock.h>
|
|
#include <lwp/condvar.h>
|
|
#include <machlwp/except.h>
|
|
#include <lwp/message.h>
|
|
#include <lwp/process.h>
|
|
#include <lwp/monitor.h>
|
|
#ifndef lint
|
|
SCCSID(@(#) schedule.c 1.1 94/10/31 Copyr 1986 Sun Micro);
|
|
#endif lint
|
|
|
|
#ifndef SHAREDLIB
|
|
int __LwpLibInit = 0; /* non-zero if initialized */
|
|
#endif SHAREDLIB
|
|
int __HighPrio; /* highest priority current runnable lwp */
|
|
lwp_t Nullproc; /* have something for lwp_errno until init */
|
|
lwp_t *__Curproc = &Nullproc; /* the current running process */
|
|
qheader_t *__RunQ = QHNULL; /* set of run queues (1 per priority) */
|
|
int __MaxPrio = MINPRIO; /* highest available scheduling priority */
|
|
int __UniqId = 0; /* unique id for locks and keys */
|
|
|
|
/*
|
|
* PRIMITIVES contained herein:
|
|
* pod_setmaxpri(prio)
|
|
* pod_getmaxsize()
|
|
* pod_getmaxpri()
|
|
*/
|
|
|
|
/*
|
|
* pod_getmaxsize() -- PRIMITIVE.
|
|
* Return maximum possible size of pod.
|
|
*/
|
|
int
|
|
pod_getmaxsize()
|
|
{
|
|
return (MAXPRIO);
|
|
}
|
|
|
|
/*
|
|
* pod_getmaxpri() -- PRIMITIVE.
|
|
* Return current highest legal prio for pod.
|
|
*/
|
|
int
|
|
pod_getmaxpri()
|
|
{
|
|
return (__MaxPrio);
|
|
}
|
|
|
|
/*
|
|
* pod_setmaxpri -- PRIMITIVE.
|
|
* set maximum pod size. Visible priorities range from MINPRIO to __Maxprio
|
|
* so there are a total of __MaxPrio+1 priorities since we always allocate
|
|
* a priority (NUGPRIO) for the library. In reality, priorities
|
|
* range from [NUGPRIO .. __MaxPrio].
|
|
*/
|
|
int
|
|
pod_setmaxpri(prio)
|
|
int prio; /* new number of scheduling priorities */
|
|
{
|
|
qheader_t *tempq = QHNULL;
|
|
register int i;
|
|
|
|
if (__LwpLibInit == 0) { /* initialize by hand to avoid 2 MEM_ALLOCS */
|
|
__MaxPrio = prio;
|
|
__LwpLibInit++;
|
|
__lwp_init();
|
|
return (0);
|
|
}
|
|
LOCK();
|
|
ERROR((prio > MAXPRIO), LE_NOROOM);
|
|
ERROR((prio < __MaxPrio), LE_INVALIDARG);
|
|
if (prio == __MaxPrio) {
|
|
UNLOCK();
|
|
return (0);
|
|
}
|
|
tempq = (qheader_t *)MEM_ALLOC(sizeof (qheader_t) * (prio + 1));
|
|
if ((tempq == QHNULL) || (__RunQ == QHNULL)) {
|
|
__panic("Can't create pod");
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
/* copy RunQ to tempq */
|
|
for (i = NUGPRIO; i <= __MaxPrio; i++) {
|
|
tempq[i].hq_head = __RunQ[i].hq_head;
|
|
tempq[i].hq_tail = __RunQ[i].hq_tail;
|
|
}
|
|
MEM_FREE(__RunQ, (sizeof (qheader_t) * (__MaxPrio + 1)));
|
|
__MaxPrio = prio;
|
|
__RunQ = tempq;
|
|
UNLOCK();
|
|
for (i = 0; i < __SlaveThreads; i++) {
|
|
if (!SAMETHREAD(__Slaves[i], THREADNULL))
|
|
(void)lwp_setpri(__Slaves[i], __MaxPrio);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* __lwp_init: initialize library.
|
|
* N.B. Order of initialization is important.
|
|
*/
|
|
void
|
|
__lwp_init()
|
|
{
|
|
thread_t idlethread;
|
|
extern void __init_util();
|
|
|
|
INIT_QUEUE(&Nullproc.lwp_ctx);
|
|
Nullproc.lwp_prio = NUGPRIO;
|
|
__RunQ = (qheader_t *)MEM_ALLOC(sizeof (qheader_t) * (__MaxPrio + 1));
|
|
__HighPrio = NUGPRIO;
|
|
__init_lwp();
|
|
__init_sig();
|
|
__init_asynch();
|
|
__init_agent();
|
|
__init_msg();
|
|
__init_mon();
|
|
__init_exc();
|
|
__init_cv();
|
|
__init_clock();
|
|
__init_machdep();
|
|
__init_ctx();
|
|
__init_stks();
|
|
__init_util();
|
|
__maincreate();
|
|
|
|
/* don't use LWPSERVER flag: this guy runs at lowest priority */
|
|
(void)lwp_create(&idlethread, __idle, MINPRIO, 0,
|
|
(stkalign_t *)&__IdleStack[IDLESTACK], 0);
|
|
|
|
/* give idle lower than legal (for client) priority */
|
|
REMX_ITEM(&__RunQ[MINPRIO], idlethread.thread_id);
|
|
INS_QUEUE(&__RunQ[NUGPRIO], idlethread.thread_id);
|
|
((lwp_t *)(idlethread.thread_id))->lwp_prio = NUGPRIO;
|
|
((lwp_t *)(idlethread.thread_id))->lwp_lock = UNIQUEID();
|
|
}
|
|
|
|
/*
|
|
* Scheduler loop for the set of lwps.
|
|
* Find the highest priority runnable lwp and set it going.
|
|
* Note that __HighPrio can be the priority of the process that
|
|
* last did a WAIT but may not be the priority of the next
|
|
* eligible process. In the worst case, since the process that did the WAIT
|
|
* was at the highest priority currently, only a priority less than
|
|
* __HighPrio can be eligible.
|
|
* If returning from an interrupt to the same process, it is probably cheaper
|
|
* to restore the saved context than to return back through the call
|
|
* chain to the rti.
|
|
* We had to always save full context on interrupt because we didn't know
|
|
* in advance if this would be the case.
|
|
*/
|
|
void
|
|
__schedule()
|
|
{
|
|
register int i;
|
|
register lwp_t *oldproc = __Curproc;
|
|
register lwp_t *newproc;
|
|
register qheader_t *rq;
|
|
LOCK();
|
|
LWPTRACE(tr_SCHEDULE, 5, ("scheduling\n"));
|
|
for (i = __HighPrio; i >= NUGPRIO; i--, __HighPrio--) {
|
|
rq = &__RunQ[i];
|
|
if (!ISEMPTYQ(rq)) {
|
|
newproc = __Curproc = (lwp_t *)FIRSTQ(rq);
|
|
if (((oldproc != LWPNULL) && !ISEMPTYQ(&oldproc->lwp_ctx))
|
|
|| !ISEMPTYQ(&newproc->lwp_ctx)) {
|
|
__ctx_change(oldproc, newproc);
|
|
}
|
|
LWPTRACE(tr_SCHEDULE, 2,
|
|
("about to schedule %x\n", (int)__Curproc));
|
|
if (!newproc->lwp_full && (__SigLocked == 0)) {
|
|
|
|
/*
|
|
* do a simple context switch (only non-volatile
|
|
* registers, no temps or sr.)
|
|
* This is the case on a yield or where
|
|
* there is no asynchronous event indirectly
|
|
* responsible for the context switch (i.e.,
|
|
* waiting for a monitor or a message).
|
|
*/
|
|
|
|
LWPTRACE(tr_SCHEDULE, 2, ("swtch call\n"));
|
|
CSWTCH();
|
|
} else {
|
|
|
|
/*
|
|
* do a full context switch, restoring temps, sr,
|
|
* etc., as needed.
|
|
*/
|
|
|
|
LWPTRACE(tr_SCHEDULE, 2, ("full swtch call\n"));
|
|
__full_swtch();
|
|
}
|
|
__panic("return from swtch");
|
|
/* NOTREACHED */
|
|
}
|
|
}
|
|
UNLOCK();
|
|
LWPTRACE(tr_SCHEDULE, 1, ("schedule exiting\n"));
|
|
HALT();
|
|
/* NOTREACHED */
|
|
}
|