Compare commits

...

75 Commits

Author SHA1 Message Date
Ariadne Conill a0323579ac libucontext 1.3.2 2024-10-06 18:37:08 -07:00
Volker Christian 302fbd7452 loongarch64, x86: Fix compile issue by not using trampoline.c but startcontext.S for those two architectures also. 2024-10-06 12:01:38 -07:00
Ariadne Conill d64402737b loongarch64: rewrite makecontext in C
ci/woodpecker/push/woodpecker Pipeline was successful Details
also fix MCONTEXT_PC and MCONTEXT_GREGS so they actually read and write to/from
the correct addresses in the ucontext structure.
2024-08-12 13:17:41 -07:00
Ariadne Conill c3d26b7940 libucontext 1.3.1
ci/woodpecker/push/woodpecker Pipeline was successful Details
ci/woodpecker/tag/woodpecker Pipeline was successful Details
2024-08-07 20:33:42 -07:00
Ariadne Conill e07c8d0ac5 loongarch64: fix return values from getcontext/swapcontext
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 20:28:53 -07:00
Ariadne Conill ed663cf0e5 loongarch64: fix assembly warnings
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 20:25:18 -07:00
Ariadne Conill f593205e95 build: disable ARM hard float support by default
ci/woodpecker/push/woodpecker Pipeline was successful Details
It appears to be broken.
2024-08-07 20:06:26 -07:00
Ariadne Conill a65049c8d4 arm: disable use of .end directive in assembly
ci/woodpecker/push/woodpecker Pipeline was successful Details
Fixes build failure on GCC 14.
2024-08-07 20:00:15 -07:00
Ariadne Conill 828fc9e950 common-defs: allow override of END assembly macro
ci/woodpecker/push/woodpecker Pipeline was successful Details
GCC 14 on ARM does not recognize the `.end` directive anymore,
it seems.
2024-08-07 19:58:30 -07:00
Ariadne Conill 3e5059e8a1 libucontext 1.3
ci/woodpecker/push/woodpecker Pipeline was successful Details
ci/woodpecker/tag/woodpecker Pipeline was successful Details
2024-08-07 19:41:46 -07:00
Ariadne Conill 570c0c8b32 README: mention that x86-32 does not use the C trampoline anymore
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 19:41:17 -07:00
Ariadne Conill 998ae99d61 or1k: fix getcontext/swapcontext return values
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 19:28:43 -07:00
Ariadne Conill c2a8b0a9d5 riscv32: fix getcontext/swapcontext return value
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 19:19:29 -07:00
Ariadne Conill e603fd7239 riscv64: fix getcontext/swapcontext return values
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 19:15:42 -07:00
Ariadne Conill c468c50b7b s390x: fix clobbering of return values in swapcontext
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 19:04:45 -07:00
Ariadne Conill c1ecb0ea59 x86: switch back to using x86-specific trampoline
ci/woodpecker/push/woodpecker Pipeline was successful Details
Jumping into the generic trampoline causes the stack pointer to get
clobbered.

Fixes #61
2024-08-07 18:34:53 -07:00
Ariadne Conill 5445f70157 tests: libucontext_posix: quiet compiler warning on glibc
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 17:57:16 -07:00
Ariadne Conill 1a2dff93e7 build: migrate to _DEFAULT_SOURCE
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 17:54:35 -07:00
L. Pereira 7badd2d5b2 Set _XOPEN_SOURCE when building on Darwin
ci/woodpecker/push/woodpecker Pipeline was successful Details
On non-freestanding builds, including <ucontext.h> on an ARM Darwin
system will produce the following error:

  In file included from include/libucontext/bits.h:6:
  /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/
	usr/include/ucontext.h:51:2: error: The deprecated
	ucontext routines require _XOPEN_SOURCE to be defined

Defining this macro on Darwin systems will make the building pass.
2024-08-07 17:49:36 -07:00
Jim Hauxwell 4975ba9051 fix file copy
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 17:48:29 -07:00
Jim Hauxwell b3cbfd9c1a fix parallel build for makefile
The copy for bits.h ran in parallel with the initial CC.  sometimes on
CI the build would fail as the file had not arrived by the time
needed.  Fix matches meson build process.
2024-08-07 17:48:29 -07:00
Sören Tempel d0b03541bf common-trampoline: Ensure omission of frame-pointer
ci/woodpecker/push/woodpecker Pipeline was successful Details
Some architecture-specific implementations of the FETCH_LINKPTR
(e.g. the one for x86) attempt to find the linkptr relative to the
stack pointer. Therefore, they make assumption about the value of
the SP at the point where the FETCH_LINKPTR code is executed. This
means that we don't want the C compiler to mess with our SP.

For this purpose, local variables in this function are currently
declared using the register storage specifier. Additionally, we
need to make sure that a frame pointer is /always/ omitted for
this function. On x86 Alpine, the frame pointer is presently not
omitted with GCC 13 when using -Os, therefore the tests segfault
with -Os on Alpine presently.

Fixes #52
2024-08-07 17:46:50 -07:00
Volker Christian 124a962b39 aarch64: fix return value if getcontext was used to acquire the current context.
x0 hast to be 0 in case setcontext is called with a context acquired by getcontext.
Thus x0=0 must be stored in getcontext.
2024-08-07 17:45:47 -07:00
Volker Christian 9e5de65076 libucontext: Add patch fixing return values of get/set/swapcontext
The arm ABI defines that the value in register r0 is used as the return
value of a function. To indicate success for get/set/swapcontext (return
value of 0) the register r0 must contain zero at the end of the function
call. Thus set r0 to zero and store it in the context. This context
is restored later and indicate successful execution, because r0 is 0.

The order registers are stored has changed so that only one additional
instruction (mov r0, #0) needs to be added to fix the return value
bug for get/set/swapcontext.

Signed-off-by: Volker Christian <me@vchrist.at>
2024-08-07 17:44:43 -07:00
Volker Christian 076e69c9c1 libucontext: Add error checking
Add error checking test_libucontext and test_libucontext_posix
to test return values of get/set/swapcontext.

Modifications are inspired by the example program source in the
linux man page of swapcontext

Signed-off-by: Volker Christian <me@vchrist.at>
2024-08-07 17:43:55 -07:00
matoro be80075e95 meson: support building docs
ci/woodpecker/push/woodpecker Pipeline was successful Details
Toggleable with -Ddocs=(true|false), defaults to false.

Requires bumping minimum meson version to 0.59.0, or 0.61.0 to also
include symlinks.
2023-05-18 18:12:55 -07:00
Ariadne Conill 4c2cfc54ac libucontext.h: add C++ externs 2023-05-18 18:11:50 -07:00
L. Pereira 0f625a86ee Fix FREESTANDING install target
When installing a FREESTANDING build, the check for an empty variable
was not being honored because the empty string would evaluate to
nothing.  Put the variable expansion in quotes so that we have an empty
string instead.
2023-05-18 18:10:01 -07:00
Ismael Luceno 8e1397f5a2 Makefile: Make variables Automake-compatible
Also split libdir into shared and static variants to enable installing to
different locations.

Signed-off-by: Ismael Luceno <ismael@iodev.co.uk>
2023-05-18 18:08:07 -07:00
Ariadne Conill 33ff253d52 Merge pull request 'Fixed empty TYPE(__proc) causing linker issues on 32-bit arm' (#36) from rlcamp/libucontext:arm_linker_fix into master
Reviewed-on: #36
2022-03-24 08:57:53 +00:00
Richard Campbell 3044c2b908 Fixed empty TYPE(__proc) causing linker issues on 32-bit arm 2022-03-23 15:18:39 -07:00
Ariadne Conill 128e4fdc4b Merge pull request 'arm_hard_float' (#35) from rlcamp/libucontext:arm_hard_float into master
Reviewed-on: #35
2022-03-23 20:15:32 +00:00
Richard Campbell 5244775fb9 Added note to readme about floating point WIP 2022-03-04 10:41:54 -08:00
Richard Campbell 9abcd8afe0 Added passthrough of FORCE_SOFT_FLOAT and FORCE_HARD_FLOAT Makefile options 2022-03-04 10:40:30 -08:00
Richard Campbell 7bc3e90984 Added arm conditional vfp save/restore 2022-03-04 10:35:25 -08:00
Ariadne Conill 4dde3417b4 libucontext 1.2
continuous-integration/woodpecker the build was successful Details
2022-02-13 09:17:12 +00:00
Ariadne Conill 6ec3e63877 NEWS: mention or1k port
continuous-integration/woodpecker the build was successful Details
2022-02-13 09:08:46 +00:00
Ariadne Conill 69ebc5e51b README: add or1k
continuous-integration/woodpecker the build was successful Details
2022-02-13 09:07:36 +00:00
Ariadne Conill 0a72eff002 or1k: add freestanding bits 2022-02-13 09:06:58 +00:00
Ariadne Conill 973e61441a or1k: add getcontext/setcontext/swapcontext 2022-02-13 08:58:38 +00:00
Ariadne Conill 00128f7575 or1k: add makecontext and trampoline 2022-02-13 08:58:03 +00:00
Ariadne Conill 7fc08a6dc6 or1k: add definitions 2022-02-13 08:57:36 +00:00
Ariadne Conill e26a93806e build: allow check_libucontext program to be run on its own like the other check steps
continuous-integration/woodpecker the build was successful Details
2022-02-13 08:54:34 +00:00
Ariadne Conill 5d2f30f96a build: check_libucontext_posix must depend on ${LIBUCONTEXT_SONAME} 2022-02-13 08:53:45 +00:00
Ariadne Conill a51dce6e2c common-trampoline: initialize link pointer to NULL
continuous-integration/woodpecker the build was successful Details
2022-02-13 07:35:23 +00:00
Ariadne Conill a5ed584aa8 build: ensure libucontext_posix.so.1 is cleaned up
continuous-integration/woodpecker the build was successful Details
2022-02-13 07:18:19 +00:00
Ariadne Conill 9943d4f5fc NEWS: prepare for 1.2
continuous-integration/woodpecker the build was successful Details
2022-02-13 06:38:00 +00:00
Ariadne Conill 9403b481bc build: use CPPFLAGS instead of CFLAGS for FREESTANDING/EXPORT_UNPREFIXED 2022-02-13 06:25:47 +00:00
Ariadne Conill 2c0c0e5d29 build: only set default CFLAGS if there are none already set 2022-02-13 06:25:11 +00:00
Ariadne Conill c8fe721e69 build: fix linking of libucontext_posix against libucontext 2022-02-13 06:19:47 +00:00
Ariadne Conill c50182d98c build: disable executable stacks 2022-02-13 06:11:37 +00:00
Ariadne Conill 55c91428ba build: use -shared correctly instead of as linker flag
continuous-integration/woodpecker the build was successful Details
2021-12-18 16:54:17 +00:00
Ariadne Conill 18aa732212 CI: also build armv7
continuous-integration/woodpecker the build was successful Details
2021-12-01 09:36:20 -06:00
Ariadne Conill 8215aedb56 add woodpecker pipeline 2021-12-01 09:33:12 -06:00
Ariadne Conill 8efa9e8b85
Merge pull request #34 from Torrekie/master
Allow building on Darwin/arm64
2021-11-14 21:27:26 -06:00
Torrekie Gen 6ddefbbbb4
Allow building on Darwin/arm64
Changes:
1. `-soname` should be `-install_name` on Darwin
2. Version suffix should placed before extension suffix (libucontext.so.1 -> libucontext.1.dylib)
3. Check for architecture specific include directory, and include it while building
4. `EXPORT_UNPREFIXED` macro shouldn't be set since Darwin don't support aliases
5. Choose correct subdir for arm64
6. Use `-dynamiclib` instead of `-shared` on Darwin for adding version info (`-current_version` and `-compatibility_version`)
2021-11-13 19:10:25 +08:00
Ariadne Conill b1b4fe9665
Merge pull request #32 from rlcamp/master
Adjusted location within ucontext of saved/restored FP regs for compat
2021-07-31 13:38:54 -05:00
Richard Campbell 1e37bf30f9 Adjusted location within ucontext of saved/restored FP regs for compatibility 2021-07-30 12:45:12 -07:00
Ariadne Conill 14d9859c00
Merge pull request #31 from rlcamp/master
Added saving/restoring of bottom 64 bits of d8-d15 per AAPCS64
2021-07-29 20:49:13 -05:00
Richard Campbell 06303df1cd Added saving/restoring of bottom 64 bits of d8-d15 per AAPCS64 2021-07-29 18:45:48 -07:00
Ariadne Conill ae058b1f38 add loongarch64 to the supported arch list 2021-06-04 09:07:38 -06:00
Peng Fan a182fee66a Add support for Loongarch64
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
2021-06-04 09:07:38 -06:00
Ariadne Conill 0108623531
Merge pull request #28 from kraj/master
meson: Add option to pass cpu
2021-05-30 11:00:18 -05:00
Khem Raj a530eed9e7 meson: Add option to pass cpu
This helps with cross compile setups, where host_cpu != target_cpu
therefore detecting it on the fly will end up with wrong cpu to build
for

Signed-off-by: Khem Raj <raj.khem@gmail.com>
2021-05-30 08:38:54 -07:00
Ariadne Conill 335ee864ef libucontext 1.1. 2021-03-09 00:46:31 -07:00
Ariadne Conill 4d8abf9b3b update README a bit 2021-03-09 00:42:26 -07:00
Ariadne Conill 7b8f3f6d04 NEWS for 1.1. 2021-03-09 00:33:41 -07:00
Ariadne Conill fb1d203677 everywhere: drop _GNU_SOURCE requirement 2021-03-09 00:25:13 -07:00
Ariadne Conill 1ad20e03e5 add riscv32 port 2021-03-09 00:00:26 -07:00
Ariadne Conill 464f98a01b
Merge pull request #27 from utmapp/qemu-support-v2
Remaining fixes for Apple Silicon and QEMU
2021-03-08 20:48:30 -06:00
osy 9b1d8f01a6 aarch64: remove usage of FUNC macro for clang
Clang's arm64 assembler does not support multiple directives on a single
line. C macros ALWAYS expand to a single line.
2021-03-08 15:13:34 -08:00
osy 5d66c194a7 x86_64: define reg names if not defined
_GNU_SOURCE can be defined without defining REG_X macros so it is not a
good indicator. (QEMU for example defines it in the build system.) x86
and x86_64 should have consistant looking defs.h so ifndef guards are
added to each REG_X definition.
2021-03-08 14:02:58 -08:00
osy f3e1b876c7 project: move freestanding include headers
This is needed because in libucontext.h we include "libucontext/bits.h".
We therefore need to have bits.h in somepath/libucontext/bits.h. In the
Makefile, somepath/freestanding/bits.h was copied to the right path but
in the meson build system, the include copy happens at the end.
2021-03-08 13:02:27 -08:00
Ariadne Conill f04d423e63
Merge pull request #26 from lpereira/armv7l-makefile-fix
Fix ARCH deduction on armv7l when using Makefiles
2021-02-05 11:46:37 -07:00
Leandro Pereira 7823593b6f Fix ARCH deduction on armv7l when using Makefiles
The Makefile on ARMv7l devices (e.g. Raspberry Pi 400 running the
stock Raspbian distro) was failing to deduct the architecture and
empty libraries were being built as a result.  Building with Meson
works fine; only building with make generated empty libraries.

Add an override for armv7l -> arm in the Makefile to address this.
2021-02-05 08:46:38 -08:00
72 changed files with 1604 additions and 161 deletions

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
include/libucontext/bits.h
*.o
examples/cooperative_threading
test_libucontext

40
.woodpecker.yml Normal file
View File

@ -0,0 +1,40 @@
pipeline:
build-x86_64:
image: alpine
commands:
- apk add --no-cache build-base
- make check ARCH=x86_64
when:
platform: linux/amd64
build-s390x:
image: alpine
commands:
- apk add --no-cache build-base
- make check ARCH=s390x
when:
platform: linux/s390x
build-ppc64le:
image: alpine
commands:
- apk add --no-cache build-base
- make check ARCH=ppc64le
when:
platform: linux/ppc64le
build-armv7:
image: alpine
commands:
- apk add --no-cache build-base
- make check ARCH=arm
when:
platform: linux/arm
build-aarch64:
image: alpine
commands:
- apk add --no-cache build-base
- make check ARCH=aarch64
when:
platform: linux/arm64

View File

@ -1,4 +1,4 @@
Copyright (c) 2018-2020 Ariadne Conill <ariadne@dereferenced.org>
Copyright (c) 2018-2022 Ariadne Conill <ariadne@dereferenced.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above

148
Makefile
View File

@ -10,48 +10,99 @@ endif
ifeq ($(ARCH),$(filter $(ARCH),ppc64le))
override ARCH = ppc64
endif
ifeq ($(ARCH),$(filter $(ARCH),armv7l))
override ARCH = arm
endif
ifeq ($(ARCH),$(filter $(ARCH),arm64))
override ARCH = aarch64
endif
LIBDIR := /lib
INCLUDEDIR := /usr/include
PKGCONFIGDIR := /usr/lib/pkgconfig
CFLAGS := -ggdb3 -O2 -Wall
prefix = /usr
libdir = ${prefix}/lib
shared_libdir = ${libdir}
static_libdir = ${libdir}
includedir = ${prefix}/include
pkgconfigdir = ${prefix}/lib/pkgconfig
CFLAGS ?= -ggdb3 -O2 -Wall
CPPFLAGS := -Iinclude -Iarch/${ARCH} -Iarch/common
EXPORT_UNPREFIXED := yes
ifneq ($(shell uname),Darwin)
EXPORT_UNPREFIXED := yes
else
# Darwin does not support aliases
EXPORT_UNPREFIXED := no
CPPFLAGS += -D_XOPEN_SOURCE
endif
FREESTANDING := no
ifeq ($(FREESTANDING),yes)
CFLAGS += -DFREESTANDING -isystem arch/${ARCH}/freestanding
EXPORT_UNPREFIXED = no
CPPFLAGS += -DFREESTANDING
EXPORT_UNPREFIXED = no -Iarch/${ARCH}/include
else
CPPFLAGS += -Iarch/common/include
endif
# ARM hard float support is presently broken.
FORCE_SOFT_FLOAT := yes
ifeq ($(FORCE_SOFT_FLOAT),yes)
CPPFLAGS += -DFORCE_SOFT_FLOAT
endif
FORCE_HARD_FLOAT := no
ifeq ($(FORCE_HARD_FLOAT),yes)
CPPFLAGS += -DFORCE_HARD_FLOAT
endif
ifeq ($(EXPORT_UNPREFIXED),yes)
CFLAGS += -DEXPORT_UNPREFIXED
CPPFLAGS += -DEXPORT_UNPREFIXED
endif
LIBUCONTEXT_C_SRC = $(wildcard arch/${ARCH}/*.c)
LIBUCONTEXT_S_SRC = $(wildcard arch/${ARCH}/*.S)
ifeq ($(shell test -d arch/${ARCH}/include; echo $?),0)
CPPFLAGS += -Iarch/${ARCH}/include
endif
LIBUCONTEXT_VERSION := $(shell head -n 1 VERSION)
LIBUCONTEXT_OBJ = ${LIBUCONTEXT_C_SRC:.c=.o} ${LIBUCONTEXT_S_SRC:.S=.o}
LIBUCONTEXT_SOVERSION = 1
LIBUCONTEXT_NAME = libucontext.so
ifeq ($(shell uname),Darwin)
LIBUCONTEXT_NAME = libucontext.dylib
LIBUCONTEXT_SONAME = libucontext.${LIBUCONTEXT_SOVERSION}.dylib
LIBUCONTEXT_POSIX_NAME = libucontext_posix.dylib
LIBUCONTEXT_POSIX_SONAME = libucontext_posix.${LIBUCONTEXT_SOVERSION}.dylib
LIBUCONTEXT_LINKER_FLAGS = -Wl,-dynamiclib,-install_name,${LIBUCONTEXT_SONAME},-current_version,${LIBUCONTEXT_SOVERSION},-compatibility_version,${LIBUCONTEXT_SOVERSION}
LIBUCONTEXT_POSIX_LINKER_FLAGS = -Wl,-dynamiclib,-install_name,${LIBUCONTEXT_POSIX_SONAME},-current_version,${LIBUCONTEXT_SOVERSION},-compatibility_version,${LIBUCONTEXT_SOVERSION}
else
LIBUCONTEXT_NAME = libucontext.so
LIBUCONTEXT_SONAME = libucontext.so.${LIBUCONTEXT_SOVERSION}
LIBUCONTEXT_POSIX_NAME = libucontext_posix.so
LIBUCONTEXT_POSIX_SONAME = libucontext_posix.so.${LIBUCONTEXT_SOVERSION}
LIBUCONTEXT_LINKER_FLAGS = -shared -Wl,-soname,${LIBUCONTEXT_SONAME} -Wl,-z,noexecstack
LIBUCONTEXT_POSIX_LINKER_FLAGS = -shared -Wl,-soname,${LIBUCONTEXT_POSIX_SONAME} -Wl,-z,noexecstack
ASFLAGS = -Wa,--noexecstack
endif
LIBUCONTEXT_STATIC_NAME = libucontext.a
LIBUCONTEXT_PC = libucontext.pc
LIBUCONTEXT_SONAME = libucontext.so.${LIBUCONTEXT_SOVERSION}
LIBUCONTEXT_PATH = ${LIBDIR}/${LIBUCONTEXT_SONAME}
LIBUCONTEXT_STATIC_PATH = ${LIBDIR}/${LIBUCONTEXT_STATIC_NAME}
LIBUCONTEXT_PATH = ${shared_libdir}/${LIBUCONTEXT_SONAME}
LIBUCONTEXT_STATIC_PATH = ${static_libdir}/${LIBUCONTEXT_STATIC_NAME}
LIBUCONTEXT_HEADERS = \
include/libucontext/libucontext.h \
include/libucontext/bits.h
include/libucontext/libucontext.h
ifeq ($(FREESTANDING),yes)
LIBUCONTEXT_HEADERS += arch/${ARCH}/include/libucontext/bits.h
else
LIBUCONTEXT_HEADERS += arch/common/include/libucontext/bits.h
endif
LIBUCONTEXT_EXAMPLES = \
examples/cooperative_threading
LIBUCONTEXT_POSIX_NAME = libucontext_posix.so
LIBUCONTEXT_POSIX_STATIC_NAME = libucontext_posix.a
LIBUCONTEXT_POSIX_C_SRC = libucontext_posix.c
LIBUCONTEXT_POSIX_OBJ = ${LIBUCONTEXT_POSIX_C_SRC:.c=.o}
LIBUCONTEXT_POSIX_SONAME = libucontext_posix.so.${LIBUCONTEXT_SOVERSION}
LIBUCONTEXT_POSIX_PATH = ${LIBDIR}/${LIBUCONTEXT_POSIX_SONAME}
LIBUCONTEXT_POSIX_STATIC_PATH = ${LIBDIR}/${LIBUCONTEXT_POSIX_STATIC_NAME}
LIBUCONTEXT_POSIX_PATH = ${shared_libdir}/${LIBUCONTEXT_POSIX_SONAME}
LIBUCONTEXT_POSIX_STATIC_PATH = ${static_libdir}/${LIBUCONTEXT_POSIX_STATIC_NAME}
ifeq ($(FREESTANDING),yes)
LIBUCONTEXT_POSIX_NAME =
@ -61,8 +112,7 @@ endif
all: ${LIBUCONTEXT_SONAME} ${LIBUCONTEXT_STATIC_NAME} ${LIBUCONTEXT_POSIX_NAME} ${LIBUCONTEXT_POSIX_STATIC_NAME} ${LIBUCONTEXT_PC}
${LIBUCONTEXT_POSIX_NAME}: ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_POSIX_OBJ}
$(CC) -fPIC -o ${LIBUCONTEXT_POSIX_NAME} -Wl,-soname,${LIBUCONTEXT_POSIX_SONAME} \
-shared ${LIBUCONTEXT_POSIX_OBJ} ${LDFLAGS}
$(CC) -fPIC -o ${LIBUCONTEXT_POSIX_NAME} ${LIBUCONTEXT_POSIX_LINKER_FLAGS} ${LIBUCONTEXT_POSIX_OBJ} -L. -lucontext ${LDFLAGS}
${LIBUCONTEXT_POSIX_STATIC_NAME}: ${LIBUCONTEXT_STATIC_NAME} ${LIBUCONTEXT_POSIX_OBJ}
$(AR) rcs ${LIBUCONTEXT_POSIX_STATIC_NAME} ${LIBUCONTEXT_POSIX_OBJ}
@ -70,20 +120,20 @@ ${LIBUCONTEXT_POSIX_STATIC_NAME}: ${LIBUCONTEXT_STATIC_NAME} ${LIBUCONTEXT_POSIX
${LIBUCONTEXT_POSIX_SONAME}: ${LIBUCONTEXT_POSIX_NAME}
ln -sf ${LIBUCONTEXT_POSIX_NAME} ${LIBUCONTEXT_POSIX_SONAME}
${LIBUCONTEXT_STATIC_NAME}: ${LIBUCONTEXT_HEADERS} ${LIBUCONTEXT_OBJ}
${LIBUCONTEXT_STATIC_NAME}: ${LIBUCONTEXT_OBJ}
$(AR) rcs ${LIBUCONTEXT_STATIC_NAME} ${LIBUCONTEXT_OBJ}
${LIBUCONTEXT_NAME}: ${LIBUCONTEXT_HEADERS} ${LIBUCONTEXT_OBJ}
$(CC) -fPIC -o ${LIBUCONTEXT_NAME} -Wl,-soname,${LIBUCONTEXT_SONAME} \
-shared ${LIBUCONTEXT_OBJ} ${LDFLAGS}
${LIBUCONTEXT_NAME}: ${LIBUCONTEXT_OBJ}
$(CC) -fPIC -o ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_LINKER_FLAGS} ${LIBUCONTEXT_OBJ} ${LDFLAGS}
${LIBUCONTEXT_SONAME}: ${LIBUCONTEXT_NAME}
ln -sf ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_SONAME}
${LIBUCONTEXT_PC}: libucontext.pc.in
sed -e s:@LIBUCONTEXT_VERSION@:${LIBUCONTEXT_VERSION}:g \
-e s:@LIBUCONTEXT_LIBDIR@:${LIBDIR}:g \
-e s:@LIBUCONTEXT_INCLUDEDIR@:${INCLUDEDIR}:g $< > $@
-e s:@LIBUCONTEXT_SHARED_LIBDIR@:${shared_libdir}:g \
-e s:@LIBUCONTEXT_STATIC_LIBDIR@:${static_libdir}:g \
-e s:@LIBUCONTEXT_INCLUDEDIR@:${includedir}:g $< > $@
MANPAGES_SYMLINKS_3 = \
libucontext_getcontext.3 \
@ -102,10 +152,10 @@ MANPAGES = ${MANPAGES_3}
docs: ${MANPAGES}
.c.o:
$(CC) -std=gnu99 -D_BSD_SOURCE -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} -c -o $@ $<
$(CC) -std=gnu99 -D_DEFAULT_SOURCE -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} -c -o $@ $<
.S.o:
$(CC) -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} -c -o $@ $<
$(CC) -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} ${ASFLAGS} -c -o $@ $<
${LIBUCONTEXT_NAME}_clean:
rm -f ${LIBUCONTEXT_NAME}
@ -122,12 +172,12 @@ libucontext_obj_clean:
${LIBUCONTEXT_PC}_clean:
rm -f ${LIBUCONTEXT_PC}
bits_clean:
rm -f include/libucontext/bits.h
${LIBUCONTEXT_POSIX_NAME}_clean:
rm -f ${LIBUCONTEXT_POSIX_NAME}
${LIBUCONTEXT_POSIX_SONAME}_clean:
rm -f ${LIBUCONTEXT_POSIX_SONAME}
${LIBUCONTEXT_POSIX_STATIC_NAME}_clean:
rm -f ${LIBUCONTEXT_POSIX_STATIC_NAME}
@ -152,8 +202,8 @@ clean: ${LIBUCONTEXT_NAME}_clean
clean: ${LIBUCONTEXT_SONAME}_clean
clean: ${LIBUCONTEXT_STATIC_NAME}_clean
clean: ${LIBUCONTEXT_PC}_clean
clean: bits_clean
clean: ${LIBUCONTEXT_POSIX_NAME}_clean
clean: ${LIBUCONTEXT_POSIX_SONAME}_clean
clean: ${LIBUCONTEXT_POSIX_STATIC_NAME}_clean
clean: libucontext_posix_obj_clean
clean: libucontext_obj_clean
@ -163,13 +213,13 @@ clean: docs_clean
install: all
install -D -m755 ${LIBUCONTEXT_NAME} ${DESTDIR}${LIBUCONTEXT_PATH}
install -D -m664 ${LIBUCONTEXT_STATIC_NAME} ${DESTDIR}${LIBUCONTEXT_STATIC_PATH}
ln -sf ${LIBUCONTEXT_SONAME} ${DESTDIR}${LIBDIR}/${LIBUCONTEXT_NAME}
ln -sf ${LIBUCONTEXT_SONAME} ${DESTDIR}${shared_libdir}/${LIBUCONTEXT_NAME}
for i in ${LIBUCONTEXT_HEADERS}; do \
destfn=$$(echo $$i | sed s:include/::g); \
install -D -m644 $$i ${DESTDIR}${INCLUDEDIR}/$$destfn; \
install -D -m644 $$i ${DESTDIR}${includedir}/$$destfn; \
done
install -D -m644 ${LIBUCONTEXT_PC} ${DESTDIR}${PKGCONFIGDIR}/${LIBUCONTEXT_PC}
if [ -n ${LIBUCONTEXT_POSIX_NAME} ]; then \
install -D -m644 ${LIBUCONTEXT_PC} ${DESTDIR}${pkgconfigdir}/${LIBUCONTEXT_PC}
if [ -n "${LIBUCONTEXT_POSIX_NAME}" ]; then \
install -D -m755 ${LIBUCONTEXT_POSIX_NAME} ${DESTDIR}${LIBUCONTEXT_POSIX_PATH}; \
install -D -m644 ${LIBUCONTEXT_POSIX_STATIC_NAME} ${DESTDIR}${LIBUCONTEXT_POSIX_STATIC_PATH}; \
fi
@ -183,11 +233,11 @@ install_docs: docs
ifneq (${FREESTANDING},yes)
check: check_libucontext_posix
check_libucontext_posix: test_libucontext_posix ${LIBUCONTEXT_POSIX_SONAME}
check_libucontext_posix: test_libucontext_posix ${LIBUCONTEXT_POSIX_SONAME} ${LIBUCONTEXT_SONAME}
env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext_posix
test_libucontext_posix: test_libucontext_posix.c ${LIBUCONTEXT_POSIX_NAME}
$(CC) -std=gnu99 -D_BSD_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext -lucontext_posix
$(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext -lucontext_posix
endif
ifeq ($(EXPORT_UNPREFIXED),yes)
@ -197,30 +247,20 @@ check_libucontext_bare_posixabi: test_libucontext_bare_posixabi ${LIBUCONTEXT_SO
env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext_bare_posixabi
test_libucontext_bare_posixabi: test_libucontext_posix.c ${LIBUCONTEXT_NAME}
$(CC) -std=gnu99 -D_BSD_SOURCE ${CFLAGS} ${CPPFLAGS} test_libucontext_posix.c -o $@ -L. -lucontext
$(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} test_libucontext_posix.c -o $@ -L. -lucontext
endif
check: test_libucontext ${LIBUCONTEXT_SONAME}
check_libucontext: test_libucontext ${LIBUCONTEXT_SONAME}
env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext
check: check_libucontext
test_libucontext: test_libucontext.c ${LIBUCONTEXT_NAME}
$(CC) -std=gnu99 -D_BSD_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext
$(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext
examples: ${LIBUCONTEXT_EXAMPLES}
examples/cooperative_threading: examples/cooperative_threading.c ${LIBUCONTEXT_NAME}
$(CC) -std=gnu99 -D_BSD_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext
ifeq ($(FREESTANDING),no)
include/libucontext/bits.h: arch/common/bits.h
cp arch/common/bits.h $@
else
include/libucontext/bits.h: arch/${ARCH}/freestanding/bits.h
cp arch/${ARCH}/freestanding/bits.h $@
endif
$(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext
PACKAGE_NAME = libucontext
PACKAGE_VERSION = ${LIBUCONTEXT_VERSION}

76
NEWS
View File

@ -1,3 +1,79 @@
Changes from 1.3.1 to 1.3.2
---------------------------
* Rewrite makecontext in C on LoongArch.
* Fix building x86 and loongarch64 variants on Meson.
Patch by Volker Christian.
Changes from 1.3 to 1.3.1
-------------------------
* Disable hard-float support on ARM by default.
* Fix up getcontext/swapcontext return values on LoongArch.
* Fix assembler warnings when building on LoongArch.
Changes from 1.2 to 1.3
-----------------------
* Fix up getcontext/swapcontext return values across a few ports.
Patches contributed for ARM and test suite by Volker Christian.
* Add support for hard-float on ARM.
Patches contributed by Richard Campbell.
* Align build system variables with those used by Automake.
Patch contributed by Ismael Luceno.
* Fix sporadic parallel build failures.
Patches contributed by Jim Hauxwell.
* Ensure frame pointers are omitted when using the C trampoline.
Patch contributed by Sören Tempel.
* Define _XOPEN_SOURCE when building on Darwin.
Patch contributed by L. Pereira.
* Add support for building the manpages with Meson.
Patch contributed by matoro.
* Migrate build from _BSD_SOURCE to _DEFAULT_SOURCE.
Changes from 1.1 to 1.2
-----------------------
* Added Loongarch64 port.
* Added OpenRISC (or1k) port.
* Fixed various build system issues:
- libucontext_posix.so is no longer underlinked
- Executable stacks are now disabled when using GNU-like toolchains
- CPPFLAGS is used consistently
- Users may now build on Darwin without using Meson
* aarch64 now implements the necessary SIMD register save/restore as
mandatory in AAPCS64.
Patches contributed by Richard Campbell.
Changes from 1.0 to 1.1
-----------------------
* Added RISC-V RV32 port.
* Cleaned up use of _GNU_SOURCE in C code.
Partially from patches contributed by osy.
* Added automatic detection of armv7l architecture.
Patch contributed by Leandro Pereira.
* Fixed installation path of libucontext_posix.a.
* Work around deficiency in clang built-in assembler on AArch64 targets.
Patch contributed by osy.
Changes from 0.13.1 to 1.0
--------------------------

View File

@ -20,15 +20,18 @@ target to do it.
|--------------|---------------|---------|-----------------------|-------------------|
| aarch64 | ✓ | | ✓ | ✓ |
| arm | ✓ | | ✓ | ✓ |
| loongarch64 | ✓ | | ✓ | |
| m68k | ✓ | | ✓ | ✓ |
| mips | ✓ | | ✓ | |
| mips64 | ✓ | | ✓ | |
| or1k | ✓ | | ✓ | ✓ |
| ppc | ✓ | ✓ | | |
| ppc64 | ✓ | ✓ | | |
| riscv32 | ✓ | | ✓ | ✓ |
| riscv64 | ✓ | | ✓ | ✓ |
| s390x | ✓ | | ✓ | |
| sh | ✓ | | ✓ | ✓ |
| x86 | ✓ | | ✓ | |
| x86 | ✓ | | ✓ | |
| x86_64 | ✓ | | ✓ | ✓ |
@ -70,15 +73,26 @@ $ make DESTDIR=out install_docs
```
## real-world use cases
`libucontext` is used on almost all musl distributions to provide the legacy `ucontext.h` API.
Additionally, it is used by:
* [UTM](https://getutm.app) -- friendly qemu distribution for macOS and iOS devices. UTM uses libucontext
as qemu's coroutine backend.
* [Lwan](https://lwan.ws) -- a high-performance embeddable asynchronous web server. Lwan uses libucontext
to provide green threads when building on non-x86 architectures.
## caveats
`libucontext`, while largely functionally equivalent does have some differences over traditional POSIX
ucontext functions:
* Saving and restoring the signal mask is not implemented. This is largely a non-issue because most
uses of these functions did not modify the signal mask anyway, but saving/restoring the signal mask
(even though it is unmodified in basically all cases in practice) induces a significant performance
penalty due to having to make kernel syscalls.
* Saving and restoring the signal mask is not implemented by default in order to avoid kernel syscall
overhead. Use `-lucontext_posix` if you actually need this functionality, which provides a POSIX
compliant implementation at the cost of performance.
* Only basic GPR registers are saved and restored when context swapping. The glibc implementation uses
hardware capability detection to save/restore other register groups, such as the FPU registers or
@ -87,4 +101,5 @@ ucontext functions:
save/restore FPU registers or vector registers may be added in a later release as a build-time
setting -- for now, we assume a soft-float ABI with no optional processor features. In practice, this
does not really matter, code using these functions are unlikely to be impacted by this design
assumption.
assumption. This is a work in progress, as newer compilers will spill even non-floating-point state
through floating point registers when allowed to do so.

View File

@ -1 +1 @@
1.0
1.3.2

View File

@ -9,6 +9,7 @@
#define SP_OFFSET 432
#define PC_OFFSET 440
#define PSTATE_OFFSET 448
#define FPSIMD_CONTEXT_OFFSET 464
#ifndef FPSIMD_MAGIC
# define FPSIMD_MAGIC 0x46508001

View File

@ -15,26 +15,15 @@
ALIAS(getcontext, libucontext_getcontext)
ALIAS(__getcontext, libucontext_getcontext)
FUNC(libucontext_getcontext)
.global PROC_NAME(libucontext_getcontext);
.align 2;
TYPE(libucontext_getcontext)
ENT(libucontext_getcontext)
PROC_NAME(libucontext_getcontext):
str xzr, [x0, #REG_OFFSET(0)]
/* save GPRs */
stp x0, x1, [x0, #REG_OFFSET(0)]
/* save x2 and x3 for reuse */
stp x2, x3, [x0, #REG_OFFSET(2)]
stp x4, x5, [x0, #REG_OFFSET(4)]
stp x6, x7, [x0, #REG_OFFSET(6)]
stp x8, x9, [x0, #REG_OFFSET(8)]
stp x10, x11, [x0, #REG_OFFSET(10)]
stp x12, x13, [x0, #REG_OFFSET(12)]
stp x14, x15, [x0, #REG_OFFSET(14)]
stp x16, x17, [x0, #REG_OFFSET(16)]
stp x18, x19, [x0, #REG_OFFSET(18)]
stp x20, x21, [x0, #REG_OFFSET(20)]
stp x22, x23, [x0, #REG_OFFSET(22)]
stp x24, x25, [x0, #REG_OFFSET(24)]
stp x26, x27, [x0, #REG_OFFSET(26)]
stp x28, x29, [x0, #REG_OFFSET(28)]
str x30, [x0, #REG_OFFSET(30)]
/* save current program counter in link register */
str x30, [x0, #PC_OFFSET]
@ -46,8 +35,32 @@ FUNC(libucontext_getcontext)
/* save pstate */
str xzr, [x0, #PSTATE_OFFSET]
/* TODO: SIMD / FPRs */
add x2, x0, #FPSIMD_CONTEXT_OFFSET
stp q8, q9, [x2, #144]
stp q10, q11, [x2, #176]
stp q12, q13, [x2, #208]
stp q14, q15, [x2, #240]
/* save GPRs and return value 0 */
mov x2, x0
mov x0, #0
stp x0, x1, [x2, #REG_OFFSET(0)]
/* x2 and x3 have already been saved */
stp x4, x5, [x2, #REG_OFFSET(4)]
stp x6, x7, [x2, #REG_OFFSET(6)]
stp x8, x9, [x2, #REG_OFFSET(8)]
stp x10, x11, [x2, #REG_OFFSET(10)]
stp x12, x13, [x2, #REG_OFFSET(12)]
stp x14, x15, [x2, #REG_OFFSET(14)]
stp x16, x17, [x2, #REG_OFFSET(16)]
stp x18, x19, [x2, #REG_OFFSET(18)]
stp x20, x21, [x2, #REG_OFFSET(20)]
stp x22, x23, [x2, #REG_OFFSET(22)]
stp x24, x25, [x2, #REG_OFFSET(24)]
stp x26, x27, [x2, #REG_OFFSET(26)]
stp x28, x29, [x2, #REG_OFFSET(28)]
str x30, [x2, #REG_OFFSET(30)]
ret
END(libucontext_getcontext)

View File

@ -10,9 +10,6 @@
* from the use of this software.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stddef.h>
#include <stdarg.h>
#include <string.h>

View File

@ -15,7 +15,11 @@
ALIAS(setcontext, libucontext_setcontext)
ALIAS(__setcontext, libucontext_setcontext)
FUNC(libucontext_setcontext)
.global PROC_NAME(libucontext_setcontext);
.align 2;
TYPE(libucontext_setcontext)
ENT(libucontext_setcontext)
PROC_NAME(libucontext_setcontext):
/* restore GPRs */
ldp x18, x19, [x0, #REG_OFFSET(18)]
ldp x20, x21, [x0, #REG_OFFSET(20)]
@ -29,7 +33,11 @@ FUNC(libucontext_setcontext)
ldr x2, [x0, #SP_OFFSET]
mov sp, x2
/* TODO: SIMD / FPRs */
add x2, x0, #FPSIMD_CONTEXT_OFFSET
ldp q8, q9, [x2, #144]
ldp q10, q11, [x2, #176]
ldp q12, q13, [x2, #208]
ldp q14, q15, [x2, #240]
/* save current program counter in link register */
ldr x16, [x0, #PC_OFFSET]

View File

@ -15,7 +15,11 @@
ALIAS(swapcontext, libucontext_swapcontext)
ALIAS(__swapcontext, libucontext_swapcontext)
FUNC(libucontext_swapcontext)
.global PROC_NAME(libucontext_swapcontext);
.align 2;
TYPE(libucontext_swapcontext)
ENT(libucontext_swapcontext)
PROC_NAME(libucontext_swapcontext):
str xzr, [x0, #REG_OFFSET(0)]
/* save GPRs */
@ -45,6 +49,12 @@ FUNC(libucontext_swapcontext)
/* save pstate */
str xzr, [x0, #PSTATE_OFFSET]
add x2, x0, #FPSIMD_CONTEXT_OFFSET
stp q8, q9, [x2, #144]
stp q10, q11, [x2, #176]
stp q12, q13, [x2, #208]
stp q14, q15, [x2, #240]
/* context to swap to is in x1 so... we move to x0 and call setcontext */
/* store our link register in x28 */
mov x28, x30

View File

@ -2,8 +2,11 @@
#define REG_SZ (4)
#define MCONTEXT_GREGS (32)
#define VFP_MAGIC_OFFSET (232)
#define VFP_D8_OFFSET (304)
#define TYPE(__proc)
#define TYPE(__proc) .type __proc, %function;
#define END(__proc)
#define FETCH_LINKPTR(dest) \
asm("movs %0, r4" : "=r" ((dest)))

View File

@ -22,6 +22,27 @@ FUNC(libucontext_getcontext)
str r13, [r0, #REG_OFFSET(13)]
str r14, [r0, #REG_OFFSET(15)]
#ifndef FORCE_SOFT_FLOAT
#ifndef FORCE_HARD_FLOAT
/* test for vfp, set kernel-defined magic number in uc_regspace */
push {r0-r1,fp,lr}
mov r0, #16
bl getauxval
tst r0, #64
pop {r0-r1,fp,lr}
moveq r2, #0
ldrne r2, =#0x56465001
str r2, [r0, #VFP_MAGIC_OFFSET]
beq 1f
#endif
/* if vfp detected, save d8-d15 */
.fpu vfp
add r1, r0, #VFP_D8_OFFSET
vstmia r1, {d8-d15}
.fpu softvfp
1:
#endif
/* return 0 */
mov r0, #0
mov pc, lr

View File

@ -23,6 +23,8 @@ typedef struct libucontext_ucontext {
struct libucontext_ucontext *uc_link;
libucontext_stack_t uc_stack;
libucontext_mcontext_t uc_mcontext;
unsigned long uc_sigmask[128 / sizeof(long)];
unsigned long long uc_regspace[64];
} libucontext_ucontext_t;
#endif

View File

@ -10,9 +10,6 @@
* from the use of this software.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stddef.h>
#include <stdarg.h>
#include <string.h>

View File

@ -16,6 +16,22 @@ ALIAS(setcontext, libucontext_setcontext)
ALIAS(__setcontext, libucontext_setcontext)
FUNC(libucontext_setcontext)
#ifndef FORCE_SOFT_FLOAT
#ifndef FORCE_HARD_FLOAT
/* test for vfp magic number set by getcontext */
ldr r2, [r0, #VFP_MAGIC_OFFSET]
ldr r3, =#0x56465001
cmp r2, r3
bne 1f
#endif
/* if vfp in use, restore d8-d15 from uc_regspace */
.fpu vfp
add r14, r0, #VFP_D8_OFFSET
vldmia r14, {d8-d15}
.fpu softvfp
1:
#endif
/* copy all of the current registers into the ucontext structure */
add r14, r0, #REG_OFFSET(0)
ldmia r14, {r0-r12}

View File

@ -16,12 +16,34 @@ ALIAS(swapcontext, libucontext_swapcontext)
ALIAS(__swapcontext, libucontext_swapcontext)
FUNC(libucontext_swapcontext)
/* copy all of the current registers into the ucontext structure */
add r2, r0, #REG_OFFSET(0)
stmia r2, {r0-r12}
str r13, [r0,#REG_OFFSET(13)]
str r14, [r0,#REG_OFFSET(15)]
#ifndef FORCE_SOFT_FLOAT
#ifndef FORCE_HARD_FLOAT
/* test for vfp magic number, copy to other ucontext */
ldr r3, [r1, #VFP_MAGIC_OFFSET]
ldr r4, =#0x56465001
str r3, [r0, #VFP_MAGIC_OFFSET]
cmp r3, r4
bne 1f
#endif
/* if vfp in use, save and restore d8-d15 */
.fpu vfp
add r2, r0, #VFP_D8_OFFSET
vstmia r2, {d8-d15}
add r14, r1, #VFP_D8_OFFSET
vldmia r14, {d8-d15}
.fpu softvfp
1:
#endif
/* copy all of the current registers into the ucontext structure */
str r13, [r0,#REG_OFFSET(13)]
str r14, [r0,#REG_OFFSET(15)]
add r2, r0, #REG_OFFSET(0)
/* copy r0 with value 0 to indicate success (return value 0) */
mov r0, #0
stmia r2, {r0-r12}
/* load new registers from the second ucontext structure */
add r14, r1, #REG_OFFSET(0)
ldmia r14, {r0-r12}

View File

@ -40,6 +40,8 @@
ENT(__proc) \
PROC_NAME(__proc): \
SETUP_FRAME(__proc)
#ifndef END
#ifdef __clang__
#define END(__proc)
#else
@ -47,6 +49,7 @@ PROC_NAME(__proc): \
.end __proc; \
.size __proc,.-__proc;
#endif
#endif
#ifdef EXPORT_UNPREFIXED
#define ALIAS(__alias, __real) \

View File

@ -14,11 +14,23 @@
#include <stdlib.h>
#include <stdio.h>
/* We need to make sure that the C compiler doesn't push any
* additional data to the stack frame. Otherwise, assumptions
* made by the architecture-specific implementation of the
* FETCH_LINKPTR() macro about the location of the linkptr,
* relative to the stack pointer, will not hold.
*
* Hence, we compile this function with -fomit-frame-pointer
* and use the register storage-class specifier for all local
* vars. Note that the latter is just a "suggestion" (see C99).
*/
__attribute__ ((visibility ("hidden")))
__attribute__ ((optimize ("omit-frame-pointer")))
void
libucontext_trampoline(void)
{
register libucontext_ucontext_t *uc_link;
register libucontext_ucontext_t *uc_link = NULL;
FETCH_LINKPTR(uc_link);

82
arch/loongarch64/defs.h Normal file
View File

@ -0,0 +1,82 @@
#ifndef __ARCH_LOONGARCH64_DEFS_H
#define __ARCH_LOONGARCH64_DEFS_H
#define REG_SZ (8)
#define REG_R0 (0)
#define REG_R1 (1)
#define REG_R2 (2)
#define REG_R3 (3)
#define REG_R4 (4)
#define REG_R5 (5)
#define REG_R6 (6)
#define REG_R7 (7)
#define REG_R8 (8)
#define REG_R9 (9)
#define REG_R10 (10)
#define REG_R11 (11)
#define REG_R12 (12)
#define REG_R13 (13)
#define REG_R14 (14)
#define REG_R15 (15)
#define REG_R16 (16)
#define REG_R17 (17)
#define REG_R18 (18)
#define REG_R19 (19)
#define REG_R20 (20)
#define REG_R21 (21)
#define REG_R22 (22)
#define REG_R23 (23)
#define REG_R24 (24)
#define REG_R25 (25)
#define REG_R26 (26)
#define REG_R27 (27)
#define REG_R28 (28)
#define REG_R29 (29)
#define REG_R30 (30)
#define REG_R31 (31)
/* $a0 is $4 , also $v0, same as $5, $a1 and $v1*/
#define REG_A0 (4)
/* stack pointer is actually $3 */
#define REG_SP (3)
/* frame pointer is actually $22 */
#define REG_FP (22)
/* $s0 is $23 */
#define REG_S0 (23)
/* $ra is $1 */
#define REG_RA (1)
/* offset to mc_gregs in ucontext_t */
#define MCONTEXT_GREGS (184)
/* offset to PC in ucontext_t */
#define MCONTEXT_PC (176)
/* offset to uc_link in ucontext_t */
#define UCONTEXT_UC_LINK (8)
/* offset to uc_stack.ss_sp in ucontext_t */
#define UCONTEXT_STACK_PTR (16)
/* offset to uc_stack.ss_size in ucontext_t */
#define UCONTEXT_STACK_SIZE (32)
/* Stack alignment, from Kernel source */
#define ALSZ 15
#define ALMASK ~15
#define FRAMESZ (((LOCALSZ * REG_SZ) + ALSZ) & ALMASK)
#define PUSH_FRAME(__proc) \
addi.d $sp, $sp, -FRAMESZ;
#define POP_FRAME(__proc) \
addi.d $sp, $sp, FRAMESZ;
#include <common-defs.h>
#endif

View File

@ -0,0 +1,43 @@
#ifndef LIBUCONTEXT_BITS_H
#define LIBUCONTEXT_BITS_H
typedef unsigned long long libucontext_greg_t, libucontext_gregset_t[32];
/* Container for all general registers. */
typedef __loongarch_mc_gp_state gregset_t;
/* Container for floating-point state. */
typedef union __loongarch_mc_fp_state fpregset_t;
union __loongarch_mc_fp_state {
unsigned int __val32[256 / 32];
unsigned long long __val64[256 / 64];
};
typedef struct mcontext_t {
unsigned long long __pc;
unsigned long long __gregs[32];
unsigned int __flags;
unsigned int __fcsr;
unsigned int __vcsr;
unsigned long long __fcc;
union __loongarch_mc_fp_state __fpregs[32] __attribute__((__aligned__ (32)));
unsigned int __reserved;
} mcontext_t;
typedef struct {
void *ss_sp;
int ss_flags;
size_t ss_size;
} libucontext_stack_t;
typedef struct libucontext_ucontext {
unsigned long uc_flags;
struct libucontext_ucontext *uc_link;
libucontext_stack_t uc_stack;
libucontext_mcontext_t uc_mcontext;
} libucontext_ucontext_t;
#endif

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2021 Peng Fan <fanpeng@loongson.cn>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#define LOCALSZ (1)
#include "defs.h"
ALIAS(getcontext, libucontext_getcontext)
FUNC(libucontext_getcontext)
/* copy $sp, $fp to temporary registers so we don't clobber them */
move $a2, $sp
move $a3, $fp
PUSH_FRAME(libucontext_getcontext)
/* set registers */
st.d $s0, $a0, REG_OFFSET(23)
st.d $s1, $a0, REG_OFFSET(24)
st.d $s2, $a0, REG_OFFSET(25)
st.d $s3, $a0, REG_OFFSET(26)
st.d $s4, $a0, REG_OFFSET(27)
st.d $s5, $a0, REG_OFFSET(28)
st.d $s6, $a0, REG_OFFSET(29)
st.d $s7, $a0, REG_OFFSET(30)
st.d $s8, $a0, REG_OFFSET(31)
st.d $a2, $a0, REG_OFFSET(3)
st.d $zero, $a0, REG_OFFSET(4)
st.d $a3, $a0, REG_OFFSET(22)
st.d $ra, $a0, REG_OFFSET(1)
st.d $ra, $a0, (MCONTEXT_PC)
move $a0, $zero
POP_FRAME(libucontext_getcontext)
jr $ra
END(libucontext_getcontext)

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2024 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "defs.h"
#include <libucontext/libucontext.h>
extern void libucontext_trampoline(void);
void
libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...)
{
libucontext_greg_t *sp, *regp;
va_list va;
int i;
/* set up and align the stack. */
sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
sp -= argc < 8 ? 0 : argc - 8;
sp = (libucontext_greg_t *) (((uintptr_t) sp & -16L));
/* set up the ucontext structure */
ucp->uc_mcontext.__gregs[REG_RA] = (libucontext_greg_t) libucontext_trampoline;
ucp->uc_mcontext.__gregs[REG_S0] = (libucontext_greg_t) ucp->uc_link;
ucp->uc_mcontext.__gregs[REG_SP] = (libucontext_greg_t) sp;
ucp->uc_mcontext.__pc = (libucontext_greg_t) func;
va_start(va, argc);
/* first 8 args go in $a0 through $a7. */
regp = &(ucp->uc_mcontext.__gregs[REG_A0]);
for (i = 0; (i < argc && i < 8); i++)
*regp++ = va_arg (va, libucontext_greg_t);
/* remainder overflows into stack */
for (; i < argc; i++)
*sp++ = va_arg (va, libucontext_greg_t);
va_end(va);
}
#ifdef EXPORT_UNPREFIXED
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
#endif

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2021 Peng Fan <fanpeng@loongson.cn>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#define LOCALSZ (1)
#include "defs.h"
ALIAS(setcontext, libucontext_setcontext)
FUNC(libucontext_setcontext)
PUSH_FRAME(libucontext_setcontext)
/* move the context to $v0, in LA, $v0 = $a0 = $4 */
move $t5, $a0
/* load the registers */
ld.d $a0, $t5, REG_OFFSET(4)
ld.d $a1, $t5, REG_OFFSET(5)
ld.d $a2, $t5, REG_OFFSET(6)
ld.d $a3, $t5, REG_OFFSET(7)
ld.d $a4, $t5, REG_OFFSET(8)
ld.d $a5, $t5, REG_OFFSET(9)
ld.d $a6, $t5, REG_OFFSET(10)
ld.d $a7, $t5, REG_OFFSET(11)
ld.d $s0, $t5, REG_OFFSET(23)
ld.d $s1, $t5, REG_OFFSET(24)
ld.d $s2, $t5, REG_OFFSET(25)
ld.d $s3, $t5, REG_OFFSET(26)
ld.d $s4, $t5, REG_OFFSET(27)
ld.d $s5, $t5, REG_OFFSET(28)
ld.d $s6, $t5, REG_OFFSET(29)
ld.d $s7, $t5, REG_OFFSET(30)
ld.d $s8, $t5, REG_OFFSET(31)
ld.d $sp, $t5, REG_OFFSET(3)
ld.d $fp, $t5, REG_OFFSET(22)
ld.d $ra, $t5, REG_OFFSET(1)
ld.d $t8, $t5, (MCONTEXT_PC)
jr $t8
move $a0, $zero
POP_FRAME(libucontext_setcontext)
END(libucontext_setcontext)

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2021 Peng Fan <fanpeng@loongson.cn>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#define LOCALSZ (4)
#include "defs.h"
FUNC(libucontext_trampoline)
/* call setcontext */
move $a0, $s0
/* we receive our initial ucontext in $s0, so if $s0 is nil, bail */
beqz $s0, no_linked_context
la.got $t8, libucontext_setcontext
jr $t8
no_linked_context:
move $a0, $zero
la.global $t8, exit
jr $t8
END(libucontext_trampoline)

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2021 Peng Fan <fanpeng@loongson.cn>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#define LOCALSZ (4)
#include "defs.h"
#define A1_OFFSET (FRAMESZ - (1 * REG_SZ))
ALIAS(swapcontext, libucontext_swapcontext)
FUNC(libucontext_swapcontext)
/* copy $sp, $fp to temporary registers so we don't clobber them */
move $a3, $sp
move $a4, $fp
move $t5, $a0
PUSH_FRAME(libucontext_swapcontext)
/* set registers */
st.d $s0, $t5, REG_OFFSET(23)
st.d $s1, $t5, REG_OFFSET(24)
st.d $s2, $t5, REG_OFFSET(25)
st.d $s3, $t5, REG_OFFSET(26)
st.d $s4, $t5, REG_OFFSET(27)
st.d $s5, $t5, REG_OFFSET(28)
st.d $s6, $t5, REG_OFFSET(29)
st.d $s7, $t5, REG_OFFSET(30)
st.d $s8, $t5, REG_OFFSET(31)
st.d $a3, $t5, REG_OFFSET(3)
st.d $zero, $t5, REG_OFFSET(4)
st.d $a4, $t5, REG_OFFSET(22)
st.d $ra, $t5, REG_OFFSET(1)
st.d $ra, $t5, (MCONTEXT_PC)
/* copy new context address in $a1 to stack */
st.d $a1, $sp, A1_OFFSET
/* load new context address into $v0 */
ld.d $t4, $sp, A1_OFFSET
/* load the registers */
ld.d $a0, $t4, REG_OFFSET(4)
ld.d $a1, $t4, REG_OFFSET(5)
ld.d $a2, $t4, REG_OFFSET(6)
ld.d $a3, $t4, REG_OFFSET(7)
ld.d $a4, $t4, REG_OFFSET(8)
ld.d $a5, $t4, REG_OFFSET(9)
ld.d $a6, $t4, REG_OFFSET(10)
ld.d $a7, $t4, REG_OFFSET(11)
ld.d $s0, $t4, REG_OFFSET(23)
ld.d $s1, $t4, REG_OFFSET(24)
ld.d $s2, $t4, REG_OFFSET(25)
ld.d $s3, $t4, REG_OFFSET(26)
ld.d $s4, $t4, REG_OFFSET(27)
ld.d $s5, $t4, REG_OFFSET(28)
ld.d $s6, $t4, REG_OFFSET(29)
ld.d $s7, $t4, REG_OFFSET(30)
ld.d $s8, $t4, REG_OFFSET(31)
ld.d $sp, $t4, REG_OFFSET(3)
ld.d $fp, $t4, REG_OFFSET(22)
ld.d $ra, $t4, REG_OFFSET(1)
ld.d $t8, $t4, (MCONTEXT_PC)
jr $t8
move $a0, $zero
fail:
la.global $t8, exit
POP_FRAME(libucontext_swapcontext)
jirl $ra, $t8, 0
move $a0, $zero
END(libucontext_swapcontext)

View File

@ -10,9 +10,6 @@
* from the use of this software.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stddef.h>
#include <stdarg.h>
#include <string.h>

22
arch/or1k/defs.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef __ARCH_OR1K_DEFS_H
#define __ARCH_OR1K_DEFS_H
#define REG_SZ (4)
#define MCONTEXT_GREGS (20)
#define REG_SP (1)
#define REG_FP (2)
#define REG_RA (9)
#define REG_SA (11)
#define REG_LR (14)
#define REG_PC (33)
#define REG_SR (34)
#define PC_OFFSET REG_OFFSET(REG_PC)
#define FETCH_LINKPTR(dest) \
asm("l.ori %0, r14, 0" :: "r" ((dest)))
#include "common-defs.h"
#endif

39
arch/or1k/getcontext.S Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2022 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include "defs.h"
ALIAS(getcontext, libucontext_getcontext)
ALIAS(__getcontext, libucontext_getcontext)
FUNC(libucontext_getcontext)
l.sw REG_OFFSET(1)(r3), r1 /* store r1 and r2 */
l.sw REG_OFFSET(2)(r3), r2
l.sw REG_OFFSET(9)(r3), r9 /* link register */
l.sw REG_OFFSET(11)(r3), r0 /* return value is 0 */
l.sw REG_OFFSET(10)(r3), r10 /* store r10 for TLS */
l.sw REG_OFFSET(14)(r3), r14 /* store r14 through r30 even */
l.sw REG_OFFSET(16)(r3), r16
l.sw REG_OFFSET(18)(r3), r18
l.sw REG_OFFSET(20)(r3), r20
l.sw REG_OFFSET(22)(r3), r22
l.sw REG_OFFSET(24)(r3), r24
l.sw REG_OFFSET(26)(r3), r26
l.sw REG_OFFSET(28)(r3), r28
l.sw REG_OFFSET(30)(r3), r30
l.ori r11, r0, 0
l.jr r9
END(libucontext_getcontext)

View File

@ -0,0 +1,28 @@
#ifndef LIBUCONTEXT_BITS_H
#define LIBUCONTEXT_BITS_H
typedef struct sigaltstack {
void *ss_sp;
int ss_flags;
size_t ss_size;
} libucontext_stack_t;
typedef int libucontext_greg_t, libucontext_gregset_t[32];
typedef struct {
struct {
libucontext_gregset_t gpr;
libucontext_greg_t pc;
libucontext_greg_t sr;
} regs;
unsigned long oldmask;
} libucontext_mcontext_t;
typedef struct libucontext_ucontext {
unsigned long uc_flags;
struct libucontext_ucontext *uc_link;
libucontext_stack_t uc_stack;
libucontext_mcontext_t uc_mcontext;
} libucontext_ucontext_t;
#endif

61
arch/or1k/makecontext.c Normal file
View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2022 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "defs.h"
#include <libucontext/libucontext.h>
extern void libucontext_trampoline(void);
void
libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...)
{
libucontext_greg_t *sp;
va_list va;
int i;
/* set up and align the stack. */
sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
sp -= argc < 6 ? 0 : (argc - 6);
sp = (libucontext_greg_t *) (((uintptr_t) sp & ~0x3));
/* set up the ucontext structure */
ucp->uc_mcontext.regs.gpr[REG_SP] = (libucontext_greg_t) sp;
ucp->uc_mcontext.regs.gpr[REG_RA] = (libucontext_greg_t) &libucontext_trampoline;
ucp->uc_mcontext.regs.gpr[REG_FP] = 0;
ucp->uc_mcontext.regs.gpr[REG_SA] = (libucontext_greg_t) func;
ucp->uc_mcontext.regs.gpr[REG_LR] = (libucontext_greg_t) ucp->uc_link;
va_start(va, argc);
/* args less than argv[6] have dedicated registers, else they overflow onto stack */
for (i = 0; i < argc; i++)
{
if (i < 6)
ucp->uc_mcontext.regs.gpr[i + 3] = va_arg (va, libucontext_greg_t);
else
sp[i - 6] = va_arg (va, libucontext_greg_t);
}
va_end(va);
}
#ifdef EXPORT_UNPREFIXED
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
#endif

48
arch/or1k/setcontext.S Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2022 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include "defs.h"
ALIAS(setcontext, libucontext_setcontext)
ALIAS(__setcontext, libucontext_setcontext)
FUNC(libucontext_setcontext)
l.ori r30, r3, 0 /* avoid clobbering r3 by copying to r30 */
l.lwz r3, REG_OFFSET(3)(r30) /* restore r3-r8 (argument registers) */
l.lwz r4, REG_OFFSET(4)(r30)
l.lwz r5, REG_OFFSET(5)(r30)
l.lwz r6, REG_OFFSET(6)(r30)
l.lwz r7, REG_OFFSET(7)(r30)
l.lwz r8, REG_OFFSET(8)(r30)
l.lwz r1, REG_OFFSET(1)(r30) /* restore stack/frame pointers */
l.lwz r2, REG_OFFSET(2)(r30)
l.lwz r9, REG_OFFSET(9)(r30) /* restore link register and starting address register */
l.lwz r11, REG_OFFSET(11)(r30)
l.lwz r10, REG_OFFSET(10)(r30) /* restore TLS register */
l.lwz r14, REG_OFFSET(14)(r30) /* restore r14-r30, even only */
l.lwz r16, REG_OFFSET(16)(r30)
l.lwz r18, REG_OFFSET(18)(r30)
l.lwz r20, REG_OFFSET(20)(r30)
l.lwz r22, REG_OFFSET(22)(r30)
l.lwz r24, REG_OFFSET(24)(r30)
l.lwz r26, REG_OFFSET(26)(r30)
l.lwz r28, REG_OFFSET(28)(r30)
l.lwz r30, REG_OFFSET(30)(r30)
l.jr r11 /* jump to new starting address */
l.ori r11, r0, 0
END(libucontext_setcontext)

68
arch/or1k/swapcontext.S Normal file
View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2022 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include "defs.h"
ALIAS(swapcontext, libucontext_swapcontext)
ALIAS(__swapcontext, libucontext_swapcontext)
FUNC(libucontext_swapcontext)
/* copy context into r3 like getcontext */
l.sw REG_OFFSET(1)(r3), r1 /* store r1 and r2 */
l.sw REG_OFFSET(2)(r3), r2
l.sw REG_OFFSET(9)(r3), r9 /* link register */
l.sw REG_OFFSET(11)(r3), r0 /* return value is zero */
l.sw REG_OFFSET(10)(r3), r10 /* store r10 for TLS */
l.sw REG_OFFSET(14)(r3), r14 /* store r14 through r30 even */
l.sw REG_OFFSET(16)(r3), r16
l.sw REG_OFFSET(18)(r3), r18
l.sw REG_OFFSET(20)(r3), r20
l.sw REG_OFFSET(22)(r3), r22
l.sw REG_OFFSET(24)(r3), r24
l.sw REG_OFFSET(26)(r3), r26
l.sw REG_OFFSET(28)(r3), r28
l.sw REG_OFFSET(30)(r3), r30
/* set the new context from r4 */
l.ori r30, r4, 0 /* copy r4 to r30 to avoid clobbering */
l.lwz r3, REG_OFFSET(3)(r30) /* restore r3-r8 (argument registers) */
l.lwz r4, REG_OFFSET(4)(r30)
l.lwz r5, REG_OFFSET(5)(r30)
l.lwz r6, REG_OFFSET(6)(r30)
l.lwz r7, REG_OFFSET(7)(r30)
l.lwz r8, REG_OFFSET(8)(r30)
l.lwz r1, REG_OFFSET(1)(r30) /* restore stack/frame pointers */
l.lwz r2, REG_OFFSET(2)(r30)
l.lwz r9, REG_OFFSET(9)(r30) /* restore link register and starting address register */
l.lwz r11, REG_OFFSET(11)(r30)
l.lwz r10, REG_OFFSET(10)(r30) /* restore TLS register */
l.lwz r14, REG_OFFSET(14)(r30) /* restore r14-r30, even only */
l.lwz r16, REG_OFFSET(16)(r30)
l.lwz r18, REG_OFFSET(18)(r30)
l.lwz r20, REG_OFFSET(20)(r30)
l.lwz r22, REG_OFFSET(22)(r30)
l.lwz r24, REG_OFFSET(24)(r30)
l.lwz r26, REG_OFFSET(26)(r30)
l.lwz r28, REG_OFFSET(28)(r30)
l.lwz r30, REG_OFFSET(30)(r30)
l.ori r11, r0, 0
l.jr r9 /* jump to new starting address */
END(libucontext_swapcontext)

View File

@ -11,9 +11,6 @@
* from the use of this software.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdarg.h>
#include <stdint.h>

View File

@ -11,9 +11,6 @@
* from the use of this software.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdarg.h>
#include <stdint.h>

55
arch/riscv32/defs.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef __ARCH_RISCV64_DEFS_H
#define __ARCH_RISCV64_DEFS_H
#define REG_SZ (4)
#define MCONTEXT_GREGS (160)
/* program counter is saved in x0 as well as x1, similar to mips */
#ifndef REG_PC
#define REG_PC (0)
#endif
#ifndef REG_RA
#define REG_RA (1)
#endif
#ifndef REG_SP
#define REG_SP (2)
#endif
#ifndef REG_S0
#define REG_S0 (8)
#endif
#define REG_S1 (9)
#ifndef REG_A0
#define REG_A0 (10)
#endif
#define REG_A1 (11)
#define REG_A2 (12)
#define REG_A3 (13)
#define REG_A4 (14)
#define REG_A5 (15)
#define REG_A6 (16)
#define REG_A7 (17)
#define REG_S2 (18)
#define REG_S3 (19)
#define REG_S4 (20)
#define REG_S5 (21)
#define REG_S6 (22)
#define REG_S7 (23)
#define REG_S8 (24)
#define REG_S9 (25)
#define REG_S10 (26)
#define REG_S11 (27)
#define PC_OFFSET REG_OFFSET(REG_PC)
#define FETCH_LINKPTR(dest) \
asm("mv %0, s1" : "=r" ((dest)))
#include "common-defs.h"
#endif

46
arch/riscv32/getcontext.S Normal file
View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include "defs.h"
ALIAS(getcontext, libucontext_getcontext)
ALIAS(__getcontext, libucontext_getcontext)
FUNC(libucontext_getcontext)
sw ra, REG_OFFSET(REG_PC)(a0)
sw ra, REG_OFFSET(REG_RA)(a0)
sw sp, REG_OFFSET(REG_SP)(a0)
/* first saved register block */
sw s0, REG_OFFSET(REG_S0)(a0)
sw s1, REG_OFFSET(REG_S1)(a0)
/* return register block */
sw x0, REG_OFFSET(REG_A0)(a0)
sw x0, REG_OFFSET(REG_A1)(a0)
/* second saved register block */
sw s2, REG_OFFSET(REG_S2)(a0)
sw s3, REG_OFFSET(REG_S3)(a0)
sw s4, REG_OFFSET(REG_S4)(a0)
sw s5, REG_OFFSET(REG_S5)(a0)
sw s6, REG_OFFSET(REG_S6)(a0)
sw s7, REG_OFFSET(REG_S7)(a0)
sw s8, REG_OFFSET(REG_S8)(a0)
sw s9, REG_OFFSET(REG_S9)(a0)
sw s10, REG_OFFSET(REG_S10)(a0)
sw s11, REG_OFFSET(REG_S11)(a0)
/* done saving, return */
mv a0, x0
ret
END(libucontext_getcontext)

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2018 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "defs.h"
#include <libucontext/libucontext.h>
extern void libucontext_trampoline(void);
void
libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...)
{
libucontext_greg_t *sp, *regp;
va_list va;
int i;
/* set up and align the stack. */
sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
sp -= argc < 8 ? 0 : argc - 8;
sp = (libucontext_greg_t *) (((uintptr_t) sp & -16L));
/* set up the ucontext structure */
ucp->uc_mcontext.__gregs[REG_RA] = (libucontext_greg_t) libucontext_trampoline;
ucp->uc_mcontext.__gregs[REG_S0] = 0;
ucp->uc_mcontext.__gregs[REG_S1] = (libucontext_greg_t) ucp->uc_link;
ucp->uc_mcontext.__gregs[REG_SP] = (libucontext_greg_t) sp;
ucp->uc_mcontext.__gregs[REG_PC] = (libucontext_greg_t) func;
va_start(va, argc);
/* first 8 args go in $a0 through $a7. */
regp = &(ucp->uc_mcontext.__gregs[REG_A0]);
for (i = 0; (i < argc && i < 8); i++)
*regp++ = va_arg (va, libucontext_greg_t);
/* remainder overflows into stack */
for (; i < argc; i++)
*sp++ = va_arg (va, libucontext_greg_t);
va_end(va);
}
#ifdef EXPORT_UNPREFIXED
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
#endif

56
arch/riscv32/setcontext.S Normal file
View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include "defs.h"
ALIAS(setcontext, libucontext_setcontext)
ALIAS(__setcontext, libucontext_setcontext)
FUNC(libucontext_setcontext)
/* move $a0 to $t0 to avoid clobbering. */
mv t0, a0
lw t1, PC_OFFSET(t0)
lw ra, REG_OFFSET(REG_RA)(t0)
lw sp, REG_OFFSET(REG_SP)(t0)
/* first saved register block */
lw s0, REG_OFFSET(REG_S0)(t0)
lw s1, REG_OFFSET(REG_S1)(t0)
/* return register block */
lw a0, REG_OFFSET(REG_A0)(t0)
lw a1, REG_OFFSET(REG_A1)(t0)
/* argument register block */
lw a2, REG_OFFSET(REG_A2)(t0)
lw a3, REG_OFFSET(REG_A3)(t0)
lw a4, REG_OFFSET(REG_A4)(t0)
lw a5, REG_OFFSET(REG_A5)(t0)
lw a6, REG_OFFSET(REG_A6)(t0)
lw a7, REG_OFFSET(REG_A7)(t0)
/* second saved register block */
lw s2, REG_OFFSET(REG_S2)(t0)
lw s3, REG_OFFSET(REG_S3)(t0)
lw s4, REG_OFFSET(REG_S4)(t0)
lw s5, REG_OFFSET(REG_S5)(t0)
lw s6, REG_OFFSET(REG_S6)(t0)
lw s7, REG_OFFSET(REG_S7)(t0)
lw s8, REG_OFFSET(REG_S8)(t0)
lw s9, REG_OFFSET(REG_S9)(t0)
lw s10, REG_OFFSET(REG_S10)(t0)
lw s11, REG_OFFSET(REG_S11)(t0)
/* done restoring, jump to new pc in S1 */
jr t1
END(libucontext_setcontext)

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include "defs.h"
ALIAS(swapcontext, libucontext_swapcontext)
ALIAS(__swapcontext, libucontext_swapcontext)
FUNC(libucontext_swapcontext)
/* move $a1 to $t0 to avoid clobbering. */
mv t0, a1
sw ra, REG_OFFSET(REG_PC)(a0)
sw ra, REG_OFFSET(REG_RA)(a0)
sw sp, REG_OFFSET(REG_SP)(a0)
/* first saved register block */
sw s0, REG_OFFSET(REG_S0)(a0)
sw s1, REG_OFFSET(REG_S1)(a0)
/* return register block */
sw x0, REG_OFFSET(REG_A0)(a0)
sw x0, REG_OFFSET(REG_A1)(a0)
/* second saved register block */
sw s2, REG_OFFSET(REG_S2)(a0)
sw s3, REG_OFFSET(REG_S3)(a0)
sw s4, REG_OFFSET(REG_S4)(a0)
sw s5, REG_OFFSET(REG_S5)(a0)
sw s6, REG_OFFSET(REG_S6)(a0)
sw s7, REG_OFFSET(REG_S7)(a0)
sw s8, REG_OFFSET(REG_S8)(a0)
sw s9, REG_OFFSET(REG_S9)(a0)
sw s10, REG_OFFSET(REG_S10)(a0)
sw s11, REG_OFFSET(REG_S11)(a0)
/* restore the other context from $t0. */
lw t1, REG_OFFSET(REG_PC)(t0)
lw ra, REG_OFFSET(REG_RA)(t0)
lw sp, REG_OFFSET(REG_SP)(t0)
/* first saved register block */
lw s0, REG_OFFSET(REG_S0)(t0)
lw s1, REG_OFFSET(REG_S1)(t0)
/* return register block */
lw a0, REG_OFFSET(REG_A0)(t0)
lw a1, REG_OFFSET(REG_A1)(t0)
/* argument register block */
lw a2, REG_OFFSET(REG_A2)(t0)
lw a3, REG_OFFSET(REG_A3)(t0)
lw a4, REG_OFFSET(REG_A4)(t0)
lw a5, REG_OFFSET(REG_A5)(t0)
lw a6, REG_OFFSET(REG_A6)(t0)
lw a7, REG_OFFSET(REG_A7)(t0)
/* second saved register block */
lw s2, REG_OFFSET(REG_S2)(t0)
lw s3, REG_OFFSET(REG_S3)(t0)
lw s4, REG_OFFSET(REG_S4)(t0)
lw s5, REG_OFFSET(REG_S5)(t0)
lw s6, REG_OFFSET(REG_S6)(t0)
lw s7, REG_OFFSET(REG_S7)(t0)
lw s8, REG_OFFSET(REG_S8)(t0)
lw s9, REG_OFFSET(REG_S9)(t0)
lw s10, REG_OFFSET(REG_S10)(t0)
lw s11, REG_OFFSET(REG_S11)(t0)
/* done swapping, jump to new PC in S1 */
jr t1
END(libucontext_swapcontext)

View File

@ -0,0 +1,3 @@
#include "defs.h"
#include <libucontext/libucontext.h>
#include "common-trampoline.c"

View File

@ -25,8 +25,8 @@ FUNC(libucontext_getcontext)
sd s1, REG_OFFSET(REG_S1)(a0)
/* return register block */
sd a0, REG_OFFSET(REG_A0)(a0)
sd a1, REG_OFFSET(REG_A1)(a0)
sd x0, REG_OFFSET(REG_A0)(a0)
sd x0, REG_OFFSET(REG_A1)(a0)
/* second saved register block */
sd s2, REG_OFFSET(REG_S2)(a0)
@ -41,5 +41,6 @@ FUNC(libucontext_getcontext)
sd s11, REG_OFFSET(REG_S11)(a0)
/* done saving, return */
mv a0, x0
ret
END(libucontext_getcontext)

View File

@ -0,0 +1,48 @@
#ifndef LIBUCONTEXT_BITS_H
#define LIBUCONTEXT_BITS_H
typedef unsigned long libucontext_greg_t;
typedef unsigned long libucontext__riscv_mc_gp_state[32];
struct libucontext__riscv_mc_f_ext_state {
unsigned int __f[32];
unsigned int __fcsr;
};
struct libucontext__riscv_mc_d_ext_state {
unsigned long long __f[32];
unsigned int __fcsr;
};
struct libucontext__riscv_mc_q_ext_state {
unsigned long long __f[64] __attribute__((aligned(16)));
unsigned int __fcsr;
unsigned int __reserved[3];
};
union libucontext__riscv_mc_fp_state {
struct libucontext__riscv_mc_f_ext_state __f;
struct libucontext__riscv_mc_d_ext_state __d;
struct libucontext__riscv_mc_q_ext_state __q;
};
typedef struct libucontext_mcontext {
libucontext__riscv_mc_gp_state __gregs;
union libucontext__riscv_mc_fp_state __fpregs;
} libucontext_mcontext_t;
typedef struct {
void *ss_sp;
int ss_flags;
size_t ss_size;
} libucontext_stack_t;
typedef struct libucontext_ucontext {
unsigned long uc_flags;
struct libucontext_ucontext *uc_link;
libucontext_stack_t uc_stack;
unsigned char __pad[128];
libucontext_mcontext_t uc_mcontext;
} libucontext_ucontext_t;
#endif

View File

@ -10,9 +10,6 @@
* from the use of this software.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stddef.h>
#include <stdarg.h>
#include <string.h>

View File

@ -28,8 +28,8 @@ FUNC(libucontext_swapcontext)
sd s1, REG_OFFSET(REG_S1)(a0)
/* return register block */
sd a0, REG_OFFSET(REG_A0)(a0)
sd a1, REG_OFFSET(REG_A1)(a0)
sd x0, REG_OFFSET(REG_A0)(a0)
sd x0, REG_OFFSET(REG_A1)(a0)
/* second saved register block */
sd s2, REG_OFFSET(REG_S2)(a0)

View File

@ -10,9 +10,6 @@
* from the use of this software.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stddef.h>
#include <stdarg.h>
#include <string.h>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org>
* Copyright (c) 2018, 2020, 2024 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -19,12 +19,14 @@ FUNC(libucontext_swapcontext)
lgr %r1, %r2 /* use %r1 to save current context to */
lgr %r0, %r3 /* use %r0 for source context */
la %r2, 0 /* zero out future return value */
stam %a0, %a15, AREG_OFFSET(0)(%r1) /* store access registers */
stmg %r0, %r15, REG_OFFSET(0)(%r1) /* store general-purpose registers */
lgr %r2, %r0 /* swap %r0 to %r2 (XXX: figure out why it hates loading from %r0) */
lam %a2, %a15, AREG_OFFSET(2)(%r2) /* load access registers, but skip %a0 and %a1 which are for TLS */
lmg %r0, %r15, REG_OFFSET(0)(%r2) /* load general-purpose registers */
lgr %r5, %r0 /* copy %r0 to %r5 so that %r0 doesn't get clobbered */
lam %a2, %a15, AREG_OFFSET(2)(%r5) /* load access registers, but skip %a0 and %a1 which are for TLS */
lmg %r0, %r15, REG_OFFSET(0)(%r5) /* load general-purpose registers */
br %r14 /* return to new link register address */
END(libucontext_swapcontext)

View File

@ -10,9 +10,6 @@
* from the use of this software.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stddef.h>
#include <stdarg.h>
#include <string.h>

View File

@ -1,7 +1,6 @@
#ifndef __ARCH_X86_DEFS_H
#define __ARCH_X86_DEFS_H
#ifndef _GNU_SOURCE
#ifndef REG_GS
# define REG_GS (0)
#endif
@ -53,15 +52,11 @@
#ifndef REG_EIP
# define REG_EIP (14)
#endif
#endif
#define REG_SZ (4)
#define MCONTEXT_GREGS (20)
#define FETCH_LINKPTR(dest) \
asm("movl (%%esp, %%ebx, 4), %0" : "=r" ((dest)));
#include "common-defs.h"
#endif

View File

@ -11,9 +11,6 @@
* from the use of this software.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stddef.h>
#include <stdarg.h>
#include <string.h>

41
arch/x86/startcontext.S Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include "defs.h"
FUNC(libucontext_trampoline)
/* get the proper context into position and test for NULL */
leal (%esp,%ebx,4), %esp
cmpl $0, (%esp)
/* restore global offset table, exit@plt and libucontext_setcontext@plt need this */
call __i686_get_pc_thunk_bx
addl $_GLOBAL_OFFSET_TABLE_, %ebx
/* if we have no linked context, lets get out of here */
je no_linked_context
/* call setcontext to switch to the linked context */
call libucontext_setcontext@plt
movl %eax, (%esp)
no_linked_context:
/* we are returning into a null context, it seems, so maybe we should exit */
call exit@plt
/* something is really hosed, call hlt to force termination */
hlt
__i686_get_pc_thunk_bx:
mov (%esp), %ebx
ret
END(libucontext_trampoline)

View File

@ -1,29 +1,95 @@
#ifndef __ARCH_X86_64_DEFS_H
#define __ARCH_X86_64_DEFS_H
#ifndef _GNU_SOURCE
#ifndef REG_R8
# define REG_R8 (0)
#endif
#ifndef REG_R9
# define REG_R9 (1)
#endif
#ifndef REG_R10
# define REG_R10 (2)
#endif
#ifndef REG_R11
# define REG_R11 (3)
#endif
#ifndef REG_R12
# define REG_R12 (4)
#endif
#ifndef REG_R13
# define REG_R13 (5)
#endif
#ifndef REG_R14
# define REG_R14 (6)
#endif
#ifndef REG_R15
# define REG_R15 (7)
#endif
#ifndef REG_RDI
# define REG_RDI (8)
#endif
#ifndef REG_RSI
# define REG_RSI (9)
#endif
#ifndef REG_RBP
# define REG_RBP (10)
#endif
#ifndef REG_RBX
# define REG_RBX (11)
#endif
#ifndef REG_RDX
# define REG_RDX (12)
#endif
#ifndef REG_RAX
# define REG_RAX (13)
#endif
#ifndef REG_RCX
# define REG_RCX (14)
#endif
#ifndef REG_RSP
# define REG_RSP (15)
#endif
#ifndef REG_RIP
# define REG_RIP (16)
#endif
#ifndef REG_EFL
# define REG_EFL (17)
#endif
#ifndef REG_CSGSFS
# define REG_CSGSFS (18)
#endif
#ifndef REG_ERR
# define REG_ERR (19)
#endif
#ifndef REG_TRAPNO
# define REG_TRAPNO (20)
#endif
#ifndef REG_OLDMASK
# define REG_OLDMASK (21)
#endif
#ifndef REG_CR2
# define REG_CR2 (22)
#endif

View File

@ -10,9 +10,6 @@
* from the use of this software.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stddef.h>
#include <stdarg.h>
#include <string.h>

21
doc/meson.build Normal file
View File

@ -0,0 +1,21 @@
scdoc = find_program('scdoc', required: true)
custom_target(
'libucontext.3',
output: 'libucontext.3',
input: 'libucontext.scd',
command: [ scdoc ],
feed: true,
capture: true,
install: true,
install_dir: get_option('mandir') / 'man3'
)
if meson.version().version_compare('>=0.61.0')
foreach link : [ 'get', 'make', 'set', 'swap' ]
install_symlink('libucontext_' + link + 'context.3',
pointing_to: 'libucontext.3',
install_dir: get_option('mandir') / 'man3'
)
endforeach
endif

View File

@ -4,9 +4,17 @@
#include <stddef.h>
#include <libucontext/bits.h>
#ifdef __cplusplus
extern "C" {
#endif
int libucontext_getcontext(libucontext_ucontext_t *);
void libucontext_makecontext(libucontext_ucontext_t *, void (*)(), int, ...);
int libucontext_setcontext(const libucontext_ucontext_t *);
int libucontext_swapcontext(libucontext_ucontext_t *, const libucontext_ucontext_t *);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,8 +1,9 @@
libdir=@LIBUCONTEXT_LIBDIR@
libdir=@LIBUCONTEXT_SHARED_LIBDIR@
static_libdir=@LIBUCONTEXT_STATIC_LIBDIR@
includedir=@LIBUCONTEXT_INCLUDEDIR@
Name: libucontext
Version: @LIBUCONTEXT_VERSION@
Description: ucontext library implementation (standalone)
Libs: -L${libdir} -lucontext
Libs: -L${libdir} -L${static_libdir} -lucontext
Cflags: -I${includedir}

View File

@ -1,12 +1,16 @@
project(
'libucontext',
'c',
meson_version : '>=0.55.0',
meson_version : '>=0.59.0',
default_options: ['c_std=gnu11', 'default_library=both'],
version : run_command('head', files('VERSION')).stdout()
)
cpu = host_machine.cpu_family()
cpu = get_option('cpu')
if cpu == ''
cpu = host_machine.cpu_family()
endif
if cpu == 'sh4'
cpu = 'sh'
endif
@ -36,7 +40,7 @@ if cpu in ['ppc', 'ppc64']
'arch' / cpu / 'retfromsyscall.c'
]
endif
if cpu not in ['mips', 'mips64', 'ppc', 'ppc64', 's390x']
if cpu not in ['loongarch64', 'mips', 'mips64', 'ppc', 'ppc64', 's390x', 'x86']
project_source_files += [
'arch' / cpu / 'trampoline.c'
]
@ -52,7 +56,7 @@ project_includes = [
]
build_args = [
'-D_BSD_SOURCE'
'-D_DEFAULT_SOURCE'
]
@ -70,9 +74,11 @@ if freestanding
build_args += '-DFREESTANDING'
build_posix = false
export_unprefixed = false
project_headers += ['arch' / cpu / 'freestanding/bits.h']
project_headers += ['arch' / cpu / 'include/libucontext/bits.h']
project_includes += ['arch' / cpu / 'include']
else
project_headers += ['arch/common/bits.h']
project_headers += ['arch/common/include/libucontext/bits.h']
project_includes += ['arch/common/include']
endif
if export_unprefixed
@ -138,9 +144,8 @@ endif
# Docs
# ====
# TODO: meson.build for docs
if not meson.is_subproject()
#subdir('docs')
if not meson.is_subproject() and get_option('docs')
subdir('doc')
endif
# ==========

View File

@ -1,4 +1,8 @@
option('freestanding', type : 'boolean', value : false,
description: 'Do not use system headers')
option('export_unprefixed', type : 'boolean', value : true,
description: 'Export POSIX 2004 ucontext names as alises')
description: 'Export POSIX 2004 ucontext names as alises')
option('cpu', type : 'string', value : '',
description: 'Target CPU architecture for cross compile')
option('docs', type : 'boolean', value : false,
description: 'Build and install man pages')

View File

@ -9,6 +9,9 @@
#include <string.h>
#include <libucontext/libucontext.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
static libucontext_ucontext_t ctx[3];
@ -36,7 +39,8 @@ static void f1 (int a, int b, int c, int d, int e, int f, int g, int h, int i, i
printf("looks like all arguments are passed correctly\n");
printf("swap back to f2\n");
libucontext_swapcontext(&ctx[1], &ctx[2]);
if (libucontext_swapcontext(&ctx[1], &ctx[2]) != 0)
handle_error("libucontext_swapcontext");
printf("finish f1\n");
}
@ -44,7 +48,8 @@ static void f1 (int a, int b, int c, int d, int e, int f, int g, int h, int i, i
static void f2 (void) {
printf("start f2\n");
printf("swap to f1\n");
libucontext_swapcontext(&ctx[2], &ctx[1]);
if (libucontext_swapcontext(&ctx[2], &ctx[1]) != 0)
handle_error("libucontext_swapcontext");
printf("finish f2, should swap to f1\n");
}
@ -63,7 +68,8 @@ int main (int argc, const char *argv[]) {
printf("setting up context 1\n");
libucontext_getcontext(&ctx[1]);
if (libucontext_getcontext(&ctx[1]) != 0)
handle_error("libucontext_getcontext");
ctx[1].uc_stack.ss_sp = st1;
ctx[1].uc_stack.ss_size = sizeof st1;
ctx[1].uc_link = &ctx[0];
@ -83,16 +89,20 @@ int main (int argc, const char *argv[]) {
printf("doing initial swapcontext\n");
libucontext_swapcontext(&ctx[0], &ctx[2]);
if (libucontext_swapcontext(&ctx[0], &ctx[2]) != 0)
handle_error("libucontext_swapcontext");
printf("returned from initial swapcontext\n");
/* test ability to use getcontext/setcontext without makecontext */
libucontext_getcontext(&ctx[1]);
if (libucontext_getcontext(&ctx[1]) != 0)
handle_error("libucontext_getcontext");
printf("done = %d\n", done);
if (done++ == 0) libucontext_setcontext(&ctx[1]);
if (done++ == 0)
if (libucontext_setcontext(&ctx[1]) != 0)
handle_error("libucontext_setcontext");
if (done != 2) {
fprintf(stderr, "wrong value for done. got %d, expected 2\n", done);
abort();

View File

@ -9,6 +9,9 @@
#include <string.h>
#include <ucontext.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
static ucontext_t ctx[3];
@ -36,7 +39,8 @@ static void f1 (int a, int b, int c, int d, int e, int f, int g, int h, int i, i
printf("looks like all arguments are passed correctly\n");
printf("swap back to f2\n");
swapcontext(&ctx[1], &ctx[2]);
if (swapcontext(&ctx[1], &ctx[2]) != 0)
handle_error("swapcontext");
printf("finish f1\n");
}
@ -44,7 +48,8 @@ static void f1 (int a, int b, int c, int d, int e, int f, int g, int h, int i, i
static void f2 (void) {
printf("start f2\n");
printf("swap to f1\n");
swapcontext(&ctx[2], &ctx[1]);
if (swapcontext(&ctx[2], &ctx[1]) != 0)
handle_error("swapcontext");
printf("finish f2, should swap to f1\n");
}
@ -67,7 +72,7 @@ int main (int argc, const char *argv[]) {
ctx[1].uc_stack.ss_sp = st1;
ctx[1].uc_stack.ss_size = sizeof st1;
ctx[1].uc_link = &ctx[0];
makecontext(&ctx[1], f1, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
makecontext(&ctx[1], (void *) f1, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
printf("setting up context 2\n");
@ -77,22 +82,25 @@ int main (int argc, const char *argv[]) {
ctx[2].uc_stack.ss_sp = st2;
ctx[2].uc_stack.ss_size = sizeof st2;
ctx[2].uc_link = &ctx[1];
makecontext(&ctx[2], f2, 0);
makecontext(&ctx[2], (void *) f2, 0);
printf("doing initial swapcontext\n");
swapcontext(&ctx[0], &ctx[2]);
if (swapcontext(&ctx[0], &ctx[2]) != 0)
handle_error("swapcontext");
printf("returned from initial swapcontext\n");
/* test ability to use getcontext/setcontext without makecontext */
getcontext(&ctx[1]);
if (getcontext(&ctx[1]) != 0)
handle_error("getcontext");
printf("done = %d\n", done);
if (done++ == 0) setcontext(&ctx[1]);
if (done++ == 0)
if (setcontext(&ctx[1]) != 0)
handle_error("setcontext");
if (done != 2) {
fprintf(stderr, "wrong value for done. got %d, expected 2\n", done);
abort();