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