mirror of https://github.com/bsnes-emu/bsnes.git
Merge libco repository's commit 'd31c6e75a54be12307d65fd80f55adfbe7aa9d67' into master
This commit is contained in:
commit
d72874fa59
|
@ -0,0 +1,7 @@
|
||||||
|
ISC License (ISC)
|
||||||
|
|
||||||
|
Copyright byuu and the higan team
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
@ -1,5 +1,4 @@
|
||||||
libco
|
# libco
|
||||||
-----
|
|
||||||
|
|
||||||
libco is a cooperative multithreading library written in C89.
|
libco is a cooperative multithreading library written in C89.
|
||||||
|
|
||||||
|
@ -21,7 +20,10 @@ It currently includes backends for:
|
||||||
* POSIX platforms (setjmp)
|
* POSIX platforms (setjmp)
|
||||||
* Windows platforms (fibers)
|
* Windows platforms (fibers)
|
||||||
|
|
||||||
License
|
See [doc/targets.md] for details.
|
||||||
=======
|
|
||||||
|
See [doc/usage.md] for documentation.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
libco is released under the ISC license.
|
libco is released under the ISC license.
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
#include "libco.h"
|
#include "libco.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#ifdef LIBCO_MPROTECT
|
#ifdef LIBCO_MPROTECT
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -85,13 +83,13 @@ cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void))
|
||||||
}
|
}
|
||||||
|
|
||||||
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
||||||
void* memory = malloc(size);
|
void* memory = LIBCO_MALLOC(size);
|
||||||
if(!memory) return (cothread_t)0;
|
if(!memory) return (cothread_t)0;
|
||||||
return co_derive(memory, size, entrypoint);
|
return co_derive(memory, size, entrypoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void co_delete(cothread_t handle) {
|
void co_delete(cothread_t handle) {
|
||||||
free(handle);
|
LIBCO_FREE(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void co_switch(cothread_t handle) {
|
void co_switch(cothread_t handle) {
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
#include "libco.h"
|
#include "libco.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -114,7 +111,7 @@ static void (*co_swap)(cothread_t, cothread_t) = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void crash() {
|
static void crash() {
|
||||||
assert(0); /* called only if cothread_t entrypoint returns */
|
LIBCO_ASSERT(0); /* called only if cothread_t entrypoint returns */
|
||||||
}
|
}
|
||||||
|
|
||||||
cothread_t co_active() {
|
cothread_t co_active() {
|
||||||
|
@ -142,13 +139,13 @@ cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void))
|
||||||
}
|
}
|
||||||
|
|
||||||
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
||||||
void* memory = malloc(size);
|
void* memory = LIBCO_MALLOC(size);
|
||||||
if(!memory) return (cothread_t)0;
|
if(!memory) return (cothread_t)0;
|
||||||
return co_derive(memory, size, entrypoint);
|
return co_derive(memory, size, entrypoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void co_delete(cothread_t handle) {
|
void co_delete(cothread_t handle) {
|
||||||
free(handle);
|
LIBCO_FREE(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void co_switch(cothread_t handle) {
|
void co_switch(cothread_t handle) {
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
#include "libco.h"
|
#include "libco.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#ifdef LIBCO_MPROTECT
|
#ifdef LIBCO_MPROTECT
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
@ -61,13 +59,13 @@ cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void))
|
||||||
}
|
}
|
||||||
|
|
||||||
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
||||||
void* memory = malloc(size);
|
void* memory = LIBCO_MALLOC(size);
|
||||||
if(!memory) return (cothread_t)0;
|
if(!memory) return (cothread_t)0;
|
||||||
return co_derive(memory, size, entrypoint);
|
return co_derive(memory, size, entrypoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void co_delete(cothread_t handle) {
|
void co_delete(cothread_t handle) {
|
||||||
free(handle);
|
LIBCO_FREE(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void co_switch(cothread_t handle) {
|
void co_switch(cothread_t handle) {
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
body {
|
|
||||||
background: #333;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
background: #444;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #aaf;
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title></title>
|
|
||||||
<link href="style.css" rel="stylesheet" type="text/css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<b>Supported targets:</b><br/><br/>
|
|
||||||
|
|
||||||
Note that supported targets are only those that have been tested and confirmed
|
|
||||||
working. It is quite possible that libco will work on more processors, compilers
|
|
||||||
and operating systems than those listed below.
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<b>libco.x86</b><br/>
|
|
||||||
Overhead: ~5x<br/>
|
|
||||||
Supported processor(s): 32-bit x86<br/>
|
|
||||||
Supported compiler(s): any<br/>
|
|
||||||
Supported operating system(s):<ul>
|
|
||||||
<li>Windows</li>
|
|
||||||
<li>Mac OS X</li>
|
|
||||||
<li>Linux</li>
|
|
||||||
<li>BSD</li>
|
|
||||||
</ul>
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<b>libco.amd64</b><br/>
|
|
||||||
Overhead: ~10x (Windows), ~6x (all other platforms)<br/>
|
|
||||||
Supported processor(s): 64-bit amd64<br/>
|
|
||||||
Supported compiler(s): any<br/>
|
|
||||||
Supported operating system(s):<ul>
|
|
||||||
<li>Windows</li>
|
|
||||||
<li>Mac OS X</li>
|
|
||||||
<li>Linux</li>
|
|
||||||
<li>BSD</li>
|
|
||||||
</ul>
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<b>libco.ppc</b><br/>
|
|
||||||
Overhead: ~20x<br/>
|
|
||||||
Supported processor(s): 32-bit PowerPC, 64-bit PowerPC<br/>
|
|
||||||
Supported compiler(s): GNU GCC<br/>
|
|
||||||
Supported operating system(s):<ul>
|
|
||||||
</ul>
|
|
||||||
<li>Mac OS X</li>
|
|
||||||
<li>Linux</li>
|
|
||||||
<li>BSD</li>
|
|
||||||
<li>Playstation 3</li>
|
|
||||||
</ul>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
Note: this module contains compiler flags to enable/disable FPU and Altivec
|
|
||||||
support.
|
|
||||||
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<b>libco.fiber</b><br/>
|
|
||||||
Overhead: ~15x<br/>
|
|
||||||
Supported processor(s): Processor independent<br/>
|
|
||||||
Supported compiler(s): any<br/>
|
|
||||||
Supported operating system(s):<ul>
|
|
||||||
<li>Windows</li>
|
|
||||||
</ul>
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<b>libco.sjlj</b><br/>
|
|
||||||
Overhead: ~30x<br/>
|
|
||||||
Supported processor(s): Processor independent<br/>
|
|
||||||
Supported compiler(s): any<br/>
|
|
||||||
Supported operating system(s):<ul>
|
|
||||||
<li>Mac OS X</li>
|
|
||||||
<li>Linux</li>
|
|
||||||
<li>BSD</li>
|
|
||||||
<li>Solaris</li>
|
|
||||||
</ul>
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<b>libco.ucontext</b><br/>
|
|
||||||
Overhead: <b><font color="#ff0000">~300x</font></b><br/>
|
|
||||||
Supported processor(s): Processor independent<br/>
|
|
||||||
Supported compiler(s): any<br/>
|
|
||||||
Supported operating system(s):<ul>
|
|
||||||
<li>Linux</li>
|
|
||||||
<li>BSD</li>
|
|
||||||
</ul>
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
# Supported targets
|
||||||
|
In the following lists, supported targets are only those that have been tested
|
||||||
|
and confirmed working. It is quite possible that libco will work on more
|
||||||
|
processors, compilers and operating systems than those listed below.
|
||||||
|
|
||||||
|
The "Overhead" is the cost of switching co-routines, as compared to an ordinary
|
||||||
|
C function call.
|
||||||
|
|
||||||
|
## libco.x86
|
||||||
|
* **Overhead:** ~5x
|
||||||
|
* **Supported processor(s):** 32-bit x86
|
||||||
|
*** Supported compiler(s**): any
|
||||||
|
* **Supported operating system(s):**
|
||||||
|
* Windows
|
||||||
|
* Mac OS X
|
||||||
|
* Linux
|
||||||
|
* BSD
|
||||||
|
|
||||||
|
## libco.amd64
|
||||||
|
* **Overhead:** ~10x (Windows), ~6x (all other platforms)
|
||||||
|
* **Supported processor(s):** 64-bit amd64
|
||||||
|
*** Supported compiler(s**): any
|
||||||
|
* **Supported operating system(s):**
|
||||||
|
* Windows
|
||||||
|
* Mac OS X
|
||||||
|
* Linux
|
||||||
|
* BSD
|
||||||
|
|
||||||
|
## libco.ppc
|
||||||
|
* **Overhead:** ~20x
|
||||||
|
* **Supported processor(s):** 32-bit PowerPC, 64-bit PowerPC
|
||||||
|
* **Supported compiler(s):** GNU GCC
|
||||||
|
* **Supported operating system(s):**
|
||||||
|
* Mac OS X
|
||||||
|
* Linux
|
||||||
|
* BSD
|
||||||
|
* Playstation 3
|
||||||
|
|
||||||
|
**Note:** this module contains compiler flags to enable/disable FPU and Altivec
|
||||||
|
support.
|
||||||
|
|
||||||
|
## libco.fiber
|
||||||
|
This uses Windows' "fibers" API.
|
||||||
|
* **Overhead:** ~15x
|
||||||
|
* **Supported processor(s):** Processor independent
|
||||||
|
* **Supported compiler(s):** any
|
||||||
|
* **Supported operating system(s):**
|
||||||
|
* Windows
|
||||||
|
|
||||||
|
## libco.sjlj
|
||||||
|
This uses the C standard library's `setjump`/`longjmp` APIs.
|
||||||
|
* **Overhead:** ~30x
|
||||||
|
* **Supported processor(s):** Processor independent
|
||||||
|
* **Supported compiler(s):** any
|
||||||
|
* **Supported operating system(s):**
|
||||||
|
* Mac OS X
|
||||||
|
* Linux
|
||||||
|
* BSD
|
||||||
|
* Solaris
|
||||||
|
|
||||||
|
## libco.ucontext
|
||||||
|
This uses the POSIX "ucontext" API.
|
||||||
|
* **Overhead:** ***~300x***
|
||||||
|
* **Supported processor(s):** Processor independent
|
||||||
|
* **Supported compiler(s):** any
|
||||||
|
* **Supported operating system(s):**
|
||||||
|
* Linux
|
||||||
|
* BSD
|
|
@ -1,108 +1,130 @@
|
||||||
<html>
|
# License
|
||||||
<head>
|
|
||||||
<title></title>
|
|
||||||
<link href="style.css" rel="stylesheet" type="text/css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<b>License:</b><br/><br/>
|
|
||||||
libco is released under the ISC license.
|
libco is released under the ISC license.
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<b>Foreword:</b><br/><br/>
|
# Foreword
|
||||||
libco is a cross-platform, permissively licensed implementation of
|
libco is a cross-platform, permissively licensed implementation of
|
||||||
cooperative-multithreading; a feature that is sorely lacking from the ISO C/C++
|
cooperative-multithreading; a feature that is sorely lacking from the ISO C/C++
|
||||||
standard.<br/>
|
standard.
|
||||||
|
|
||||||
The library is designed for maximum speed and portability, and not for safety or
|
The library is designed for maximum speed and portability, and not for safety or
|
||||||
features. If safety or extra functionality is desired, a wrapper API can easily
|
features. If safety or extra functionality is desired, a wrapper API can easily
|
||||||
be written to encapsulate all library functions.<br/>
|
be written to encapsulate all library functions.
|
||||||
|
|
||||||
Behavior of executing operations that are listed as not permitted below result
|
Behavior of executing operations that are listed as not permitted below result
|
||||||
in undefined behavior. They may work anyway, they may cause undesired / unknown
|
in undefined behavior. They may work anyway, they may cause undesired / unknown
|
||||||
behavior, or they may crash the program entirely.<br/>
|
behavior, or they may crash the program entirely.
|
||||||
|
|
||||||
The goal of this library was to simplify the base API as much as possible,
|
The goal of this library was to simplify the base API as much as possible,
|
||||||
implementing only that which cannot be implemented using pure C. Additional
|
implementing only that which cannot be implemented using pure C. Additional
|
||||||
functionality after this would only complicate ports of this library to new
|
functionality after this would only complicate ports of this library to new
|
||||||
platforms.
|
platforms.
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<b>Porting:</b><br/><br/>
|
# Porting
|
||||||
This document is included as a reference for porting libco. Please submit any
|
This document is included as a reference for porting libco. Please submit any
|
||||||
ports you create to me, so that libco can become more useful. Please note that
|
ports you create to me, so that libco can become more useful. Please note that
|
||||||
since libco is permissively licensed, you must submit your code as a work of the
|
since libco is permissively licensed, you must submit your code as a work of the
|
||||||
public domain in order for it to be included in the official distribution.
|
public domain in order for it to be included in the official distribution.
|
||||||
|
|
||||||
Full credit will be given in the source code of the official release. Please
|
Full credit will be given in the source code of the official release. Please
|
||||||
do not bother submitting code to me under any other license -- including GPL,
|
do not bother submitting code to me under any other license -- including GPL,
|
||||||
LGPL, BSD or CC -- I am not interested in creating a library with multiple
|
LGPL, BSD or CC -- I am not interested in creating a library with multiple
|
||||||
different licenses depending on which targets are used.
|
different licenses depending on which targets are used.
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<b>Synopsis:</b><br/><br/>
|
Note that there are a variety of compile-time options in `settings.h`,
|
||||||
<code>
|
so if you want to use libco on a platform where it is not supported by default,
|
||||||
typedef void* cothread_t;<br/>
|
you may be able to configure the implementation appropriately without having
|
||||||
<br/>
|
to make a whole new port.
|
||||||
cothread_t co_active();<br/>
|
|
||||||
cothread_t co_create(unsigned int heapsize, void (*coentry)(void));<br/>
|
|
||||||
void co_delete(cothread_t cothread);<br/>
|
|
||||||
void co_switch(cothread_t cothread);<br/>
|
|
||||||
</code>
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<b>Usage:</b>
|
# Synopsis
|
||||||
<hr/>
|
```c
|
||||||
|
typedef void* cothread_t;
|
||||||
|
|
||||||
<code>typedef void* cothread_t;</code><br/><br/>
|
cothread_t co_active();
|
||||||
Handle to cothread.<br/>
|
cothread_t co_create(unsigned int heapsize, void (*coentry)(void));
|
||||||
Handle must be of type void*.<br/>
|
void co_delete(cothread_t cothread);
|
||||||
A value of null (0) indicates an uninitialized or invalid
|
void co_switch(cothread_t cothread);
|
||||||
handle, whereas a non-zero value indicates a valid handle.
|
```
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<code>cothread_t co_active();</code><br/><br/>
|
# Usage
|
||||||
Return handle to current cothread. Always returns a valid handle, even when
|
## cothread_t
|
||||||
called from the main program thread.
|
```c
|
||||||
<hr/>
|
typedef void* cothread_t;
|
||||||
|
```
|
||||||
|
Handle to cothread.
|
||||||
|
|
||||||
<code>cothread_t co_derive(void* memory, unsigned int heapsize, void (*coentry)(void));</code><br/><br/>
|
Handle must be of type `void*`.
|
||||||
Initializes new cothread.</br>
|
|
||||||
This function is identical to co_create, only it attempts to use the provided
|
A value of `null` (0) indicates an uninitialized or invalid handle, whereas a non-zero value indicates a valid handle.
|
||||||
|
|
||||||
|
## co_active
|
||||||
|
```c
|
||||||
|
cothread_t co_active();
|
||||||
|
```
|
||||||
|
Return handle to current cothread.
|
||||||
|
|
||||||
|
Always returns a valid handle, even when called from the main program thread.
|
||||||
|
|
||||||
|
## co_derive
|
||||||
|
```c
|
||||||
|
cothread_t co_derive(void* memory,
|
||||||
|
unsigned int heapsize,
|
||||||
|
void (*coentry)(void));
|
||||||
|
```
|
||||||
|
Initializes new cothread.
|
||||||
|
|
||||||
|
This function is identical to `co_create`, only it attempts to use the provided
|
||||||
memory instead of allocating new memory on the heap. Please note that certain
|
memory instead of allocating new memory on the heap. Please note that certain
|
||||||
implementations (currently only Windows Fibers) cannot be created using existing
|
implementations (currently only Windows Fibers) cannot be created using existing
|
||||||
memory, and as such, this function will fail.
|
memory, and as such, this function will fail.
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<code>cothread_t co_create(unsigned int heapsize, void (*coentry)(void));</code><br/><br/>
|
## co_create
|
||||||
Create new cothread.<br/>
|
```c
|
||||||
Heapsize is the amount of memory allocated for the cothread stack, specified
|
cothread_t co_create(unsigned int heapsize,
|
||||||
|
void (*coentry)(void));
|
||||||
|
```
|
||||||
|
Create new cothread.
|
||||||
|
|
||||||
|
`heapsize` is the amount of memory allocated for the cothread stack, specified
|
||||||
in bytes. This is unfortunately impossible to make fully portable. It is
|
in bytes. This is unfortunately impossible to make fully portable. It is
|
||||||
recommended to specify sizes using `n * sizeof(void*)'. It is better to err
|
recommended to specify sizes using `n * sizeof(void*)`. It is better to err
|
||||||
on the side of caution and allocate more memory than will be needed to ensure
|
on the side of caution and allocate more memory than will be needed to ensure
|
||||||
compatibility with other platforms, within reason. A typical heapsize for a
|
compatibility with other platforms, within reason. A typical heapsize for a
|
||||||
32-bit architecture is ~1MB.<br/>
|
32-bit architecture is ~1MB.
|
||||||
|
|
||||||
When the new cothread is first called, program execution jumps to coentry.
|
When the new cothread is first called, program execution jumps to coentry.
|
||||||
This function does not take any arguments, due to portability issues with
|
This function does not take any arguments, due to portability issues with
|
||||||
passing function arguments. However, arguments can be simulated by the use
|
passing function arguments. However, arguments can be simulated by the use
|
||||||
of global variables, which can be set before the first call to each cothread.<br/>
|
of global variables, which can be set before the first call to each cothread.
|
||||||
coentry() must not return, and should end with an appropriate co_switch()
|
|
||||||
statement. Behavior is undefined if entry point returns normally.<br/>
|
`coentry()` must not return, and should end with an appropriate `co_switch()`
|
||||||
|
statement. Behavior is undefined if entry point returns normally.
|
||||||
|
|
||||||
Library is responsible for allocating cothread stack memory, to free
|
Library is responsible for allocating cothread stack memory, to free
|
||||||
the user from needing to allocate special memory capable of being used
|
the user from needing to allocate special memory capable of being used
|
||||||
as program stack memory on platforms where this is required.<br/>
|
as program stack memory on platforms where this is required.
|
||||||
User is always responsible for deleting cothreads with co_delete().<br/>
|
|
||||||
Return value of null (0) indicates cothread creation failed.
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<code>void co_delete(cothread_t cothread);</code><br/><br/>
|
User is always responsible for deleting cothreads with `co_delete()`.
|
||||||
Delete specified cothread.<br/>
|
|
||||||
Null (0) or invalid cothread handle is not allowed.<br/>
|
Return value of `null` (0) indicates cothread creation failed.
|
||||||
Passing handle of active cothread to this function is not allowed.<br/>
|
|
||||||
Passing handle of primary cothread is not allowed.
|
## co_delete
|
||||||
<hr/>
|
```c
|
||||||
|
void co_delete(cothread_t cothread);
|
||||||
|
```
|
||||||
|
Delete specified cothread.
|
||||||
|
|
||||||
|
`null` (0) or invalid cothread handle is not allowed.
|
||||||
|
|
||||||
<code>void co_switch(cothread_t cothread);</code><br/><br/>
|
|
||||||
Switch to specified cothread.<br/>
|
|
||||||
Null (0) or invalid cothread handle is not allowed.<br/>
|
|
||||||
Passing handle of active cothread to this function is not allowed.
|
Passing handle of active cothread to this function is not allowed.
|
||||||
<hr/>
|
|
||||||
|
|
||||||
</body>
|
Passing handle of primary cothread is not allowed.
|
||||||
</html>
|
|
||||||
|
## co_switch
|
||||||
|
```c
|
||||||
|
void co_switch(cothread_t cothread);
|
||||||
|
```
|
||||||
|
Switch to specified cothread.
|
||||||
|
|
||||||
|
`null` (0) or invalid cothread handle is not allowed.
|
||||||
|
|
||||||
|
Passing handle of active cothread to this function is not allowed.
|
|
@ -13,12 +13,12 @@ extern "C" {
|
||||||
|
|
||||||
typedef void* cothread_t;
|
typedef void* cothread_t;
|
||||||
|
|
||||||
cothread_t co_active();
|
cothread_t co_active(void);
|
||||||
cothread_t co_derive(void*, unsigned int, void (*)(void));
|
cothread_t co_derive(void*, unsigned int, void (*)(void));
|
||||||
cothread_t co_create(unsigned int, void (*)(void));
|
cothread_t co_create(unsigned int, void (*)(void));
|
||||||
void co_delete(cothread_t);
|
void co_delete(cothread_t);
|
||||||
void co_switch(cothread_t);
|
void co_switch(cothread_t);
|
||||||
int co_serializable();
|
int co_serializable(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "libco.h"
|
#include "libco.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -327,7 +326,7 @@ cothread_t co_derive(void* memory, unsigned int size, void (*entry_)(void)) {
|
||||||
static uint32_t* co_create_(unsigned size, uintptr_t entry) {
|
static uint32_t* co_create_(unsigned size, uintptr_t entry) {
|
||||||
(void)entry;
|
(void)entry;
|
||||||
|
|
||||||
uint32_t* t = (uint32_t*)malloc(size);
|
uint32_t* t = (uint32_t*)LIBCO_MALLOC(size);
|
||||||
|
|
||||||
#if LIBCO_PPCDESC
|
#if LIBCO_PPCDESC
|
||||||
if(t) {
|
if(t) {
|
||||||
|
@ -390,7 +389,7 @@ cothread_t co_create(unsigned int size, void (*entry_)(void)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void co_delete(cothread_t t) {
|
void co_delete(cothread_t t) {
|
||||||
free(t);
|
LIBCO_FREE(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void co_init_(void) {
|
static void co_init_(void) {
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -223,7 +222,7 @@ __asm__(
|
||||||
|
|
||||||
cothread_t co_active() {
|
cothread_t co_active() {
|
||||||
if(!co_active_handle) {
|
if(!co_active_handle) {
|
||||||
co_active_handle = (struct ppc64_context*)malloc(MIN_STACK + sizeof(struct ppc64_context));
|
co_active_handle = (struct ppc64_context*)LIBCO_MALLOC(MIN_STACK + sizeof(struct ppc64_context));
|
||||||
}
|
}
|
||||||
return (cothread_t)co_active_handle;
|
return (cothread_t)co_active_handle;
|
||||||
}
|
}
|
||||||
|
@ -255,13 +254,13 @@ cothread_t co_derive(void* memory, unsigned int size, void (*coentry)(void)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cothread_t co_create(unsigned int size, void (*coentry)(void)) {
|
cothread_t co_create(unsigned int size, void (*coentry)(void)) {
|
||||||
void* memory = malloc(size);
|
void* memory = LIBCO_MALLOC(size);
|
||||||
if(!memory) return (cothread_t)0;
|
if(!memory) return (cothread_t)0;
|
||||||
return co_derive(memory, size, coentry);
|
return co_derive(memory, size, coentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void co_delete(cothread_t handle) {
|
void co_delete(cothread_t handle) {
|
||||||
free(handle);
|
LIBCO_FREE(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void co_switch(cothread_t to) {
|
void co_switch(cothread_t to) {
|
||||||
|
|
|
@ -10,20 +10,85 @@
|
||||||
do not use this unless you are certain your application won't use SSE */
|
do not use this unless you are certain your application won't use SSE */
|
||||||
/* #define LIBCO_NO_SSE */
|
/* #define LIBCO_NO_SSE */
|
||||||
|
|
||||||
#if defined(LIBCO_C)
|
#if !defined(thread_local) // User can override thread_local for obscure compilers
|
||||||
#if defined(LIBCO_MP)
|
#if !defined(LIBCO_MP) // Running in single-threaded environment
|
||||||
#define thread_local __thread
|
|
||||||
#else
|
|
||||||
#define thread_local
|
#define thread_local
|
||||||
|
#else // Running in multi-threaded environment
|
||||||
|
#if defined(__STDC_VERSION__) // Compiling as C Language
|
||||||
|
#if defined(_MSC_VER) // Don't rely on MSVC's C11 support
|
||||||
|
#define thread_local __declspec(thread)
|
||||||
|
#elif __STDC_VERSION__ < 201112L // If we are on C90/99
|
||||||
|
#if defined(__clang__) || defined(__GNUC__) // Clang and GCC
|
||||||
|
#define thread_local __thread
|
||||||
|
#else // Otherwise, we ignore the directive (unless user provides their own)
|
||||||
|
#define thread_local
|
||||||
|
#endif
|
||||||
|
#else // C11 and newer define thread_local in threads.h
|
||||||
|
#include <threads.h>
|
||||||
|
#endif
|
||||||
|
#elif defined(__cplusplus) // Compiling as C++ Language
|
||||||
|
#if __cplusplus < 201103L // thread_local is a C++11 feature
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define thread_local __declspec(thread)
|
||||||
|
#elif defined(__clang__) || defined(__GNUC__)
|
||||||
|
#define thread_local __thread
|
||||||
|
#else // Otherwise, we ignore the directive (unless user provides their own)
|
||||||
|
#define thread_local
|
||||||
|
#endif
|
||||||
|
#else // In C++ >= 11, thread_local in a builtin keyword
|
||||||
|
// Don't do anything
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __STDC_VERSION__ >= 201112L
|
/* In alignas(a), 'a' should be a power of two that is at least the type's
|
||||||
#if !defined(_MSC_VER)
|
alignment and at most the implementation's alignment limit. This limit is
|
||||||
#include <stdalign.h>
|
2**13 on MSVC. To be portable to MSVC through at least version 10.0,
|
||||||
#endif
|
'a' should be an integer constant, as MSVC does not support expressions
|
||||||
#else
|
such as 1 << 3.
|
||||||
#define alignas(bytes)
|
|
||||||
|
The following C11 requirements are NOT supported on MSVC:
|
||||||
|
|
||||||
|
- If 'a' is zero, alignas has no effect.
|
||||||
|
- alignas can be used multiple times; the strictest one wins.
|
||||||
|
- alignas (TYPE) is equivalent to alignas (alignof (TYPE)).
|
||||||
|
*/
|
||||||
|
#if !defined(alignas)
|
||||||
|
#if defined(__STDC_VERSION__) // C Language
|
||||||
|
#if defined(_MSC_VER) // Don't rely on MSVC's C11 support
|
||||||
|
#define alignas(bytes) __declspec(align(bytes))
|
||||||
|
#elif __STDC_VERSION__ >= 201112L // C11 and above
|
||||||
|
#include <stdalign.h>
|
||||||
|
#elif defined(__clang__) || defined(__GNUC__) // C90/99 on Clang/GCC
|
||||||
|
#define alignas(bytes) __attribute__ ((aligned (bytes)))
|
||||||
|
#else // Otherwise, we ignore the directive (user should provide their own)
|
||||||
|
#define alignas(bytes)
|
||||||
|
#endif
|
||||||
|
#elif defined(__cplusplus) // C++ Language
|
||||||
|
#if __cplusplus < 201103L
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define alignas(bytes) __declspec(align(bytes))
|
||||||
|
#elif defined(__clang__) || defined(__GNUC__) // C++98/03 on Clang/GCC
|
||||||
|
#define alignas(bytes) __attribute__ ((aligned (bytes)))
|
||||||
|
#else // Otherwise, we ignore the directive (unless user provides their own)
|
||||||
|
#define alignas(bytes)
|
||||||
|
#endif
|
||||||
|
#else // C++ >= 11 has alignas keyword
|
||||||
|
// Do nothing
|
||||||
|
#endif
|
||||||
|
#endif // = !defined(__STDC_VERSION__) && !defined(__cplusplus)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LIBCO_ASSERT)
|
||||||
|
#include <assert.h>
|
||||||
|
#define LIBCO_ASSERT assert
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LIBCO_MALLOC) || !defined(LIBCO_FREE)
|
||||||
|
#include <stdlib.h>
|
||||||
|
#define LIBCO_MALLOC malloc
|
||||||
|
#define LIBCO_FREE free
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
|
@ -34,5 +99,6 @@
|
||||||
#define section(name) __attribute__((section("." #name "#")))
|
#define section(name) __attribute__((section("." #name "#")))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* if defined(LIBCO_C) */
|
/* if defined(LIBCO_C) */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
#include "libco.h"
|
#include "libco.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -68,7 +65,7 @@ static const unsigned char co_swap_function[4096] = {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void crash() {
|
static void crash() {
|
||||||
assert(0); /* called only if cothread_t entrypoint returns */
|
LIBCO_ASSERT(0); /* called only if cothread_t entrypoint returns */
|
||||||
}
|
}
|
||||||
|
|
||||||
cothread_t co_active() {
|
cothread_t co_active() {
|
||||||
|
@ -96,13 +93,13 @@ cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void))
|
||||||
}
|
}
|
||||||
|
|
||||||
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
||||||
void* memory = malloc(size);
|
void* memory = LIBCO_MALLOC(size);
|
||||||
if(!memory) return (cothread_t)0;
|
if(!memory) return (cothread_t)0;
|
||||||
return co_derive(memory, size, entrypoint);
|
return co_derive(memory, size, entrypoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void co_delete(cothread_t handle) {
|
void co_delete(cothread_t handle) {
|
||||||
free(handle);
|
LIBCO_FREE(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void co_switch(cothread_t handle) {
|
void co_switch(cothread_t handle) {
|
||||||
|
|
Loading…
Reference in New Issue