/*
Copyright (c) 1993 Xerox Corporation.  All rights reserved.
*/
/*
$Id$

$Date$
 *
 * PCR←ThCtl -- "Thread Control" interface.
 *
 * Nearly machine independent.
 * Mostly for use by GC and Debugger.
 *
 */


#ifndef	←←PCR←ThCtl←h
#define ←←PCR←ThCtl←h 1


#include <config/PCR←StdTypes.h>
#include <th/PCR←ThTypes.h>
#include <th/PCR←ThCtlTypes.h>



/*
 * RunExclusive
 *
 * Used to stop the world (briefly?) ...
 */

typedef enum {

    /* nonexclusive ... */
    PCR←ThCtl←ExclusiveMode←null = 0,

    /* stop threads attempting to write clean pages (see PCR←VD.h) */
    PCR←ThCtl←ExclusiveMode←stopWriters = 1,

    /* stop all threads not ignoring exclusive */
    PCR←ThCtl←ExclusiveMode←stopNormal = 2,

    /* stop all threads except self */
    PCR←ThCtl←ExclusiveMode←stopAll = 3,

    PCR←ThCtl←ExclusiveMode←last = LONG←MAX

} PCR←ThCtl←ExclusiveMode;


extern PCR←ThCtl←ExclusiveMode
PCR←ThCtl←GetExclusiveMode(void);

extern PCR←ERes
PCR←ThCtl←SetExclusiveMode(
    PCR←ThCtl←ExclusiveMode mode,
    const PCR←sigset←t *sigMask,
    PCR←Msec wakeup
);
/*
    Get/Set exclusive running mode.
    Setting mode non-null acquires a lock;
      setting mode to null releases the lock.

    Success:
      PCR←ERes←okay
    Failure:
      PCR←ETIMEDOUT
      EINVAL
*/



extern PCR←Bool
PCR←ThCtl←GetIgnoreRunExclusive(void);

extern void
PCR←ThCtl←SetIgnoreRunExclusive(PCR←Bool ignore);
/*
    Get/Set ignore-run-exclusive property for this thread

    WIZARDS ONLY: threads that ignore run-exclusive must be very
      well-behaved to avoid confusing the debugger (which would
      be annoying) and the GC (which would be catastrophic).
    In particular, they are expected never to write on pages that
      are being managed by any virtual dirty bits implementation.
*/


/*
 * Thread enumeration
 */

typedef PCR←ERes (PCR←ThCtl←EachThreadProc)(PCR←Th←T *t, PCR←Any data);
/*
    Callback for PCR←ThCtl←ApplyToAllOtherThreads below.
    Called in critical section -- may not allocate, etc.
*/

extern PCR←ERes
PCR←ThCtl←ApplyToAllOtherThreads(
    PCR←ThCtl←EachThreadProc *proc,
    PCR←Any data
);
/*
    Enumerate all threads except current one.
    Apply (*proc)(thread, data) to each, in critical section.
    If that call returns a result other than PCR←ERes←okay, 
      terminate the enumeration returning that result.
    Otherwise return PCR←ERes←okay.
    Note that proc is called in critical section, so it cannot wait,
      allocate, etc.  This is inconvenient, but necessary to give
      a consistent snapshot of thread state.  Most clients will want
      to use PCR←ThCtl←Enumerate, below.
*/


extern PCR←ERes
PCR←ThCtl←GetThreads(PCR←Th←T ** t, unsigned nt);
/*
    Enumerate all nonterminated threads, or as many as will fit,
      *not* including the current thread,
      into the supplied array of PCR←Th←T *'s.
    Return the total number of nonterminated threads, not counting
      the current thread.  This may exceed nt.
    May be called in critical section, in which case state
      of thread table won't change until exit from the
      critical section.
    It is okay for t to be NIL if nt is 0.

    Success:
      number of threads to be stored.
    Failure:
      EFAULT -- bad t
*/


/*
 *
 * Querying thread state
 *
 */

extern PCR←ERes
PCR←ThCtl←GetInfo(
    PCR←Th←T *t,
    PCR←ThCtl←TInfo *ti /* result */
);
/*
    Get thread info about specified thread.
    For a thread t other than the caller, the information reflects
      the state of t the last time it was switched away from.  Thus,
      the information is guaranteed reliable if the caller can guarantee
      t won't be switched to again, e.g. the caller is holding the
      run-exclusive lock and t is not ignoring it.
    If t is the caller (or NIL), the information reflects the state at
      the point of the call.  The state will change immediately, but
      in ways that are under the caller's control.
    May be called from a critical section.
    
    Success:
      0
    Failure:
      EFAULT or EINVAL if t not a valid thread pointer;
*/

extern PCR←ERes
PCR←ThCtl←SetInfo(
    PCR←Th←T *t,
    PCR←ThCtl←TInfo *ti
);
/*
    Set thread info about specified thread.
    WIZARDS AND DEBUGGER WRITERS ONLY!
    It is not legal to do this to yourself.
    May be called from a critical section.

    The fields that are set:
      pri
      ignoreRunExclusive
      state (if not null)
      stkLow (if not NIL)
      stkHi (if not NIL)
      mdContext (if not NIL)
      
    Success:
      0
    Failure:
      EFAULT or EINVAL
*/


#endif /* ! ←←PCR←ThCtl←h */

/*
$Log$
*/