eCos: An Operating System For Embedded Systems      
by Gary Thomas

Listing One
/* ---------------------------------------------------------------------
 * {{CFG_DATA
 cdl_package CYGPKG_KERNEL {
     display  "eCos kernel"
     type     boolean
     requires CYGFUN_HAL_COMMON_KERNEL_SUPPORT
     description "
         This package contains the core functionality of the eCos
         kernel. It relies on functionality provided by various HAL
         packages and by the eCos infrastructure. In turn the eCos
         kernel provides support for other packages such as the device
         drivers and the uITRON compatibility layer."
     doc ref/ecos-ref/ecos-kernel-overview.html
 }
 cdl_component CYGPKG_KERNEL_SCHED {
     display "Kernel schedulers"
     type    dummy
     parent  CYGPKG_KERNEL
     description "
         The eCos kernel provides a choice of schedulers. In addition
         there are a number of configuration options to control the
         detailed behaviour of these schedulers.
     "
     doc ref/ecos-ref/ecos-kernel-overview.html#THE-SCHEDULER
 }
 cdl_option CYGSEM_KERNEL_SCHED_MLQUEUE {
     display    "Multi-level queue scheduler"
     type       radio
     parent     CYGPKG_KERNEL_SCHED
     description "
         The multi-level queue scheduler supports multiple priority
         levels and multiple threads at each priority level.
         Preemption between priority levels is automatic. Timeslicing
         within a given priority level is controlled by a separate
         configuration option."
     doc ref/ecos-ref/ecos-kernel-overview.html#THE-SCHEDULER
 }
 cdl_option CYGSEM_KERNEL_SCHED_BITMAP {
     display    "Bitmap scheduler"
     type       radio
     parent     CYGPKG_KERNEL_SCHED
     description "
         The bitmap scheduler supports multiple priority levels, but
         only one thread can exist at each priority level. This means
         that scheduling decisions are very simple to ensure the
         schedulers efficiency. Preemption between priority levels is
         automatic. Timeslicing within a given priority level is
         irrelevant since there can be only one thread at each
         priority level."
     doc ref/ecos-ref/ecos-kernel-overview.html#THE-SCHEDULER
 }
 # NOTE: this option makes sense only if the current scheduler
 # supports multiple priority levels.
 cdl_option CYGNUM_KERNEL_SCHED_PRIORITIES {
     display            "Number of priority levels"
     type               count
     legal_values       1 to 32
     parent             CYGPKG_KERNEL_SCHED
     description "
         This option controls the number of priority levels that are
         available. For some types of schedulers, including the bitmap
         scheduler, this may impose an upper bound on the number of
         threads in the system. For other schedulers, such as the
         mlqueue scheduler, the number of threads is independent from
         the number of priority levels. Note that the lowest priority
         level is normally used only by the idle thread, although
         application threads can run at this priority if necessary."
     doc ref/ecos-ref/ecos-kernel-overview.html#THE-SCHEDULER
 }
  # NOTE: this option makes sense only for some of the schedulers.
  # Timeslicing is irrelevant for bitmap schedulers.
  cdl_option CYGSEM_KERNEL_SCHED_TIMESLICE {
      display           "Scheduler timeslicing"
      parent            CYGPKG_KERNEL_SCHED
      requires          !CYGSEM_KERNEL_SCHED_BITMAP
      requires          CYGVAR_KERNEL_COUNTERS_CLOCK
      description "
          Some schedulers, including the mlqueue scheduler, support
          timeslicing. This means that the kernel will check regularly
          whether or not there is another runnable thread with the
          same priority, and if there is such a thread will do
          an automatic context switch. Not all applications require
          timeslicing, for example, because every thread performs a
          blocking operation regularly. For these applications, it is
          possible to disable timeslicing, which reduces the overhead
          associated with timer interrupts."
  }
  cdl_option CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS {
      display           "Number of clock ticks between timeslices"
      parent            CYGPKG_KERNEL_SCHED
      type              count
      legal_values      1 to 65535
      active_if CYGSEM_KERNEL_SCHED_TIMESLICE
      description "
          Assuming timeslicing is enabled, how frequently should it
          take place? The value of this option corresponds to the
          number of clock ticks that should occur before a timeslice
          takes place, so increasing the value reduces the frequency
          of timeslices."
  }
 }}CFG_DATA */
#define CYGSEM_KERNEL_SCHED_MLQUEUE
#undef  CYGSEM_KERNEL_SCHED_BITMAP
#define CYGNUM_KERNEL_SCHED_PRIORITIES          32
#define CYGSEM_KERNEL_SCHED_TIMESLICE
#define CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS      5


Listing Two 
// -------------------------------------------------------------------------
cyg_uint32 Cyg_RealTimeClock::isr(cyg_vector vector, CYG_ADDRWORD data)
{
#ifdef HAL_CLOCK_LATENCY
    if (measure_clock_latency) {
        cyg_int32 delta;
        HAL_CLOCK_LATENCY(&delta);
        // Note: Ignore a latency of 0 when finding min_clock_latency.
        if (delta > 0) {
            // Valid delta measured
            total_clock_latency += delta;
            total_clock_interrupts++;
            if (min_clock_latency > delta) min_clock_latency = delta;
            if (max_clock_latency < delta) max_clock_latency = delta;
        }
    }
#endif
  CYG_INSTRUMENT_CLOCK( ISR, 0, 0);
  HAL_CLOCK_RESET( CYGNUM_HAL_INTERRUPT_RTC, CYGNUM_KERNEL_COUNTERS_RTC_PERIOD
 );
    Cyg_Interrupt::acknowledge_interrupt(CYGNUM_HAL_INTERRUPT_RTC);
    return Cyg_Interrupt::CALL_DSR|Cyg_Interrupt::HANDLED;
}
// -------------------------------------------------------------------------

Listing Three
// Scheduler class. This is the public scheduler interface seen by the
// rest of the kernel.
class Cyg_Scheduler
    : public Cyg_Scheduler_Implementation
{
    friend class Cyg_Thread;
    // This function is the actual implementation of the unlock function. 
    // The unlock() later is an inline shell that deals with the common case.
    static void             unlock_inner();
public:
    // The following API functions are common to all scheduler implementations.
    // claim the preemption lock
    static void             lock();         
    // release the preemption lock and possibly reschedule
    static void             unlock();
    // release the preemption lock without rescheduling
    static void             unlock_simple();
    // return a pointer to the current thread
    static Cyg_Thread       *get_current_thread();
    // Return current value of lock
    static cyg_ucount32 get_sched_lock();
    // Return current number of thread switches
    static cyg_ucount32 get_thread_switches();
    // Start execution of the scheduler
    static void start() __attribute__ ((noreturn));
    // The only  scheduler instance should be this one...
    static Cyg_Scheduler scheduler;
};


Listing Four
//==========================================================================
//      sched/mlqueue.cxx
//      Multi-level queue scheduler class implementation
//==========================================================================
// Description:  This file contains the implementations of
//                  Cyg_Scheduler_Implementation
//                  Cyg_SchedThread_Implementation
//                  Cyg_ThreadQueue_Implementation
//==========================================================================
#include <pkgconf/kernel.h>
#include <cyg/kernel/ktypes.h>         // base kernel types
#include <cyg/infra/cyg_trac.h>        // tracing macros
#include <cyg/infra/cyg_ass.h>         // assertion macros
#include <cyg/kernel/sched.hxx>        // our header
#include <cyg/hal/hal_arch.h>          // Architecture specific definitions
#include <cyg/kernel/thread.inl>       // thread inlines
#include <cyg/kernel/sched.inl>        // scheduler inlines

#ifdef CYGSEM_KERNEL_SCHED_MLQUEUE
  ... actual implementations of scheduler classes go here
#endif // CYGSEM_KERNEL_SCHED_MLQUEUE





4


