1  /*
   2   * \brief  Thread interface
   3   * \author Norman Feske
   4   * \date   2006-04-28
   5   */

   6  
   7  /*
   8   * Copyright (C) 2006-2016 Genode Labs GmbH
   9   *
  10   * This file is part of the Genode OS framework, which is distributed
  11   * under the terms of the GNU General Public License version 2.
  12   */

  13  
  14  #ifndef _INCLUDE__BASE__THREAD_H_
  15  #define _INCLUDE__BASE__THREAD_H_
  16  
  17  /* Genode includes */
  18  #include <base/exception.h>
  19  #include <base/lock.h>
  20  #include <base/native_types.h>
  21  #include <base/trace/logger.h>
  22  #include <cpu/consts.h>
  23  #include <util/string.h>
  24  #include <util/bit_allocator.h>
  25  #include <ram_session/ram_session.h>  /* for `Ram_dataspace_capability` type */
  26  #include <cpu_session/cpu_session.h>  /* for `Thread_capability` type */
  27  #include <cpu_session/capability.h>   /* for `Cpu_session_capability` type */
  28  
  29  namespace Genode {
  30  
  31     struct Native_utcb;
  32     class Rm_session;
  33     class Thread_base;
  34     class Stack;
  35     template <unsigned> class Thread;
  36  }

  37  
  38  
  39  /**
  40   * Concurrent control flow
  41   *
  42   * A `Thread_base` object corresponds to a physical thread. The execution
  43   * starts at the `entry()` method as soon as `start()` is called.
  44   */

  45  class Genode::Thread_base
  46  {
  47     public:
  48  
  49        class Out_of_stack_space : public Exception { };
  50        class Stack_too_large    : public Exception { };
  51        class Stack_alloc_failed : public Exception { };

  52  
  53     private:
  54  
  55        /**
  56         * Allocate and locally attach a new stack
  57         *
  58         * \param stack_size   size of this threads stack
  59         * \param main_thread  wether this is the main thread
  60         */

  61        Stack *_alloc_stack(size_t stack_size, char const *name, bool main_thread);

  62  
  63        /**
  64         * Detach and release stack of the thread
  65         */

  66        void _free_stack(Stack *stack);

  67  
  68        /**
  69         * Platform-specific thread-startup code
  70         *
  71         * On some platforms, each new thread has to perform a startup
  72         * protocol, e.g., waiting for a message from the kernel. This hook
  73         * method allows for the implementation of such protocols.
  74         */

  75        void _thread_bootstrap();

  76  
  77        /**
  78         * Helper for thread startup
  79         */

  80        static void _thread_start();

  81  
  82        /**
  83         * Hook for platform-specific destructor supplements
  84         */

  85        void _deinit_platform_thread();

  86  
  87     protected:
  88  
  89        /**
  90         * Capability for this thread (set by _start())
  91         *
  92         * Used if thread creation involves core`s CPU service.
  93         */

  94        Genode::Thread_capability _thread_cap;
  95  
  96        /**
  97         * Capability to pager paging this thread (created by _start())
  98         */

  99        Genode::Pager_capability  _pager_cap;
 100  
 101        /**
 102         * Pointer to cpu session used for this thread
 103         */

 104        Genode::Cpu_session *_cpu_session;
 105  
 106        /**
 107         * Base pointer to Trace::Control area used by this thread
 108         */

 109        Trace::Control *_trace_control;
 110  
 111        /**
 112         * Pointer to primary stack
 113         */

 114        Stack *_stack;
 115  
 116        /**
 117         * Physical thread ID
 118         */

 119        Native_thread _tid;
 120  
 121        /**
 122         * Lock used for synchronizing the finalization of the thread
 123         */

 124        Genode::Lock _join_lock;
 125  
 126        /**
 127         * Thread type
 128         *
 129         * Some threads need special treatment at construction. This enum
 130         * is solely used to distinguish them at construction.
 131         */

 132        enum Type { NORMAL, MAIN, REINITIALIZED_MAIN };

 133  
 134     private:
 135  
 136        Trace::Logger _trace_logger;
 137  
 138        /**
 139         * Return `Trace::Logger` instance of calling thread
 140         *
 141         * This method is used by the tracing framework internally.
 142         */

 143        static Trace::Logger *_logger();

 144  
 145        /**
 146         * Hook for platform-specific constructor supplements
 147         *
 148         * \param weight  weighting regarding the CPU session quota
 149         * \param type    enables selection of special initialization
 150         */

 151        void _init_platform_thread(size_t weight, Type type);

 152  
 153     public:
 154  
 155        /**
 156         * Constructor
 157         *
 158         * \noapi
 159         *
 160         * FIXME: With type = Forked_main_thread the stack allocation
 161         *        gets skipped but we should at least set Stack::ds_cap in a
 162         *        way that it references the dataspace of the already attached
 163         *        stack.
 164         */

 165        Thread_base(size_t weight, const char *name, size_t stack_size,
 166                    Type type)
;

 167  
 168        /**
 169         * Constructor
 170         *
 171         * \param weight      weighting regarding the CPU session quota
 172         * \param name        thread name (for debugging)
 173         * \param stack_size  stack size
 174         *
 175         * \throw Stack_too_large
 176         * \throw Stack_alloc_failed
 177         * \throw Out_of_stack_space
 178         *
 179         * The stack for the new thread will be allocated from the RAM session
 180         * of the component environment. A small portion of the stack size is
 181         * internally used by the framework for storing thread-specific
 182         * information such as the thread`s name.
 183         */

 184        Thread_base(size_t weight, const char *name, size_t stack_size)
 185        : Thread_base(weight, name, stack_size, NORMAL) { }

 186  
 187        /**
 188         * Constructor
 189         *
 190         * Variant of the constructor that allows the use of a different
 191         * CPU session.
 192         *
 193         * \noapi Using multiple CPU sessions within a single component is
 194         *        an experimental feature.
 195         *
 196         * \param weight      weighting regarding the CPU session quota
 197         * \param name        thread name (for debugging)
 198         * \param stack_size  stack size
 199         * \param type        enables selection of special construction
 200         * \param cpu_session capability to cpu session used for construction
 201         *
 202         * \throw Stack_too_large
 203         * \throw Stack_alloc_failed
 204         * \throw Out_of_stack_space
 205         */

 206        Thread_base(size_t weight, const char *name, size_t stack_size,
 207                    Type type, Cpu_session *)
;

 208  
 209        /**
 210         * Destructor
 211         */

 212        virtual ~Thread_base();

 213  
 214        /**
 215         * Entry method of the thread
 216         */

 217        virtual void entry() = 0;

 218  
 219        /**
 220         * Start execution of the thread
 221         *
 222         * This method is virtual to enable the customization of threads
 223         * used as server activation.
 224         */

 225        virtual void start();

 226  
 227        /**
 228         * Request name of thread
 229         */

 230        void name(char *dst, size_t dst_len);

 231  
 232        /**
 233         * Add an additional stack to the thread
 234         *
 235         * \throw Stack_too_large
 236         * \throw Stack_alloc_failed
 237         * \throw Out_of_stack_space
 238         *
 239         * The stack for the new thread will be allocated from the RAM
 240         * session of the component environment. A small portion of the
 241         * stack size is internally used by the framework for storing
 242         * thread-specific information such as the thread`s name.
 243         *
 244         * \return  pointer to the new stack`s top
 245         */

 246        void* alloc_secondary_stack(char const *name, size_t stack_size);

 247  
 248        /**
 249         * Remove a secondary stack from the thread
 250         */

 251        void free_secondary_stack(void* stack_addr);

 252  
 253        /**
 254         * Request capability of thread
 255         */

 256        Genode::Thread_capability cap() const { return _thread_cap; }

 257  
 258        /**
 259         * Cancel currently blocking operation
 260         */

 261        void cancel_blocking();

 262  
 263        /**
 264         * Return thread ID
 265         *
 266         * \noapi  Only to be called from platform-specific code
 267         */

 268        Native_thread & tid() { return _tid; }

 269  
 270        /**
 271         * Return top of stack
 272         *
 273         * \return  pointer just after first stack element
 274         */

 275        void *stack_top() const;

 276  
 277        /**
 278         * Return base of stack
 279         *
 280         * \return  pointer to last stack element
 281         */

 282        void *stack_base() const;

 283  
 284        /**
 285         * Return virtual size reserved for each stack within the stack area
 286         */

 287        static size_t stack_virtual_size();

 288  
 289        /**
 290         * Return the local base address of the stack area
 291         */

 292        static addr_t stack_area_virtual_base();

 293  
 294        /**
 295         * Return total size of the stack area
 296         */

 297        static size_t stack_area_virtual_size();

 298  
 299        /**
 300         * Return `Thread_base` object corresponding to the calling thread
 301         *
 302         * \return  pointer to caller`s `Thread_base` object
 303         */

 304        static Thread_base *myself();

 305  
 306        /**
 307         * Ensure that the stack has a given size at the minimum
 308         *
 309         * \param size  minimum stack size
 310         *
 311         * \throw Stack_too_large
 312         * \throw Stack_alloc_failed
 313         */

 314        void stack_size(size_t const size);

 315  
 316        /**
 317         * Return user-level thread control block
 318         *
 319         * Note that it is safe to call this method on the result of the
 320         * `myself` class function. It handles the special case of `myself`
 321         * being 0 when called by the main thread during the component
 322         * initialization phase.
 323         */

 324        Native_utcb *utcb();

 325  
 326        /**
 327         * Block until the thread leaves the `entry` method
 328         *
 329         * Join must not be called more than once. Subsequent calls have
 330         * undefined behaviour.
 331         */

 332        void join();

 333  
 334        /**
 335         * Log null-terminated string as trace event
 336         */

 337        static void trace(char const *cstring)
 338        {
 339           _logger()->log(cstring, strlen(cstring));
 340        }

 341  
 342        /**
 343         * Log binary data as trace event
 344         */

 345        static void trace(char const *data, size_t len)
 346        {
 347           _logger()->log(data, len);
 348        }

 349  
 350        /**
 351         * Log trace event as defined in base/trace.h
 352         */

 353        template <typename EVENT>
 354        static void trace(EVENT const *event) { _logger()->log(event); }

 355  }
;

 356  
 357  
 358  template <unsigned STACK_SIZE>
 359  class Genode::Thread : public Thread_base
 360  {
 361     public:
 362  
 363        /**
 364         * Constructor
 365         *
 366         * \param weight    weighting regarding the CPU session quota
 367         * \param name      thread name (for debugging)
 368         * \param type      enables selection of special construction
 369         */

 370        explicit Thread(size_t weight, const char *name)
 371        : Thread_base(weight, name, STACK_SIZE, Type::NORMAL) { }

 372  
 373        /**
 374         * Constructor
 375         *
 376         * \param weight     weighting regarding the CPU session quota
 377         * \param name       thread name (for debugging)
 378         * \param type       enables selection of special construction
 379         *
 380         * \noapi
 381         */

 382        explicit Thread(size_t weight, const char *name, Type type)
 383        : Thread_base(weight, name, STACK_SIZE, type) { }

 384  
 385        /**
 386         * Constructor
 387         *
 388         * \param weight       weighting regarding the CPU session quota
 389         * \param name         thread name (for debugging)
 390         * \param cpu_session  thread created via specific cpu session
 391         *
 392         * \noapi
 393         */

 394        explicit Thread(size_t weight, const char *name,
 395                        Cpu_session * cpu_session)

 396        : Thread_base(weight, name, STACK_SIZE, Type::NORMAL, cpu_session) { }

 397  
 398        /**
 399         * Shortcut for `Thread(DEFAULT_WEIGHT, name, type)`
 400         *
 401         * \noapi
 402         */

 403        explicit Thread(const char *name, Type type = NORMAL)
 404        : Thread_base(Cpu_session::DEFAULT_WEIGHT, name, STACK_SIZE, type) { }

 405  
 406        /**
 407         * Shortcut for `Thread(DEFAULT_WEIGHT, name, cpu_session)`
 408         *
 409         * \noapi
 410         */

 411        explicit Thread(const char *name, Cpu_session * cpu_session)
 412        : Thread_base(Cpu_session::DEFAULT_WEIGHT, name, STACK_SIZE,
 413                      Type::NORMAL, cpu_session)

 414        { }

 415  }
;

 416  
 417  #endif /* _INCLUDE__BASE__THREAD_H_ */