Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/context.h

    red7e057 r8df5f20  
    3636#define KERN_CONTEXT_H_
    3737
    38 #include <panic.h>
    3938#include <trace.h>
    4039#include <arch/context.h>
    41 #include <arch/faddr.h>
    4240
    4341#define context_set_generic(ctx, _pc, stack, size) \
     
    4947extern int context_save_arch(context_t *ctx) __attribute__((returns_twice));
    5048extern void context_restore_arch(context_t *ctx) __attribute__((noreturn));
     49
     50/** Save register context.
     51 *
     52 * Save the current register context (including stack pointer) to a context
     53 * structure. A subsequent call to context_restore() will return to the same
     54 * address as the corresponding call to context_save().
     55 *
     56 * Note that context_save_arch() must reuse the stack frame of the function
     57 * which called context_save(). We guarantee this by:
     58 *
     59 *   a) implementing context_save_arch() in assembly so that it does not create
     60 *      its own stack frame, and by
     61 *   b) defining context_save() as a macro because the inline keyword is just a
     62 *      hint for the compiler, not a real constraint; the application of a macro
     63 *      will definitely not create a stack frame either.
     64 *
     65 * To imagine what could happen if there were some extra stack frames created
     66 * either by context_save() or context_save_arch(), we need to realize that the
     67 * sp saved in the contex_t structure points to the current stack frame as it
     68 * existed when context_save_arch() was executing. After the return from
     69 * context_save_arch() and context_save(), any extra stack frames created by
     70 * these functions will be destroyed and their contents sooner or later
     71 * overwritten by functions called next. Any attempt to restore to a context
     72 * saved like that would therefore lead to a disaster.
     73 *
     74 * @param ctx Context structure.
     75 *
     76 * @return context_save() returns 1, context_restore() returns 0.
     77 *
     78 */
     79#define context_save(ctx)  context_save_arch(ctx)
    5180
    5281/** Restore register context.
     
    6291 *
    6392 */
    64 _NO_TRACE __attribute__((noreturn))
    65     static inline void context_restore(context_t *ctx)
     93_NO_TRACE static inline void context_restore(context_t *ctx)
    6694{
    6795        context_restore_arch(ctx);
    68 }
    69 
    70 /**
    71  * Saves current context to the variable pointed to by `self`,
    72  * and restores the context denoted by `other`.
    73  *
    74  * When the `self` context is later restored by another call to
    75  * `context_swap()`, the control flow behaves as if the earlier call to
    76  * `context_swap()` just returned.
    77  */
    78 _NO_TRACE static inline void context_swap(context_t *self, context_t *other)
    79 {
    80         if (context_save_arch(self))
    81                 context_restore_arch(other);
    82 }
    83 
    84 _NO_TRACE static inline void context_create(context_t *context,
    85     void (*fn)(void), void *stack_base, size_t stack_size)
    86 {
    87         *context = (context_t) { 0 };
    88         context_set(context, FADDR(fn), stack_base, stack_size);
    89 }
    90 
    91 __attribute__((noreturn)) static inline void context_replace(void (*fn)(void),
    92     void *stack_base, size_t stack_size)
    93 {
    94         context_t ctx;
    95         context_create(&ctx, fn, stack_base, stack_size);
    96         context_restore(&ctx);
    9796}
    9897
Note: See TracChangeset for help on using the changeset viewer.