Compare commits
35 Commits
Author | SHA1 | Date |
---|---|---|
Ariadne Conill | a0323579ac | |
Volker Christian | 302fbd7452 | |
Ariadne Conill | d64402737b | |
Ariadne Conill | c3d26b7940 | |
Ariadne Conill | e07c8d0ac5 | |
Ariadne Conill | ed663cf0e5 | |
Ariadne Conill | f593205e95 | |
Ariadne Conill | a65049c8d4 | |
Ariadne Conill | 828fc9e950 | |
Ariadne Conill | 3e5059e8a1 | |
Ariadne Conill | 570c0c8b32 | |
Ariadne Conill | 998ae99d61 | |
Ariadne Conill | c2a8b0a9d5 | |
Ariadne Conill | e603fd7239 | |
Ariadne Conill | c468c50b7b | |
Ariadne Conill | c1ecb0ea59 | |
Ariadne Conill | 5445f70157 | |
Ariadne Conill | 1a2dff93e7 | |
L. Pereira | 7badd2d5b2 | |
Jim Hauxwell | 4975ba9051 | |
Jim Hauxwell | b3cbfd9c1a | |
Sören Tempel | d0b03541bf | |
Volker Christian | 124a962b39 | |
Volker Christian | 9e5de65076 | |
Volker Christian | 076e69c9c1 | |
matoro | be80075e95 | |
Ariadne Conill | 4c2cfc54ac | |
L. Pereira | 0f625a86ee | |
Ismael Luceno | 8e1397f5a2 | |
Ariadne Conill | 33ff253d52 | |
Richard Campbell | 3044c2b908 | |
Ariadne Conill | 128e4fdc4b | |
Richard Campbell | 5244775fb9 | |
Richard Campbell | 9abcd8afe0 | |
Richard Campbell | 7bc3e90984 |
|
@ -1,4 +1,3 @@
|
||||||
include/libucontext/bits.h
|
|
||||||
*.o
|
*.o
|
||||||
examples/cooperative_threading
|
examples/cooperative_threading
|
||||||
test_libucontext
|
test_libucontext
|
||||||
|
|
87
Makefile
87
Makefile
|
@ -17,9 +17,13 @@ ifeq ($(ARCH),$(filter $(ARCH),arm64))
|
||||||
override ARCH = aarch64
|
override ARCH = aarch64
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LIBDIR := /lib
|
prefix = /usr
|
||||||
INCLUDEDIR := /usr/include
|
libdir = ${prefix}/lib
|
||||||
PKGCONFIGDIR := /usr/lib/pkgconfig
|
shared_libdir = ${libdir}
|
||||||
|
static_libdir = ${libdir}
|
||||||
|
includedir = ${prefix}/include
|
||||||
|
pkgconfigdir = ${prefix}/lib/pkgconfig
|
||||||
|
|
||||||
CFLAGS ?= -ggdb3 -O2 -Wall
|
CFLAGS ?= -ggdb3 -O2 -Wall
|
||||||
CPPFLAGS := -Iinclude -Iarch/${ARCH} -Iarch/common
|
CPPFLAGS := -Iinclude -Iarch/${ARCH} -Iarch/common
|
||||||
ifneq ($(shell uname),Darwin)
|
ifneq ($(shell uname),Darwin)
|
||||||
|
@ -27,12 +31,28 @@ ifneq ($(shell uname),Darwin)
|
||||||
else
|
else
|
||||||
# Darwin does not support aliases
|
# Darwin does not support aliases
|
||||||
EXPORT_UNPREFIXED := no
|
EXPORT_UNPREFIXED := no
|
||||||
|
CPPFLAGS += -D_XOPEN_SOURCE
|
||||||
endif
|
endif
|
||||||
FREESTANDING := no
|
FREESTANDING := no
|
||||||
|
|
||||||
ifeq ($(FREESTANDING),yes)
|
ifeq ($(FREESTANDING),yes)
|
||||||
CPPFLAGS += -DFREESTANDING
|
CPPFLAGS += -DFREESTANDING
|
||||||
EXPORT_UNPREFIXED = no
|
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
|
endif
|
||||||
|
|
||||||
ifeq ($(EXPORT_UNPREFIXED),yes)
|
ifeq ($(EXPORT_UNPREFIXED),yes)
|
||||||
|
@ -67,18 +87,22 @@ else
|
||||||
endif
|
endif
|
||||||
LIBUCONTEXT_STATIC_NAME = libucontext.a
|
LIBUCONTEXT_STATIC_NAME = libucontext.a
|
||||||
LIBUCONTEXT_PC = libucontext.pc
|
LIBUCONTEXT_PC = libucontext.pc
|
||||||
LIBUCONTEXT_PATH = ${LIBDIR}/${LIBUCONTEXT_SONAME}
|
LIBUCONTEXT_PATH = ${shared_libdir}/${LIBUCONTEXT_SONAME}
|
||||||
LIBUCONTEXT_STATIC_PATH = ${LIBDIR}/${LIBUCONTEXT_STATIC_NAME}
|
LIBUCONTEXT_STATIC_PATH = ${static_libdir}/${LIBUCONTEXT_STATIC_NAME}
|
||||||
LIBUCONTEXT_HEADERS = \
|
LIBUCONTEXT_HEADERS = \
|
||||||
include/libucontext/libucontext.h \
|
include/libucontext/libucontext.h
|
||||||
include/libucontext/bits.h
|
ifeq ($(FREESTANDING),yes)
|
||||||
|
LIBUCONTEXT_HEADERS += arch/${ARCH}/include/libucontext/bits.h
|
||||||
|
else
|
||||||
|
LIBUCONTEXT_HEADERS += arch/common/include/libucontext/bits.h
|
||||||
|
endif
|
||||||
LIBUCONTEXT_EXAMPLES = \
|
LIBUCONTEXT_EXAMPLES = \
|
||||||
examples/cooperative_threading
|
examples/cooperative_threading
|
||||||
LIBUCONTEXT_POSIX_STATIC_NAME = libucontext_posix.a
|
LIBUCONTEXT_POSIX_STATIC_NAME = libucontext_posix.a
|
||||||
LIBUCONTEXT_POSIX_C_SRC = libucontext_posix.c
|
LIBUCONTEXT_POSIX_C_SRC = libucontext_posix.c
|
||||||
LIBUCONTEXT_POSIX_OBJ = ${LIBUCONTEXT_POSIX_C_SRC:.c=.o}
|
LIBUCONTEXT_POSIX_OBJ = ${LIBUCONTEXT_POSIX_C_SRC:.c=.o}
|
||||||
LIBUCONTEXT_POSIX_PATH = ${LIBDIR}/${LIBUCONTEXT_POSIX_SONAME}
|
LIBUCONTEXT_POSIX_PATH = ${shared_libdir}/${LIBUCONTEXT_POSIX_SONAME}
|
||||||
LIBUCONTEXT_POSIX_STATIC_PATH = ${LIBDIR}/${LIBUCONTEXT_POSIX_STATIC_NAME}
|
LIBUCONTEXT_POSIX_STATIC_PATH = ${static_libdir}/${LIBUCONTEXT_POSIX_STATIC_NAME}
|
||||||
|
|
||||||
ifeq ($(FREESTANDING),yes)
|
ifeq ($(FREESTANDING),yes)
|
||||||
LIBUCONTEXT_POSIX_NAME =
|
LIBUCONTEXT_POSIX_NAME =
|
||||||
|
@ -96,10 +120,10 @@ ${LIBUCONTEXT_POSIX_STATIC_NAME}: ${LIBUCONTEXT_STATIC_NAME} ${LIBUCONTEXT_POSIX
|
||||||
${LIBUCONTEXT_POSIX_SONAME}: ${LIBUCONTEXT_POSIX_NAME}
|
${LIBUCONTEXT_POSIX_SONAME}: ${LIBUCONTEXT_POSIX_NAME}
|
||||||
ln -sf ${LIBUCONTEXT_POSIX_NAME} ${LIBUCONTEXT_POSIX_SONAME}
|
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}
|
$(AR) rcs ${LIBUCONTEXT_STATIC_NAME} ${LIBUCONTEXT_OBJ}
|
||||||
|
|
||||||
${LIBUCONTEXT_NAME}: ${LIBUCONTEXT_HEADERS} ${LIBUCONTEXT_OBJ}
|
${LIBUCONTEXT_NAME}: ${LIBUCONTEXT_OBJ}
|
||||||
$(CC) -fPIC -o ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_LINKER_FLAGS} ${LIBUCONTEXT_OBJ} ${LDFLAGS}
|
$(CC) -fPIC -o ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_LINKER_FLAGS} ${LIBUCONTEXT_OBJ} ${LDFLAGS}
|
||||||
|
|
||||||
${LIBUCONTEXT_SONAME}: ${LIBUCONTEXT_NAME}
|
${LIBUCONTEXT_SONAME}: ${LIBUCONTEXT_NAME}
|
||||||
|
@ -107,8 +131,9 @@ ${LIBUCONTEXT_SONAME}: ${LIBUCONTEXT_NAME}
|
||||||
|
|
||||||
${LIBUCONTEXT_PC}: libucontext.pc.in
|
${LIBUCONTEXT_PC}: libucontext.pc.in
|
||||||
sed -e s:@LIBUCONTEXT_VERSION@:${LIBUCONTEXT_VERSION}:g \
|
sed -e s:@LIBUCONTEXT_VERSION@:${LIBUCONTEXT_VERSION}:g \
|
||||||
-e s:@LIBUCONTEXT_LIBDIR@:${LIBDIR}:g \
|
-e s:@LIBUCONTEXT_SHARED_LIBDIR@:${shared_libdir}:g \
|
||||||
-e s:@LIBUCONTEXT_INCLUDEDIR@:${INCLUDEDIR}:g $< > $@
|
-e s:@LIBUCONTEXT_STATIC_LIBDIR@:${static_libdir}:g \
|
||||||
|
-e s:@LIBUCONTEXT_INCLUDEDIR@:${includedir}:g $< > $@
|
||||||
|
|
||||||
MANPAGES_SYMLINKS_3 = \
|
MANPAGES_SYMLINKS_3 = \
|
||||||
libucontext_getcontext.3 \
|
libucontext_getcontext.3 \
|
||||||
|
@ -127,7 +152,7 @@ MANPAGES = ${MANPAGES_3}
|
||||||
docs: ${MANPAGES}
|
docs: ${MANPAGES}
|
||||||
|
|
||||||
.c.o:
|
.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:
|
.S.o:
|
||||||
$(CC) -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} ${ASFLAGS} -c -o $@ $<
|
$(CC) -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} ${ASFLAGS} -c -o $@ $<
|
||||||
|
@ -147,9 +172,6 @@ libucontext_obj_clean:
|
||||||
${LIBUCONTEXT_PC}_clean:
|
${LIBUCONTEXT_PC}_clean:
|
||||||
rm -f ${LIBUCONTEXT_PC}
|
rm -f ${LIBUCONTEXT_PC}
|
||||||
|
|
||||||
bits_clean:
|
|
||||||
rm -f include/libucontext/bits.h
|
|
||||||
|
|
||||||
${LIBUCONTEXT_POSIX_NAME}_clean:
|
${LIBUCONTEXT_POSIX_NAME}_clean:
|
||||||
rm -f ${LIBUCONTEXT_POSIX_NAME}
|
rm -f ${LIBUCONTEXT_POSIX_NAME}
|
||||||
|
|
||||||
|
@ -180,7 +202,6 @@ clean: ${LIBUCONTEXT_NAME}_clean
|
||||||
clean: ${LIBUCONTEXT_SONAME}_clean
|
clean: ${LIBUCONTEXT_SONAME}_clean
|
||||||
clean: ${LIBUCONTEXT_STATIC_NAME}_clean
|
clean: ${LIBUCONTEXT_STATIC_NAME}_clean
|
||||||
clean: ${LIBUCONTEXT_PC}_clean
|
clean: ${LIBUCONTEXT_PC}_clean
|
||||||
clean: bits_clean
|
|
||||||
clean: ${LIBUCONTEXT_POSIX_NAME}_clean
|
clean: ${LIBUCONTEXT_POSIX_NAME}_clean
|
||||||
clean: ${LIBUCONTEXT_POSIX_SONAME}_clean
|
clean: ${LIBUCONTEXT_POSIX_SONAME}_clean
|
||||||
clean: ${LIBUCONTEXT_POSIX_STATIC_NAME}_clean
|
clean: ${LIBUCONTEXT_POSIX_STATIC_NAME}_clean
|
||||||
|
@ -192,13 +213,13 @@ clean: docs_clean
|
||||||
install: all
|
install: all
|
||||||
install -D -m755 ${LIBUCONTEXT_NAME} ${DESTDIR}${LIBUCONTEXT_PATH}
|
install -D -m755 ${LIBUCONTEXT_NAME} ${DESTDIR}${LIBUCONTEXT_PATH}
|
||||||
install -D -m664 ${LIBUCONTEXT_STATIC_NAME} ${DESTDIR}${LIBUCONTEXT_STATIC_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 \
|
for i in ${LIBUCONTEXT_HEADERS}; do \
|
||||||
destfn=$$(echo $$i | sed s:include/::g); \
|
destfn=$$(echo $$i | sed s:include/::g); \
|
||||||
install -D -m644 $$i ${DESTDIR}${INCLUDEDIR}/$$destfn; \
|
install -D -m644 $$i ${DESTDIR}${includedir}/$$destfn; \
|
||||||
done
|
done
|
||||||
install -D -m644 ${LIBUCONTEXT_PC} ${DESTDIR}${PKGCONFIGDIR}/${LIBUCONTEXT_PC}
|
install -D -m644 ${LIBUCONTEXT_PC} ${DESTDIR}${pkgconfigdir}/${LIBUCONTEXT_PC}
|
||||||
if [ -n ${LIBUCONTEXT_POSIX_NAME} ]; then \
|
if [ -n "${LIBUCONTEXT_POSIX_NAME}" ]; then \
|
||||||
install -D -m755 ${LIBUCONTEXT_POSIX_NAME} ${DESTDIR}${LIBUCONTEXT_POSIX_PATH}; \
|
install -D -m755 ${LIBUCONTEXT_POSIX_NAME} ${DESTDIR}${LIBUCONTEXT_POSIX_PATH}; \
|
||||||
install -D -m644 ${LIBUCONTEXT_POSIX_STATIC_NAME} ${DESTDIR}${LIBUCONTEXT_POSIX_STATIC_PATH}; \
|
install -D -m644 ${LIBUCONTEXT_POSIX_STATIC_NAME} ${DESTDIR}${LIBUCONTEXT_POSIX_STATIC_PATH}; \
|
||||||
fi
|
fi
|
||||||
|
@ -216,7 +237,7 @@ check_libucontext_posix: test_libucontext_posix ${LIBUCONTEXT_POSIX_SONAME} ${LI
|
||||||
env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext_posix
|
env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext_posix
|
||||||
|
|
||||||
test_libucontext_posix: test_libucontext_posix.c ${LIBUCONTEXT_POSIX_NAME}
|
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
|
endif
|
||||||
|
|
||||||
ifeq ($(EXPORT_UNPREFIXED),yes)
|
ifeq ($(EXPORT_UNPREFIXED),yes)
|
||||||
|
@ -226,7 +247,7 @@ check_libucontext_bare_posixabi: test_libucontext_bare_posixabi ${LIBUCONTEXT_SO
|
||||||
env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext_bare_posixabi
|
env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext_bare_posixabi
|
||||||
|
|
||||||
test_libucontext_bare_posixabi: test_libucontext_posix.c ${LIBUCONTEXT_NAME}
|
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
|
endif
|
||||||
|
|
||||||
check_libucontext: test_libucontext ${LIBUCONTEXT_SONAME}
|
check_libucontext: test_libucontext ${LIBUCONTEXT_SONAME}
|
||||||
|
@ -235,23 +256,11 @@ check_libucontext: test_libucontext ${LIBUCONTEXT_SONAME}
|
||||||
check: check_libucontext
|
check: check_libucontext
|
||||||
|
|
||||||
test_libucontext: test_libucontext.c ${LIBUCONTEXT_NAME}
|
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: ${LIBUCONTEXT_EXAMPLES}
|
||||||
examples/cooperative_threading: examples/cooperative_threading.c ${LIBUCONTEXT_NAME}
|
examples/cooperative_threading: examples/cooperative_threading.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
|
||||||
|
|
||||||
ifeq ($(FREESTANDING),no)
|
|
||||||
|
|
||||||
include/libucontext/bits.h: arch/common/include/libucontext/bits.h
|
|
||||||
cp $< $@
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
include/libucontext/bits.h: arch/${ARCH}/include/libucontext/bits.h
|
|
||||||
cp $< $@
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
PACKAGE_NAME = libucontext
|
PACKAGE_NAME = libucontext
|
||||||
PACKAGE_VERSION = ${LIBUCONTEXT_VERSION}
|
PACKAGE_VERSION = ${LIBUCONTEXT_VERSION}
|
||||||
|
|
43
NEWS
43
NEWS
|
@ -1,3 +1,46 @@
|
||||||
|
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
|
Changes from 1.1 to 1.2
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ target to do it.
|
||||||
| riscv64 | ✓ | | ✓ | ✓ |
|
| riscv64 | ✓ | | ✓ | ✓ |
|
||||||
| s390x | ✓ | | ✓ | |
|
| s390x | ✓ | | ✓ | |
|
||||||
| sh | ✓ | | ✓ | ✓ |
|
| sh | ✓ | | ✓ | ✓ |
|
||||||
| x86 | ✓ | | ✓ | ✓ |
|
| x86 | ✓ | | ✓ | |
|
||||||
| x86_64 | ✓ | | ✓ | ✓ |
|
| x86_64 | ✓ | | ✓ | ✓ |
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,4 +101,5 @@ ucontext functions:
|
||||||
save/restore FPU registers or vector registers may be added in a later release as a build-time
|
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
|
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
|
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.
|
||||||
|
|
|
@ -22,23 +22,8 @@ ALIAS(__getcontext, libucontext_getcontext)
|
||||||
PROC_NAME(libucontext_getcontext):
|
PROC_NAME(libucontext_getcontext):
|
||||||
str xzr, [x0, #REG_OFFSET(0)]
|
str xzr, [x0, #REG_OFFSET(0)]
|
||||||
|
|
||||||
/* save GPRs */
|
/* save x2 and x3 for reuse */
|
||||||
stp x0, x1, [x0, #REG_OFFSET(0)]
|
|
||||||
stp x2, x3, [x0, #REG_OFFSET(2)]
|
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 */
|
/* save current program counter in link register */
|
||||||
str x30, [x0, #PC_OFFSET]
|
str x30, [x0, #PC_OFFSET]
|
||||||
|
@ -56,6 +41,26 @@ PROC_NAME(libucontext_getcontext):
|
||||||
stp q12, q13, [x2, #208]
|
stp q12, q13, [x2, #208]
|
||||||
stp q14, q15, [x2, #240]
|
stp q14, q15, [x2, #240]
|
||||||
|
|
||||||
|
/* save GPRs and return value 0 */
|
||||||
|
mov x2, x0
|
||||||
mov x0, #0
|
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
|
ret
|
||||||
END(libucontext_getcontext)
|
END(libucontext_getcontext)
|
||||||
|
|
|
@ -2,8 +2,11 @@
|
||||||
|
|
||||||
#define REG_SZ (4)
|
#define REG_SZ (4)
|
||||||
#define MCONTEXT_GREGS (32)
|
#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) \
|
#define FETCH_LINKPTR(dest) \
|
||||||
asm("movs %0, r4" : "=r" ((dest)))
|
asm("movs %0, r4" : "=r" ((dest)))
|
||||||
|
|
|
@ -22,6 +22,27 @@ FUNC(libucontext_getcontext)
|
||||||
str r13, [r0, #REG_OFFSET(13)]
|
str r13, [r0, #REG_OFFSET(13)]
|
||||||
str r14, [r0, #REG_OFFSET(15)]
|
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 */
|
/* return 0 */
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
mov pc, lr
|
mov pc, lr
|
||||||
|
|
|
@ -23,6 +23,8 @@ typedef struct libucontext_ucontext {
|
||||||
struct libucontext_ucontext *uc_link;
|
struct libucontext_ucontext *uc_link;
|
||||||
libucontext_stack_t uc_stack;
|
libucontext_stack_t uc_stack;
|
||||||
libucontext_mcontext_t uc_mcontext;
|
libucontext_mcontext_t uc_mcontext;
|
||||||
|
unsigned long uc_sigmask[128 / sizeof(long)];
|
||||||
|
unsigned long long uc_regspace[64];
|
||||||
} libucontext_ucontext_t;
|
} libucontext_ucontext_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,6 +16,22 @@ ALIAS(setcontext, libucontext_setcontext)
|
||||||
ALIAS(__setcontext, libucontext_setcontext)
|
ALIAS(__setcontext, libucontext_setcontext)
|
||||||
|
|
||||||
FUNC(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 */
|
/* copy all of the current registers into the ucontext structure */
|
||||||
add r14, r0, #REG_OFFSET(0)
|
add r14, r0, #REG_OFFSET(0)
|
||||||
ldmia r14, {r0-r12}
|
ldmia r14, {r0-r12}
|
||||||
|
|
|
@ -16,11 +16,33 @@ ALIAS(swapcontext, libucontext_swapcontext)
|
||||||
ALIAS(__swapcontext, libucontext_swapcontext)
|
ALIAS(__swapcontext, libucontext_swapcontext)
|
||||||
|
|
||||||
FUNC(libucontext_swapcontext)
|
FUNC(libucontext_swapcontext)
|
||||||
|
#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 */
|
/* 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 r13, [r0,#REG_OFFSET(13)]
|
||||||
str r14, [r0,#REG_OFFSET(15)]
|
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 */
|
/* load new registers from the second ucontext structure */
|
||||||
add r14, r1, #REG_OFFSET(0)
|
add r14, r1, #REG_OFFSET(0)
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
ENT(__proc) \
|
ENT(__proc) \
|
||||||
PROC_NAME(__proc): \
|
PROC_NAME(__proc): \
|
||||||
SETUP_FRAME(__proc)
|
SETUP_FRAME(__proc)
|
||||||
|
|
||||||
|
#ifndef END
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#define END(__proc)
|
#define END(__proc)
|
||||||
#else
|
#else
|
||||||
|
@ -47,6 +49,7 @@ PROC_NAME(__proc): \
|
||||||
.end __proc; \
|
.end __proc; \
|
||||||
.size __proc,.-__proc;
|
.size __proc,.-__proc;
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef EXPORT_UNPREFIXED
|
#ifdef EXPORT_UNPREFIXED
|
||||||
#define ALIAS(__alias, __real) \
|
#define ALIAS(__alias, __real) \
|
||||||
|
|
|
@ -14,7 +14,19 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.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__ ((visibility ("hidden")))
|
||||||
|
__attribute__ ((optimize ("omit-frame-pointer")))
|
||||||
void
|
void
|
||||||
libucontext_trampoline(void)
|
libucontext_trampoline(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,11 +45,17 @@
|
||||||
/* frame pointer is actually $22 */
|
/* frame pointer is actually $22 */
|
||||||
#define REG_FP (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 */
|
/* offset to mc_gregs in ucontext_t */
|
||||||
#define MCONTEXT_GREGS (48)
|
#define MCONTEXT_GREGS (184)
|
||||||
|
|
||||||
/* offset to PC in ucontext_t */
|
/* offset to PC in ucontext_t */
|
||||||
#define MCONTEXT_PC (40)
|
#define MCONTEXT_PC (176)
|
||||||
|
|
||||||
/* offset to uc_link in ucontext_t */
|
/* offset to uc_link in ucontext_t */
|
||||||
#define UCONTEXT_UC_LINK (8)
|
#define UCONTEXT_UC_LINK (8)
|
||||||
|
|
|
@ -35,11 +35,14 @@ FUNC(libucontext_getcontext)
|
||||||
st.d $s8, $a0, REG_OFFSET(31)
|
st.d $s8, $a0, REG_OFFSET(31)
|
||||||
|
|
||||||
st.d $a2, $a0, REG_OFFSET(3)
|
st.d $a2, $a0, REG_OFFSET(3)
|
||||||
|
st.d $zero, $a0, REG_OFFSET(4)
|
||||||
st.d $a3, $a0, REG_OFFSET(22)
|
st.d $a3, $a0, REG_OFFSET(22)
|
||||||
st.d $ra, $a0, REG_OFFSET(1)
|
st.d $ra, $a0, REG_OFFSET(1)
|
||||||
|
|
||||||
st.d $ra, $a0, (MCONTEXT_PC)
|
st.d $ra, $a0, (MCONTEXT_PC)
|
||||||
|
|
||||||
|
move $a0, $zero
|
||||||
|
|
||||||
POP_FRAME(libucontext_getcontext)
|
POP_FRAME(libucontext_getcontext)
|
||||||
|
|
||||||
jr $ra
|
jr $ra
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "defs.h"
|
|
||||||
|
|
||||||
#define LOCALSZ (6)
|
|
||||||
|
|
||||||
#define A3_OFF (FRAMESZ - (5 * REG_SZ))
|
|
||||||
#define A4_OFF (FRAMESZ - (4 * REG_SZ))
|
|
||||||
#define A5_OFF (FRAMESZ - (3 * REG_SZ))
|
|
||||||
#define A6_OFF (FRAMESZ - (2 * REG_SZ))
|
|
||||||
#define A7_OFF (FRAMESZ - (1 * REG_SZ))
|
|
||||||
|
|
||||||
ALIAS(makecontext, libucontext_makecontext)
|
|
||||||
|
|
||||||
FUNC(libucontext_makecontext)
|
|
||||||
PUSH_FRAME(libucontext_makecontext)
|
|
||||||
|
|
||||||
move $t5, $a0
|
|
||||||
move $t4, $a1
|
|
||||||
|
|
||||||
/* store $a3 through $a7 to the stack frame. */
|
|
||||||
st.d $a3, $sp, A3_OFF
|
|
||||||
st.d $a4, $sp, A4_OFF
|
|
||||||
st.d $a5, $sp, A5_OFF
|
|
||||||
st.d $a6, $sp, A6_OFF
|
|
||||||
st.d $a7, $sp, A7_OFF
|
|
||||||
|
|
||||||
/* set $zero in the mcontext to 1. */
|
|
||||||
addi.d $v0, $zero, 1
|
|
||||||
st.d $v0, $t5, REG_OFFSET(0)
|
|
||||||
|
|
||||||
/* ensure the stack is aligned on a quad-word boundary. */
|
|
||||||
ld.d $t0, $t5, UCONTEXT_STACK_PTR
|
|
||||||
ld.d $t2, $t5, UCONTEXT_STACK_SIZE
|
|
||||||
/* the third argument(from zero), that's the first argument of func() */
|
|
||||||
addi.d $t1, $sp, A3_OFF
|
|
||||||
add.d $t0, $t0, $t2
|
|
||||||
|
|
||||||
addi.d $t7, $zero, ALMASK
|
|
||||||
and $t0, $t0, $t7
|
|
||||||
|
|
||||||
/* number of args */
|
|
||||||
beq $a2, $zero, no_more_arguments
|
|
||||||
bltu $a2, $zero, no_more_arguments
|
|
||||||
|
|
||||||
/* store register arguments. */
|
|
||||||
addi.d $t2, $t5, MCONTEXT_GREGS + (4 * REG_SZ)
|
|
||||||
move $t3, $zero
|
|
||||||
|
|
||||||
store_register_arg:
|
|
||||||
addi.d $t3, $t3, 1
|
|
||||||
ld.d $v1, $t1, 0
|
|
||||||
addi.d $t1, $t1, REG_SZ
|
|
||||||
st.d $v1, $t2, 0
|
|
||||||
addi.d $t2, $t2, REG_SZ
|
|
||||||
addi.d $t6, $zero, 8
|
|
||||||
bltu $t3, $t6, store_register_arg
|
|
||||||
bgeu $t3, $a2, no_more_arguments
|
|
||||||
|
|
||||||
/* make room for stack arguments. */
|
|
||||||
sub.d $t2, $a2, $t3
|
|
||||||
|
|
||||||
addi.d $t6, $zero, 3
|
|
||||||
sll.d $t2, $t2, $t6
|
|
||||||
|
|
||||||
sub.d $t0, $t0, $t2
|
|
||||||
|
|
||||||
addi.d $t6, $zero, ALMASK
|
|
||||||
and $t0, $t0, $t6
|
|
||||||
|
|
||||||
/* store stack arguments. */
|
|
||||||
move $t2, $t0
|
|
||||||
|
|
||||||
store_stack_arg:
|
|
||||||
addi.d $t3, $t3, 1
|
|
||||||
ld.d $v1, $t1, 0
|
|
||||||
addi.d $t1, $t1, REG_SZ
|
|
||||||
st.d $v1, $t2, 0
|
|
||||||
addi.d $t2, $t2, REG_SZ
|
|
||||||
bltu $t3, $a2, store_stack_arg
|
|
||||||
|
|
||||||
no_more_arguments:
|
|
||||||
/* trampoline setup. */
|
|
||||||
la.got $t8, libucontext_trampoline
|
|
||||||
|
|
||||||
ld.d $v1, $t5, UCONTEXT_UC_LINK
|
|
||||||
st.d $v1, $t5, REG_OFFSET(23)
|
|
||||||
|
|
||||||
st.d $t0, $t5, REG_OFFSET(3)
|
|
||||||
|
|
||||||
st.d $t8, $t5, REG_OFFSET(1)
|
|
||||||
|
|
||||||
st.d $t4, $t5, MCONTEXT_PC
|
|
||||||
|
|
||||||
POP_FRAME(libucontext_makecontext)
|
|
||||||
|
|
||||||
jr $ra
|
|
||||||
END(libucontext_makecontext)
|
|
|
@ -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
|
|
@ -49,7 +49,7 @@ FUNC(libucontext_setcontext)
|
||||||
ld.d $t8, $t5, (MCONTEXT_PC)
|
ld.d $t8, $t5, (MCONTEXT_PC)
|
||||||
|
|
||||||
jr $t8
|
jr $t8
|
||||||
move $v0, $zero
|
move $a0, $zero
|
||||||
|
|
||||||
POP_FRAME(libucontext_setcontext)
|
POP_FRAME(libucontext_setcontext)
|
||||||
END(libucontext_setcontext)
|
END(libucontext_setcontext)
|
||||||
|
|
|
@ -39,6 +39,7 @@ FUNC(libucontext_swapcontext)
|
||||||
st.d $s8, $t5, REG_OFFSET(31)
|
st.d $s8, $t5, REG_OFFSET(31)
|
||||||
|
|
||||||
st.d $a3, $t5, REG_OFFSET(3)
|
st.d $a3, $t5, REG_OFFSET(3)
|
||||||
|
st.d $zero, $t5, REG_OFFSET(4)
|
||||||
st.d $a4, $t5, REG_OFFSET(22)
|
st.d $a4, $t5, REG_OFFSET(22)
|
||||||
st.d $ra, $t5, REG_OFFSET(1)
|
st.d $ra, $t5, REG_OFFSET(1)
|
||||||
|
|
||||||
|
@ -77,7 +78,7 @@ FUNC(libucontext_swapcontext)
|
||||||
ld.d $t8, $t4, (MCONTEXT_PC)
|
ld.d $t8, $t4, (MCONTEXT_PC)
|
||||||
|
|
||||||
jr $t8
|
jr $t8
|
||||||
move $v0, $zero
|
move $a0, $zero
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
la.global $t8, exit
|
la.global $t8, exit
|
||||||
|
@ -85,5 +86,5 @@ fail:
|
||||||
POP_FRAME(libucontext_swapcontext)
|
POP_FRAME(libucontext_swapcontext)
|
||||||
|
|
||||||
jirl $ra, $t8, 0
|
jirl $ra, $t8, 0
|
||||||
move $v0, $zero
|
move $a0, $zero
|
||||||
END(libucontext_swapcontext)
|
END(libucontext_swapcontext)
|
||||||
|
|
|
@ -19,8 +19,8 @@ FUNC(libucontext_getcontext)
|
||||||
l.sw REG_OFFSET(1)(r3), r1 /* store r1 and r2 */
|
l.sw REG_OFFSET(1)(r3), r1 /* store r1 and r2 */
|
||||||
l.sw REG_OFFSET(2)(r3), r2
|
l.sw REG_OFFSET(2)(r3), r2
|
||||||
|
|
||||||
l.sw REG_OFFSET(9)(r3), r9 /* store r9 to both r9 and r11 in the context */
|
l.sw REG_OFFSET(9)(r3), r9 /* link register */
|
||||||
l.sw REG_OFFSET(11)(r3), r9
|
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(10)(r3), r10 /* store r10 for TLS */
|
||||||
|
|
||||||
|
@ -34,6 +34,6 @@ FUNC(libucontext_getcontext)
|
||||||
l.sw REG_OFFSET(28)(r3), r28
|
l.sw REG_OFFSET(28)(r3), r28
|
||||||
l.sw REG_OFFSET(30)(r3), r30
|
l.sw REG_OFFSET(30)(r3), r30
|
||||||
|
|
||||||
l.jr r9
|
|
||||||
l.ori r11, r0, 0
|
l.ori r11, r0, 0
|
||||||
|
l.jr r9
|
||||||
END(libucontext_getcontext)
|
END(libucontext_getcontext)
|
||||||
|
|
|
@ -20,8 +20,8 @@ FUNC(libucontext_swapcontext)
|
||||||
l.sw REG_OFFSET(1)(r3), r1 /* store r1 and r2 */
|
l.sw REG_OFFSET(1)(r3), r1 /* store r1 and r2 */
|
||||||
l.sw REG_OFFSET(2)(r3), r2
|
l.sw REG_OFFSET(2)(r3), r2
|
||||||
|
|
||||||
l.sw REG_OFFSET(9)(r3), r9 /* store r9 to both r9 and r11 in the context */
|
l.sw REG_OFFSET(9)(r3), r9 /* link register */
|
||||||
l.sw REG_OFFSET(11)(r3), r9
|
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(10)(r3), r10 /* store r10 for TLS */
|
||||||
|
|
||||||
|
@ -63,6 +63,6 @@ FUNC(libucontext_swapcontext)
|
||||||
l.lwz r28, REG_OFFSET(28)(r30)
|
l.lwz r28, REG_OFFSET(28)(r30)
|
||||||
l.lwz r30, REG_OFFSET(30)(r30)
|
l.lwz r30, REG_OFFSET(30)(r30)
|
||||||
|
|
||||||
l.jr r11 /* jump to new starting address */
|
|
||||||
l.ori r11, r0, 0
|
l.ori r11, r0, 0
|
||||||
|
l.jr r9 /* jump to new starting address */
|
||||||
END(libucontext_swapcontext)
|
END(libucontext_swapcontext)
|
||||||
|
|
|
@ -25,8 +25,8 @@ FUNC(libucontext_getcontext)
|
||||||
sw s1, REG_OFFSET(REG_S1)(a0)
|
sw s1, REG_OFFSET(REG_S1)(a0)
|
||||||
|
|
||||||
/* return register block */
|
/* return register block */
|
||||||
sw a0, REG_OFFSET(REG_A0)(a0)
|
sw x0, REG_OFFSET(REG_A0)(a0)
|
||||||
sw a1, REG_OFFSET(REG_A1)(a0)
|
sw x0, REG_OFFSET(REG_A1)(a0)
|
||||||
|
|
||||||
/* second saved register block */
|
/* second saved register block */
|
||||||
sw s2, REG_OFFSET(REG_S2)(a0)
|
sw s2, REG_OFFSET(REG_S2)(a0)
|
||||||
|
@ -41,5 +41,6 @@ FUNC(libucontext_getcontext)
|
||||||
sw s11, REG_OFFSET(REG_S11)(a0)
|
sw s11, REG_OFFSET(REG_S11)(a0)
|
||||||
|
|
||||||
/* done saving, return */
|
/* done saving, return */
|
||||||
|
mv a0, x0
|
||||||
ret
|
ret
|
||||||
END(libucontext_getcontext)
|
END(libucontext_getcontext)
|
||||||
|
|
|
@ -28,8 +28,8 @@ FUNC(libucontext_swapcontext)
|
||||||
sw s1, REG_OFFSET(REG_S1)(a0)
|
sw s1, REG_OFFSET(REG_S1)(a0)
|
||||||
|
|
||||||
/* return register block */
|
/* return register block */
|
||||||
sw a0, REG_OFFSET(REG_A0)(a0)
|
sw x0, REG_OFFSET(REG_A0)(a0)
|
||||||
sw a1, REG_OFFSET(REG_A1)(a0)
|
sw x0, REG_OFFSET(REG_A1)(a0)
|
||||||
|
|
||||||
/* second saved register block */
|
/* second saved register block */
|
||||||
sw s2, REG_OFFSET(REG_S2)(a0)
|
sw s2, REG_OFFSET(REG_S2)(a0)
|
||||||
|
|
|
@ -25,8 +25,8 @@ FUNC(libucontext_getcontext)
|
||||||
sd s1, REG_OFFSET(REG_S1)(a0)
|
sd s1, REG_OFFSET(REG_S1)(a0)
|
||||||
|
|
||||||
/* return register block */
|
/* return register block */
|
||||||
sd a0, REG_OFFSET(REG_A0)(a0)
|
sd x0, REG_OFFSET(REG_A0)(a0)
|
||||||
sd a1, REG_OFFSET(REG_A1)(a0)
|
sd x0, REG_OFFSET(REG_A1)(a0)
|
||||||
|
|
||||||
/* second saved register block */
|
/* second saved register block */
|
||||||
sd s2, REG_OFFSET(REG_S2)(a0)
|
sd s2, REG_OFFSET(REG_S2)(a0)
|
||||||
|
@ -41,5 +41,6 @@ FUNC(libucontext_getcontext)
|
||||||
sd s11, REG_OFFSET(REG_S11)(a0)
|
sd s11, REG_OFFSET(REG_S11)(a0)
|
||||||
|
|
||||||
/* done saving, return */
|
/* done saving, return */
|
||||||
|
mv a0, x0
|
||||||
ret
|
ret
|
||||||
END(libucontext_getcontext)
|
END(libucontext_getcontext)
|
||||||
|
|
|
@ -28,8 +28,8 @@ FUNC(libucontext_swapcontext)
|
||||||
sd s1, REG_OFFSET(REG_S1)(a0)
|
sd s1, REG_OFFSET(REG_S1)(a0)
|
||||||
|
|
||||||
/* return register block */
|
/* return register block */
|
||||||
sd a0, REG_OFFSET(REG_A0)(a0)
|
sd x0, REG_OFFSET(REG_A0)(a0)
|
||||||
sd a1, REG_OFFSET(REG_A1)(a0)
|
sd x0, REG_OFFSET(REG_A1)(a0)
|
||||||
|
|
||||||
/* second saved register block */
|
/* second saved register block */
|
||||||
sd s2, REG_OFFSET(REG_S2)(a0)
|
sd s2, REG_OFFSET(REG_S2)(a0)
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* 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 %r1, %r2 /* use %r1 to save current context to */
|
||||||
lgr %r0, %r3 /* use %r0 for source context */
|
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 */
|
stam %a0, %a15, AREG_OFFSET(0)(%r1) /* store access registers */
|
||||||
stmg %r0, %r15, REG_OFFSET(0)(%r1) /* store general-purpose 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) */
|
lgr %r5, %r0 /* copy %r0 to %r5 so that %r0 doesn't get clobbered */
|
||||||
lam %a2, %a15, AREG_OFFSET(2)(%r2) /* load access registers, but skip %a0 and %a1 which are for TLS */
|
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)(%r2) /* load general-purpose registers */
|
lmg %r0, %r15, REG_OFFSET(0)(%r5) /* load general-purpose registers */
|
||||||
|
|
||||||
br %r14 /* return to new link register address */
|
br %r14 /* return to new link register address */
|
||||||
END(libucontext_swapcontext)
|
END(libucontext_swapcontext)
|
||||||
|
|
|
@ -57,9 +57,6 @@
|
||||||
|
|
||||||
#define MCONTEXT_GREGS (20)
|
#define MCONTEXT_GREGS (20)
|
||||||
|
|
||||||
#define FETCH_LINKPTR(dest) \
|
|
||||||
asm("movl (%%esp, %%ebx, 4), %0" : "=r" ((dest)));
|
|
||||||
|
|
||||||
#include "common-defs.h"
|
#include "common-defs.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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)
|
|
@ -1,3 +0,0 @@
|
||||||
#include "defs.h"
|
|
||||||
#include <libucontext/libucontext.h>
|
|
||||||
#include "common-trampoline.c"
|
|
|
@ -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
|
|
@ -4,9 +4,17 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <libucontext/bits.h>
|
#include <libucontext/bits.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
int libucontext_getcontext(libucontext_ucontext_t *);
|
int libucontext_getcontext(libucontext_ucontext_t *);
|
||||||
void libucontext_makecontext(libucontext_ucontext_t *, void (*)(), int, ...);
|
void libucontext_makecontext(libucontext_ucontext_t *, void (*)(), int, ...);
|
||||||
int libucontext_setcontext(const libucontext_ucontext_t *);
|
int libucontext_setcontext(const libucontext_ucontext_t *);
|
||||||
int libucontext_swapcontext(libucontext_ucontext_t *, const libucontext_ucontext_t *);
|
int libucontext_swapcontext(libucontext_ucontext_t *, const libucontext_ucontext_t *);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
libdir=@LIBUCONTEXT_LIBDIR@
|
libdir=@LIBUCONTEXT_SHARED_LIBDIR@
|
||||||
|
static_libdir=@LIBUCONTEXT_STATIC_LIBDIR@
|
||||||
includedir=@LIBUCONTEXT_INCLUDEDIR@
|
includedir=@LIBUCONTEXT_INCLUDEDIR@
|
||||||
|
|
||||||
Name: libucontext
|
Name: libucontext
|
||||||
Version: @LIBUCONTEXT_VERSION@
|
Version: @LIBUCONTEXT_VERSION@
|
||||||
Description: ucontext library implementation (standalone)
|
Description: ucontext library implementation (standalone)
|
||||||
Libs: -L${libdir} -lucontext
|
Libs: -L${libdir} -L${static_libdir} -lucontext
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
11
meson.build
11
meson.build
|
@ -1,7 +1,7 @@
|
||||||
project(
|
project(
|
||||||
'libucontext',
|
'libucontext',
|
||||||
'c',
|
'c',
|
||||||
meson_version : '>=0.55.0',
|
meson_version : '>=0.59.0',
|
||||||
default_options: ['c_std=gnu11', 'default_library=both'],
|
default_options: ['c_std=gnu11', 'default_library=both'],
|
||||||
version : run_command('head', files('VERSION')).stdout()
|
version : run_command('head', files('VERSION')).stdout()
|
||||||
)
|
)
|
||||||
|
@ -40,7 +40,7 @@ if cpu in ['ppc', 'ppc64']
|
||||||
'arch' / cpu / 'retfromsyscall.c'
|
'arch' / cpu / 'retfromsyscall.c'
|
||||||
]
|
]
|
||||||
endif
|
endif
|
||||||
if cpu not in ['mips', 'mips64', 'ppc', 'ppc64', 's390x']
|
if cpu not in ['loongarch64', 'mips', 'mips64', 'ppc', 'ppc64', 's390x', 'x86']
|
||||||
project_source_files += [
|
project_source_files += [
|
||||||
'arch' / cpu / 'trampoline.c'
|
'arch' / cpu / 'trampoline.c'
|
||||||
]
|
]
|
||||||
|
@ -56,7 +56,7 @@ project_includes = [
|
||||||
]
|
]
|
||||||
|
|
||||||
build_args = [
|
build_args = [
|
||||||
'-D_BSD_SOURCE'
|
'-D_DEFAULT_SOURCE'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -144,9 +144,8 @@ endif
|
||||||
# Docs
|
# Docs
|
||||||
# ====
|
# ====
|
||||||
|
|
||||||
# TODO: meson.build for docs
|
if not meson.is_subproject() and get_option('docs')
|
||||||
if not meson.is_subproject()
|
subdir('doc')
|
||||||
#subdir('docs')
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# ==========
|
# ==========
|
||||||
|
|
|
@ -4,3 +4,5 @@ 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 : '',
|
option('cpu', type : 'string', value : '',
|
||||||
description: 'Target CPU architecture for cross compile')
|
description: 'Target CPU architecture for cross compile')
|
||||||
|
option('docs', type : 'boolean', value : false,
|
||||||
|
description: 'Build and install man pages')
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <libucontext/libucontext.h>
|
#include <libucontext/libucontext.h>
|
||||||
|
|
||||||
|
#define handle_error(msg) \
|
||||||
|
do { perror(msg); exit(EXIT_FAILURE); } while (0)
|
||||||
|
|
||||||
static libucontext_ucontext_t ctx[3];
|
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("looks like all arguments are passed correctly\n");
|
||||||
|
|
||||||
printf("swap back to f2\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");
|
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) {
|
static void f2 (void) {
|
||||||
printf("start f2\n");
|
printf("start f2\n");
|
||||||
printf("swap to f1\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");
|
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");
|
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_sp = st1;
|
||||||
ctx[1].uc_stack.ss_size = sizeof st1;
|
ctx[1].uc_stack.ss_size = sizeof st1;
|
||||||
ctx[1].uc_link = &ctx[0];
|
ctx[1].uc_link = &ctx[0];
|
||||||
|
@ -83,16 +89,20 @@ int main (int argc, const char *argv[]) {
|
||||||
printf("doing initial swapcontext\n");
|
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");
|
printf("returned from initial swapcontext\n");
|
||||||
|
|
||||||
|
|
||||||
/* test ability to use getcontext/setcontext without makecontext */
|
/* 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);
|
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) {
|
if (done != 2) {
|
||||||
fprintf(stderr, "wrong value for done. got %d, expected 2\n", done);
|
fprintf(stderr, "wrong value for done. got %d, expected 2\n", done);
|
||||||
abort();
|
abort();
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
|
|
||||||
|
#define handle_error(msg) \
|
||||||
|
do { perror(msg); exit(EXIT_FAILURE); } while (0)
|
||||||
|
|
||||||
static ucontext_t ctx[3];
|
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("looks like all arguments are passed correctly\n");
|
||||||
|
|
||||||
printf("swap back to f2\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");
|
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) {
|
static void f2 (void) {
|
||||||
printf("start f2\n");
|
printf("start f2\n");
|
||||||
printf("swap to f1\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");
|
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_sp = st1;
|
||||||
ctx[1].uc_stack.ss_size = sizeof st1;
|
ctx[1].uc_stack.ss_size = sizeof st1;
|
||||||
ctx[1].uc_link = &ctx[0];
|
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");
|
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_sp = st2;
|
||||||
ctx[2].uc_stack.ss_size = sizeof st2;
|
ctx[2].uc_stack.ss_size = sizeof st2;
|
||||||
ctx[2].uc_link = &ctx[1];
|
ctx[2].uc_link = &ctx[1];
|
||||||
makecontext(&ctx[2], f2, 0);
|
makecontext(&ctx[2], (void *) f2, 0);
|
||||||
|
|
||||||
|
|
||||||
printf("doing initial swapcontext\n");
|
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");
|
printf("returned from initial swapcontext\n");
|
||||||
|
|
||||||
|
|
||||||
/* test ability to use getcontext/setcontext without makecontext */
|
/* test ability to use getcontext/setcontext without makecontext */
|
||||||
getcontext(&ctx[1]);
|
if (getcontext(&ctx[1]) != 0)
|
||||||
|
handle_error("getcontext");
|
||||||
printf("done = %d\n", done);
|
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) {
|
if (done != 2) {
|
||||||
fprintf(stderr, "wrong value for done. got %d, expected 2\n", done);
|
fprintf(stderr, "wrong value for done. got %d, expected 2\n", done);
|
||||||
abort();
|
abort();
|
||||||
|
|
Loading…
Reference in New Issue