Update to v101r18 release.

byuu says:

Changelog:

  - added 30 new PAL games to icarus (courtesy of Mikerochip)
  - new version of libco no longer requires mprotect nor W|X permissions
  - nall: default C compiler to -std=c11 instead of -std=c99
  - nall: use `-fno-strict-aliasing` during compilation
  - updated nall/certificates (hopefully for the last time)
  - updated nall/http to newer coding conventions
  - nall: improve handling of range() function

I didn't really work on higan at all, this is mostly just a release
because lots of other things have changed.

The most interesting is `-fno-strict-aliasing` ... basically, it joins
`-fwrapv` as being "stop the GCC developers from doing *really* evil
shit that could lead to security vulnerabilities or instabilities."

For the most part, it's a ~2% speed penalty for higan. Except for the
Sega Genesis, where it's a ~10% speedup. I have no idea how that's
possible, but clearly something's going very wrong with strict aliasing
on the Genesis core.

So ... it is what it is. If you need the performance for the non-Genesis
cores, you can turn it off in your builds. But I'm getting quite sick of
C++'s "surprises" and clever compiler developers, so I'm keeping it on
in all of my software going forward.
This commit is contained in:
Tim Allen 2016-09-14 21:55:53 +10:00
parent d6e9d94ec3
commit c6fc15f8d2
26 changed files with 980 additions and 514 deletions

View File

@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "101.17";
static const string Version = "101.18";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "http://byuu.org/";

View File

@ -12,6 +12,128 @@ cartridge sha256:dd499445275fca6692c0487a8bd70a23f6c8e78e766df0e3c58fbbe53f8adb0
: name: Legende de Zelda - La Triforce des Dieux, La
: title: La Legende de Zelda: La Triforce des Dieux
cartridge sha256:41084f83e269d46b9d589f11c802a15e84fede57d604c7986053f2858f757adc
:board region=pal
: rom name=program.rom size=0x100000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-ASDP-EUR
: board: SHVC-1A0N-20
: revision: 1.0
: name: Archer Maclean's Super Dropzone
: title: Archer Maclean's Super Dropzone
cartridge sha256:6fe482f91a59a71992e14014a0a4e23fb866cf4e870c10d57c81b0c20ae6688e
:board region=pal
: rom name=program.rom size=0x100000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-3U-EUR
: board: SHVC-1A0N-30
: revision: 1.0
: name: International Superstar Soccer
: title: International Superstar Soccer
cartridge sha256:2516843fa405ab1aa1f242b57f19977519aefb68599474d2c7065aaef88ecb88
:board region=pal
: rom name=program.rom size=0x200000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-AJGP-EUR
: board: SHVC-1A0N-30
: revision: 1.0
: name: Jungle Strike
: title: Jungle Strike
cartridge sha256:964f8391806bc8d674f24aa2f201b20982d2f2f3e3efb2f730c4a34a289c3007
:board region=pal
: rom name=program.rom size=0x300000
: map address=00-3f,80-bf:8000-ffff
: map address=40-7d,c0-ff:0000-ffff
:
:information
: serial: SNSP-28-EUR
: board: SHVC-BJ0N-01
: revision: 1.1
: name: Mortal Kombat 2
: title: Mortal Kombat II
cartridge sha256:b7fa4b79590ecdef2d0303b5cbccf1e1a3af31fca289652acbdb3d5381137f24
:board region=pal
: rom name=program.rom size=0x400000
: map address=00-3f,80-bf:8000-ffff
: map address=40-7d,c0-ff:0000-ffff
:
:information
: serial: SNSP-A3MP-EUR
: board: SHVC-1J0N-20
: revision: 1.0
: name: Mortal Kombat 3
: title: Mortal Kombat 3
cartridge sha256:166fe888ac03f88cce5759c1008021082bd81254aab8fea8203cdb13080709d7
:board region=pal
: rom name=program.rom size=0x100000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-APFP-EUR
: board: SHVC-1A0N-20
: revision: 1.0
: name: Pinball Fantasies
: title: Pinball Fantasies
cartridge sha256:09fdef0c959e7275563f65d8267d95a20104f054e9438e9ac739ef7f46120a2d
:board region=pal
: rom name=program.rom size=0x100000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-JA-EUR
: board: SHVC-1A0N-20
: revision: 1.0
: name: Smash Tennis
: title: Smash Tennis
cartridge sha256:9638d4daa7bc63fd178b77c4487c3b080def5b808c0b7ccc959101f33e221b42
:board region=pal
: rom name=program.rom size=0x200000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-AMCP-EUR
: board: SHVC-1A0N-20
: revision: 1.0
: name: Spider-Man & Venom - Maximum Carnage
: title: Spider-Man & Venom: Maximum Carnage
cartridge sha256:abe8db202f9bd12d845a4c7ecb97d85fb149d7f17a608b3eae015d92f52f2c04
:board region=pal
: superfx
: map address=00-3f,80-bf:3000-34ff
: rom name=program.rom size=0x100000
: map address=00-3f,80-bf:8000-ffff mask=0x8000
: map address=40-5f,c0-df:0000-ffff
: ram name=save.ram size=0x10000
: map address=00-3f,80-bf:6000-7fff size=0x2000
: map address=70-71,f0-f1:0000-ffff
:
:information
: serial: SNSP-CQ-FAH
: board: SHVC-1CA6B-01
: revision: 1.0
: name: Stunt Race FX
: title: Stunt Race FX
cartridge sha256:e678a29a93111cf2016c487ba9977b14de8f719040651a42c74bd74eea2d0d81
:board region=ntsc
: rom name=program.rom size=0x200000
@ -70,6 +192,35 @@ cartridge sha256:1444ab11f96f7750db992e9a4160532b27abede8a7054128c09f448300c91eb
: name: Secret of Mana
: title: Secret of Mana
cartridge sha256:35c1d6623748f66e254843cf340121e3e268a8301951f35c7ba3ef666bc293bf
:board region=pal
: rom name=program.rom size=0x200000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-S2-NOE
: board: SHVC-1A0N-10
: revision: 1.0
: name: Street Fighter II - The World Warrior
: title: Street Fighter II: The World Warrior
cartridge sha256:4d7fc331a811b8dc630b469262fd6f45e289243cef83101f32038158967d1b28
:board region=pal
: rom name=program.rom size=0x40000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
: icd2 revision=1
: map address=00-3f,80-bf:6000-67ff,7000-7fff
: rom name=sgb.boot.rom size=0x100
:
:information
: serial: SNSP-A-SG-NOE
: board: SGB-R-10
: revision: 1.2
: name: Super Game Boy
: title: Super Game Boy
cartridge sha256:613cd1a31eaded18648168bd7453a57830ca9a6f3c10de5154625436fbd49556
:board region=pal
: rom name=program.rom size=0x400000
@ -85,6 +236,202 @@ cartridge sha256:613cd1a31eaded18648168bd7453a57830ca9a6f3c10de5154625436fbd4955
: name: Terranigma
: title: Terranigma
cartridge sha256:a1105819d48c04d680c8292bbfa9abbce05224f1bc231afd66af43b7e0a1fd4e
:board region=pal
: rom name=program.rom size=0x200000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: ram name=save.ram size=0x2000
: map address=70-7d,f0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-4L-NOE
: board: SHVC-1A3M-30
: revision: 1.0
: name: Unirally
: title: Unirally
cartridge sha256:0a49023824d812c64cd262db6e85ce9900c88af7ac6dab3e47078ab0dd1e546c
:board region=pal
: rom name=program.rom size=0x200000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-YN-UKV
: board: SHVC-2A0N-10
: revision: 1.0
: name: Bubsy I - Claws Encounters of the Furred Kind
: title: Bubsy in Claws Encounters of the Furred Kind
cartridge sha256:dddacae010766c1201f50810fcf15dff7c0f6d41ac1a1004c8eea4873a71db12
:board region=pal
: rom name=program.rom size=0x80000
: map address=00-1f,80-9f:8000-ffff mask=0x8000
: ram name=save.ram size=0x800
: map address=70-7d,f0-ff:0000-ffff
:
:information
: serial: SNSP-FZ-UKV
: board: SHVC-1A1B-05
: revision: 1.0
: name: F-Zero
: title: F-Zero
cartridge sha256:e9e2152411fec3bd10e8cd4587b62717169a25a4cd28f491f8e477b9aae2fcee
:board region=pal
: rom name=program.rom size=0x100000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-7N-UKV
: board: SHVC-1A0N-20
: revision: 1.0
: name: Fun & Games
: title: fun 'n games
cartridge sha256:9d936f3b0b5bea0b7c4588e65fa147fff1108d0e630337dd75eb16133a55e317
:board region=pal
: rom name=program.rom size=0x80000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: ram name=save.ram size=0x2000
: map address=70-7d,f0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-8S-UKV
: board: SHVC-1A3M-20
: revision: 1.1
: name: International Sensible Soccer - World Champions
: title: International Sensible Soccer: World Champions
cartridge sha256:ddad4a3708b8cf760e520b784f42d7085154b0699f3824b8d722512ccab687cb
:board region=pal
: rom name=program.rom size=0x400000
: map address=00-3f,80-bf:8000-ffff
: map address=40-7d,c0-ff:0000-ffff
:
:information
: serial: SNSP-AKLP-UKV
: board: SHVC-1J0N-20
: revision: 1.0
: name: Killer Instinct
: title: Killer Instinct
cartridge sha256:654183585e88abf965b19570c194f3d69ef209a7f2d32f71881eceaea6a3487e
:board region=pal
: rom name=program.rom size=0x100000
: map address=00-1f,80-9f:8000-ffff mask=0x8000
: ram name=save.ram size=0x2000
: map address=70-7d,f0-ff:0000-ffff
:
:information
: serial: SNSP-ZL-UKV
: board: SHVC-1A3B-13
: revision: 1.0
: name: Legend of Zelda - A Link to the Past, The
: title: The Legend of Zelda: A Link to the Past
cartridge sha256:d147bfe392e8c2129fb887379410804d79be426bbffdd01cec7bd2332e03f39e
:board region=pal
: rom name=program.rom size=0x80000
: map address=00-1f,80-9f:8000-ffff mask=0x8000
: necdsp model=uPD7725 frequency=8000000
: map address=30-3f,b0-bf:8000-ffff mask=0x3fff
: prom name=dsp1b.program.rom size=0x1800
: drom name=dsp1b.data.rom size=0x800
: dram name=dsp1b.data.ram size=0x200 volatile
:
:information
: serial: SNSP-PW-UKV
: board: SHVC-1B0N-10
: revision: 1.0
: name: Pilotwings
: title: Pilotwings
cartridge sha256:5702fb6978229e398075cf0d20927b47a5881b572532813557e86b8e9cf63db0
:board region=pal
: rom name=program.rom size=0x200000
: map address=00-3f,80-bf:8000-ffff
: map address=40-7d,c0-ff:0000-ffff
: ram name=save.ram size=0x2000
: map address=20-3f,a0-bf:6000-7fff mask=0xe000
:
:information
: serial: SNSP-K2-UKV
: board: SHVC-1J3M-20
: revision: 1.1
: name: Secret of Mana
: title: Secret of Mana
cartridge sha256:e95278ec68bf983111a52e38d5e6031c41141858e87e2cb8ef92fdfe17e41a15
:board region=pal
: rom name=program.rom size=0x80000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: ram name=save.ram size=0x2000
: map address=70-7d,f0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-8S-UKV
: board: SHVC-1A3M-20
: revision: 1.0
: name: Sensible Soccer - European Champions
: title: Sensible Soccer: European Champions
cartridge sha256:8c7a8aa1d16aeef31244b016ac951eab0b9ccd46daea61adbe890e5c5daa29c6
:board region=pal
: rom name=program.rom size=0x200000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-XN-UKV
: board: SHVC-1A0N-30
: revision: 1.0
: name: Star Trek - The Next Generation - Future's Past
: title: Star Trek: The Next Generation - Future's Past
cartridge sha256:80e7ba7c756c70eedd55ca4548c1965f84f9ef01d3a5ca91a2e5465a6930c49a
:board region=pal
: superfx
: map address=00-3f,80-bf:3000-34ff
: rom name=program.rom size=0x100000
: map address=00-1f,80-9f:8000-ffff mask=0x8000
: ram name=save.ram size=0x8000
: map address=60-7d,e0-ff:0000-ffff
:
:information
: serial: SNSP-FO-UKV
: board: SNSP-1C0N5S-01
: revision: 1.1
: name: Starwing
: title: Starwing
cartridge sha256:b8ee1b5b9deae5c84fa209815515030109cc271b645a18de882aaf1b254cda1f
:board region=pal
: rom name=program.rom size=0x280000
: map address=00-3f,80-bf:8000-ffff
: map address=40-7d,c0-ff:0000-ffff
:
:information
: serial: SNSP-TI-UKV
: board: SHVC-BJ0N-01
: revision: 1.0
: name: Street Fighter II Turbo - Hyper Fighting
: title: Street Fighter II Turbo: Hyper Fighting
cartridge sha256:df43b3a4f511401a4d162ee6e7e3b08485533600dc44a29ee0a829b937b144d4
:board region=pal
: rom name=program.rom size=0x80000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-KE-UKV
: board: SHVC-1A0N-20
: revision: 1.0
: name: Striker
: title: Striker
cartridge sha256:f1a75578e6711716340bb26ea93bf05d5762bc7da21dbc19576fc65de1e885b5
:board region=pal
: rom name=program.rom size=0x100000
@ -98,6 +445,81 @@ cartridge sha256:f1a75578e6711716340bb26ea93bf05d5762bc7da21dbc19576fc65de1e885b
: name: Super Aleste
: title: Super Aleste
cartridge sha256:9760fb407282d91005044fb08f9c15dc3e0ae65063a02eedfbbd285566501fd0
:board region=pal
: rom name=program.rom size=0x200000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: ram name=save.ram size=0x2000
: map address=70-7d,f0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-4M-UKV
: board: SHVC-2A3M-01
: revision: 1.0
: name: Super Mario All-Stars
: title: Super Mario All-Stars
cartridge sha256:12d04359329bd646fc65c62db6121b4a7e4ece68556d68252e81ced421069f4c
:board region=pal
: rom name=program.rom size=0x80000
: map address=00-3f,80-bf:8000-ffff
: map address=40-7d,c0-ff:0000-ffff
: ram name=save.ram size=0x800
: map address=20-3f,a0-bf:6000-7fff mask=0xe000
: necdsp model=uPD7725 frequency=8000000
: map address=00-1f,80-9f:6000-7fff mask=0xfff
: prom name=dsp1.program.rom size=0x1800
: drom name=dsp1.data.rom size=0x800
: dram name=dsp1.data.ram size=0x200 volatile
:
:information
: serial: SNSP-MK-UKV
: board: SHVC-1K1B-01
: revision: 1.0
: name: Super Mario Kart
: title: Super Mario Kart
cartridge sha256:640acb63dae038ad6f0ae65e103416f5a1f84d4a37ddaeeab5046122def774d5
:board region=pal
: rom name=program.rom size=0x300000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: ram name=save.ram size=0x2000
: map address=70-7d,f0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-RI-UKV
: board: SHVC-BA3M-10
: revision: 1.0
: name: Super Metroid
: title: Super Metroid
cartridge sha256:3438e78d35634d0ed7f58cb395c77da548fb601248725a18365edaed38a565d5
:board region=pal
: rom name=program.rom size=0x200000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: ram name=save.ram size=0x2000
: map address=70-7d,f0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-4Q-UKV
: board: SHVC-1A3M-30
: revision: 1.0
: name: Super Punch-Out!!
: title: Super Punch-Out!!
cartridge sha256:7c7e90fb7c762769219234baf7b5fa6bf574fff7dc63b7134d49ec7c8b38ea7e
:board region=pal
: rom name=program.rom size=0x100000
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
:
:information
: serial: SNSP-SR-UKV
: board: SHVC-1A0N-02
: revision: 1.0
: name: Super R-Type
: title: Super R-Type
cartridge sha256:2ffe8828480f943056fb1ab5c3c84d48a0bf8cbe3ed7c9960b349b59adb07f3b
:board region=ntsc
: rom name=program.rom size=0x200000

View File

@ -1,15 +1,12 @@
/*
libco.amd64 (2015-06-19)
libco.amd64 (2016-09-14)
author: byuu
license: public domain
*/
#define LIBCO_C
#include "libco.h"
//Win64 only: provides a substantial speed-up, but will thrash XMM regs
//do not use this unless you are certain your application won't use SSE
//#define LIBCO_AMD64_NO_SSE
#include "settings.h"
#include <assert.h>
#include <stdlib.h>
@ -22,9 +19,14 @@ 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;
#ifdef LIBCO_MPROTECT
alignas(4096)
#else
section(text)
#endif
#ifdef _WIN32
/* ABI: Win64 */
static unsigned char co_swap_function[] = {
static const unsigned char co_swap_function[4096] = {
0x48, 0x89, 0x22, /* mov [rdx],rsp */
0x48, 0x8b, 0x21, /* mov rsp,[rcx] */
0x58, /* pop rax */
@ -36,7 +38,7 @@ static void (*co_swap)(cothread_t, cothread_t) = 0;
0x4c, 0x89, 0x6a, 0x30, /* mov [rdx+48],r13 */
0x4c, 0x89, 0x72, 0x38, /* mov [rdx+56],r14 */
0x4c, 0x89, 0x7a, 0x40, /* mov [rdx+64],r15 */
#if !defined(LIBCO_AMD64_NO_SSE)
#if !defined(LIBCO_NO_SSE)
0x0f, 0x29, 0x72, 0x50, /* movaps [rdx+ 80],xmm6 */
0x0f, 0x29, 0x7a, 0x60, /* movaps [rdx+ 96],xmm7 */
0x44, 0x0f, 0x29, 0x42, 0x70, /* movaps [rdx+112],xmm8 */
@ -57,7 +59,7 @@ static void (*co_swap)(cothread_t, cothread_t) = 0;
0x4c, 0x8b, 0x69, 0x30, /* mov r13,[rcx+48] */
0x4c, 0x8b, 0x71, 0x38, /* mov r14,[rcx+56] */
0x4c, 0x8b, 0x79, 0x40, /* mov r15,[rcx+64] */
#if !defined(LIBCO_AMD64_NO_SSE)
#if !defined(LIBCO_NO_SSE)
0x0f, 0x28, 0x71, 0x50, /* movaps xmm6, [rcx+ 80] */
0x0f, 0x28, 0x79, 0x60, /* movaps xmm7, [rcx+ 96] */
0x44, 0x0f, 0x28, 0x41, 0x70, /* movaps xmm8, [rcx+112] */
@ -75,13 +77,15 @@ static void (*co_swap)(cothread_t, cothread_t) = 0;
#include <windows.h>
void co_init() {
static void co_init() {
#ifdef LIBCO_MPROTECT
DWORD old_privileges;
VirtualProtect(co_swap_function, sizeof co_swap_function, PAGE_EXECUTE_READWRITE, &old_privileges);
VirtualProtect((void*)co_swap_function, sizeof co_swap_function, PAGE_EXECUTE_READ, &old_privileges);
#endif
}
#else
/* ABI: SystemV */
static unsigned char co_swap_function[] = {
static const unsigned char co_swap_function[4096] = {
0x48, 0x89, 0x26, /* mov [rsi],rsp */
0x48, 0x8b, 0x27, /* mov rsp,[rdi] */
0x58, /* pop rax */
@ -103,11 +107,13 @@ static void (*co_swap)(cothread_t, cothread_t) = 0;
#include <unistd.h>
#include <sys/mman.h>
void co_init() {
static void co_init() {
#ifdef LIBCO_MPROTECT
unsigned long long addr = (unsigned long long)co_swap_function;
unsigned long long base = addr - (addr % sysconf(_SC_PAGESIZE));
unsigned long long size = (addr - base) + sizeof co_swap_function;
mprotect((void*)base, size, PROT_READ | PROT_WRITE | PROT_EXEC);
mprotect((void*)base, size, PROT_READ | PROT_EXEC);
#endif
}
#endif

View File

@ -1,11 +1,12 @@
/*
libco.arm (2015-06-18)
libco.arm (2016-09-14)
author: byuu
license: public domain
*/
#define LIBCO_C
#include "libco.h"
#include "settings.h"
#include <assert.h>
#include <stdlib.h>
@ -20,17 +21,24 @@ 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 unsigned long co_swap_function[] = {
#ifdef LIBCO_MPROTECT
alignas(4096)
#else
section(text)
#endif
static const unsigned long co_swap_function[1024] = {
0xe8a16ff0, /* stmia r1!, {r4-r11,sp,lr} */
0xe8b0aff0, /* ldmia r0!, {r4-r11,sp,pc} */
0xe12fff1e, /* bx lr */
};
void co_init() {
static void co_init() {
#ifdef LIBCO_MPROTECT
unsigned long addr = (unsigned long)co_swap_function;
unsigned long base = addr - (addr % sysconf(_SC_PAGESIZE));
unsigned long size = (addr - base) + sizeof co_swap_function;
mprotect((void*)base, size, PROT_READ | PROT_WRITE | PROT_EXEC);
mprotect((void*)base, size, PROT_READ | PROT_EXEC);
#endif
}
cothread_t co_active() {

View File

@ -17,7 +17,7 @@ extern "C" {
static thread_local cothread_t co_active_ = 0;
static void __stdcall co_thunk(void *coentry) {
static void __stdcall co_thunk(void* coentry) {
((void (*)(void))coentry)();
}

View File

@ -1,6 +1,5 @@
/*
libco
version: 0.17 (2015-06-18)
libco v18 (2016-09-14)
author: byuu
license: public domain
*/
@ -8,14 +7,6 @@
#ifndef LIBCO_H
#define LIBCO_H
#ifdef LIBCO_C
#ifdef LIBCO_MP
#define thread_local __thread
#else
#define thread_local
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -1,37 +1,33 @@
/*
libco.ppc (2010-10-17)
libco.ppc (2016-09-14)
author: blargg
license: public domain
*/
/* PowerPC 32/64 using embedded or external asm, with optional
floating-point and AltiVec save/restore */
#define LIBCO_C
#include "libco.h"
#include "settings.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#define LIBCO_MPROTECT (__unix__ && !LIBCO_PPC_ASM)
#if LIBCO_MPROTECT
#include <unistd.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/mman.h>
#endif
/* State format (offsets in 32-bit words)
/* state format (offsets in 32-bit words)
+0 Pointer to swap code
Rest of function descriptor for entry function
+8 PC
+10 SP
Special regs
GPRs
FPRs
VRs
stack
+0 pointer to swap code
rest of function descriptor for entry function
+8 PC
+10 SP
special registers
GPRs
FPRs
VRs
stack
*/
enum { state_size = 1024 };
@ -40,369 +36,332 @@ enum { stack_align = 256 };
static thread_local cothread_t co_active_handle = 0;
/**** Determine environment ****/
/* determine environment */
#define LIBCO_PPC64 (_ARCH_PPC64 || __PPC64__ || __ppc64__ || __powerpc64__)
/* Whether function calls are indirect through a descriptor,
or are directly to function */
/* whether function calls are indirect through a descriptor, or are directly to function */
#ifndef LIBCO_PPCDESC
#if !_CALL_SYSV && (_CALL_AIX || _CALL_AIXDESC || LIBCO_PPC64)
#define LIBCO_PPCDESC 1
#endif
#if !_CALL_SYSV && (_CALL_AIX || _CALL_AIXDESC || LIBCO_PPC64)
#define LIBCO_PPCDESC 1
#endif
#endif
#ifdef LIBCO_PPC_ASM
#ifdef __cplusplus
extern "C"
#endif
/* Swap code is in ppc.S */
void co_swap_asm( cothread_t, cothread_t );
#define CO_SWAP_ASM( x, y ) co_swap_asm( x, y )
#ifdef LIBCO_MPROTECT
alignas(4096)
#else
/* Swap code is here in array. Please leave dieassembly comments,
as they make it easy to see what it does, and reorder instructions
if one wants to see whether that improves performance. */
static const uint32_t libco_ppc_code [] = {
#if LIBCO_PPC64
0x7d000026, /* mfcr r8 */
0xf8240028, /* std r1,40(r4) */
0x7d2802a6, /* mflr r9 */
0xf9c40048, /* std r14,72(r4) */
0xf9e40050, /* std r15,80(r4) */
0xfa040058, /* std r16,88(r4) */
0xfa240060, /* std r17,96(r4) */
0xfa440068, /* std r18,104(r4) */
0xfa640070, /* std r19,112(r4) */
0xfa840078, /* std r20,120(r4) */
0xfaa40080, /* std r21,128(r4) */
0xfac40088, /* std r22,136(r4) */
0xfae40090, /* std r23,144(r4) */
0xfb040098, /* std r24,152(r4) */
0xfb2400a0, /* std r25,160(r4) */
0xfb4400a8, /* std r26,168(r4) */
0xfb6400b0, /* std r27,176(r4) */
0xfb8400b8, /* std r28,184(r4) */
0xfba400c0, /* std r29,192(r4) */
0xfbc400c8, /* std r30,200(r4) */
0xfbe400d0, /* std r31,208(r4) */
0xf9240020, /* std r9,32(r4) */
0xe8e30020, /* ld r7,32(r3) */
0xe8230028, /* ld r1,40(r3) */
0x48000009, /* bl 1 */
0x7fe00008, /* trap */
0x91040030,/*1:stw r8,48(r4) */
0x80c30030, /* lwz r6,48(r3) */
0x7ce903a6, /* mtctr r7 */
0xe9c30048, /* ld r14,72(r3) */
0xe9e30050, /* ld r15,80(r3) */
0xea030058, /* ld r16,88(r3) */
0xea230060, /* ld r17,96(r3) */
0xea430068, /* ld r18,104(r3) */
0xea630070, /* ld r19,112(r3) */
0xea830078, /* ld r20,120(r3) */
0xeaa30080, /* ld r21,128(r3) */
0xeac30088, /* ld r22,136(r3) */
0xeae30090, /* ld r23,144(r3) */
0xeb030098, /* ld r24,152(r3) */
0xeb2300a0, /* ld r25,160(r3) */
0xeb4300a8, /* ld r26,168(r3) */
0xeb6300b0, /* ld r27,176(r3) */
0xeb8300b8, /* ld r28,184(r3) */
0xeba300c0, /* ld r29,192(r3) */
0xebc300c8, /* ld r30,200(r3) */
0xebe300d0, /* ld r31,208(r3) */
0x7ccff120, /* mtcr r6 */
#else
0x7d000026, /* mfcr r8 */
0x90240028, /* stw r1,40(r4) */
0x7d2802a6, /* mflr r9 */
0x91a4003c, /* stw r13,60(r4) */
0x91c40040, /* stw r14,64(r4) */
0x91e40044, /* stw r15,68(r4) */
0x92040048, /* stw r16,72(r4) */
0x9224004c, /* stw r17,76(r4) */
0x92440050, /* stw r18,80(r4) */
0x92640054, /* stw r19,84(r4) */
0x92840058, /* stw r20,88(r4) */
0x92a4005c, /* stw r21,92(r4) */
0x92c40060, /* stw r22,96(r4) */
0x92e40064, /* stw r23,100(r4) */
0x93040068, /* stw r24,104(r4) */
0x9324006c, /* stw r25,108(r4) */
0x93440070, /* stw r26,112(r4) */
0x93640074, /* stw r27,116(r4) */
0x93840078, /* stw r28,120(r4) */
0x93a4007c, /* stw r29,124(r4) */
0x93c40080, /* stw r30,128(r4) */
0x93e40084, /* stw r31,132(r4) */
0x91240020, /* stw r9,32(r4) */
0x80e30020, /* lwz r7,32(r3) */
0x80230028, /* lwz r1,40(r3) */
0x48000009, /* bl 1 */
0x7fe00008, /* trap */
0x91040030,/*1:stw r8,48(r4) */
0x80c30030, /* lwz r6,48(r3) */
0x7ce903a6, /* mtctr r7 */
0x81a3003c, /* lwz r13,60(r3) */
0x81c30040, /* lwz r14,64(r3) */
0x81e30044, /* lwz r15,68(r3) */
0x82030048, /* lwz r16,72(r3) */
0x8223004c, /* lwz r17,76(r3) */
0x82430050, /* lwz r18,80(r3) */
0x82630054, /* lwz r19,84(r3) */
0x82830058, /* lwz r20,88(r3) */
0x82a3005c, /* lwz r21,92(r3) */
0x82c30060, /* lwz r22,96(r3) */
0x82e30064, /* lwz r23,100(r3) */
0x83030068, /* lwz r24,104(r3) */
0x8323006c, /* lwz r25,108(r3) */
0x83430070, /* lwz r26,112(r3) */
0x83630074, /* lwz r27,116(r3) */
0x83830078, /* lwz r28,120(r3) */
0x83a3007c, /* lwz r29,124(r3) */
0x83c30080, /* lwz r30,128(r3) */
0x83e30084, /* lwz r31,132(r3) */
0x7ccff120, /* mtcr r6 */
section(text)
#endif
static const uint32_t libco_ppc_code[1024] = {
#if LIBCO_PPC64
0x7d000026, /* mfcr r8 */
0xf8240028, /* std r1,40(r4) */
0x7d2802a6, /* mflr r9 */
0xf9c40048, /* std r14,72(r4) */
0xf9e40050, /* std r15,80(r4) */
0xfa040058, /* std r16,88(r4) */
0xfa240060, /* std r17,96(r4) */
0xfa440068, /* std r18,104(r4) */
0xfa640070, /* std r19,112(r4) */
0xfa840078, /* std r20,120(r4) */
0xfaa40080, /* std r21,128(r4) */
0xfac40088, /* std r22,136(r4) */
0xfae40090, /* std r23,144(r4) */
0xfb040098, /* std r24,152(r4) */
0xfb2400a0, /* std r25,160(r4) */
0xfb4400a8, /* std r26,168(r4) */
0xfb6400b0, /* std r27,176(r4) */
0xfb8400b8, /* std r28,184(r4) */
0xfba400c0, /* std r29,192(r4) */
0xfbc400c8, /* std r30,200(r4) */
0xfbe400d0, /* std r31,208(r4) */
0xf9240020, /* std r9,32(r4) */
0xe8e30020, /* ld r7,32(r3) */
0xe8230028, /* ld r1,40(r3) */
0x48000009, /* bl 1 */
0x7fe00008, /* trap */
0x91040030, /*1:stw r8,48(r4) */
0x80c30030, /* lwz r6,48(r3) */
0x7ce903a6, /* mtctr r7 */
0xe9c30048, /* ld r14,72(r3) */
0xe9e30050, /* ld r15,80(r3) */
0xea030058, /* ld r16,88(r3) */
0xea230060, /* ld r17,96(r3) */
0xea430068, /* ld r18,104(r3) */
0xea630070, /* ld r19,112(r3) */
0xea830078, /* ld r20,120(r3) */
0xeaa30080, /* ld r21,128(r3) */
0xeac30088, /* ld r22,136(r3) */
0xeae30090, /* ld r23,144(r3) */
0xeb030098, /* ld r24,152(r3) */
0xeb2300a0, /* ld r25,160(r3) */
0xeb4300a8, /* ld r26,168(r3) */
0xeb6300b0, /* ld r27,176(r3) */
0xeb8300b8, /* ld r28,184(r3) */
0xeba300c0, /* ld r29,192(r3) */
0xebc300c8, /* ld r30,200(r3) */
0xebe300d0, /* ld r31,208(r3) */
0x7ccff120, /* mtcr r6 */
#else
0x7d000026, /* mfcr r8 */
0x90240028, /* stw r1,40(r4) */
0x7d2802a6, /* mflr r9 */
0x91a4003c, /* stw r13,60(r4) */
0x91c40040, /* stw r14,64(r4) */
0x91e40044, /* stw r15,68(r4) */
0x92040048, /* stw r16,72(r4) */
0x9224004c, /* stw r17,76(r4) */
0x92440050, /* stw r18,80(r4) */
0x92640054, /* stw r19,84(r4) */
0x92840058, /* stw r20,88(r4) */
0x92a4005c, /* stw r21,92(r4) */
0x92c40060, /* stw r22,96(r4) */
0x92e40064, /* stw r23,100(r4) */
0x93040068, /* stw r24,104(r4) */
0x9324006c, /* stw r25,108(r4) */
0x93440070, /* stw r26,112(r4) */
0x93640074, /* stw r27,116(r4) */
0x93840078, /* stw r28,120(r4) */
0x93a4007c, /* stw r29,124(r4) */
0x93c40080, /* stw r30,128(r4) */
0x93e40084, /* stw r31,132(r4) */
0x91240020, /* stw r9,32(r4) */
0x80e30020, /* lwz r7,32(r3) */
0x80230028, /* lwz r1,40(r3) */
0x48000009, /* bl 1 */
0x7fe00008, /* trap */
0x91040030, /*1:stw r8,48(r4) */
0x80c30030, /* lwz r6,48(r3) */
0x7ce903a6, /* mtctr r7 */
0x81a3003c, /* lwz r13,60(r3) */
0x81c30040, /* lwz r14,64(r3) */
0x81e30044, /* lwz r15,68(r3) */
0x82030048, /* lwz r16,72(r3) */
0x8223004c, /* lwz r17,76(r3) */
0x82430050, /* lwz r18,80(r3) */
0x82630054, /* lwz r19,84(r3) */
0x82830058, /* lwz r20,88(r3) */
0x82a3005c, /* lwz r21,92(r3) */
0x82c30060, /* lwz r22,96(r3) */
0x82e30064, /* lwz r23,100(r3) */
0x83030068, /* lwz r24,104(r3) */
0x8323006c, /* lwz r25,108(r3) */
0x83430070, /* lwz r26,112(r3) */
0x83630074, /* lwz r27,116(r3) */
0x83830078, /* lwz r28,120(r3) */
0x83a3007c, /* lwz r29,124(r3) */
0x83c30080, /* lwz r30,128(r3) */
0x83e30084, /* lwz r31,132(r3) */
0x7ccff120, /* mtcr r6 */
#endif
#ifndef LIBCO_PPC_NOFP
0xd9c400e0, /* stfd f14,224(r4) */
0xd9e400e8, /* stfd f15,232(r4) */
0xda0400f0, /* stfd f16,240(r4) */
0xda2400f8, /* stfd f17,248(r4) */
0xda440100, /* stfd f18,256(r4) */
0xda640108, /* stfd f19,264(r4) */
0xda840110, /* stfd f20,272(r4) */
0xdaa40118, /* stfd f21,280(r4) */
0xdac40120, /* stfd f22,288(r4) */
0xdae40128, /* stfd f23,296(r4) */
0xdb040130, /* stfd f24,304(r4) */
0xdb240138, /* stfd f25,312(r4) */
0xdb440140, /* stfd f26,320(r4) */
0xdb640148, /* stfd f27,328(r4) */
0xdb840150, /* stfd f28,336(r4) */
0xdba40158, /* stfd f29,344(r4) */
0xdbc40160, /* stfd f30,352(r4) */
0xdbe40168, /* stfd f31,360(r4) */
0xc9c300e0, /* lfd f14,224(r3) */
0xc9e300e8, /* lfd f15,232(r3) */
0xca0300f0, /* lfd f16,240(r3) */
0xca2300f8, /* lfd f17,248(r3) */
0xca430100, /* lfd f18,256(r3) */
0xca630108, /* lfd f19,264(r3) */
0xca830110, /* lfd f20,272(r3) */
0xcaa30118, /* lfd f21,280(r3) */
0xcac30120, /* lfd f22,288(r3) */
0xcae30128, /* lfd f23,296(r3) */
0xcb030130, /* lfd f24,304(r3) */
0xcb230138, /* lfd f25,312(r3) */
0xcb430140, /* lfd f26,320(r3) */
0xcb630148, /* lfd f27,328(r3) */
0xcb830150, /* lfd f28,336(r3) */
0xcba30158, /* lfd f29,344(r3) */
0xcbc30160, /* lfd f30,352(r3) */
0xcbe30168, /* lfd f31,360(r3) */
#endif
#ifndef LIBCO_PPC_NOFP
0xd9c400e0, /* stfd f14,224(r4) */
0xd9e400e8, /* stfd f15,232(r4) */
0xda0400f0, /* stfd f16,240(r4) */
0xda2400f8, /* stfd f17,248(r4) */
0xda440100, /* stfd f18,256(r4) */
0xda640108, /* stfd f19,264(r4) */
0xda840110, /* stfd f20,272(r4) */
0xdaa40118, /* stfd f21,280(r4) */
0xdac40120, /* stfd f22,288(r4) */
0xdae40128, /* stfd f23,296(r4) */
0xdb040130, /* stfd f24,304(r4) */
0xdb240138, /* stfd f25,312(r4) */
0xdb440140, /* stfd f26,320(r4) */
0xdb640148, /* stfd f27,328(r4) */
0xdb840150, /* stfd f28,336(r4) */
0xdba40158, /* stfd f29,344(r4) */
0xdbc40160, /* stfd f30,352(r4) */
0xdbe40168, /* stfd f31,360(r4) */
0xc9c300e0, /* lfd f14,224(r3) */
0xc9e300e8, /* lfd f15,232(r3) */
0xca0300f0, /* lfd f16,240(r3) */
0xca2300f8, /* lfd f17,248(r3) */
0xca430100, /* lfd f18,256(r3) */
0xca630108, /* lfd f19,264(r3) */
0xca830110, /* lfd f20,272(r3) */
0xcaa30118, /* lfd f21,280(r3) */
0xcac30120, /* lfd f22,288(r3) */
0xcae30128, /* lfd f23,296(r3) */
0xcb030130, /* lfd f24,304(r3) */
0xcb230138, /* lfd f25,312(r3) */
0xcb430140, /* lfd f26,320(r3) */
0xcb630148, /* lfd f27,328(r3) */
0xcb830150, /* lfd f28,336(r3) */
0xcba30158, /* lfd f29,344(r3) */
0xcbc30160, /* lfd f30,352(r3) */
0xcbe30168, /* lfd f31,360(r3) */
#endif
#ifdef __ALTIVEC__
0x7ca042a6, /* mfvrsave r5 */
0x39040180, /* addi r8,r4,384 */
0x39240190, /* addi r9,r4,400 */
0x70a00fff, /* andi. r0,r5,4095 */
0x90a40034, /* stw r5,52(r4) */
0x4182005c, /* beq- 2 */
0x7e8041ce, /* stvx v20,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7ea049ce, /* stvx v21,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7ec041ce, /* stvx v22,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7ee049ce, /* stvx v23,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f0041ce, /* stvx v24,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7f2049ce, /* stvx v25,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f4041ce, /* stvx v26,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7f6049ce, /* stvx v27,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f8041ce, /* stvx v28,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7fa049ce, /* stvx v29,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7fc041ce, /* stvx v30,r0,r8 */
0x7fe049ce, /* stvx v31,r0,r9 */
0x80a30034,/*2:lwz r5,52(r3) */
0x39030180, /* addi r8,r3,384 */
0x39230190, /* addi r9,r3,400 */
0x70a00fff, /* andi. r0,r5,4095 */
0x7ca043a6, /* mtvrsave r5 */
0x4d820420, /* beqctr */
0x7e8040ce, /* lvx v20,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7ea048ce, /* lvx v21,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7ec040ce, /* lvx v22,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7ee048ce, /* lvx v23,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f0040ce, /* lvx v24,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7f2048ce, /* lvx v25,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f4040ce, /* lvx v26,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7f6048ce, /* lvx v27,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f8040ce, /* lvx v28,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7fa048ce, /* lvx v29,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7fc040ce, /* lvx v30,r0,r8 */
0x7fe048ce, /* lvx v31,r0,r9 */
#endif
#ifdef __ALTIVEC__
0x7ca042a6, /* mfvrsave r5 */
0x39040180, /* addi r8,r4,384 */
0x39240190, /* addi r9,r4,400 */
0x70a00fff, /* andi. r0,r5,4095 */
0x90a40034, /* stw r5,52(r4) */
0x4182005c, /* beq- 2 */
0x7e8041ce, /* stvx v20,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7ea049ce, /* stvx v21,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7ec041ce, /* stvx v22,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7ee049ce, /* stvx v23,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f0041ce, /* stvx v24,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7f2049ce, /* stvx v25,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f4041ce, /* stvx v26,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7f6049ce, /* stvx v27,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f8041ce, /* stvx v28,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7fa049ce, /* stvx v29,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7fc041ce, /* stvx v30,r0,r8 */
0x7fe049ce, /* stvx v31,r0,r9 */
0x80a30034, /*2:lwz r5,52(r3) */
0x39030180, /* addi r8,r3,384 */
0x39230190, /* addi r9,r3,400 */
0x70a00fff, /* andi. r0,r5,4095 */
0x7ca043a6, /* mtvrsave r5 */
0x4d820420, /* beqctr */
0x7e8040ce, /* lvx v20,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7ea048ce, /* lvx v21,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7ec040ce, /* lvx v22,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7ee048ce, /* lvx v23,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f0040ce, /* lvx v24,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7f2048ce, /* lvx v25,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f4040ce, /* lvx v26,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7f6048ce, /* lvx v27,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f8040ce, /* lvx v28,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7fa048ce, /* lvx v29,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7fc040ce, /* lvx v30,r0,r8 */
0x7fe048ce, /* lvx v31,r0,r9 */
#endif
0x4e800420, /* bctr */
0x4e800420, /* bctr */
};
#if LIBCO_PPCDESC
/* Function call goes through indirect descriptor */
#define CO_SWAP_ASM( x, y ) \
((void (*)( cothread_t, cothread_t )) (uintptr_t) x)( x, y )
#else
/* Function call goes directly to code */
#define CO_SWAP_ASM( x, y ) \
((void (*)( cothread_t, cothread_t )) (uintptr_t) libco_ppc_code)( x, y )
#endif
#if LIBCO_PPCDESC
/* function call goes through indirect descriptor */
#define CO_SWAP_ASM(x, y) ((void (*)(cothread_t, cothread_t))(uintptr_t)x)(x, y)
#else
/* function call goes directly to code */
#define CO_SWAP_ASM(x, y) ((void (*)(cothread_t, cothread_t))(uintptr_t)libco_ppc_code)(x, y)
#endif
static uint32_t* co_create_( unsigned size, uintptr_t entry )
{
uint32_t* t = (uint32_t*) malloc( size );
(void) entry;
#if LIBCO_PPCDESC
if ( t )
{
/* Copy entry's descriptor */
memcpy( t, (void*) entry, sizeof (void*) * 3 );
/* Set function pointer to swap routine */
#ifdef LIBCO_PPC_ASM
*(const void**) t = *(void**) &co_swap_asm;
#else
*(const void**) t = libco_ppc_code;
#endif
}
#endif
return t;
static uint32_t* co_create_(unsigned size, uintptr_t entry) {
(void)entry;
uint32_t* t = (uint32_t*)malloc(size);
#if LIBCO_PPCDESC
if(t) {
memcpy(t, (void*)entry, sizeof(void*) * 3); /* copy entry's descriptor */
*(const void**)t = libco_ppc_code; /* set function pointer to swap routine */
}
#endif
return t;
}
cothread_t co_create( unsigned int size, void (*entry_)( void ) )
{
uintptr_t entry = (uintptr_t) entry_;
uint32_t* t = NULL;
/* Be sure main thread was successfully allocated */
if ( co_active() )
{
size += state_size + above_stack + stack_align;
t = co_create_( size, entry );
}
if ( t )
{
uintptr_t sp;
int shift;
/* Save current registers into new thread, so that any special ones will
have proper values when thread is begun */
CO_SWAP_ASM( t, t );
#if LIBCO_PPCDESC
/* Get real address */
entry = (uintptr_t) *(void**) entry;
#endif
/* Put stack near end of block, and align */
sp = (uintptr_t) t + size - above_stack;
sp -= sp % stack_align;
/* On PPC32, we save and restore GPRs as 32 bits. For PPC64, we
save and restore them as 64 bits, regardless of the size the ABI
uses. So, we manually write pointers at the proper size. We always
save and restore at the same address, and since PPC is big-endian,
we must put the low byte first on PPC32. */
/* If uintptr_t is 32 bits, >>32 is undefined behavior, so we do two shifts
and don't have to care how many bits uintptr_t is. */
#if LIBCO_PPC64
shift = 16;
#else
shift = 0;
#endif
/* Set up so entry will be called on next swap */
t [8] = (uint32_t) (entry >> shift >> shift);
t [9] = (uint32_t) entry;
t [10] = (uint32_t) (sp >> shift >> shift);
t [11] = (uint32_t) sp;
}
return t;
cothread_t co_create(unsigned int size, void (*entry_)(void)) {
uintptr_t entry = (uintptr_t)entry_;
uint32_t* t = 0;
/* be sure main thread was successfully allocated */
if(co_active()) {
size += state_size + above_stack + stack_align;
t = co_create_(size, entry);
}
if(t) {
uintptr_t sp;
int shift;
/* save current registers into new thread, so that any special ones will have proper values when thread is begun */
CO_SWAP_ASM(t, t);
#if LIBCO_PPCDESC
entry = (uintptr_t)*(void**)entry; /* get real address */
#endif
/* put stack near end of block, and align */
sp = (uintptr_t)t + size - above_stack;
sp -= sp % stack_align;
/* on PPC32, we save and restore GPRs as 32 bits. for PPC64, we
save and restore them as 64 bits, regardless of the size the ABI
uses. so, we manually write pointers at the proper size. we always
save and restore at the same address, and since PPC is big-endian,
we must put the low byte first on PPC32. */
/* if uintptr_t is 32 bits, >>32 is undefined behavior,
so we do two shifts and don't have to care how many bits uintptr_t is. */
#if LIBCO_PPC64
shift = 16;
#else
shift = 0;
#endif
/* set up so entry will be called on next swap */
t[ 8] = (uint32_t)(entry >> shift >> shift);
t[ 9] = (uint32_t)entry;
t[10] = (uint32_t)(sp >> shift >> shift);
t[11] = (uint32_t)sp;
}
return t;
}
void co_delete( cothread_t t )
{
free( t );
void co_delete(cothread_t t) {
free(t);
}
static void co_init_( void )
{
#if LIBCO_MPROTECT
/* TODO: pre- and post-pad PPC code so that this doesn't make other
data executable and writable */
long page_size = sysconf( _SC_PAGESIZE );
if ( page_size > 0 )
{
uintptr_t align = page_size;
uintptr_t begin = (uintptr_t) libco_ppc_code;
uintptr_t end = begin + sizeof libco_ppc_code;
/* Align beginning and end */
end += align - 1;
end -= end % align;
begin -= begin % align;
mprotect( (void*) begin, end - begin, PROT_READ | PROT_WRITE | PROT_EXEC );
}
#endif
co_active_handle = co_create_( state_size, (uintptr_t) &co_switch );
static void co_init_(void) {
#if LIBCO_MPROTECT
long page_size = sysconf(_SC_PAGESIZE);
if(page_size > 0) {
uintptr_t align = page_size;
uintptr_t begin = (uintptr_t)libco_ppc_code;
uintptr_t end = begin + sizeof libco_ppc_code;
/* align beginning and end */
end += align - 1;
end -= end % align;
begin -= begin % align;
mprotect((void*)begin, end - begin, PROT_READ | PROT_EXEC);
}
#endif
co_active_handle = co_create_(state_size, (uintptr_t)&co_switch);
}
cothread_t co_active()
{
if ( !co_active_handle )
co_init_();
return co_active_handle;
cothread_t co_active() {
if(!co_active_handle) co_init_();
return co_active_handle;
}
void co_switch( cothread_t t )
{
cothread_t old = co_active_handle;
co_active_handle = t;
CO_SWAP_ASM( t, old );
void co_switch(cothread_t t) {
cothread_t old = co_active_handle;
co_active_handle = t;
CO_SWAP_ASM(t, old);
}

36
libco/settings.h Normal file
View File

@ -0,0 +1,36 @@
#ifdef LIBCO_C
/*[amd64, arm, ppc, x86]:
by default, co_swap_function is marked as a text (code) section
if not supported, uncomment the below line to use mprotect instead */
/* #define LIBCO_MPROTECT */
/*[amd64]:
Win64 only: provides a substantial speed-up, but will thrash XMM regs
do not use this unless you are certain your application won't use SSE */
/* #define LIBCO_NO_SSE */
#ifdef LIBCO_C
#ifdef LIBCO_MP
#define thread_local __thread
#else
#define thread_local
#endif
#endif
#if __STDC_VERSION__ >= 201112L
#ifndef _MSC_VER
#include <stdalign.h>
#endif
#else
#define alignas(bytes)
#endif
#ifndef _MSC_VER
#define section(name) __attribute__((section("." #name "#")))
#else
#define section(name) __declspec(allocate("." #name))
#endif
/* ifdef LIBCO_C */
#endif

View File

@ -5,11 +5,9 @@
*/
/*
* Note this was designed for UNIX systems. Based on ideas expressed in a paper
* by Ralf Engelschall.
* For SJLJ on other systems, one would want to rewrite springboard() and
* co_create() and hack the jmb_buf stack pointer.
*/
note this was designed for UNIX systems. Based on ideas expressed in a paper by Ralf Engelschall.
for SJLJ on other systems, one would want to rewrite springboard() and co_create() and hack the jmb_buf stack pointer.
*/
#define LIBCO_C
#include "libco.h"
@ -25,11 +23,12 @@ extern "C" {
typedef struct {
sigjmp_buf context;
void (*coentry)(void);
void *stack;
void* stack;
} cothread_struct;
static thread_local cothread_struct co_primary;
static thread_local cothread_struct *creating, *co_running = 0;
static thread_local cothread_struct* creating;
static thread_local cothread_struct* co_running = 0;
static void springboard(int ignored) {
if(sigsetjmp(creating->context, 0)) {

View File

@ -5,16 +5,16 @@
*/
/*
* WARNING: the overhead of POSIX ucontext is very high,
* assembly versions of libco or libco_sjlj should be much faster
*
* This library only exists for two reasons:
* 1 - as an initial test for the viability of a ucontext implementation
* 2 - to demonstrate the power and speed of libco over existing implementations,
* such as pth (which defaults to wrapping ucontext on unix targets)
*
* Use this library only as a *last resort*
*/
WARNING: the overhead of POSIX ucontext is very high,
assembly versions of libco or libco_sjlj should be much faster
this library only exists for two reasons:
1: as an initial test for the viability of a ucontext implementation
2: to demonstrate the power and speed of libco over existing implementations,
such as pth (which defaults to wrapping ucontext on unix targets)
use this library only as a *last resort*
*/
#define LIBCO_C
#include "libco.h"
@ -28,7 +28,7 @@ extern "C" {
#endif
static thread_local ucontext_t co_primary;
static thread_local ucontext_t *co_running = 0;
static thread_local ucontext_t* co_running = 0;
cothread_t co_active() {
if(!co_running) co_running = &co_primary;
@ -37,7 +37,7 @@ cothread_t co_active() {
cothread_t co_create(unsigned int heapsize, void (*coentry)(void)) {
if(!co_running) co_running = &co_primary;
ucontext_t *thread = (ucontext_t*)malloc(sizeof(ucontext_t));
ucontext_t* thread = (ucontext_t*)malloc(sizeof(ucontext_t));
if(thread) {
if((!getcontext(thread) && !(thread->uc_stack.ss_sp = 0)) && (thread->uc_stack.ss_sp = malloc(heapsize))) {
thread->uc_link = co_running;
@ -59,7 +59,7 @@ void co_delete(cothread_t cothread) {
}
void co_switch(cothread_t cothread) {
ucontext_t *old_thread = co_running;
ucontext_t* old_thread = co_running;
co_running = (ucontext_t*)cothread;
swapcontext(old_thread, co_running);
}

View File

@ -1,11 +1,12 @@
/*
libco.x86 (2009-10-12)
libco.x86 (2016-09-14)
author: byuu
license: public domain
*/
#define LIBCO_C
#include "libco.h"
#include "settings.h"
#include <assert.h>
#include <stdlib.h>
@ -26,8 +27,13 @@ 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;
#ifdef LIBCO_MPROTECT
alignas(4096)
#else
section(text)
#endif
/* ABI: fastcall */
static unsigned char co_swap_function[] = {
static const unsigned char co_swap_function[4096] = {
0x89, 0x22, /* mov [edx],esp */
0x8b, 0x21, /* mov esp,[ecx] */
0x58, /* pop eax */
@ -45,19 +51,23 @@ static unsigned char co_swap_function[] = {
#ifdef _WIN32
#include <windows.h>
void co_init() {
static void co_init() {
#ifdef LIBCO_MPROTECT
DWORD old_privileges;
VirtualProtect(co_swap_function, sizeof co_swap_function, PAGE_EXECUTE_READWRITE, &old_privileges);
VirtualProtect((void*)co_swap_function, sizeof co_swap_function, PAGE_EXECUTE_READ, &old_privileges);
#endif
}
#else
#include <unistd.h>
#include <sys/mman.h>
void co_init() {
static void co_init() {
#ifdef LIBCO_MPROTECT
unsigned long addr = (unsigned long)co_swap_function;
unsigned long base = addr - (addr % sysconf(_SC_PAGESIZE));
unsigned long size = (addr - base) + sizeof co_swap_function;
mprotect((void*)base, size, PROT_READ | PROT_WRITE | PROT_EXEC);
mprotect((void*)base, size, PROT_READ | PROT_EXEC);
#endif
}
#endif

View File

@ -36,8 +36,8 @@ ifeq ($(platform),)
endif
endif
cflags := -x c -std=c99
objcflags := -x objective-c -std=c99
cflags := -x c -std=c11
objcflags := -x objective-c -std=c11
cppflags := -x c++ -std=c++14
objcppflags := -x objective-c++ -std=c++14
flags :=
@ -61,10 +61,10 @@ endif
# clang settings
ifeq ($(findstring clang++,$(compiler)),clang++)
flags += -fwrapv
flags += -fno-strict-aliasing -fwrapv
# gcc settings
else ifeq ($(findstring g++,$(compiler)),g++)
flags += -fwrapv
flags += -fno-strict-aliasing -fwrapv
endif
# windows settings

View File

@ -1,12 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIByDCCAU6gAwIBAgIJAI83xahWv0iSMAoGCCqGSM49BAMDMB4xDTALBgNVBAMM
BGJ5dXUxDTALBgNVBAoMBGJ5dXUwIBcNMTYwODMxMDQ1MjEzWhgPMjA5MTA4MTMw
NDUyMTNaMB4xDTALBgNVBAMMBGJ5dXUxDTALBgNVBAoMBGJ5dXUwdjAQBgcqhkjO
PQIBBgUrgQQAIgNiAAT5ArnlLKmJZrkmDwBNroM+djFS1CM/KLVXGZQUmkjyDJSB
/JeC/aT3v4g236kzcHu4+FBDPT1MhPUmtFC+mGjnWjtQsGHuTknGYXpjOEK77PXy
LL2m9gXB0eKE0SkMIdijVjBUMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYE
FErJPHQ5yHMo18r8c0LI4XmrKjnRMB8GA1UdIwQYMBaAFErJPHQ5yHMo18r8c0LI
4XmrKjnRMAoGCCqGSM49BAMDA2gAMGUCMQDAcBz38wdb5lJmcMf8Y1eqPZxXkgCt
OZklW1cXZnoB2w3yjdImujHVyEfhK684HCkCMEjsxEUPRf8tB0UKO836qKmAKFHW
OYBX8Sx6jlzonkb1miqjxiNQdTmGdkWk1IsP8Q==
MIIByTCCAU6gAwIBAgIJAMGBxB7ujnmaMAoGCCqGSM49BAMDMB4xDTALBgNVBAMM
BGJ5dXUxDTALBgNVBAoMBGJ5dXUwIBcNMTYwOTExMTM1MjE3WhgPMjA5MTA4MjQx
MzUyMTdaMB4xDTALBgNVBAMMBGJ5dXUxDTALBgNVBAoMBGJ5dXUwdjAQBgcqhkjO
PQIBBgUrgQQAIgNiAATgdIzJOkXMo3vfw+wshinYYt76IAox5sRcXYfbkTHZ5dGU
Sf/DlrCe/kTIhXe6mKUI6eUjPH7U5UruvHtwi6I7QILHoar1tp4rVGKp7mB3KuIS
qfuu90JhXMfUcwQp3WOjVjBUMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYE
FKD7mEF6/bmtxOUSu05E0iYjRCrJMB8GA1UdIwQYMBaAFKD7mEF6/bmtxOUSu05E
0iYjRCrJMAoGCCqGSM49BAMDA2kAMGYCMQD3Nv8o4qbHOZUd8GUh4ye6Y08WkJ2w
8BZWTJFzAp+4nP9XZJeROQJd97+kQOCdLAICMQC2DtybVIQXaxefAaGi7IvtYcbL
fAWdtu5/dc7bzMpy9GicQkpw8uluxauX8gdnU/4=
-----END CERTIFICATE-----

View File

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB6jCCAXCgAwIBAgIJAOrEeJHQ9mppMAoGCCqGSM49BAMDMB4xDTALBgNVBAMM
BGJ5dXUxDTALBgNVBAoMBGJ5dXUwIBcNMTYwOTExMTM1NDIwWhgPMjA5MTA4MjQx
MzU0MjBaMCIxETAPBgNVBAMMCGJ5dXUubmV0MQ0wCwYDVQQKDARieXV1MHYwEAYH
KoZIzj0CAQYFK4EEACIDYgAEL4l9yJtcslBRuaTr7wHJ/Wc7DIspKGv2S2+LYsxE
k3dZI902+J726IX2yiurWlLUEc3B+ooKs3VmhaW1QsStKdYVJVVGBD29zz3rvD/V
oeWjw63yZrSqNQ5S41qXNcMho3QwcjAMBgNVHRMBAf8EAjAAMCIGA1UdEQEB/wQY
MBaCCGJ5dXUubmV0ggoqLmJ5dXUubmV0MB0GA1UdDgQWBBTeXV7JKLjCikQbk+Um
ayFF8yRiSTAfBgNVHSMEGDAWgBSg+5hBev25rcTlErtORNImI0QqyTAKBggqhkjO
PQQDAwNoADBlAjEAgk0ud6h0OAfWNH6pSvMiyHAWQuh24cvkQY3mUNsZzAy36QEQ
X4UBWewxz1lyaFzLAjACXJZ1rZsMnGIgWXvFAsO2v53A612Ba3vH76naExASKbmx
VafrFb6bHXEc3aH/Xws=
-----END CERTIFICATE-----

View File

@ -1,13 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB6zCCAXCgAwIBAgIJAPQ6cLpDt9l8MAoGCCqGSM49BAMDMB4xDTALBgNVBAMM
BGJ5dXUxDTALBgNVBAoMBGJ5dXUwIBcNMTYwODMxMDQ1MzQyWhgPMjA5MTA4MTMw
NDUzNDJaMCIxETAPBgNVBAMMCGJ5dXUub3JnMQ0wCwYDVQQKDARieXV1MHYwEAYH
KoZIzj0CAQYFK4EEACIDYgAEuYjwx8y8nO9yAR7Hb8AB8lB1SSXk1lBm9ofcEzkN
SLOvrC+ESHR1C+w9krlbJlSq2wPA482DIW3aLukfNIdwhuTciVFBZfk0bgRgVqXq
Ha+iyL64/naqzWGxk5m/HDkFo3QwcjAMBgNVHRMBAf8EAjAAMCIGA1UdEQEB/wQY
MBaCCGJ5dXUub3JnggoqLmJ5dXUub3JnMB0GA1UdDgQWBBSJd/vrUirTNFcxur/9
hN+Q55H+AzAfBgNVHSMEGDAWgBRKyTx0OchzKNfK/HNCyOF5qyo50TAKBggqhkjO
PQQDAwNpADBmAjEAh5Jc3nepWmrRJDLaGzy7ews23uEcrz3PfBbtJrTC3qw5b2Ig
fqZ6h5/nG7BXAeq9AjEAnxwn221GihthlL6nzSS5SRyjmR6crGfqWcQwSQTp8b+8
DqXqRKiYVHoiedKJslCF
MIIB6jCCAXCgAwIBAgIJAOrEeJHQ9mpoMAoGCCqGSM49BAMDMB4xDTALBgNVBAMM
BGJ5dXUxDTALBgNVBAoMBGJ5dXUwIBcNMTYwOTExMTM1MzU1WhgPMjA5MTA4MjQx
MzUzNTVaMCIxETAPBgNVBAMMCGJ5dXUub3JnMQ0wCwYDVQQKDARieXV1MHYwEAYH
KoZIzj0CAQYFK4EEACIDYgAEH+ny1an5De9P1TJ0vmpGlpmrZszuV1lKTPut28Vx
98ieuBdmSNG493sJ+ga+adXPtItkck5M0jITR1NxcWvVlZtJG8L6ctEuVF6smkoy
1dbxzEeTIs+xjRQqaLN4U67ho3QwcjAMBgNVHRMBAf8EAjAAMCIGA1UdEQEB/wQY
MBaCCGJ5dXUub3JnggoqLmJ5dXUub3JnMB0GA1UdDgQWBBRhhKSsc+qUaBUNiyJX
j17UDBFuuTAfBgNVHSMEGDAWgBSg+5hBev25rcTlErtORNImI0QqyTAKBggqhkjO
PQQDAwNoADBlAjEApEbI/wT/cU7DRFvBEmfFMtVDJCJCTz4UEo1lJI9SPOEtgX3x
gJZg4deqeoAEffVGAjB2RWI1UPi/jnpJwTsuw4sp5UqFhY48qfqddPiSO4qlmb8s
1aEdP6gHoji22pHrKbY=
-----END CERTIFICATE-----

View File

@ -4,6 +4,18 @@
#include <nall/serial.hpp>
using namespace nall;
using int8 = Integer< 8>;
using int16 = Integer<16>;
using int24 = Integer<24>;
using int32 = Integer<32>;
using int64 = Integer<64>;
using uint8 = Natural< 8>;
using uint16 = Natural<16>;
using uint24 = Natural<24>;
using uint32 = Natural<32>;
using uint64 = Natural<64>;
struct FX {
auto open(string_vector& args) -> bool;
auto close() -> void;

View File

@ -5,18 +5,18 @@
namespace nall { namespace HTTP {
struct Client : Role {
inline auto open(const string& hostname, unsigned port = 80) -> bool;
inline auto open(const string& hostname, uint port = 80) -> bool;
inline auto upload(const Request& request) -> bool;
inline auto download(const Request& request) -> Response;
inline auto close() -> void;
~Client() { close(); }
private:
signed fd = -1;
int fd = -1;
addrinfo* info = nullptr;
};
auto Client::open(const string& hostname, unsigned port) -> bool {
auto Client::open(const string& hostname, uint port) -> bool {
addrinfo hint = {0};
hint.ai_family = AF_UNSPEC;
hint.ai_socktype = SOCK_STREAM;

View File

@ -83,10 +83,10 @@ struct Variables {
struct Message {
using type = Message;
virtual auto head(const function<bool (const uint8_t* data, unsigned size)>& callback) const -> bool = 0;
virtual auto head(const function<bool (const uint8_t* data, uint size)>& callback) const -> bool = 0;
virtual auto setHead() -> bool = 0;
virtual auto body(const function<bool (const uint8_t* data, unsigned size)>& callback) const -> bool = 0;
virtual auto body(const function<bool (const uint8_t* data, uint size)>& callback) const -> bool = 0;
virtual auto setBody() -> bool = 0;
Variables header;

View File

@ -9,14 +9,14 @@ namespace nall { namespace HTTP {
struct Request : Message {
using type = Request;
enum class RequestType : unsigned { None, Head, Get, Post };
enum class RequestType : uint { None, Head, Get, Post };
explicit operator bool() const { return requestType() != RequestType::None; }
inline auto head(const function<bool (const uint8_t* data, unsigned size)>& callback) const -> bool override;
inline auto head(const function<bool (const uint8_t* data, uint size)>& callback) const -> bool override;
inline auto setHead() -> bool override;
inline auto body(const function<bool (const uint8_t* data, unsigned size)>& callback) const -> bool override;
inline auto body(const function<bool (const uint8_t* data, uint size)>& callback) const -> bool override;
inline auto setBody() -> bool override;
auto ipv4() const -> bool { return _ipv6 == false; }
@ -40,7 +40,7 @@ struct Request : Message {
string _path;
};
auto Request::head(const function<bool (const uint8_t*, unsigned)>& callback) const -> bool {
auto Request::head(const function<bool (const uint8_t*, uint)>& callback) const -> bool {
if(!callback) return false;
string output;
@ -122,7 +122,7 @@ auto Request::setHead() -> bool {
return true;
}
auto Request::body(const function<bool (const uint8_t*, unsigned)>& callback) const -> bool {
auto Request::body(const function<bool (const uint8_t*, uint)>& callback) const -> bool {
if(!callback) return false;
if(_body) {

View File

@ -11,19 +11,19 @@ struct Response : Message {
Response(const Request& request) { setRequest(request); }
explicit operator bool() const { return responseType() != 0; }
auto operator()(unsigned responseType) -> type& { return setResponseType(responseType); }
auto operator()(uint responseType) -> type& { return setResponseType(responseType); }
inline auto head(const function<bool (const uint8_t* data, unsigned size)>& callback) const -> bool override;
inline auto head(const function<bool (const uint8_t* data, uint size)>& callback) const -> bool override;
inline auto setHead() -> bool override;
inline auto body(const function<bool (const uint8_t* data, unsigned size)>& callback) const -> bool override;
inline auto body(const function<bool (const uint8_t* data, uint size)>& callback) const -> bool override;
inline auto setBody() -> bool override;
auto request() const -> const Request* { return _request; }
auto setRequest(const Request& value) -> type& { _request = &value; return *this; }
auto responseType() const -> unsigned { return _responseType; }
auto setResponseType(unsigned value) -> type& { _responseType = value; return *this; }
auto responseType() const -> uint { return _responseType; }
auto setResponseType(uint value) -> type& { _responseType = value; return *this; }
auto hasData() const -> bool { return (bool)_data; }
auto data() const -> const vector<uint8_t>& { return _data; }
@ -38,20 +38,20 @@ struct Response : Message {
inline auto setText(const string& value) -> type&;
inline auto hasBody() const -> bool;
inline auto findContentLength() const -> unsigned;
inline auto findContentLength() const -> uint;
inline auto findContentType() const -> string;
inline auto findContentType(const string& suffix) const -> string;
inline auto findResponseType() const -> string;
inline auto setFileETag() -> void;
const Request* _request = nullptr;
unsigned _responseType = 0;
uint _responseType = 0;
vector<uint8_t> _data;
string _file;
string _text;
};
auto Response::head(const function<bool (const uint8_t*, unsigned)>& callback) const -> bool {
auto Response::head(const function<bool (const uint8_t*, uint)>& callback) const -> bool {
if(!callback) return false;
string output;
@ -106,7 +106,7 @@ auto Response::setHead() -> bool {
return true;
}
auto Response::body(const function<bool (const uint8_t*, unsigned)>& callback) const -> bool {
auto Response::body(const function<bool (const uint8_t*, uint)>& callback) const -> bool {
if(!callback) return false;
if(!hasBody()) return true;
bool chunked = header["Transfer-Encoding"].value() == "chunked";
@ -154,7 +154,7 @@ auto Response::hasBody() const -> bool {
return true;
}
auto Response::findContentLength() const -> unsigned {
auto Response::findContentLength() const -> uint {
if(auto contentLength = header["Content-Length"]) return contentLength.value().natural();
if(_body) return _body.size();
if(hasData()) return data().size();
@ -229,6 +229,17 @@ auto Response::setData(const vector<uint8_t>& value) -> type& {
}
auto Response::setFile(const string& value) -> type& {
//block path escalation exploits ("../" and "..\" in the file location)
bool valid = true;
for(uint n : range(value.size())) {
if(value(n + 0, '\0') != '.') continue;
if(value(n + 1, '\0') != '.') continue;
if(value(n + 2, '\0') != '/' && value(n + 2, '\0') != '\\') continue;
valid = false;
break;
}
if(!valid) return *this;
_file = value;
string eTag = {"\"", chrono::utc::datetime(file::timestamp(value, file::time::modify)), "\""};
header.assign("Content-Length", file::size(value));

View File

@ -10,18 +10,18 @@ namespace nall { namespace HTTP {
struct Role {
struct Settings {
signed connectionLimit = 1 * 1024; //server
signed headSizeLimit = 16 * 1024; //client, server
signed bodySizeLimit = 8192 * 1024; //client, server
signed chunkSize = 32 * 1024; //client, server
signed threadStackSize = 128 * 1024; //server
signed timeoutReceive = 15 * 1000; //server
signed timeoutSend = 15 * 1000; //server
int connectionLimit = 1 * 1024; //server
int headSizeLimit = 16 * 1024; //client, server
int bodySizeLimit = 8192 * 1024; //client, server
int chunkSize = 32 * 1024; //client, server
int threadStackSize = 128 * 1024; //server
int timeoutReceive = 15 * 1000; //server
int timeoutSend = 15 * 1000; //server
} settings;
inline auto configure(const string& parameters) -> bool;
inline auto download(signed fd, Message& message) -> bool;
inline auto upload(signed fd, const Message& message) -> bool;
inline auto download(int fd, Message& message) -> bool;
inline auto upload(int fd, const Message& message) -> bool;
};
auto Role::configure(const string& parameters) -> bool {
@ -42,7 +42,7 @@ auto Role::configure(const string& parameters) -> bool {
return true;
}
auto Role::download(signed fd, Message& message) -> bool {
auto Role::download(int fd, Message& message) -> bool {
auto& head = message._head;
auto& body = message._body;
string chunk;
@ -55,9 +55,9 @@ auto Role::download(signed fd, Message& message) -> bool {
bool chunked = false;
bool chunkReceived = false;
bool chunkFooterReceived = true;
signed length = 0;
signed chunkLength = 0;
signed contentLength = 0;
int length = 0;
int chunkLength = 0;
int contentLength = 0;
while(true) {
if(auto limit = settings.headSizeLimit) if(head.size() >= limit) return false;
@ -116,7 +116,7 @@ auto Role::download(signed fd, Message& message) -> bool {
p += length;
length = 0;
} else {
signed transferLength = min(length, chunkLength);
int transferLength = min(length, chunkLength);
body.resize(body.size() + transferLength);
memory::copy(body.get() + body.size() - transferLength, p, transferLength);
@ -135,10 +135,10 @@ auto Role::download(signed fd, Message& message) -> bool {
return true;
}
auto Role::upload(signed fd, const Message& message) -> bool {
auto transfer = [&](const uint8_t* data, unsigned size) -> bool {
auto Role::upload(int fd, const Message& message) -> bool {
auto transfer = [&](const uint8_t* data, uint size) -> bool {
while(size) {
signed length = send(fd, data, min(size, settings.chunkSize), MSG_NOSIGNAL);
int length = send(fd, data, min(size, settings.chunkSize), MSG_NOSIGNAL);
if(length < 0) return false;
data += length;
size -= length;
@ -146,8 +146,8 @@ auto Role::upload(signed fd, const Message& message) -> bool {
return true;
};
if(message.head([&](const uint8_t* data, unsigned size) -> bool { return transfer(data, size); })) {
if(message.body([&](const uint8_t* data, unsigned size) -> bool { return transfer(data, size); })) {
if(message.head([&](const uint8_t* data, uint size) -> bool { return transfer(data, size); })) {
if(message.body([&](const uint8_t* data, uint size) -> bool { return transfer(data, size); })) {
return true;
}
}

View File

@ -6,7 +6,7 @@
namespace nall { namespace HTTP {
struct Server : Role, service {
inline auto open(unsigned port = 8080, const string& serviceName = "", const string& command = "") -> bool;
inline auto open(uint port = 8080, const string& serviceName = "", const string& command = "") -> bool;
inline auto main(const function<Response (Request&)>& function = {}) -> void;
inline auto scan() -> string;
inline auto close() -> void;
@ -14,10 +14,10 @@ struct Server : Role, service {
private:
function<Response (Request&)> callback;
std::atomic<signed> connections{0};
std::atomic<int> connections{0};
signed fd4 = -1;
signed fd6 = -1;
int fd4 = -1;
int fd6 = -1;
struct sockaddr_in addrin4 = {0};
struct sockaddr_in6 addrin6 = {0};
@ -31,7 +31,7 @@ private:
auto ipv6_scan() -> bool;
};
auto Server::open(unsigned port, const string& serviceName, const string& command) -> bool {
auto Server::open(uint port, const string& serviceName, const string& command) -> bool {
if(serviceName) {
if(!service::command(serviceName, command)) return false;
}
@ -62,21 +62,21 @@ auto Server::open(unsigned port, const string& serviceName, const string& comman
#endif
#if defined(SO_NOSIGPIPE) //BSD, OSX
signed nosigpipe = 1;
if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(signed));
if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(signed));
int nosigpipe = 1;
if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(int));
if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(int));
#endif
#if defined(SO_REUSEADDR) //BSD, Linux, OSX
signed reuseaddr = 1;
if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(signed));
if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(signed));
int reuseaddr = 1;
if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int));
if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int));
#endif
#if defined(SO_REUSEPORT) //BSD, OSX
signed reuseport = 1;
if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_REUSEPORT, &reuseport, sizeof(signed));
if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_REUSEPORT, &reuseport, sizeof(signed));
int reuseport = 1;
if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_REUSEPORT, &reuseport, sizeof(int));
if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_REUSEPORT, &reuseport, sizeof(int));
#endif
}
@ -117,7 +117,7 @@ auto Server::ipv4_scan() -> bool {
thread::create([&](uintptr) {
thread::detach();
signed clientfd = -1;
int clientfd = -1;
struct sockaddr_in settings = {0};
socklen_t socklen = sizeof(sockaddr_in);
@ -164,7 +164,7 @@ auto Server::ipv6_scan() -> bool {
thread::create([&](uintptr) {
thread::detach();
signed clientfd = -1;
int clientfd = -1;
struct sockaddr_in6 settings = {0};
socklen_t socklen = sizeof(sockaddr_in6);
@ -178,9 +178,9 @@ auto Server::ipv6_scan() -> bool {
Request request;
request._ipv6 = true;
//RFC5952 IPv6 encoding: the first longest 2+ consecutive zero-sequence is compressed to "::"
signed zeroOffset = -1;
signed zeroLength = 0;
signed zeroCounter = 0;
int zeroOffset = -1;
int zeroLength = 0;
int zeroCounter = 0;
for(auto n : range(8)) {
uint16_t value = ipSegment[n];
if(value == 0) zeroCounter++;
@ -191,7 +191,7 @@ auto Server::ipv6_scan() -> bool {
if(value != 0) zeroCounter = 0;
}
if(zeroLength == 1) zeroOffset = -1;
for(unsigned n = 0; n < 8;) {
for(uint n = 0; n < 8;) {
if(n == zeroOffset) {
request._ip.append(n == 0 ? "::" : ":");
n += zeroLength;

View File

@ -329,3 +329,8 @@ struct string_format : vector<string> {
#include <nall/string/markup/xml.hpp>
#include <nall/string/transform/cml.hpp>
#include <nall/string/transform/dml.hpp>
namespace nall {
//inline auto range(const string& value) { return range_t{0, (int)value.size(), 1}; }
//inline auto rrange(const string& value) { return range_t{(int)value.size() - 1, -1, -1}; }
}

View File

@ -8,8 +8,8 @@ using SharedNode = shared_pointer<ManagedNode>;
struct ManagedNode {
ManagedNode() = default;
ManagedNode(const string& name) : _name(name) {}
ManagedNode(const string& name, const string& value) : _name(name), _value(value) {}
explicit ManagedNode(const string& name) : _name(name) {}
explicit ManagedNode(const string& name, const string& value) : _name(name), _value(value) {}
auto clone() const -> SharedNode {
SharedNode clone{new ManagedNode(_name, _value)};
@ -46,8 +46,8 @@ protected:
struct Node {
Node() : shared(new ManagedNode) {}
Node(const SharedNode& source) : shared(source ? source : new ManagedNode) {}
Node(const string& name) : shared(new ManagedNode(name)) {}
Node(const string& name, const string& value) : shared(new ManagedNode(name, value)) {}
explicit Node(const string& name) : shared(new ManagedNode(name)) {}
explicit Node(const string& name, const string& value) : shared(new ManagedNode(name, value)) {}
auto unique() const -> bool { return shared.unique(); }
auto clone() const -> Node { return shared->clone(); }
@ -133,9 +133,6 @@ protected:
}}
namespace nall {
inline range_t range(const Markup::Node& node) {
return range_t{0, (int)node.size(), 1};
}
inline auto range(const Markup::Node& value) { return range_t{0, (int)value.size(), 1}; }
inline auto rrange(const Markup::Node& value) { return range_t{(int)value.size() - 1, -1, -1}; }
}

View File

@ -107,3 +107,8 @@ private:
#include <nall/vector/modify.hpp>
#include <nall/vector/iterator.hpp>
#include <nall/vector/utility.hpp>
namespace nall {
template<typename T> inline auto range(const vector<T>& value) { return range_t{0, (int)value.size(), 1}; }
template<typename T> inline auto rrange(const vector<T>& value) { return range_t{(int)value.size() - 1, -1, -1}; }
}

View File

@ -26,12 +26,4 @@ private:
uint offset;
};
template<typename T> inline auto range(const vector<T>& container) {
return range_t{0, (int)container.size(), 1};
}
template<typename T> inline auto rrange(const vector<T>& container) {
return range_t{(int)container.size() - 1, -1, -1};
}
}