/* * Copyright (c) 2018 CZ.NIC, z.s.p.o. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <context.h> #include <setjmp.h> #include <tls.h> #include <libarch/fibril.h> #include <libarch/faddr.h> /** * Saves current context to the variable pointed to by `self`, * and restores the context denoted by `other`. * * When the `self` context is later restored by another call to * `context_swap()`, the control flow behaves as if the earlier call to * `context_swap()` just returned. */ void context_swap(context_t *self, context_t *other) { if (!__context_save(self)) __context_restore(other, 1); } void context_create(context_t *context, const context_create_t *arg) { __context_save(context); context_set(context, FADDR(arg->fn), arg->stack_base, arg->stack_size, arg->tls); } uintptr_t context_get_pc(context_t *ctx) { // This is a simple wrapper for now, and exists to allow // potential future implementation of context_swap to omit // program counter from the context structure (e.g. if it's // stored on the stack). return ctx->pc; } uintptr_t context_get_fp(context_t *ctx) { return _context_get_fp(ctx); }