1  /**
   2   * \brief  CPU (processing time) manager session interface
   3   * \author Christian Helmuth
   4   * \date   2006-06-27
   5   *
   6   * :Question:
   7   *
   8   *   Why are thread operations not methods of the thread but
   9   *   methods of the CPU session?
  10   *
  11   * :Answer:
  12   *
  13   *   This enables the CPU session to impose policies on thread
  14   *   operations. These policies are based on the session
  15   *   construction arguments. If thread operations would be
  16   *   provided as thread methods, Thread would need to consult
  17   *   its container object (its CPU session) about the authorization
  18   *   of each operation and, thereby, would introduce a circular
  19   *   dependency between CPU session and Thread.
  20   */

  21  
  22  /*
  23   * Copyright (C) 2006-2010 Genode Labs GmbH
  24   *
  25   * This file is part of the Genode OS framework, which is distributed
  26   * under the terms of the GNU General Public License version 2.
  27   */

  28  
  29  #ifndef _INCLUDE__CPU_SESSION__CPU_SESSION_H_
  30  #define _INCLUDE__CPU_SESSION__CPU_SESSION_H_
  31  
  32  #include <base/stdint.h>
  33  #include <base/exception.h>
  34  #include <base/thread_state.h>
  35  #include <thread/capability.h>
  36  #include <pager/capability.h>
  37  
  38  namespace Genode {
  39  
  40     class Cpu_session
  41     {
  42        protected:
  43  
  44           enum Opcode {
  45              CREATE_THREAD, KILL_THREAD, FIRST, NEXT, SET_PAGER, START,
  46              CANCEL_BLOCKING, NAME, STATE
  47           }
;

  48  
  49        public:
  50  
  51           /*********************
  52            ** Exception types **
  53            *********************/

  54  
  55           class Thread_creation_failed public Exception { };
  56  
  57  
  58           static const char *service_name() { return "CPU"; }
  59  
  60           enum { THREAD_NAME_LEN = 32 };
  61           enum { PRIORITY_LIMIT = 1 << 16 };
  62           enum { DEFAULT_PRIORITY = 0 };
  63  
  64           virtual ~Cpu_session() { }
  65  
  66           /**
  67            * Create a new thread
  68            *
  69            * \param   name  name for the thread
  70            * \return        capability representing the new thread
  71            * \throw         Thread_creation_failed
  72            */

  73           virtual Thread_capability create_thread(const char *name) = 0;

  74  
  75           /**
  76            * Kill an existing thread
  77            *
  78            * \param thread  capability of the thread to kill
  79            */

  80           virtual void kill_thread(Thread_capability thread) = 0;

  81  
  82           /**
  83            * Retrieve thread list of CPU session
  84            *
  85            * The next() function returns an invalid capability if the
  86            * specified thread does not exists or if it is the last one
  87            * of the CPU session.
  88            */

  89           virtual Thread_capability first() = 0;

  90           virtual Thread_capability next(Thread_capability curr) = 0;
  91  
  92           /**
  93            * Set paging capabilities for thread
  94            *
  95            * \param thread  thread to configure
  96            * \param pager   capability used to propagate page faults
  97            */

  98           virtual int set_pager(Thread_capability thread,
  99                                 Pager_capability  pager)
 = 0;

 100  
 101           /**
 102            * Modify instruction and stack pointer of thread - start the
 103            * thread
 104            *
 105            * \param thread  thread to start
 106            * \param ip      initial instruction pointer
 107            * \param sp      initial stack pointer
 108            *
 109            * \return        0 on success
 110            */

 111           virtual int start(Thread_capability threadaddr_t ipaddr_t sp) = 0;

 112  
 113           /**
 114            * Cancel a currently blocking operation
 115            *
 116            * \param thread  thread to unblock
 117            */

 118           virtual void cancel_blocking(Thread_capability thread) = 0;

 119  
 120           /**
 121            * Return thread name
 122            *
 123            * \param thread    thread to query
 124            * \param name_dst  destination string buffer
 125            * \param name_len  length of destination string buffer
 126            *
 127            * \return          0 on success
 128            */

 129           virtual int name(Thread_capability thread,
 130                            char *name_dstsize_t name_len)
 = 0;

 131  
 132           /**
 133            * Return thread state
 134            *
 135            * \param thread     thread to spy on
 136            * \param state_dst  result
 137            *
 138            * \return           0 on success
 139            */

 140           virtual int state(Thread_capability thread,
 141                             Thread_state *state_dst)
 = 0;

 142  
 143           /**
 144            * Translate generic priority value to kernel-specific priority levels
 145            *
 146            * \param pf_prio_limit  maximum priority used for the kernel, must
 147            *                       be power of 2
 148            * \param prio           generic priority value as used by the CPU
 149            *                       session interface
 150            * \param inverse        order of platform priorities, if true
 151            *                       `pf_prio_limit` corresponds to the highest
 152            *                       priority, otherwise it refers to the
 153            *                       lowest priority.
 154            * \return               platform-specific priority value
 155            */

 156           static unsigned scale_priority(unsigned pf_prio_limit, unsigned prio,
 157                                          bool inverse = true)

 158           {
 159              /* if no priorities are used, use the platform priority limit */
 160              if (prio == 0) return pf_prio_limit;
 161  
 162              /*
 163               * Generic priority values are (0 is highest, `PRIORITY_LIMIT`
 164               * is lowest. On platforms where priority levels are defined
 165               * the other way round, we have to invert the priority value.
 166               */

 167              prio = inverse ? Cpu_session::PRIORITY_LIMIT - prio : prio;
 168  
 169              /* scale value to platform priority range 0..pf_prio_limit */
 170              return (prio*pf_prio_limit)/Cpu_session::PRIORITY_LIMIT;

 171           }

 172     }
;

 173  }

 174  
 175  #endif /* _INCLUDE__CPU_SESSION__CPU_SESSION_H_ */