On Tue, Oct 22, 2019 at 01:51:50AM -0600, Anthony J. Bentley wrote:
> 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.
Thanks!
I have sent a link to this patch upstream. Let's see what they say.
> 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
>
>