Stefan Sperling writes:
> Storing the allocated size in a new field of cothread_t is not an option?
cothread_t is not a struct, it's void *, and there are cothread_t
equality checks scattered throughout the code that make the diff
larger. That said, I don't see a better solution. Hopefully upstream
will be amenable to it so we don't have to carry all these patches.
Index: Makefile
===================================================================
RCS file: /cvs/ports/emulators/higan/Makefile,v
retrieving revision 1.6
diff -u -p -r1.6 Makefile
--- Makefile 12 Jul 2019 20:46:09 -0000 1.6
+++ Makefile 22 Oct 2019 07:50:17 -0000
@@ -5,7 +5,7 @@ COMMENT = multi-system Nintendo emulator
V = 106
DISTNAME = higan_v$V-source
PKGNAME = higan-$V
-REVISION = 3
+REVISION = 4
USE_WXNEEDED = Yes
Index: patches/patch-higan_emulator_scheduler_hpp
===================================================================
RCS file: patches/patch-higan_emulator_scheduler_hpp
diff -N patches/patch-higan_emulator_scheduler_hpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-higan_emulator_scheduler_hpp 22 Oct 2019 07:50:17 -0000
@@ -0,0 +1,36 @@
+$OpenBSD$
+
+Index: higan/emulator/scheduler.hpp
+--- higan/emulator/scheduler.hpp.orig
++++ higan/emulator/scheduler.hpp
+@@ -63,7 +63,7 @@ struct Scheduler {
+ }
+
+ inline auto synchronize(Thread& thread) -> void {
+- if(thread.handle() == _master) {
++ if(thread.handle().data == _master.data) {
+ while(enter(Mode::SynchronizeMaster) != Event::Synchronize);
+ } else {
+ _resume = thread.handle();
+@@ -72,7 +72,7 @@ struct Scheduler {
+ }
+
+ inline auto synchronize() -> void {
+- if(co_active() == _master) {
++ if(co_active().data == _master.data) {
+ if(_mode == Mode::SynchronizeMaster) return exit(Event::Synchronize);
+ } else {
+ if(_mode == Mode::SynchronizeSlave) return exit(Event::Synchronize);
+@@ -80,9 +80,9 @@ struct Scheduler {
+ }
+
+ private:
+- cothread_t _host = nullptr; //program thread (used to exit scheduler)
+- cothread_t _resume = nullptr; //resume thread (used to enter scheduler)
+- cothread_t _master = nullptr; //primary thread (used to synchronize
components)
++ cothread_t _host = {0}; //program thread (used to exit scheduler)
++ cothread_t _resume = {0}; //resume thread (used to enter scheduler)
++ cothread_t _master = {0}; //primary thread (used to synchronize components)
+ Mode _mode = Mode::Run;
+ Event _event = Event::Step;
+ vector<Thread*> _threads;
Index: patches/patch-higan_emulator_thread_hpp
===================================================================
RCS file: patches/patch-higan_emulator_thread_hpp
diff -N patches/patch-higan_emulator_thread_hpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-higan_emulator_thread_hpp 22 Oct 2019 07:50:17 -0000
@@ -0,0 +1,36 @@
+$OpenBSD$
+
+Index: higan/emulator/thread.hpp
+--- higan/emulator/thread.hpp.orig
++++ higan/emulator/thread.hpp
+@@ -6,10 +6,10 @@ struct Thread {
+ enum : uintmax { Second = (uintmax)-1 >> 1 };
+
+ virtual ~Thread() {
+- if(_handle) co_delete(_handle);
++ if(_handle.data) co_delete(_handle);
+ }
+
+- inline auto active() const { return co_active() == _handle; }
++ inline auto active() const { return co_active().data == _handle.data; }
+ inline auto handle() const { return _handle; }
+ inline auto frequency() const { return _frequency; }
+ inline auto scalar() const { return _scalar; }
+@@ -29,7 +29,7 @@ struct Thread {
+ }
+
+ auto create(auto (*entrypoint)() -> void, double frequency) -> void {
+- if(_handle) co_delete(_handle);
++ if(_handle.data) co_delete(_handle);
+ _handle = co_create(64 * 1024 * sizeof(void*), entrypoint);
+ setFrequency(frequency);
+ setClock(0);
+@@ -46,7 +46,7 @@ struct Thread {
+ }
+
+ protected:
+- cothread_t _handle = nullptr;
++ cothread_t _handle = {0};
+ uintmax _frequency = 0;
+ uintmax _scalar = 0;
+ uintmax _clock = 0;
Index: patches/patch-higan_fc_controller_controller_cpp
===================================================================
RCS file: patches/patch-higan_fc_controller_controller_cpp
diff -N patches/patch-higan_fc_controller_controller_cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-higan_fc_controller_controller_cpp 22 Oct 2019 07:50:17
-0000
@@ -0,0 +1,14 @@
+$OpenBSD$
+
+Index: higan/fc/controller/controller.cpp
+--- higan/fc/controller/controller.cpp.orig
++++ higan/fc/controller/controller.cpp
+@@ -7,7 +7,7 @@ ControllerPort controllerPort2;
+ #include "gamepad/gamepad.cpp"
+
+ Controller::Controller(uint port) : port(port) {
+- if(!handle()) create(Controller::Enter, 1);
++ if(!handle().data) create(Controller::Enter, 1);
+ }
+
+ Controller::~Controller() {
Index: patches/patch-higan_md_controller_controller_cpp
===================================================================
RCS file: patches/patch-higan_md_controller_controller_cpp
diff -N patches/patch-higan_md_controller_controller_cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-higan_md_controller_controller_cpp 22 Oct 2019 07:50:17
-0000
@@ -0,0 +1,14 @@
+$OpenBSD$
+
+Index: higan/md/controller/controller.cpp
+--- higan/md/controller/controller.cpp.orig
++++ higan/md/controller/controller.cpp
+@@ -9,7 +9,7 @@ ControllerPort extensionPort;
+ #include "fighting-pad/fighting-pad.cpp"
+
+ Controller::Controller(uint port) : port(port) {
+- if(!handle()) create(Controller::Enter, 1);
++ if(!handle().data) create(Controller::Enter, 1);
+ }
+
+ Controller::~Controller() {
Index: patches/patch-higan_ms_controller_controller_cpp
===================================================================
RCS file: patches/patch-higan_ms_controller_controller_cpp
diff -N patches/patch-higan_ms_controller_controller_cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-higan_ms_controller_controller_cpp 22 Oct 2019 07:50:17
-0000
@@ -0,0 +1,14 @@
+$OpenBSD$
+
+Index: higan/ms/controller/controller.cpp
+--- higan/ms/controller/controller.cpp.orig
++++ higan/ms/controller/controller.cpp
+@@ -7,7 +7,7 @@ ControllerPort controllerPort2;
+ #include "gamepad/gamepad.cpp"
+
+ Controller::Controller(uint port) : port(port) {
+- if(!handle()) create(Controller::Enter, 100);
++ if(!handle().data) create(Controller::Enter, 100);
+ }
+
+ Controller::~Controller() {
Index: patches/patch-higan_pce_controller_controller_cpp
===================================================================
RCS file: patches/patch-higan_pce_controller_controller_cpp
diff -N patches/patch-higan_pce_controller_controller_cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-higan_pce_controller_controller_cpp 22 Oct 2019 07:50:17
-0000
@@ -0,0 +1,14 @@
+$OpenBSD$
+
+Index: higan/pce/controller/controller.cpp
+--- higan/pce/controller/controller.cpp.orig
++++ higan/pce/controller/controller.cpp
+@@ -6,7 +6,7 @@ ControllerPort controllerPort;
+ #include "gamepad/gamepad.cpp"
+
+ Controller::Controller() {
+- if(!handle()) create(Controller::Enter, 1);
++ if(!handle().data) create(Controller::Enter, 1);
+ }
+
+ Controller::~Controller() {
Index: patches/patch-higan_sfc_controller_controller_cpp
===================================================================
RCS file: patches/patch-higan_sfc_controller_controller_cpp
diff -N patches/patch-higan_sfc_controller_controller_cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-higan_sfc_controller_controller_cpp 22 Oct 2019 07:50:17
-0000
@@ -0,0 +1,14 @@
+$OpenBSD$
+
+Index: higan/sfc/controller/controller.cpp
+--- higan/sfc/controller/controller.cpp.orig
++++ higan/sfc/controller/controller.cpp
+@@ -11,7 +11,7 @@ ControllerPort controllerPort2;
+ #include "justifier/justifier.cpp"
+
+ Controller::Controller(uint port) : port(port) {
+- if(!handle()) create(Controller::Enter, 1);
++ if(!handle().data) create(Controller::Enter, 1);
+ }
+
+ Controller::~Controller() {
Index: patches/patch-higan_sfc_expansion_expansion_cpp
===================================================================
RCS file: patches/patch-higan_sfc_expansion_expansion_cpp
diff -N patches/patch-higan_sfc_expansion_expansion_cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-higan_sfc_expansion_expansion_cpp 22 Oct 2019 07:50:17
-0000
@@ -0,0 +1,14 @@
+$OpenBSD$
+
+Index: higan/sfc/expansion/expansion.cpp
+--- higan/sfc/expansion/expansion.cpp.orig
++++ higan/sfc/expansion/expansion.cpp
+@@ -5,7 +5,7 @@ namespace SuperFamicom {
+ ExpansionPort expansionPort;
+
+ Expansion::Expansion() {
+- if(!handle()) create(Expansion::Enter, 1);
++ if(!handle().data) create(Expansion::Enter, 1);
+ }
+
+ Expansion::~Expansion() {
Index: patches/patch-libco_amd64_c
===================================================================
RCS file: patches/patch-libco_amd64_c
diff -N patches/patch-libco_amd64_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-libco_amd64_c 22 Oct 2019 07:50:17 -0000
@@ -0,0 +1,74 @@
+$OpenBSD$
+
+Index: libco/amd64.c
+--- libco/amd64.c.orig
++++ libco/amd64.c
+@@ -10,8 +10,8 @@ extern "C" {
+ #endif
+
+ static thread_local long long co_active_buffer[64];
+-static thread_local cothread_t co_active_handle = 0;
+-static void (*co_swap)(cothread_t, cothread_t) = 0;
++static thread_local cothread_t co_active_handle = {0};
++static void (*co_swap)(void *, void *) = 0;
+
+ #ifdef LIBCO_MPROTECT
+ alignas(4096)
+@@ -116,37 +116,47 @@ static void crash() {
+ }
+
+ cothread_t co_active() {
+- if(!co_active_handle) co_active_handle = &co_active_buffer;
++ if(!co_active_handle.data) co_active_handle.data = &co_active_buffer;
+ return co_active_handle;
+ }
+
+ cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
+- cothread_t handle;
++ cothread_t *handle = malloc(sizeof *handle);
++ if(!handle) {
++ err(1, "libco malloc failed");
++ }
+ if(!co_swap) {
+ co_init();
+- co_swap = (void (*)(cothread_t, cothread_t))co_swap_function;
++ co_swap = (void (*)(void *, void *))co_swap_function;
+ }
+- if(!co_active_handle) co_active_handle = &co_active_buffer;
++ if(!co_active_handle.data) co_active_handle.data = &co_active_buffer;
+ size += 512; /* allocate additional space for storage */
+ size &= ~15; /* align stack to 16-byte boundary */
+
+- if(handle = (cothread_t)malloc(size)) {
+- long long *p = (long long*)((char*)handle + size); /* seek to top of
stack */
++ handle->data = mmap(0, size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0);
++ if(handle->data == MAP_FAILED) {
++ err(1, "libco mmap failed");
++ } else {
++ long long *p = (long long*)((char*)handle->data + size); /* seek to top
of stack */
+ *--p = (long long)crash; /* crash if
entrypoint returns */
+ *--p = (long long)entrypoint; /* start of function
*/
+- *(long long*)handle = (long long)p; /* stack pointer */
++ *(long long*)handle->data = (long long)p; /* stack
pointer */
+ }
+
+- return handle;
++ handle->size = size;
++
++ return *handle;
+ }
+
+ void co_delete(cothread_t handle) {
+- free(handle);
++ munmap(handle.data, handle.size);
++ free(&handle);
+ }
+
+ void co_switch(cothread_t handle) {
+ register cothread_t co_previous_handle = co_active_handle;
+- co_swap(co_active_handle = handle, co_previous_handle);
++ co_active_handle = handle;
++ co_swap(co_active_handle.data, co_previous_handle.data);
+ }
+
+ #ifdef __cplusplus
Index: patches/patch-libco_arm_c
===================================================================
RCS file: patches/patch-libco_arm_c
diff -N patches/patch-libco_arm_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-libco_arm_c 22 Oct 2019 07:50:17 -0000
@@ -0,0 +1,74 @@
+$OpenBSD$
+
+Index: libco/arm.c
+--- libco/arm.c.orig
++++ libco/arm.c
+@@ -12,8 +12,8 @@ extern "C" {
+ #endif
+
+ static thread_local unsigned long co_active_buffer[64];
+-static thread_local cothread_t co_active_handle = 0;
+-static void (*co_swap)(cothread_t, cothread_t) = 0;
++static thread_local cothread_t co_active_handle = {0};
++static void (*co_swap)(void *, void *) = 0;
+
+ #ifdef LIBCO_MPROTECT
+ alignas(4096)
+@@ -36,36 +36,46 @@ static void co_init() {
+ }
+
+ cothread_t co_active() {
+- if(!co_active_handle) co_active_handle = &co_active_buffer;
++ if(!co_active_handle.data) co_active_handle.data = &co_active_buffer;
+ return co_active_handle;
+ }
+
+ cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
+- unsigned long* handle = 0;
++ cothread_t *handle = malloc(sizeof *handle);
++ if(!handle) {
++ err(1, "libco malloc failed");
++ }
+ if(!co_swap) {
+ co_init();
+- co_swap = (void (*)(cothread_t, cothread_t))co_swap_function;
++ co_swap = (void (*)(void *, void *))co_swap_function;
+ }
+- if(!co_active_handle) co_active_handle = &co_active_buffer;
++ if(!co_active_handle.data) co_active_handle.data = &co_active_buffer;
+ size += 256;
+ size &= ~15;
+
+- if(handle = (unsigned long*)malloc(size)) {
+- unsigned long* p = (unsigned long*)((unsigned char*)handle + size);
+- handle[8] = (unsigned long)p;
+- handle[9] = (unsigned long)entrypoint;
++ handle->data = (unsigned long*)mmap(0, size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0);
++ if(handle->data == MAP_FAILED) {
++ err(1, "libco mmap failed");
++ } else {
++ unsigned long* p = (unsigned long*)((unsigned char*)handle->data + size);
++ handle->data[8] = (unsigned long)p;
++ handle->data[9] = (unsigned long)entrypoint;
+ }
+
+- return handle;
++ handle->size = size;
++
++ return *handle;
+ }
+
+ void co_delete(cothread_t handle) {
+- free(handle);
++ munmap(handle.data, handle.size);
++ free(&handle);
+ }
+
+ void co_switch(cothread_t handle) {
+ cothread_t co_previous_handle = co_active_handle;
+- co_swap(co_active_handle = handle, co_previous_handle);
++ co_active_handle = handle;
++ co_swap(handle.data, co_previous_handle.data);
+ }
+
+ #ifdef __cplusplus
Index: patches/patch-libco_libco_h
===================================================================
RCS file: patches/patch-libco_libco_h
diff -N patches/patch-libco_libco_h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-libco_libco_h 22 Oct 2019 07:50:17 -0000
@@ -0,0 +1,23 @@
+$OpenBSD$
+
+Index: libco/libco.h
+--- libco/libco.h.orig
++++ libco/libco.h
+@@ -7,11 +7,16 @@
+ #ifndef LIBCO_H
+ #define LIBCO_H
+
++#include <err.h>
++
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+-typedef void* cothread_t;
++typedef struct {
++ void * data;
++ unsigned int size;
++} cothread_t;
+
+ cothread_t co_active();
+ cothread_t co_create(unsigned int, void (*)(void));
Index: patches/patch-libco_ppc_c
===================================================================
RCS file: patches/patch-libco_ppc_c
diff -N patches/patch-libco_ppc_c
Index: patches/patch-libco_x86_c
===================================================================
RCS file: patches/patch-libco_x86_c
diff -N patches/patch-libco_x86_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-libco_x86_c 22 Oct 2019 07:50:17 -0000
@@ -0,0 +1,74 @@
+$OpenBSD$
+
+Index: libco/x86.c
+--- libco/x86.c.orig
++++ libco/x86.c
+@@ -18,8 +18,8 @@ extern "C" {
+ #endif
+
+ static thread_local long co_active_buffer[64];
+-static thread_local cothread_t co_active_handle = 0;
+-static void (fastcall *co_swap)(cothread_t, cothread_t) = 0;
++static thread_local cothread_t co_active_handle = {0};
++static void (fastcall *co_swap)(void *, void *) = 0;
+
+ #ifdef LIBCO_MPROTECT
+ alignas(4096)
+@@ -70,37 +70,47 @@ static void crash() {
+ }
+
+ cothread_t co_active() {
+- if(!co_active_handle) co_active_handle = &co_active_buffer;
++ if(!co_active_handle.data) co_active_handle.data = &co_active_buffer;
+ return co_active_handle;
+ }
+
+ cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
+- cothread_t handle;
++ cothread_t *handle = malloc(sizeof *handle);
++ if(!handle) {
++ err(1, "libco malloc failed");
++ }
+ if(!co_swap) {
+ co_init();
+- co_swap = (void (fastcall*)(cothread_t, cothread_t))co_swap_function;
++ co_swap = (void (fastcall*)(void *, void *))co_swap_function;
+ }
+- if(!co_active_handle) co_active_handle = &co_active_buffer;
++ if(!co_active_handle.data) co_active_handle.data = &co_active_buffer;
+ size += 256; /* allocate additional space for storage */
+ size &= ~15; /* align stack to 16-byte boundary */
+
+- if(handle = (cothread_t)malloc(size)) {
+- long *p = (long*)((char*)handle + size); /* seek to top of stack */
++ handle->data = mmap(0, size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0);
++ if(handle->data == MAP_FAILED) {
++ err(1, "libco mmap failed");
++ } else {
++ long *p = (long*)((char*)handle->data + size); /* seek to top of stack */
+ *--p = (long)crash; /* crash if entrypoint returns
*/
+ *--p = (long)entrypoint; /* start of function */
+- *(long*)handle = (long)p; /* stack pointer */
++ *(long*)handle->data = (long)p; /* stack pointer */
+ }
+
+- return handle;
++ handle->size = size;
++
++ return *handle;
+ }
+
+ void co_delete(cothread_t handle) {
+- free(handle);
++ munmap(handle.data, handle.size);
++ free(&handle);
+ }
+
+ void co_switch(cothread_t handle) {
+ register cothread_t co_previous_handle = co_active_handle;
+- co_swap(co_active_handle = handle, co_previous_handle);
++ co_active_handle = handle;
++ co_swap(co_active_handle.data, co_previous_handle.data);
+ }
+
+ #ifdef __cplusplus