Logo Search packages:      
Sourcecode: u++ version File versions

uC++.h

//                              -*- Mode: C++ -*- 
// 
// uC++ Version 5.0.1, Copyright (C) Peter A. Buhr 1994
// 
// uC++.h -- 
// 
// Author           : Peter A. Buhr
// Created On       : Fri Dec 17 22:04:27 1993
// Last Modified By : Peter A. Buhr
// Last Modified On : Tue Aug 31 22:36:32 2004
// Update Count     : 3888
//
// This  library is free  software; you  can redistribute  it and/or  modify it
// under the terms of the GNU Lesser General Public License as published by the
// Free Software  Foundation; either  version 2.1 of  the License, or  (at your
// option) any later version.
// 
// This library 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 GNU Lesser General Public License
// for more details.
// 
// You should  have received a  copy of the  GNU Lesser General  Public License
// along  with this library.
// 


#ifndef __U_CPLUSPLUS_H__
#define __U_CPLUSPLUS_H__

#pragma __U_NOT_USER_CODE__

#if defined( __solaris__ ) && defined( __U_MULTI__ )
#include <sys/lwp.h>
#endif // __solaris__

/* The GNU Libc defines C library functions with throw () when compiled under
   C++, to enable optimizations.  When uC++ overrides these functions, it must
   provide identical exception specifications.  */
#if defined( __linux__ )
#define __THROW throw ()
#else
#define __THROW
#endif // __linux__

/* ___errno (Solaris) and __errno_location (Linux) provide libc with the
   address of the task-specific errno variable.  Both functions should take no
   arguments; however, a gcc bug (Bug c++/11390) prevents functions defined in
   system headers from being interpreted properly when they are redeclared in
   user code, such as redeclaring as "friend"s.  So some creativity is
   required.

   Irix has a similar function called __oserror, but it is not called by the
   standard library if overridden in uC++; in this case, the system ensures
   that the errnos of different kernel threads stay independent, so we can
   simply save the per-task errno on each context switch.  */
#if defined( __solaris__ )
#if ! defined( _REENTRANT )
#define _REENTRANT
#endif
#if __GNUC__ > 3 || __GNUC_MINOR__ > 3
#define __U_ERRNO_FUNC__ ___errno()
#else
// TEMPORARY: bug fixed in gcc 3.4.0
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11390
#define __U_ERRNO_FUNC__ ___errno(...)
#endif
#include <cerrno>

#elif defined( __linux__ )
#if ! defined( _LIBC_REENTRANT )
#define _LIBC_REENTRANT
#endif
#include <cerrno>
#if ( __GLIBC__ <= 2 ) && ( __GLIBC_MINOR__ < 3 )
#define __U_ERRNO_FUNC__ __errno_location( void )
#endif // ! glibc 2.3

#elif defined( __irix__ )
#if ! defined( _SGI_MP_SOURCE )
#define _SGI_MP_SOURCE
#endif
#include <cerrno>
#include <ulocks.h>

#else
    #error uC++ internal error : unsupported architecture
#endif

#ifdef __U_ERRNO_FUNC__
extern "C" int *__U_ERRNO_FUNC__ __THROW __attribute__(( used ));
#endif // __U_ERRNO_FUNC__

#if defined( __i386__ )
// #define __U_SWAPCONTEXT__                    // use builtin swapcontext
#elif defined( __ia64__ )
#define __U_SWAPCONTEXT__                       // use builtin swapcontext
#elif defined( __sparc__ )
// #define __U_SWAPCONTEXT__                    // use builtin swapcontext
#elif defined( __mips__ )
#define __U_SWAPCONTEXT__                       // use builtin swapcontext
#else
    #error uC++ internal error : unsupported architecture
#endif

#if defined( __U_MULTI__ ) && defined( __U_TLS__ )
#define __U_THREAD__ __thread
#else
#define __U_THREAD__
#endif

#include <uStaticAssert.h>                      // access: _STATIC_ASSERT_
#include <uAssert.h>
//#include <uDebug.h>

#include <uStack.h>
#include <uQueue.h>
#include <uSequence.h>
#include <uBitSet.h>
#include <uDefault.h>

#include "uKernelThreads.h"

#include <cstddef>                              // ptrdiff_t
#include <cstdlib>                              // malloc, calloc, realloc, free
#include <csignal>                              // signal, etc.
#include <ucontext.h>                           // ucontext_t
#include <inttypes.h>                           // uintptr_t

#include <exception>


#define __U_MAXENTRYBITS__ 128                        // N-1 mutex members, including destructor, and timeout
#define uMonitor uMutex class                   // simple definition of a monitor
#define uCorMonitor uMutex uCoroutine                 // simple definition of a coroutine monitor

class uKernelBoot;                              // forward declaration
uTask uBootTask;                          // forward declaration
uTask uSystemTask;                              // forward declaration
class uMachContext;                             // forward declaration
class uBaseCoroutine;                           // forward declaration
class uBaseTask;                          // forward declaration
class uSpinLock;                          // forward declaration
class uLock;                                    // forward declaration
class uOwnerLock;                         // forward declaration
class uCondLock;                          // forward declaration
class uSemaphore;                         // forward declaration
class uProcessor;                         // forward declaration
class uDefaultScheduler;                        // forward declaration
class uCluster;                                 // forward declaration
class uNBIO;                                    // forward declaration
uTask uCollector;                         // forward declaration
class uTrace;                                   // forward declaration
uCoroutine uProcessorKernel;                    // forward declaration
uTask uProcessorTask;                           // forward declaration
class uHeapManager;                             // forward declaration
class uSerial;                                  // forward declaration
class uSerialMember;                                    // forward declaration
class uNBIOnode;                                        // forward declaration
#if defined( __i386__ )
struct vperfctr;                                        // forward declaration
#endif // __i386__

extern uBaseCoroutine &uThisCoroutine();        // forward declaration
extern uBaseTask &uThisTask();                        // forward declaration
extern uProcessor &uThisProcessor();                  // forward declaration
extern uCluster &uThisCluster();                // forward declaration


//######################### Profiling ########################


uTask uProfiler;                                        // forward declaration
class uProfileSampler;                          // forward declaration

extern "C" void __cyg_profile_func_enter( void *pcCurrentFunction, void *pcCallingFunction );
extern "C" void __cyg_profile_func_exit( void *pcCurrentFunction, void *pcCallingFunction );


//######################### uAbort/uExit #########################


extern void uAbort( const char *fmt = "", ... ) __attribute__(( format (printf, 1, 2), noreturn ));
extern void uExit( int code ) __attribute__(( noreturn ));


//######################### Signal Handling #########################


// define parameter types for signal handlers

#if defined( __solaris__ ) || defined( __irix__ ) || defined( __linux__ )
#define __U_SIGCXT__ struct ucontext *
#define __U_SIGPARMS__ int sig, siginfo_t *sfp, __U_SIGCXT__ cxt
#define __U_SIGTYPE__ int, siginfo_t *, __U_SIGCXT__
#else
#define __U_SIGCXT__ struct sigcontext *
#define __U_SIGPARMS__ int sig, int code, __U_SIGCXT__ cxt, char *addr
#define __U_SIGTYPE__ int, int, __U_SIGCXT__, char *
#endif


class uSigHandlerModule {
    friend class uKernelBoot;                   // access: uSigHandlerModule
    friend uTask uLocalDebugger;                // access: uSSignal

    static void uSSignal( int sig, void (*handler)(__U_SIGPARMS__), int flags = 0 );
    static void *uSignalContextPC( __U_SIGCXT__ cxt );
    static void *uFunctionAddress( void (*function)() );
    static bool uInUserCode( __U_SIGCXT__ cxt );
    static void uSigChldHandler( __U_SIGPARMS__ );
    static void uSigTermHandler( __U_SIGPARMS__ );
    static void uSigAlrmHandler( __U_SIGPARMS__ );
    static void uSigSegvBusHandler( __U_SIGPARMS__ );

    uSigHandlerModule( uSigHandlerModule & );         // no copy
    uSigHandlerModule &operator=( uSigHandlerModule & ); // no assignment

    uSigHandlerModule();
  public:
}; // uSigHandlerModule


//######################### uProcessor #########################


class uProcessorDL : public uSeqable {
    uProcessor &uWho;
  public:
    uProcessorDL( uProcessor &w );
    uProcessor &uGet() const;
}; // uProcessorDL

typedef uSequence<uProcessorDL> uProcessorSeq;


//######################### uCluster #########################


class uClusterDL : public uSeqable {
    uCluster &uWho;
  public:
    uClusterDL( uCluster &w );
    uCluster &uGet() const;
}; // uClusterDL

typedef uSequence<uClusterDL> uClusterSeq;


//######################### uBaseTask #########################


class uBaseTaskDL : public uSeqable {
    uBaseTask &uWho;
  public:
    uBaseTaskDL( uBaseTask &w );
    uBaseTask &uGet() const;
}; // uBaseTaskDL

typedef uSequence<uBaseTaskDL> uBaseTaskSeq;


//######################### uKernelModule #########################


extern "C" {                                    // TEMPORARY: profiler allocating memory from the kernel issue
    int pthread_mutex_lock( pthread_mutex_t *mutex ) __THROW;
    int pthread_mutex_trylock( pthread_mutex_t *mutex ) __THROW;
    int pthread_mutex_unlock( pthread_mutex_t *mutex ) __THROW;
} // extern "C"


#define __U_START_KT_NAME__ uKernelModule::startThread
#if defined( __linux__) 
#define __U_START_KT_TYPE__ int __U_START_KT_NAME__( void *p )
#elif defined( __solaris__ )
#define __U_START_KT_TYPE__ void __U_START_KT_NAME__( void *p )
#elif defined ( __irix__ )
#define __U_START_KT_TYPE__ void __U_START_KT_NAME__( void *p, size_t size )
#else
    #error uC++ internal error : unsupported architecture
#endif


struct uKernelModule {
    friend void uAbortExit();                   // access: uGlobalProcessors
    friend void uExit( int retcode );                 // access: uGlobalAbort, uGlobalAbortLock, uGlobalProcessorLock
    friend void uAbort( const char *fmt, ... );       // access: uProcessorKernelStorage, uDisableInt, uCoreDumped, uGlobalAbort, uGlobalProcessorLock
    friend class uSigHandlerModule;             // access: uCoreDumped
    friend class uMachContext;                        // access: uProcessorKernelStack
    friend class uBaseCoroutine;                // access: uDisableInterrupts, uEnInterrupts
    friend class uBaseTask;                     // access: uActiveProcessorKernel
    friend class uSerial;                       // access: uActiveProcessorKernel
    friend class uSerialMember;                       // access: uActiveTask
    friend class uSerialConstructor;                  // access: uActiveTask        
    friend class uSerialDestructor;             // access: uActiveProcessorKernel
    friend class uOwnerLock;                    // access: uActiveProcessorKernel
    friend class uCondLock;                     // access: uActiveProcessorKernel
    friend class uCondition;                    // access: uActiveProcessorKernel
    friend class uContext;                      // access: uDisableInt
    friend class uCoroutineConstructor;               // access: uActiveTask
    friend class uCoroutineDestructor;                // access: uActiveTask
    friend class uCoroutineMain;                // access: uDisableInt
    friend class uTaskConstructor;              // access: uActiveTask
    friend class uTaskDestructor;               // access: uActiveTask
    friend uCoroutine uProcessorKernel;               // access: everything
    friend class uProcessor;                    // access: uGlobalProcessorLock, uDisableInt, uEnableInt
    friend class uSpinLock;                     // access: uGlobalSpinAbort
    friend uBaseTask &uThisTask();              // access: uActiveTask
    friend uProcessor &uThisProcessor();        // access: uActiveProcessor
    friend uCluster &uThisCluster();                  // access: uActiveProcessor
    friend uTask uProcessorTask;                // access: uGlobalProcessorLock, uGlobalProcessors, uSystemProcessor, uProcessorKernelStorage
    friend class uCluster;                      // access: uGlobalClusterLock, uGlobalClusters, uProcessorKernelStorage, uInKernelRF
    friend uTask uBootTask;                     // access: uSystemCluster
    friend uTask uSystemTask;                   // access: uSystemCluster
    friend class uKernelBoot;                   // access: uSystemCluster
    friend class uIStreamBoot;                        // access: uSystemCluster
    friend class uOStreamBoot;                        // access: uSystemCluster
    friend uTask uCollector;                    // access: uSystemCluster
    friend class uHeapManager;                        // access: uHeapManagerInstance, uTaskBootStorage
    friend uTask uTaskBoot;                     // access: uAttaching
    friend class uNBIO;                         // access: uActiveProcessorKernel

    // real-time

    friend class uEventList;                            // access: uActiveProcessorKernel
    friend class uEventListPop;                       // access: uActiveProcessorKernel, uInKernelRF

    // kernel visualization

    friend class uKernelSampler;                // access: uGlobalClusters
    friend class uClusterSampler;               // access: uGlobalClusters

    // debugging

    friend uTask uLocalDebugger;                // access: uActiveProcessorKernel, uActiveCluster, uActiveTask
    friend uTask uLocalDebuggerMisc;                  // access: uActiveProcessorKernel, uGlobalAbort
    friend class uLocalDebuggerHandler;               // access: uActiveCluster, uActiveTask

    // profiling

    friend int pthread_mutex_lock( pthread_mutex_t *mutex ) __THROW; // TEMPORARY: profiler allocating memory from the kernel issue
    friend int pthread_mutex_trylock( pthread_mutex_t *mutex ) __THROW; // TEMPORARY: profiler allocating memory from the kernel issue
    friend int pthread_mutex_unlock( pthread_mutex_t *mutex ) __THROW; // TEMPORARY: profiler allocating memory from the kernel issue
    friend void __cyg_profile_func_enter( void *pcCurrentFunction, void *pcCallingFunction );
    friend void __cyg_profile_func_exit( void *pcCurrentFunction, void *pcCallingFunction );
    friend class uProfilerBoot;                       // access: uTaskBoot, uSystemCluster, uSystemProcessor
    friend class uProcessorProfileInfo;               // access: uSystemProcessor, uUserProcessor
    friend class uProfileSampler;               // access: uActiveProcessor
    friend class uRUMonitor;                    // access: uGlobalClusters
    friend class uRUAnalyze;                    // access: uGlobalClusters


#if defined( __i386__ )
#if defined( __U_MULTI__ )
    unsigned int ldtValue;
#endif // __U_MULTI__
#endif // __i386__

    volatile uKernelModule *uSelf;

#   define __U_MAX_PAGE_SIZE__ (16 * 1024)
#   define uActiveProcessorKernel (THREAD_GETMEM( uProcessorKernelStorage ))
    uProcessor *uActiveProcessor;               // current active processor
    // The next two private variables shadow the corresponding fields in the
    // processor data structure. They are an optimization so that routines
    // uThisCluster and uThisTask do not have to be atomic routines, and as a
    // consequence can be inlined. The problem is the multiple uActiveProcessor
    // variables (one per UNIX process). A task executing on one processor can
    // be time sliced after loading the address of the active processor into a
    // register, rescheduled on another processor and restarted, but now the
    // previously loaded processor pointer is incorrect. By updating these two
    // shadow variables whenever the corresponding processor field is changed
    // (and this occurs atomically in the kernel), the appropriate data
    // structure (cluster or task) can be accessed with a single load
    // instruction, which is atomic.
    uCluster  *uActiveCluster;                        // current active cluster for processor
    uBaseTask *uActiveTask;                     // current active task for processor

    bool uDisableInt;                           // task in kernel: no time slice interrupts
    unsigned int uDisableIntCnt;

    bool uDisableIntSpin;                       // task in spin lock; no time slice interrupts
    unsigned int uDisableIntSpinCnt;

    unsigned int uInKernelRF;                   // in kernel roll forward flag

    uProcessorKernel *uProcessorKernelStorage;        // system-cluster processor kernel

    // The thread pointer value needs to be accessible so that it can be
    // properly restored on context switches.  On a non-tls system the thread
    // pointer points directly at the kernel module, i.e. tp == uSelf.  On a
    // tls system the system places the kernel module, so tp != uSelf.
    unsigned long threadPointer;

    inline void uDisableInterrupts() volatile {
      THREAD_SETMEM( uDisableInt, true );
      int old = THREAD_GETMEM( uDisableIntCnt );
      THREAD_SETMEM( uDisableIntCnt, old + 1 );
    } // uKernelModule::uDisableInterrupts

    inline void uEnableInterrupts() volatile {
#ifdef __U_DEBUG__
      uAssert( uDisableInt && uDisableIntCnt > 0 );
#endif // __U_DEBUG__

      uDisableIntCnt -= 1;                      // decrement number of disablings
      if ( uDisableIntCnt == 0 ) {
          // Enable interrupts first, otherwise a window exists in which a
          // signal could occur but a rollforward is not done.
          uDisableInt = false;                  // enable interrupts
          if ( THREAD_GETMEM( uInKernelRF ) && ! THREAD_GETMEM( uDisableIntSpin ) ) { // SIGALRM undelivered and not in kernel?
            uRollForward();                     // deliver SIGALRM
          } // if
      } // if
#ifdef __U_DEBUG__
      uAssert( ! THREAD_GETMEM( uDisableInt ) && THREAD_GETMEM( uDisableIntCnt ) == 0 || THREAD_GETMEM( uDisableInt ) && THREAD_GETMEM( uDisableIntCnt ) > 0 );
#endif // __U_DEBUG__
    } // KernelModule::uEnableInterrupts

    class uNoInterrupts {
      uNoInterrupts( const uNoInterrupts & );
      uNoInterrupts &operator=( const uNoInterrupts & );
      public:
      uNoInterrupts() {
          THREAD_GETMEM( uSelf )->uDisableInterrupts();
      } // uKernelModule::uNoInterrupts::uNoInterrupts

      ~uNoInterrupts() {
          THREAD_GETMEM( uSelf )->uEnableInterrupts();
      } // uKernelModule::uNoInterrupts::~uNoInterrupts
    }; // uKernelModule::uNoInterrupts

    inline void uDisableIntSpinLock() volatile {
#ifdef __U_DEBUG__
      uAssert( ! THREAD_GETMEM( uDisableIntSpin ) && THREAD_GETMEM( uDisableIntSpinCnt ) == 0 || THREAD_GETMEM( uDisableIntSpin ) && THREAD_GETMEM( uDisableIntSpinCnt ) > 0 );
#endif // __U_DEBUG__

      THREAD_SETMEM( uDisableIntSpin, true );
      int old = THREAD_GETMEM( uDisableIntSpinCnt );  // processor independent increment
      THREAD_SETMEM( uDisableIntSpinCnt, old + 1 );

#ifdef __U_DEBUG__
      uAssert( THREAD_GETMEM( uDisableIntSpin ) && THREAD_GETMEM( uDisableIntSpinCnt ) > 0 );
#endif // __U_DEBUG__
    } // uKernelModule::uDisableIntSpinLock

    inline void uEnableIntSpinLock() volatile {
#ifdef __U_DEBUG__
      uAssert( THREAD_GETMEM( uDisableIntSpin ) && THREAD_GETMEM( uDisableIntSpinCnt ) > 0 );
#endif // __U_DEBUG__

      uDisableIntSpinCnt -= 1;                  // decrement number of disablings
      if ( uDisableIntSpinCnt == 0 ) {
          uDisableIntSpin = false;              // enable interrupts

          if ( THREAD_GETMEM( uInKernelRF ) && ! THREAD_GETMEM( uDisableInt ) ) { // SIGALRM undelivered and not in kernel?
            uRollForward();                     // deliver SIGALRM
          } // if
      } // if

#ifdef __U_DEBUG__
      uAssert( ! THREAD_GETMEM( uDisableIntSpin ) && THREAD_GETMEM( uDisableIntSpinCnt ) == 0 || THREAD_GETMEM( uDisableIntSpin ) && THREAD_GETMEM( uDisableIntSpinCnt ) > 0 );
#endif // __U_DEBUG__
    } // uKernelModule::uEnableIntSpinLock

    inline void uEnableIntSpinLockNoRF() volatile {
#ifdef __U_DEBUG__
      uAssert( THREAD_GETMEM( uDisableIntSpin ) && THREAD_GETMEM( uDisableIntSpinCnt ) > 0 );
#endif // __U_DEBUG__

      uDisableIntSpinCnt -= 1;                  // decrement number of disablings
      if ( uDisableIntSpinCnt == 0 ) {
          uDisableIntSpin = false;              // enable interrupts
      } // if

#ifdef __U_DEBUG__
      uAssert( ! THREAD_GETMEM( uDisableIntSpin ) && THREAD_GETMEM( uDisableIntSpinCnt ) == 0 || THREAD_GETMEM( uDisableIntSpin ) && THREAD_GETMEM( uDisableIntSpinCnt ) > 0 );
#endif // __U_DEBUG__
    } // uKernelModule::uEnableIntSpinLock


    // shared, initialized in uC++.cc

    static bool uKernelModuleInitialized;
    static volatile __U_THREAD__ uKernelModule uKernelModuleBoot;
    static bool uInitialization;                // initialization/finalization done
    static unsigned int uAttaching;             // flag to signal the local kernel to start attaching.
    static bool uCoreDumped;                    // ensure only one core file
#ifndef __U_MULTI__
    static bool uDeadlock;                      // deadlock detected in kernel
#endif // ! __U_MULTI__
    static bool uGlobalAbort;                   // indicate aborting processor
    static bool uGlobalSpinAbort;               // indicate aborting processor to spin locks
    static uSpinLock *uGlobalAbortLock;               // only one aborting processors
    static uSpinLock *uGlobalProcessorLock;           // mutual exclusion for global processor operations
    static uProcessorSeq *uGlobalProcessors;          // global list of processors
    static uSpinLock *uGlobalClusterLock;       // mutual exclusion for global cluster operations
    static uClusterSeq *uGlobalClusters;        // global list of cluster
    static uDefaultScheduler *uSystemScheduler;       // pointer to systen scheduler for system cluster
    static uCluster *uSystemCluster;                  // pointer to system cluster
    static uProcessor *uSystemProcessor;        // pointer to system processor
    static uBootTask *uTaskBoot;                // pointer to boot task for global constructors/destructors
    static uProcessor *uUserProcessor;                // pointer to user processor
    static char uSystemProcessorStorage[];
    static char uSystemClusterStorage[];
    static char uTaskBootStorage[];

    static void uRollForward( bool inKernel = false );
    static __U_START_KT_TYPE__;

    static void startup();                      // init boot KM
    void ctor() volatile;                       // POD constructor
    void dtor() volatile;                       // POD destructor
  public:
    static uSystemTask *uTaskSystem;                  // pointer to system task for global constructors/destructors
    static uCluster *uUserCluster;              // pointer to user cluster

#if defined( __ia64__ ) && ! defined( __U_TLS__ )
    // Last machine word of this structure must be reserved for the "in atomic
    // offset load/store" flag (see uKernelThread.h).
    unsigned long uIA64OffsetStoreFlag;
    unsigned long uIA64Sysinfo;
#endif // __ia64__
}; // uKernelModule


//######################### uSpinLock #########################


class uSpinLock {
    friend class uKernelBoot;                   // access: new
    friend class uEventList;                    // access: uAcquireNoRF, uReleaseNoRF

    unsigned int uValue;

    uSpinLock( uSpinLock & );                   // no copy
    uSpinLock &operator=( uSpinLock & );        // no assignment

    void *operator new( size_t, void *storage );
    void *operator new( size_t size );

    void uAcquireNoRF();
    void uReleaseNoRF();
  public:
    uSpinLock();
    void acquire();
    bool tryacquire();
    void release();
}; // uSpinLock


// Implement mutual exclusion for a block through a class whose constructor
// acquires a lock and whose destructor releases the lock.  Useful for mutual
// exclusion in free routines. Handles exception termination and multiple block
// exit or return.

class uCSpinLock {
    uSpinLock &SpinLock;

    uCSpinLock( uCSpinLock & );                       // no copy
    uCSpinLock &operator=( uCSpinLock &);       // no assignment
  public:
    uCSpinLock( uSpinLock &SpinLock );
    ~uCSpinLock();
}; // uCSpinLock


//######################### uLock #########################


// Implement a lock that works in the uni and multi versions.  In the uni
// version, simply yield if it is not possible to get the lock immediately.

class uLock {
    friend class uKernelBoot;;                        // access: new
    friend class uSerial;                       // access: SpinLock

    unsigned int uValue;
    uSpinLock SpinLock;

    uLock( uLock & );                           // no copy
    uLock &operator=( uLock &);                       // no assignment

    void *operator new( size_t, void *storage );
    void *operator new( size_t size );
  public:
    uLock();
    uLock( unsigned int value );
    void acquire();
    bool tryacquire();
    void release();
}; // uLock


//######################### Abnormal Event Handling #########################


#include <uEHM.h>


//######################### Real-Time #########################


#include <uCalendar.h>
#include <uAlarm.h>


class uSignalHandler {
  protected:
    uBaseTask *uThis;
  public:
    virtual void uHandler() = 0;
}; // uSignalHandler

class uWakeupHndlr : public uSignalHandler {
    friend class uBaseTask;                     // access: uWakeupHndlr

    uWakeupHndlr( uBaseTask &t );
    void uHandler();
}; // uWakeupHndlr

class uCxtSwtchHndlr : public uSignalHandler {
    void uHandler();
}; // uCxtSwtchHndlr

class uTimeoutHndlr : public uSignalHandler {
    friend class uSerial;                       // access: uWakeupHndlr
    
    uSerial &serial;

    uTimeoutHndlr( uBaseTask &t, uSerial &serial );
    uTimeoutHndlr( uSerial &serial );
    void uHandler();
}; // uTimeoutHndlr

class uSelectTimeoutHndlr : public uSignalHandler {
    friend class uNBIO;
  
    uNBIOnode &uNode;
  
    uSelectTimeoutHndlr( uBaseTask &t, uNBIOnode &n );
    void uHandler();
}; // uTimeoutHndlr

class uCondLockTimedwaitHndlr : public uSignalHandler {
    friend class uCondLock;                     // access: uWakeupHndlr
    
    uCondLock &condlock;
    bool uTimedout;

    uCondLockTimedwaitHndlr( uBaseTask &t, uCondLock &condlock);
    uCondLockTimedwaitHndlr( uCondLock &condlock );
    void uHandler();
}; // uCondLockTimedwaitHndlr

class uBaseScheduleFriend;                      // forward declaration


//######################### uOwnerLock #########################


class uOwnerLock {
    friend class uCondLock;                     // access: _add, _release

    // These data fields must be initialized to zero. Therefore, this lock can
    // be used in the same storage area as a pthread_mutex_t, if
    // sizeof(pthread_mutex_t) >= sizeof(uOwnerLock).

    uSpinLock spin;
    uBaseTask *_owner;
    unsigned int count;                         // no overflow checking
    uQueue<uBaseTaskDL> waiting;

    uOwnerLock( uOwnerLock & );                       // no copy
    uOwnerLock &operator=( uOwnerLock & );            // no assignment

    void _add( uBaseTask &t );                        // helper routines for uCondLock
    void _release();
  public:
    uOwnerLock();
#ifdef __U_DEBUG__
    ~uOwnerLock();
#endif // __U_DEBUG__
    unsigned int times() const;
    uBaseTask *owner() const;
    void acquire();
    bool tryacquire();
    void release();

    void *operator new( size_t, void *storage );
    void *operator new( size_t size );
}; // uOwnerLock


//######################### uCondLock #########################


class uCondLock {
    // These data fields must be initialized to zero. Therefore, this lock can
    // be used in the same storage area as a pthread_cond_t, if
    // sizeof(pthread_cond_t) >= sizeof(uCondLock).

    friend class uCondLockTimedwaitHndlr;       // access: uWaitTimeout

    uSpinLock spin;
    uQueue<uBaseTaskDL> waiting;

    uCondLock( uCondLock & );                   // no copy
    uCondLock &operator=( uCondLock & );        // no assignment
    void uWaitTimeout( uBaseTask &t, uCondLockTimedwaitHndlr &h ); // timeout
  public:
    uCondLock();
#ifdef __U_DEBUG__
    ~uCondLock();
#endif // __U_DEBUG__
    bool empty() const;
    void wait( uOwnerLock &lock );
    bool timedwait( uOwnerLock &lock, uDuration duration );
    bool timedwait( uOwnerLock &lock, uTime time );
    void signal();
    void broadcast();

    void *operator new( size_t, void *storage );
    void *operator new( size_t size );
}; // uCondLock


//######################### uContext #########################


class uContext : public uSeqable {
    void *uKey;
  public:
    uContext();
    uContext( void *key );
    virtual ~uContext();

    // These two routines cannot be abstract (i.e., = 0) because there is a
    // race condition during initialization of a derived class when the base
    // class constructor is invoked. A context switch can occur immediately
    // after the base instance has put itself on the task context list but
    // before the virtual function vector is updated for the derived class.
    // Hence, the uSave or uRestore routine of the base class may be called.
    // This situtation is not a problem because either the task has not
    // performed any operations that involve the new context or the task is
    // removing the context and not performing anymore operations using it.

    virtual void uSave();
    virtual void uRestore();
}; // uContext

typedef uSequence<uContext> uContextSeq;


//######################### uFloatingPointContext #########################


// Provide floating point context switch support for coroutines and tasks.  It
// is built with the more general context class in the same way that a user can
// extend the amount of context that is saved and restored with a coroutine or
// task.

#if defined( __i386__ )
// saved by caller
#elif defined( __ia64__ )
// saved with integer registers
#elif defined( __sparc__ )
// saved by caller
#elif defined( __mips__ )
#define __U_FLOATINGPOINTDATASIZE__ 6                 // doubles
#else
    #error uC++ internal error : unsupported architecture
#endif


// Some architectures store the floating point registers with the integers
// registers during a basic context switch, so there is no need for a data area
// to storage the floating point registers.

#ifdef __U_FLOATINGPOINTDATASIZE__
class uFloatingPointContext : public uContext {
    static int uUniqueKey;
    double uFloatingPointData[__U_FLOATINGPOINTDATASIZE__];
  public:
    uFloatingPointContext();
#else
class uFloatingPointContext {
  public:
#endif // __U_FLOATINGPOINTDATASIZE__
    void uSave();                         // save and restore the floating point context
    void uRestore();
} __attribute__(( unused )); // uFloatingPointContext


//######################### uMachContext #########################


#if defined( __U_SWAPCONTEXT__ )
#define uSwitch( from, to ) swapcontext( (ucontext_t *)(from), (ucontext_t *)(to) )
#define __U_CONTEXT_T__ ucontext_t
#else
#define __U_CONTEXT_T__ uContext_t
extern "C" void uSwitch( void *from, void *to ) asm ("uSwitch"); // assembler routine that performs the context switch
#endif


// Define a class that contains the machine dependent context and routines that
// initialize and switch between contexts.

class uMachContext {
    friend class uContext;                      // access: uAdditionalContexts
    friend class uProcessorTask;                // access: uSize, uBase, uLimit
    friend class uBaseCoroutine;                // access: uMachContext
    friend class uCoroutineConstructor;               // access: uStartHere
    friend class uTaskConstructor;              // access: uStartHere
    friend uTask uBootTask;                     // access: uStorage
    friend uCoroutine uProcessorKernel;               // access: uStorage
    friend class uProcessor;                    // access: uStorage
    friend class uKernelBoot;                   // access: uBase, uSP
#ifdef __U_ERRNO_FUNC__
    friend int *__U_ERRNO_FUNC__ __THROW;       // access: uErrno
#endif // __U_ERRNO_FUNC__
    friend __U_START_KT_TYPE__;                       // acesss: uInvokeCoroutine

    // profiling

    friend class uProfilerBoot;                       // access: uSP, uLimit
    friend uTask uProfiler;                     // access: uSP, uLimit
    friend class uProfileSampler;               // access: uLimit
    friend void __cyg_profile_func_enter( void *pcCurrentFunction, void *pcCallingFunction );
    friend void __cyg_profile_func_exit( void *pcCurrentFunction, void *pcCallingFunction );

    struct uContext_t {
      void *uSP;
      void *uFP;
      void *uPC;
    };

    unsigned int uSize;                         // size of stack
    void *uStorage;                             // pointer to stack
    void *uBase;                          // base of stack
    void *uLimit;                         // stack grows towards stack limit
    int uErrno;                                 // copy of global UNIX variable errno

    union {
      long int uAllExtras;                      // allow access to all extra flags
      struct {                            // put all extra flags in this structure
          unsigned int uContexts : 1;                 // user defined contexts
      } uIs;
    } uExtras;                                  // indicates extra work during the context switch

    void uCreateContext( unsigned int stacksize );    // used by all constructors

    static void uInvokeCoroutine( uBaseCoroutine &This ) __attribute__(( noreturn ));
    static void uInvokeTask( uBaseTask &This ) __attribute__(( noreturn ));

    // This routine returns the magic word that is placed at both ends of an
    // allocated stack.  Later, those locations can be checked to see if the
    // magic word is still intact.

    unsigned int uMagic();

    void uStartHere( void (*uInvoke)( uMachContext & ) );

    uMachContext( uMachContext & );             // no copy
    uMachContext &operator=( uMachContext & );        // no assignment
  protected:
    uContextSeq uAdditionalContexts;                  // list of additional contexts for this execution state

    void uExtraSave();
    void uExtraRestore();

    void uSave() {
#if ! defined( __U_ERRNO_FUNC__ )
      uErrno = errno;
#endif // ! __U_ERRNO_FUNC__
      // Any extra work that must occur on this side of a context switch is
      // performed here.
      if ( uExtras.uAllExtras ) {
          uExtraSave();
      } // if

#ifdef __U_DEBUG__
      uVerify();
#endif // __U_DEBUG__
    } // uMachContext::uSave

    void uRestore() {
#ifdef __U_DEBUG__
      uVerify();
#endif // __U_DEBUG__

      // Any extra work that must occur on this side of a context switch is
      // performed here.
      if ( uExtras.uAllExtras ) {
          uExtraRestore();
      } // if
#if ! defined( __U_ERRNO_FUNC__ )
      errno = uErrno;
#endif // ! __U_ERRNO_FUNC__
    } // uMachContext::uRestore

    virtual void main() = 0;                    // starting routine for coroutine or task
  public:
    uMachContext( unsigned int stacksize );
    virtual ~uMachContext();

    void *uStackPointer() const;
#if defined( __ia64__ )
    void *uRegisterStackPointer() const;
#endif // __ia64__
    unsigned int uStackSize() const;
    ptrdiff_t uStackFree() const;
    ptrdiff_t uStackUsed() const;
    void uVerify();

    static void *uRtnAdr( void (*rtn)() );
}; // uMachContext


//######################### uBaseCoroutine #########################


class uBaseCoroutine : public uMachContext {
    friend class uBaseTask;                     // access: serial
    friend class uCoroutineMain;                // access: uState, uCoStarter, uCoFinish
    friend class uTaskDestructor;               // access: uProfileSamplerInstance
    friend class uKernelBoot;                   // access: uContextSw
    friend class uMachContext;                        // access: uCoStarter, uCoFinish, uStart
    friend uTask uBootTask;                     // access: uNotHalted
    friend class uCoroutineConstructor;               // access: uName
    friend class uTaskConstructor;              // access: uName
    friend uCoroutine uProcessorKernel;               // access: uContextSw
    friend class uSerialDestructor;                     // access: uCurrSerialOwner, uCurrSerialCount
    friend class uSerialMember;                         // access: uCurrSerialOwner, uCurrSerialCount

    // exception handling

    friend class uEHM;                          // access: uSyncHandlers, uAsyncHandlers, uDAEStack
    friend class uEHM::uResumptionHandlers;           // access: uSyncHandlers, uAsyncHandlers
    friend class uEHM::uDeliverAEStack;               // access: uDAEStack
    friend class uEHM::uRaiseWorkHorseInit;           // access: uSyncHandlers
    friend void uEHM::uUnexpectedHandler();           // access: uUnexpectedRtn
    friend std::unexpected_handler std::set_unexpected( std::unexpected_handler func ) throw(); // access: uUnexpectedRtn

    // profiling

    friend uTask uProfiler;                             // access: uProfileSamplerInstance
    friend class uProfilerBoot;                         // access: uProfileSamplerInstance, serial
    friend class uProfileSampler;               // access: uFuncID, uState, uName
    friend void __cyg_profile_func_enter( void *pcCurrentFunction, void *pcCallingFunction );
    friend void __cyg_profile_func_exit( void *pcCurrentFunction, void *pcCallingFunction );
    friend class uTaskSampler;                        // access: uProfileSamplerInstance
    friend class uExecutionMonitor;             // access: uProfileSamplerInstance
    friend class uCGMonitor;                    // access: uProfileSamplerInstance
    friend class uESMonitor;                    // access: uProfileSamplerInstance
    friend class uPOTMonitor;                   // access: uProfileSamplerInstance
    friend class uMemMonitor;                   // access: uProfileSamplerInstance
    friend class uHWFunctionMonitor;                    // access: uProfileSamplerInstance
    friend class uHWNonFunctionMonitor;                 // access: uProfileSamplerInstance
  public:
    enum uCoroutineState { uHalt, uActive, uInActive };
  private:
    const char *uName;                          // text name, initialized by uC++ generated code
    bool uNotHalted;                            // indicate if execuation state is not halted
    uCoroutineState uState;                     // current execution status for coroutine
    uBaseCoroutine *uStart;                     // first coroutine to resume this one
    uSerial *serial;                            // serial instance for cormonitor and task

    uBaseCoroutine *uLast;                      // last coroutine to resume this one
    uBaseTask *uCurrSerialOwner;                // task accessing monitors from this coroutine
    unsigned int uCurrSerialCount;              // counter to determine when to unset uCurrSerialOwner

    // exception handling

    uEHM::uResumptionHandlers *uHandlerStackTop, *uHandlerStackVisualTop;
    uEHM::uDualClass *RaisedObj;                        // the object that is currently being handled during resumption
    uEHM::uDeliverAEStack *uDAEStack;
    std::unexpected_handler uUnexpectedRtn;           // per coroutine handling unexpected action

    // profiling

    uProfileSampler *uProfileSamplerInstance;         // pointer to related profiling object

    void uCreateCoroutine();

    void uSetState( uCoroutineState state ) {
      uState = state;
    } // uBaseCoroutine::uSetState

    void uContextSw();                          // switch between a task and the kernel
    void uContextSw2();                         // switch between two coroutine contexts
    void uCoStarter();                          // remembers who started a coroutine
    void uCoFinish() __attribute__(( noreturn ));

    uBaseCoroutine( uBaseCoroutine & );               // no copy
    uBaseCoroutine &operator=( uBaseCoroutine & );    // no assignment
  protected:
    // Duplicate "main" (see uMachContext) to get better error message about
    // missing "main" member for coroutine.
    virtual void main() = 0;                    // starting routine for coroutine
  public:
    uBaseCoroutine();
    uBaseCoroutine( unsigned int stacksize );

    const char *uGetName() const;
    const char *uSetName( const char *name );

    uCoroutineState uGetState() const {
      return uNotHalted ? uState : uHalt;
    } // uBaseCoroutine::uGetState

    // exception handling

    uDualEvent uFailure;                        // general failure

    // These members should be private but cannot be because they are
    // referenced from user code.

    void uCoResume();
    void uCoSuspend();

    uBaseCoroutine &uLastResume() const;        // last coroutine that resumed the current coroutine

    // exception handling

    uEHM::uAsyncAEMsgBuffer uAsyncAEBuf;        // list of pending nonlocal exceptions
}; // uBaseCoroutine


//######################### Abnormal Event Handling #########################


// Include the kernel generated exception definitions.

#include <uKernelEvent.h>


//######################### uBaseCoroutine (cont) #########################


uDualEvent uBaseCoroutine::uFailure : public uKernelFailure {
    const uBaseCoroutine &cor;
    char uName[uEHMMaxName + sizeof("...")];          // room for "...\0"

    void uCreateFailure();
  public:
    uFailure( const uBaseCoroutine &cor, const char *const msg = "" );
    uFailure( const char *const msg = "" );
    virtual ~uFailure();
    const uBaseCoroutine &uDst() const;
    const char *uGetName() const;
    virtual void defaultTerminate() const;
}; // uBaseCoroutine::uFailure


//######################### Real-Time (cont) #########################


class uBaseScheduleFriend {
  protected:
    uBaseTask &uGetInheritTask( uBaseTask &t ) const;
    int uGetActivePriority( uBaseTask &t ) const;
    int uGetActivePriorityValue( uBaseTask &t ) const;
    int uSetActivePriority( uBaseTask &t1, int p );
    int uSetActivePriority( uBaseTask &t1, uBaseTask &t2 );
    int uGetBasePriority( uBaseTask &t ) const;
    int uSetBasePriority( uBaseTask &t, int p );
    int uGetActiveQueueValue( uBaseTask &t ) const;
    int uSetActiveQueue( uBaseTask &t1, int p );
    int uGetBaseQueue( uBaseTask &t ) const;
    int uSetBaseQueue( uBaseTask &t, int p );
    bool uIsEntryBlocked( uBaseTask &t ) const;
    bool uCheckHookConditions( uBaseTask &t1, uBaseTask &t2 ) const;
}; // uBaseScheduleFriend


template<class Node> class uBaseSchedule : protected uBaseScheduleFriend {
  public:
    virtual bool uEmpty() const = 0;
    virtual void uAdd( Node *node ) = 0;
    virtual Node *uDrop() = 0;
    virtual bool uCheckPriority( Node &owner, Node &calling ) = 0;
    virtual void uResetPriority( Node &owner, Node &calling ) = 0;
    virtual void uAddInitialize( uBaseTaskSeq &TaskList ) = 0;
    virtual void uRemoveInitialize( uBaseTaskSeq &TaskList ) = 0;
    virtual void uRescheduleTask( uBaseTaskDL *TaskNode, uBaseTaskSeq &TaskList ) = 0;
}; // uBaseSchedule


class uBasePrioritySeq : public uBaseScheduleFriend {
    friend class uSerial;
  protected:
    uBaseTaskSeq list;
    bool uExecuteHooks;
  public:
    uBasePrioritySeq();
    virtual bool uEmpty() const;
    virtual uBaseTaskDL *uHead() const;
    virtual int uAdd( uBaseTaskDL *node, uBaseTask *uOwner );
    virtual uBaseTaskDL *uDrop();
    virtual void uRemove( uBaseTaskDL *node ); 
    virtual void uOnAcquire( uBaseTask &uOwner );
    virtual void uOnRelease( uBaseTask &uOldOwner );
    int uReposition( uBaseTask *t, uSerial *s );
}; // uBasePrioritySeq


class uBasePriorityQueue : public uBasePrioritySeq {
    uQueue<uBaseTaskDL> list;
  public:
    virtual bool uEmpty() const;
    virtual uBaseTaskDL *uHead() const;
    virtual int uAdd( uBaseTaskDL *node, uBaseTask *uOwner ); 
    virtual uBaseTaskDL *uDrop();
    virtual void uRemove( uBaseTaskDL *node ); 
    virtual void uOnAcquire( uBaseTask &uOwner );
    virtual void uOnRelease( uBaseTask &uOldOwner );
}; // uBasePriorityQueue


class uRepositionEntry {
    uBaseTask &blocked;
    uBaseTask &calling;
    uSerial *bSerial;
    uSerial *cSerial;
  public:
    uRepositionEntry( uBaseTask &b, uBaseTask &c );
    int uReposition( bool RelCallingLock );
}; // uRepositionEntry


class uDefaultScheduler : public uBaseSchedule<uBaseTaskDL> {
    uBaseTaskSeq list;                          // list of tasks awaiting execution
  public:
    bool uEmpty() const;
    void uAdd( uBaseTaskDL *node );
    uBaseTaskDL *uDrop();
    bool uCheckPriority( uBaseTaskDL &owner, uBaseTaskDL &calling );
    void uResetPriority( uBaseTaskDL &owner, uBaseTaskDL &calling );
    void uAddInitialize( uBaseTaskSeq &TaskList );
    void uRemoveInitialize( uBaseTaskSeq &TaskList );
    void uRescheduleTask( uBaseTaskDL *TaskNode, uBaseTaskSeq &TaskList );
}; // uDefaultScheduler


//######################### Translator Generated Definitions #########################


class uBasePIQ {
  public:
    virtual int uGetHighestPriority() = 0;
}; // uBasePIQ


#include <uPIHeap.h>


enum uAction { uNo, uYes };                     // used to indicate the most derived constructor/destructor of an object


class uCoroutineConstructor {                   // placed in the constructor of a coroutine
  public:
    uCoroutineConstructor( uAction f, uSerial &s, uBaseCoroutine &c, const char *n );
} __attribute__(( unused )); // uCoroutineConstructor


class uCoroutineDestructor {                    // placed in the destructor of a coroutine
    uAction f;
    uBaseCoroutine &c;
  public:
    uCoroutineDestructor( uAction f, uBaseCoroutine &c );
    ~uCoroutineDestructor();
}; // uCoroutineDestructor


class uCoroutineMain {                          // placed in the main member of a coroutine
  private:
    uBaseCoroutine &c;
  public:
    uCoroutineMain( uBaseCoroutine &c );
    ~uCoroutineMain();                          // needed by the debugger
}; // uCoroutineMain


class uSerial {
    friend class uCondition;                    // access: uAcceptSignalled
    friend class uSerialConstructor;                  // access: uMutexOwner
    friend class uSerialDestructor;             // access: uAcceptSignalled
    friend class uTaskConstructor;              // access: uAcceptSignalled
    friend class uProcessor;                    // access: uAcceptSignalled
    friend class uSerialMember;                         // access: uLastRendezvous, uLastAcceptor
    friend uTask uBootTask;                     // access: uAcceptSignalled
    friend class uMachContext;                        // access: uMutexOwner, uLeave2
    friend class uBasePrioritySeq;              // access: lock, uMutexOwner TEMPORARY
    friend class uRepositionEntry;              // access: lock TEMPORARY

    // profiling

    friend uTask uProfiler;                             // access: uProfileSerialSamplerInstance
    friend class uPOTMonitor;                   // access: uProfileSerialSamplerInstance

    bool uAlive;                          // serial destroyed ?
    uSpinLock lock;                             // provide mutual exclusion while examining serial state
    uBaseTask *uMutexOwner;                     // active thread in the mutex object
    uBitSet< __U_MAXENTRYBITS__ > uMask;        // entry mask of accepted mutex members and timeout
    bool acceptMask;                            // entry mask set by uAcceptReturn or uAcceptWait
    unsigned int *uMutexMaskPosn;               // location to place mask position in accept statement
    uBasePrioritySeq &uEntryList;               // tasks waiting to enter mutex object
#if 1                                     // normally use stack; use queue for experiments
    uStack<uBaseTaskDL> uAcceptSignalled;       // tasks suspended within the mutex object
#else
    uQueue<uBaseTaskDL> uAcceptSignalled;       // tasks suspended within the mutex object
#endif
    bool uTimedoutRF;                           // timeout roll forward flag
    uBaseTask *uConstructorTask;                // identity of task creating mutex object
    enum uDestructorState { NoDestructor, DestrCalled, DestrScheduled }; // identify the state of the destructor
    uDestructorState uDestructorStatus;               // has the destructor been called ? 
    uBaseTask *uDestructorTask;                         // identity of task calling mutex object's destructor

    // real-time

    uEventNode uTimeoutEvent;                   // event node for event list
    uProcessor *uProc;                          // active processor when event added
    uEventList *uEvents;                        // event list when event added

    // exception handling

    uBaseTask *uLastAcceptor;                   // acceptor of current entry for communication between acceptor and caller

    // profiling

    uProfileSampler *uProfileSerialSamplerInstance;   // pointer to related profiling object

    void uResetDestructorStatus();              // allow destructor to be called

    uSerial( uSerial & );                       // no copy
    uSerial &operator=( uSerial & );                  // no assignment
  public:
    // These members should be private but cannot be because they are
    // referenced from user code.

    class uProtectAcceptStmt {
      uSerial &s;
      public:
      unsigned int uMutexMaskPosn;              // bit position (0-127) in the entry mask for active mutex member

      uProtectAcceptStmt( uSerial &s );
      uProtectAcceptStmt( uSerial &s, bool );
      ~uProtectAcceptStmt();
    }; // uSerial::uProtectAcceptStmt

    uSerial( uBasePrioritySeq &uEntryList );
    ~uSerial();

    void uEnter( unsigned int &mr, uBasePrioritySeq &ml, int mp );
    void uEnterDestructor( unsigned int &mr, uBasePrioritySeq &ml, int mp );
    void uEnterTimeout();
    void uDoTimeout();
    void uLeave( unsigned int mr );
    void uLeave2();
    void uAcceptStart( unsigned int &uMutexMaskPosn );
    bool uAcceptTry( uBasePrioritySeq &ml, int mp );
    void uAcceptTry();
    bool uAcceptTry2( uBasePrioritySeq &ml, int mp );
    bool uAcceptTestMask();
    void uAcceptElse();
    void uAcceptMask();
    void uAcceptPause();
    void uAcceptPause( uDuration duration );
    void uAcceptPause( uTime time );
    void uAcceptEnd();
    void uRemoveTimeout();
    bool uCheckHookConditions(uBaseTask *t);          // check conditions for executing hooks

    // exception handling

    uDualEvent uFailure;                        // raised when entry encounters an exceptional event
    uDualEvent uEntryFailure;                   // derived from uFailure
    uDualEvent uRendezvousFailure;              // derived from uFailure as accepted statement may be hidden inside any mutex entry
}; // uSerial


uDualEvent uSerial::uFailure : public uKernelFailure {      // general event for failure in a mutex member routine
    // The field serial is to identify the mutex object involved, which can be
    // a uMutexCoroutine or uTask.

    const uSerial *const serial;                // no bound exception in uC++
  public:
    uFailure( const uSerial *const serial, const char *const msg = "" );
    uFailure( const char *const msg = "" );
    virtual ~uFailure();
    const uSerial *const uSerialID();
    virtual void defaultTerminate() const;
}; // uSerial::uFailure


uDualEvent uSerial::uEntryFailure : public uSerial::uFailure {
    // this is raised at an execution when it is in either the entry queue or
    // the suspended stack of a mutex object
  public:
    uEntryFailure( const uSerial *const serial, const char *const msg = "" );
    uEntryFailure( const char *const msg = "" );
    virtual ~uEntryFailure();
    virtual void defaultTerminate() const;
}; // uSerial::uEntryFailure


uDualEvent uSerial::uRendezvousFailure : public uSerial::uFailure {
    // event when failing during a rendezvous

    // This exception should be raised at the acceptor concurrently. Rendezvous
    // failure is a entry failure because an accepted statement can be hidden
    // inside a mutex object entry.

    const uBaseCoroutine *const caller;
  public:
    uRendezvousFailure( const uSerial *const serial_id, const char *const msg = "" );
    virtual ~uRendezvousFailure();
    const uBaseCoroutine *const uCaller();
    virtual void defaultTerminate() const;
}; // uSerial::uRendezvousFailure


class uTaskConstructor {                        // placed in the constructor of a task
  public:
    uTaskConstructor( uAction f, uSerial &s, uBaseTask &t, uBasePIQ &piq, const char *n, bool profile );
} __attribute__(( unused )); // uTaskConstructor


class uTaskDestructor {                         // placed in the destructor of a task
    uAction f;
    uBaseTask &t;
  public:
    uTaskDestructor( uAction f, uBaseTask &t );
    ~uTaskDestructor();
}; // uTaskDestructor


class uTaskMain {                         // placed in the main member of a task
    uBaseTask &t;
  public:
    uTaskMain( uBaseTask &t );
    ~uTaskMain();
}; // uTaskMain


class uSerialConstructor {                      // placed in the constructor of a mutex class
    uAction f;
    uSerial &s;
  public:
    uSerialConstructor( uAction f, uSerial &s );
    uSerialConstructor( uAction f, uSerial &s, const char *n );
    ~uSerialConstructor();
}; // uSerialConstructor


class uSerialDestructor {                       // placed in the destructor of a mutex class
    unsigned int nlevel;                        // nesting level counter for accessed serial-objects
    unsigned int mr;                            // mutex recursion counter for multiple serial-object entry
    uAction f;
    uSerial &s;
  public:
    uSerialDestructor( uAction f, uSerial &s, uBasePrioritySeq &ml, int mp );
    ~uSerialDestructor();
}; // uSerialDestructor


class uSerialMember {                           // placed in the mutex member of a mutex class
    unsigned int nlevel;                        // nesting level counter for accessed serial-objects
    unsigned int mr;                            // mutex recursion counter for multiple serial-object entry
    uSerial &s;

    // exception handling

    friend class uSerial;                       // access: caller, acceptor
    friend class uCondition;                    // access: caller

    uBaseTask *acceptor;                        // acceptor of the entry invocation, NULL => no acceptor
    bool uAcceptorSuspended;                            // true only when the acceptor, if there is one, remains blocked
    bool noUserOverride;                                // true when uAcceptor has not been called
  public:
    uSerialMember( uSerial &s, uBasePrioritySeq &ml, int mp );
    ~uSerialMember();

    // Return the acceptor only when the acceptor remains suspended and the
    // mutex object has yet to be destroyed, otherwise return NULL reference.
    // Side-effect: prevent the kernel from resuming (uRaise) a concurrent
    // exception at the suspended acceptor if the rendezvous terminates with an
    // exception.

    uBaseCoroutine *uAcceptor();
}; // uSerialMember


//######################### uBaseTask (cont) #########################


class uBaseTask : public uBaseCoroutine {
    friend class uMachContext;                        // access: uProfileActive
    friend class uBaseCoroutine;                // access: uCurrCoroutine
    friend uBaseCoroutine &uThisCoroutine();          // access: uCurrCoroutine
    friend class uOwnerLock;                    // access: uEntryRef, uWake
    friend class uCondLock;                     // access: uEntryRef, uWake
    friend class uSpinLock;                             // access: uProfileActive
    friend class uSemaphore;                    // access: uEntryRef, uWake
    friend class uSerial;                       // access: uEntryRef
    friend class uSerialConstructor;                  // access: uMutexRecursion
    friend class uSerialDestructor;             // access: uMutexRef, uSetState, uWake
    friend class uCondition;                    // access: uMutexRef, uSetState, uInfo
    friend class uCoroutineConstructor;               // access: uProfileActive
    friend class uCoroutineDestructor;                // access: uProfileActive
    friend class uTaskConstructor;              // access: uStartHere, uName, uProfileActive, uSerialInstance, uCurrCluster
    friend class uTaskDestructor;               // access: uCurrCluster
    friend class uTaskMain;                     // access: uRecursion
    friend uCoroutine uProcessorKernel;               // access: uCurrCoroutine
    friend uTask uProcessorTask;                // access: uBound
    friend class uCluster;                      // access: uClusterRef, uReadyRef, uWakeupTasks
    friend uTask uBootTask;                     // access: uWake
    friend class uCoroutineMain;                // access: uProfileActive
    friend class uHeapManager;                        // access: uCurrCoroutine, uInheritTask
    friend class uEventList;                      // access: uProfileActive

    // exception handling

    friend void uEHM::uTerminateHandler();            // access: uTerminateRtn
    friend std::terminate_handler std::set_terminate( std::terminate_handler func ) throw(); // access: uTerminateRtn

    // debugging

    friend class uLocalDebuggerHandler;               // access: uTaskDebugMask
    friend uTask uLocalDebugger;                // access: DebugPCandSRR
    friend uTask uLocalDebuggerReader;                // access: DebugPCandSRR, uWake
    friend class uSigHandlerModule;             // access: DebugPCandSRR

    // profiling

    friend uTask uProfiler;                             // access: uCurrCoroutine
    friend class uProfileSampler;               // access: uFuncID, uState, uName
    friend void __cyg_profile_func_enter( void *pcCurrentFunction, void *pcCallingFunction );
    friend void __cyg_profile_func_exit( void *pcCurrentFunction, void *pcCallingFunction );
    friend class uExecutionMonitor;             // access: uProfileActive
    friend uTask uMain;                         // access: uProfileActive
  public:
    enum uTaskState { uStart, uReady, uRunning, uBlocked, uTerminate };
  private:
    void uCreateTask( uCluster &uClus );
    uBaseTask( uCluster &uClus, uProcessor &uProc );  // only used by uProcessorTask
    void uSetState( uTaskState state );
    void uWake();

    uBaseTask( uBaseTask & );                   // no copy
    uBaseTask &operator=( uBaseTask & );        // no assignment

    // debugging

    char uTaskDebugMask[8];                     // 64 bit breakpoint mask for task (used only by debugger)
    void *DebugPCandSRR;                        // PC of break point; address of return message for IPC SRR
    bool uProcessBP;                            // true if task is in the middle of processing a breakpoint

    uTaskState uState;                          // current state of task
    unsigned int uRecursion;                    // allow recursive entry of main member
    unsigned int uMutexRecursion;               // number of recursive calls while holding mutex
    uCluster *uCurrCluster;                     // cluster task is executing on
    uBaseCoroutine *uCurrCoroutine;             // coroutine being executed by tasks thread
    long int uInfo;                             // condition information stored with blocked task

    uBaseTaskDL uClusterRef;                    // double link field: list of tasks on cluster
    uBaseTaskDL uReadyRef;                      // double link field: ready queue
    uBaseTaskDL uEntryRef;                      // double link field: general entry deque (all waiting tasks)
    uBaseTaskDL uMutexRef;                      // double link field: mutex member, suspend stack, condition variable
    uProcessor &uBound;                         // processor to which this task is bound, if applicable
    uBasePrioritySeq *uCalledEntryMem;                // pointer to called mutex queue
    uOwnerLock *uLockPtr;                       // pointer to owner lock used for signalling conditions

    // event tracing

    uTrace *uTraceInstance;

    // profiling

    bool uProfileActive;                        // indicates if this context is supposed to be profiled
    void uProfileActivate( uBaseTask &t );

    // exception handling

    uSerialMember *uAcceptedCall;                       // pointer to the last mutex entry accepted by this thread
    std::terminate_handler uTerminateRtn;       // per task handling termination action
  protected:
    // real-time

    friend class uSerialMember;                       // access: uSetActivePriority, uAcceptedCall
    friend class uBaseScheduleFriend;                 // access: uGetInheritTask, uGetActivePriority, uSetActivePriority, uGetBasePriority, uSetBasePriority
    friend class uWakeupHndlr;                          // access: uWake
    friend class uBasePrioritySeq;              // access: uEntryRef, uMutexRef, uCalledEntryMem, uCurrentSerial TEMPORARY
    friend class uRepositionEntry;              // access: uEntryList TEMPORARY

    // Duplicate "main" (see uMachContext) to get better error message about
    // missing "main" member for task.
    virtual void main() = 0;                    // starting routine for task

    int uPriority;
    int uActivePriority;
    uBaseTask *uInheritTask;
    int uQueueIndex;
    int uActiveQueueIndex;
    uSerial *uCurrentSerial;

    unsigned int uCurrSerialLevel;

    uBaseTask &uGetInheritTask();
    int uSetActivePriority( int p );
    int uSetActivePriority( uBaseTask &t );
    int uSetBasePriority( int p );
    int uSetActiveQueue( int q );
    int uSetBaseQueue( int q );
    uSerial &uSetSerial(uSerial &s);
  public:
    uBasePIQ *uPIQ;                             // TEMPORARY: make private
    uBaseTask();
    uBaseTask( const unsigned int stacksize );
    uBaseTask( uCluster &uClus );
    uBaseTask( uCluster &uClus, const unsigned int stacksize );
    ~uBaseTask();

    void uYield() {
      uYieldNoPoll();
      uEHM::uPoll();
    } // uBaseTask::uYield
    void uYield( const unsigned int times );

    uCluster &uMigrate( uCluster &uClus );
    uCluster &uGetCluster() const;

    uBaseCoroutine &uGetCoroutine() const {
      return *uCurrCoroutine;
    } // uBaseTask::uGetCoroutine

    uTaskState uGetState() const {
      return uState;
    } // uBaseTask::uGetState

    int uGetActivePriority() const;
    int uGetActivePriorityValue() const;
    int uGetBasePriority() const;
    int uGetActiveQueue() const;
    int uGetActiveQueueValue() const;
    int uGetBaseQueue() const;
    uSerial *uGetSerial() const;

    // profiling

    void uProfileActivate();
    void uProfileInactivate();
    void uPrintCallStack() const;

    // These members should be private but cannot be because they are
    // referenced from user code.

    void *pthreadData;                          // pointer to pthread specific data

    void uYieldNoPoll();
    void uYieldYield( const unsigned int times );     // inserted by translator for -yield
    void uYieldInvoluntary();                           // pre-allocates metric memory before yielding

    void uSleep( const uDuration duration );
    void uSleep( const uTime time );
}; // uBaseTask


inline uBaseTask &uThisTask() {
    return *THREAD_GETMEM( uActiveTask );
} // uThisTask


inline uBaseCoroutine &uThisCoroutine() {
    return *uThisTask().uCurrCoroutine;
} // uThisCoroutine

#if defined( __U_ERRNO_FUNC__ )
// ___errno on solaris, __errno_location on linux, __oserror on irix
extern "C" inline int *__U_ERRNO_FUNC__ __THROW {
    return &uThisCoroutine().uErrno;
} // __U_ERRNO_FUNC__
#endif // __U_ERRNO_FUNC__


//######################### uCondition #########################


class uCondition {
    friend class uSerial;                       // everything

    uQueue<uBaseTaskDL> uCondQueue;             // queue of blocked tasks
    uSerial *owner;                             // mutex object owning condition, only set in uWait

    uCondition( uCondition & );                       // no copy
    uCondition &operator=( uCondition & );            // no assignment
  public:
    uCondition();
    ~uCondition();

    bool empty() const;                         // test for tasks on a condition
    long int front() const;                     // return task information

    // exception handling

    uDualEvent uWaitingFailure;                       // condition queue deleted before restarted from waiting
    friend uDualEvent uCondition::uWaitingFailure;    // access: owner

    // These members should be private but cannot be because they are
    // referenced from user code.

    void uW( uSerial &s );                      // wait on a condition
    void uW( uSerial &s, long int info );       // wait on a condition with information
    void uS( uSerial &s );                      // signal a condition
    void uSBlock( uSerial &s );                       // signal a condition
}; // uCondition


uDualEvent uCondition::uWaitingFailure : public uSerial::uFailure {
    const uCondition *const cond;
  public:
    uWaitingFailure( const uCondition *const cond, const char *const msg = "" );
    virtual ~uWaitingFailure();
    const uCondition *const uConditionID() const;
    virtual void defaultTerminate() const;
}; // uCondition::uWaitingFailure 


//######################### uProcessorKernel #########################


#define uSCHEDULE(parm...) \
    THREAD_GETMEM( uSelf )->uDisableInterrupts(); \
    uActiveProcessorKernel->uSchedule( parm ); \
    THREAD_GETMEM( uSelf )->uEnableInterrupts(); \
    /* Are uC++ kernel memory allocation hooks active? */ \
    if ( uThisTask().uProfileActive && uProfiler::uProfiler_PostallocateMetricMemory ) { \
      (*uProfiler::uProfiler_PostallocateMetricMemory)( uProfiler::uProfilerInstance, uThisTask() ); \
    }


uCoroutine uProcessorKernel {
    friend class uKernelBoot;                   // access: ~uProcessorKernel
    friend class uSerial;                       // access: uSchedule
    friend class uSerialDestructor;             // access: uSchedule
    friend class uCondition;                    // access: uSchedule
    friend class uOwnerLock;                    // access: uSchedule
    friend class uCondLock;                     // access: uSchedule
    friend class uSemaphore;                    // access: uSchedule
    friend class uBaseTask;                     // access: uSchedule
    friend uTask uProcessorTask;                // access: uTerminated
    friend class uProcessor;                    // access: uProcessorKernel

    // debugging

    bool uTerminated;                           // terminate processor kernel ?
    int uCode;                                  // schedule state
    uSpinLock *uPrevLock;                       // comunication
    uBaseTask *uNextTask;                       // task to be wakened

    // real-time

    friend class uEventList;                            // access: uContextSwitchHandler, uSetTimer
    friend class uEventListPop;                       // access: uContextSwitchHandler, uSetTimer
    friend class uSigHandlerModule;             // access: uSetTimer
    friend class uCluster;                              // access: uSetContextSwitchEvent
    friend class uNBIO;                         // access: uSetContextSwitchEvent
    friend class uCxtSwtchHndlr;                        // access uSchedule

    void taskIsBlocking();
    void uSchedule();
    void uSchedule( uSpinLock *l );
    void uSchedule( uBaseTask *t );
    void uSchedule( uSpinLock *l, uBaseTask *t );
    void uSchedule( uLock *l, uSpinLock *sl );
    void uOnBehalfOfUser();
    void uSetTimer( uDuration time );
    void uSetTimer( uTime time );
    void nextProcessor( uProcessorDL *&uCurrProc );
    void main();

    uProcessorKernel();
    ~uProcessorKernel();

    void *operator new( size_t, void *storage );
    void *operator new( size_t size );
  public:
    uClock uKernelClock;
}; // uProcessorKernel


//######################### uProcessor (cont) #########################


class uProcessor {
    friend class uKernelBoot;                   // access: uEvents
    friend class uKernelModule;                       // access: uEvents
    friend class uCluster;                      // access: uIdleRef, uExternal, uProcessorRef
    friend uTask uBootTask;                     // access: uCurrTask
    friend uCoroutine uProcessorKernel;               // access: uCurrCluster, uExternal, uCurrTask, uProcTask
    friend uTask uProcessorTask;                // access: uGlobalRef, uPid, uCurrCluster
    friend class uSerial;                       // access: uEvents
    friend class uCondLock;                     // access: uEvents
    friend class uNBIO;                         // access: uEvents
    friend class uBaseTask;                     // access: uEvents
    friend class uEventList;                    // access: uEvents
    friend class uEventListPop;                         // access: uContextSwitchHandler
    friend void uExit( int retcode );                 // access: uProcExit
    friend __U_START_KT_TYPE__;                       // access: everything
#if defined( __i386__ ) || defined( __ia64__ ) && ! defined( __old_perfmon__ )
    friend class uHWCounters;                           // access: uPerfctrContext (i386) or uPerfmon_fd (ia64)
#endif

    // debugging

    friend uTask uLocalDebugger;                // access: uDebugIgnore
    friend uTask uLocalDebuggerReader;                // access: uDebugIgnore

    bool uDebugIgnore;                          // ignore processor migration

    // profiling
    
    friend class uProfileSampler;
    friend uTask uProfiler;
    friend class uProfilerBoot;                       // access: uProcTask

#ifndef __U_MULTI__
    static                                // shared info on uniprocessor
#endif // ! __U_MULTI__
    uEventList *uEvents;                        // list of events for this processor
#ifndef __U_MULTI__
    static                                // shared info on uniprocessor
#endif // ! __U_MULTI__
    uEventNode *uContextEvent;                        // context-switch node for event list
#ifndef __U_MULTI__
    static                                // shared info on uniprocessor
#endif // ! __U_MULTI__
    uCxtSwtchHndlr *uContextSwitchHandler;            // special time slice handler

#ifdef __U_MULTI__
    uProcessorKernel uProcessorKer;             // need a uProcessorKernel
#endif // __U_MULTI__

#if defined( __i386__ )
#ifndef __U_MULTI__
    static
#endif // ! __U_MULTI__
    struct vperfctr *uPerfctrContext;                   // pointer to virtual performance counter context (used by uProfiler)
#endif // __i386__

#if defined( __ia64__ ) && ! defined( __old_perfmon__ )
#ifndef __U_MULTI__
    static
#endif // ! __U_MULTI__
    int uPerfmon_fd;                                    // file descriptor for perfmon context (used by uProfiler)
#endif // __ia64__ && ! __old_perfmon__

#if defined( __i386__ ) && defined( __U_MULTI__ )
    unsigned int ldtValue;
    
#   define U_MAX_LDT 8192
    static uBitSet< U_MAX_LDT > uLDTFreeSet;
    static uOwnerLock uLDTFreeSetLock;
    static bool uLDTFreeSetInit;
    static int uAllocLDT();
    static void uFreeLDT( int oldLDT );
#endif // __i386__ &&__U_MULTI__

    uProcessor( uProcessor & );                       // no copy
    uProcessor &operator=( uProcessor &);       // no assignment

    void *operator new( size_t, void *storage );
  protected:
    uClock *uProcessorClock;                            // clock bound to processor

#if defined( __solaris__ ) && defined( __U_MULTI__ )
    lwpid_t uPid;
#else
    pid_t uPid;
#endif

    unsigned int uPreemption;
    unsigned int uSpin;

    uProcessorTask *uProcTask;                        // handle processor specific requests
    uBaseTaskSeq uExternal;                     // ready queue for processor task

    uBaseTask *uCurrTask;                       // task executing on processor
    uCluster *uCurrCluster;                     // cluster processor currently associated with

    uProcessorDL uIdleRef;                      // double link field: list of idle processors
    uProcessorDL uProcessorRef;                       // double link field: list of processors on a cluster
    uProcessorDL uGlobalRef;                    // double link field: list of all processors

    void uCreateProcessor( uCluster &uClus, int ms, int spin );
    void uFork( uProcessor *np );
    void uSetContextSwitchEvent( int msecs );         // set the real-time timer
    void uSetContextSwitchEvent( uDuration duration );      // set the real-time timer
#ifdef __U_MULTI__
#if defined( __irix__ )
    pid_t uProcCreate( uProcessor *np );
#endif
#if defined( __irix__ ) ||  defined( __linux__ )
    void uProcWait( pid_t pid );
#endif
    void uProcExit( int retcode ) __attribute__(( noreturn ));
#endif // __U_MULTI__

    uProcessor( uCluster &uClus, double );            // used solely during kernel boot
  public:
    void *operator new( size_t size );

    uProcessor( unsigned int ms = uDefaultPreemption(), unsigned int spin = uDefaultSpin() );
    uProcessor( uCluster &uClus, unsigned int ms = uDefaultPreemption(), unsigned int spin = uDefaultSpin() );
    ~uProcessor();

    uClock &uGetClock() const;
    pid_t uGetPid() const;
    uCluster &uGetCluster() const;
    uCluster &uSetCluster( uCluster &uClus );
    uBaseTask &uGetTask() const;
    unsigned int uSetPreemption( unsigned int ms );
    unsigned int uGetPreemption() const;
    unsigned int uSetSpin( unsigned int spin );
    unsigned int uGetSpin() const;
    bool uIdle() const;
} __attribute__(( unused )); // uProcessor


//######################### uCluster (cont) #########################


#if defined( __solaris__ ) || defined( __irix__ )
#include <sys/select.h>                         // fd_set
#else
#include <sys/types.h>                          // fd_set
#endif


class uCluster {
    friend class uBaseTask;                     // access: uMakeTaskReady, uTaskAdd, uTaskRemove
    friend class uNBIO;                         // access: uMakeProcessorIdle, uMakeProcessorActive
    friend class uKernelBoot;                   // access: new, NBIO
    friend uCoroutine uProcessorKernel;               // access: NBIO, uReadyTaskTryRemove, uReadyTasksEmpty
    friend uTask uSystemTask;                   // access: uTasksOnCluster
    friend uTask uProcessorTask;                // access: uProcessorRemove, uProcessorAdd
    friend class uTaskConstructor;              // access: uTaskAdd
    friend class uTaskDestructor;               // access: uTaskRemove
    friend class uProcessor;                    // access: uProcessorAdd, uProcessorRemove
    friend uMonitor uClusterSampler;                  // access: uProcessorsOnCluster
    friend class uSerial;                       // access: uTaskResetPriority
    friend class uRealTimeBaseTask;             // access: uTaskReschedule, uSetPeriod, uSetFrame
    friend class uPeriodicBaseTask;             // access: uTaskReschedule, uSetPeriod, uSetFrame
    friend class uSporadicBaseTask;             // access: uTaskReschedule, uSetPeriod, uSetFrame
    friend class uFileAccess;                   // access: uCloseFD
    friend class uSocket;                       // access: uCloseFD
    friend class uSocketAccept;                       // access: uCloseFD

    // debugging

    friend uTask uLocalDebugger;                // access: uDebugIgnore
    friend uTask uLocalDebuggerReader;                // access: uDebugIgnore

    bool uDebugIgnore;                          // ignore cluster migration

    // profiling

    friend class uRUMonitor;                    // access: uProcessorsOnCluster
    friend class uRUAnalyze;                    // access: uProcessorsOnCluster

    // real-time

    friend class uEventList;                            // access: uWakeProcessor
    friend class uPriorityQ;                            // access: uReadyTasks

    uClusterDL uGlobalRef;                      // double link field: list of all clusters

    uCluster( uCluster & );                     // no copy
    uCluster &operator=( uCluster & );                // no assignment

    void *operator new( size_t, void *storage );
  protected:
    const char *uName;                          // textual name for cluster

    // The cluster cannot be a monitor because the processor kernel is only a
    // coroutine. If the kernel called a mutex routine in the cluster and could
    // not get in, the previous task executed by the kernel is put on the mutex
    // entry queue and the kernel is restarted. When the kernel restarts, it
    // now enters the critical section when it should be scheduling a new
    // task. Therefore explicit locks must be used for these queues.

    uSpinLock uReadyIdleTaskLock;               // protect uReadyTasks, uIdleProcessors and uTasksOnCluster
    uBaseSchedule<uBaseTaskDL> *uReadyTasks;          // list of tasks awaiting execution by processors on this cluster
    bool uDefaultReadyTasks;                    // indicates if the cluster allocated the ready task
    uProcessorSeq uIdleProcessors;              // list of idle processors associated with this cluster
    uBaseTaskSeq uTasksOnCluster;               // list of tasks on this cluster
    uSpinLock uProcessorsOnClusterLock;
    uProcessorSeq uProcessorsOnCluster;               // list of processors associated with this cluster

    unsigned int uStackSize;                    // default stack size

    // Make a pointer to allow static declaration for uniprocessor.
#ifndef __U_MULTI__
    static                                // shared info on uniprocessor
#endif // ! __U_MULTI__
    uNBIO *NBIO;                          // non-blocking I/O facilities

    void uCreateCluster( unsigned int stacksize, const char *name );
    void uWakeProcessor( int uPid );
    void uProcessorPause();
    void uMakeProcessorIdle( uProcessor &p );
    void uMakeProcessorActive( uProcessor &p );
    void uMakeProcessorActive();
    bool uReadyTasksEmpty();
    void uMakeTaskReady( uBaseTask &uReadyTask );
    uBaseTask &uReadyTaskTryRemove();
    void uTaskAdd( uBaseTask &t );
    void uTaskRemove( uBaseTask &t );
    virtual void uProcessorAdd( uProcessor &p );
    void uProcessorRemove( uProcessor &p );
    void uTaskReschedule( uBaseTask &t );
    void uCloseFD( int fd );
  public:
    void *operator new( size_t size );

    uCluster( unsigned int stacksize = uDefaultStackSize(), const char *name = "*unnamed*" );
    uCluster( const char *name );
    uCluster( uBaseSchedule<uBaseTaskDL> &ReadyQueue, unsigned int stacksize = uDefaultStackSize(), const char *name = "*unnamed*" );
    uCluster( uBaseSchedule<uBaseTaskDL> &ReadyQueue, const char *name = "*unnamed*" );
    virtual ~uCluster();

    const char *uSetName( const char *name );
    const char *uGetName() const;
    unsigned int uSetStackSize( unsigned int stacksize );
    unsigned int uGetStackSize() const;

    void uTaskResetPriority( uBaseTask &owner, uBaseTask &calling );
    void uTaskSetPriority( uBaseTask &owner, uBaseTask &calling );

    static const int uReadSelect;
    static const int uWriteSelect;
    static const int uExceptSelect;

    int uSelect( int fd, int rwe, timeval *timeout = NULL );
    int uSelect( fd_set *rfd, fd_set *wfd, fd_set *efd, timeval *timeout = NULL );
    int uSelect( int nfds, fd_set *rfd, fd_set *wfd, fd_set *efd, timeval *timeout = NULL );
}; // uCluster


//######################### uNBIO #########################


class uNBIOnode : public uSeqable {
    friend class uNBIO;
    friend class uSelectTimeoutHndlr;

    int nfds;                                   // return value
    uBaseTask *uPendingTask;
    enum { singleFd, multipleFds } fdType;
    bool uTimedout;
    union {
      struct {                            // used if waiting for only one fd
          int fd;
          int *uRWE;
      } sfd;
      struct {                            // used if waiting for multiple fds
          fd_mask uNFDs;
          fd_set *uRFDs;
          fd_set *uWFDs;
          fd_set *uEFDs;
      } mfd;
    } smfd;
    uCondition uPending;
  public:
}; // uNBIOnode


class uNBIO {                                   // monitor (private mutex member)
    friend class uCluster;                      // access: uCloseFD
    friend uCoroutine uProcessorKernel;               // access: uOkToSelect, uIOPoller

    fd_set uRFDs;                         // master copy of all waiting I/O for all tasks
    fd_set uWFDs;
    fd_set uEFDs;

    int maxFD;                                  // highest FD used in select mask
    bool uOkToSelect;                           // uniprocessor flag indicating blocking select
    int uFound;                                 // declared here so uniprocessor kernel can check if I/O occurred
    uBaseTask *uIOPoller;                       // pointer to current IO poller task, or 0
    uSequence<uNBIOnode> uPendingIO;                  // list of waiting tasks

    void uCheckIO( uDuration delay );
    bool uCheckPoller( uNBIOnode &uNode );
    void setMaxFD();
    uMutex void uCloseFD( int fd );             // called by uCluster
    uMutex bool uPollIO( uNBIOnode &uNode );
    uMutex bool uInitSfd( uNBIOnode &uNode );
    uMutex bool uInitSfd( uNBIOnode &uNode, uEventNode &uTimeoutEvent, uProcessor &proc );
    uMutex bool uInitMfds( fd_mask nfds, uNBIOnode &uNode );
    uMutex bool uInitMfds( fd_mask nfds, uNBIOnode &uNode, uEventNode &uTimeoutEvent, uProcessor &proc );
  public:
    uNBIO();
    ~uNBIO();
    int uSelect( int fd, int &rwe, timeval *timeout = NULL );
    int uSelect( fd_mask nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, timeval *timeout = NULL );
}; // uNBIO


//######################### uMain #########################


uTask uMain {
    // The arguments that are passed to main are passed to the first user task
    // and stored as member variables.

    int argc;
    char **argv;

    // A reference to a variable that holds the return code that the uMain task
    // returns to the OS.

    int &uRetCode;

    // Main routine for the first user task, declared here, defined by user.

    void main();
  public:
    uMain( uCluster &cluster, int size, int argc, char *argv[], int &retcode );
    ~uMain();
}; // uMain


//######################### Kernel Boot #########################


class uKernelBoot {
    static int uCount;

    static void startup();
    static void finishup();
  public:
    uKernelBoot() {
      uCount += 1;
      if ( uCount == 1 ) {
          startup();
      } // if
#ifdef __U_DEBUG_H__
      uDebugPrt( "(uKernelBoot &)0x%p.uKernelBoot\n", this );
#endif // __U_DEBUG_H__
    } // uKernelBoot::uKernelBoot

    ~uKernelBoot() {
#ifdef __U_DEBUG_H__
      uDebugPrt( "(uKernelBoot &)0x%p.~uKernelBoot\n", this );
#endif // __U_DEBUG_H__
      if ( uCount == 1 ) {
          finishup();
      } // if
      uCount -= 1;
    } // uKernelBoot::uKernelBoot
}; // uKernelBoot


// debugging

#ifdef __U_DEBUG__
#include <uLocalDebugger.h>
#endif // __U_DEBUG__


// Create an instance in each translation unit, but only the first instance to
// execute performs the system bootstrap. Do not include instances in the
// kernel modules.

#ifndef __U_KERNEL__
static uKernelBoot uBootKernel;

#if __U_LOCALDEBUGGER_H__
static uLocalDebuggerBoot uBootLocalDebugger;
#endif // __U_LOCALDEBUGGER_H__

#if defined( __U_PROFILE__ )
#ifndef __U_PROFILEABLE_ONLY__
#include <uProfilerBoot.h>
#ifndef __U_EXECUTABLE_FILENAME__
static uProfilerBoot uBootProfiler( "a.out" ); 
#else
static uProfilerBoot uBootProfiler( __U_EXECUTABLE_FILENAME__ ); // executable file name must be in quotes
#endif // __U_EXECUTABLE_FILENAME__

#endif // __U_PROFILEABLE_ONLY__
#endif // __U_PROFILE__

#endif // __U_KERNEL__


#pragma __U_USER_CODE__


#endif // __U_CPLUSPLUS_H__


// Local Variables: //
// compile-command: "gmake install" //
// End: //

Generated by  Doxygen 1.6.0   Back to index