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

Reply via email to