/* begincopyright
  Copyright (c) 1988 Xerox Corporation. All rights reserved.
  Use and copying of this software and preparation of derivative works based
  upon this software are permitted. Any distribution of this software or
  derivative works must comply with all applicable United States export
  control laws. This software is made available AS IS, and Xerox Corporation
  makes no warranty about the software, its performance or its conformity to
  any specification. Any person obtaining a copy of this software is requested
  to send their name and post office or electronic mail address to:
    PCR Coordinator
    Xerox PARC
    3333 Coyote Hill Rd.
    Palo Alto, CA 94304
  endcopyright */

/*
 * ThreadsSchedCtl.h
 *
 * Demers, February 6, 1990 7:41:00 pm PST
 *
 * Scheduling control
 */

#ifndef XR←BASIC←TYPES←
#   include "BasicTypes.h"
#endif

#ifndef ←XR←THREADS←
#   include "Threads.h"
#endif


/*
 * Global sched control lock
 */


extern int /* 0 or -errno */
XR←SchedCtlLock(/* bool wait */);
/*
    Acquire lock for global SchedCtl operations.
    The wait is abortable.
*/

extern int /* 0 or -errno */
XR←SchedCtlUnlock();


/*
 * Scheduler control operations ...
 *
 * Should be called only from a thread.
 * For some operations, caller must hold schedCtl lock.
 */


/* thread groups */

typedef unsigned long XR←SchedCtlWhich;

#define XR←SchedCtlWhichSelf() \
	((XR←SchedCtlWhich)(-1))
#define XR←SchedCtlWhichIsSelf(w) \
	((w) == XR←SchedCtlWhichSelf())

#define XR←SchedCtlWhichFromPri(pri) \
	((XR←SchedCtlWhich)(pri))
#define XR←SchedCtlWhichToPri(w) \
	((XR←Pri)(w))
#define XR←SchedCtlWhichIsPri(w) \
	( (((XR←Pri)(w)) > XR←PRI←IDLE) && (((XR←Pri)(w)) <= XR←PRI←LAST) )

#define XR←SchedCtlWhichFromThread(t) \
	((XR←SchedCtlWhich)(t))
#define XR←SchedCtlWhichToThread(w) \
	((XR←Thread)(w))
#define XR←SchedCtlWhichIsThread(w) \
	( (((XR←Pri)(w)) > XR←PRI←LAST)) && (!XR←SchedCtlWhichIsSelf(w)) )


/* schedCtl ops */

typedef enum {
    scop←nop = 0,
    scop←getProcessor = 1,
    scop←setProcessor = 2,
    scop←getPriority = 3,
    scop←setPriority = 4,
    scop←disable = 5,
    scop←enable = 6,
    scop←lastInvalid = 0x7fffffff
} XR←SchedCtlOp;



extern int /* result >= 0 or -errno */
XR←SchedCtl(/*
    XR←SchedCtlWhich which,
    XR←SchedCtlOp op,
    unsigned long *argp
*/);
/*
    Execute the specified opcode, changing scheduling parameters
      for threads identified by which.
    If which is not SELF, the caller must hold the schedCtl lock.
    Don't wait for the command to take effect on all processors
      (see XR←SchedCtlWait below).
    Return an op-specific nonnegative value on success,
      or (-XR←GetErrno()) on failure.


    Op == scop←nop
    
      Do nothing

    Op == scop←setProcessor
    Op == scop←getProcessor

      Set/get processor on which specified threads may be scheduled.
      Arg values:
*/

#       define scop←ProcessorRestrictedBit(i) \
		(01 << (i))
#       define scop←IsRestricted(processorArg,bit) \
		( ((processorArg) & (bit)) != 0 )

#       define scop←processorArgAny \
		((unsigned long)(0))
#       define scop←processorArgNone \
		((unsigned long)(-1))
#       define scop←processorArgVP(i) \
		( (unsigned long) (~scop←ProcessorRestrictedBit(i)) )
#       define scop←processorArgNotVP(i) \
		( (unsigned long) scop←ProcessorRestrictedBit(i) )

/*
      Success result is 0.


    Op == scop←setPriority
    Op == scop←getPriority

      Set/get scheduling priority.  Legal only if which is Self.
      Arg is an XR←PRI value > XR←PRI←IDLE



    Op == scop←disable
    Op == scop←enable

      Disable or enable scheduling of specified thread.
      The caller itself cannot be included among the specified threads.
      Multiple disable/enable calls are accumulated.
*/


extern int /* 0 or -errno */
XR←SchedCtlAll(/*
    XR←SchedCtlOp othersOp,
    unsigned long *othersArgp,
    XR←SchedCtlOp myOp,
    unsigned long *myArgp
*/);
/*
    Issue a SchedCtl to every group, treating the group
      of the current thread specially.
    Don't wait for the op to take effect on all processors,
      (see XR←SchedCtlWait below).
    Return 0 on success, (-XR←GetErrno()) on failure.
*/


int /* 0 or -errno */
XR←SchedCtlWait();
/*
    Wait for all previous schedCtl operations issued by this thread
      to take effect.
    Return 0 on success, (-XR←GetErrno()) on failure.
*/


/*
 * Creature Comforts ...
 */

int /* result or -errno */
XR←SchedCtlRunAtomically(/*
    int (*proc)(XR←Pointer data),
    XR←Pointer data
*/);
/*
    Stop all other priorities.
    Call (*proc)(data) on processor 0.
    Restart all priorities.
    Result is the value returned by proc (which is assumed to
      be nonnegative) or (-XR←GetErrno()).
*/