├── .gitignore ├── README.md ├── config.m4 ├── config.w32 ├── examples ├── Workerman │ ├── Autoloader.php │ ├── Db │ │ ├── AbstractPool.php │ │ ├── Db.php │ │ ├── MySQL.php │ │ └── MysqlPool.php │ └── Protocols │ │ ├── Frame.php │ │ ├── Http.php │ │ ├── Http │ │ ├── Chunk.php │ │ ├── Request.php │ │ ├── Response.php │ │ ├── ServerSentEvents.php │ │ ├── Session.php │ │ ├── Session │ │ │ ├── FileSessionHandler.php │ │ │ └── RedisSessionHandler.php │ │ └── mime.types │ │ ├── ProtocolInterface.php │ │ ├── Text.php │ │ ├── Websocket.php │ │ └── Ws.php ├── http_server.php ├── start.php ├── start_ab.php ├── swoole.php ├── test_channel.php ├── test_hook_tcp.php ├── test_require.php ├── test_sleep.php ├── test_yield.php ├── websocket_server.php └── 思路 ├── include ├── array.h ├── asm_context.h ├── base.h ├── channel.h ├── context.h ├── coroutine.h ├── file.h ├── hash.h ├── header.h ├── helper.h ├── khash.h ├── list.h ├── log.h ├── queue.h ├── runtime.h ├── socket.h ├── stack.h ├── timer.h ├── wm_socket.h ├── wm_string.h ├── worker.h ├── worker │ ├── connection.h │ ├── loop.h │ └── wm_signal.h ├── workerman.h └── workerman_config.h ├── make.sh ├── make2.sh ├── php_channel.c ├── php_connection.c ├── php_coroutine.c ├── php_runtime.c ├── php_timer.c ├── php_worker.c ├── php_workerman.c ├── src ├── core │ ├── array.c │ ├── base.c │ ├── file.c │ ├── log.c │ ├── socket.c │ ├── timer.c │ └── wm_string.c ├── coroutine │ ├── channel.c │ ├── context.c │ ├── coroutine.c │ └── socket.c ├── runtime.c ├── worker.c └── worker │ ├── connection.c │ ├── loop.c │ └── signal.c └── thirdparty └── boost └── asm ├── jump_arm64_aapcs_elf_gas.S ├── jump_arm64_aapcs_macho_gas.S ├── jump_arm_aapcs_elf_gas.S ├── jump_arm_aapcs_macho_gas.S ├── jump_arm_aapcs_pe_armasm.asm ├── jump_combined_sysv_macho_gas.S ├── jump_i386_ms_pe_gas.asm ├── jump_i386_ms_pe_masm.asm ├── jump_i386_sysv_elf_gas.S ├── jump_i386_sysv_macho_gas.S ├── jump_i386_x86_64_sysv_macho_gas.S ├── jump_mips32_o32_elf_gas.S ├── jump_ppc32_ppc64_sysv_macho_gas.S ├── jump_ppc32_sysv_elf_gas.S ├── jump_ppc32_sysv_macho_gas.S ├── jump_ppc32_sysv_xcoff_gas.S ├── jump_ppc64_sysv_elf_gas.S ├── jump_ppc64_sysv_macho_gas.S ├── jump_ppc64_sysv_xcoff_gas.S ├── jump_sparc64_sysv_elf_gas.S ├── jump_sparc_sysv_elf_gas.S ├── jump_x86_64_ms_pe_gas.asm ├── jump_x86_64_ms_pe_masm.asm ├── jump_x86_64_sysv_elf_gas.S ├── jump_x86_64_sysv_macho_gas.S ├── make_arm64_aapcs_elf_gas.S ├── make_arm64_aapcs_macho_gas.S ├── make_arm_aapcs_elf_gas.S ├── make_arm_aapcs_macho_gas.S ├── make_arm_aapcs_pe_armasm.asm ├── make_combined_sysv_macho_gas.S ├── make_i386_ms_pe_gas.asm ├── make_i386_ms_pe_masm.asm ├── make_i386_sysv_elf_gas.S ├── make_i386_sysv_macho_gas.S ├── make_i386_x86_64_sysv_macho_gas.S ├── make_mips32_o32_elf_gas.S ├── make_ppc32_ppc64_sysv_macho_gas.S ├── make_ppc32_sysv_elf_gas.S ├── make_ppc32_sysv_macho_gas.S ├── make_ppc32_sysv_xcoff_gas.S ├── make_ppc64_sysv_elf_gas.S ├── make_ppc64_sysv_macho_gas.S ├── make_ppc64_sysv_xcoff_gas.S ├── make_sparc64_sysv_elf_gas.S ├── make_sparc_sysv_elf_gas.S ├── make_x86_64_ms_pe_gas.asm ├── make_x86_64_ms_pe_masm.asm ├── make_x86_64_sysv_elf_gas.S └── make_x86_64_sysv_macho_gas.S /.gitignore: -------------------------------------------------------------------------------- 1 | *.lo 2 | *.la 3 | .libs 4 | acinclude.m4 5 | aclocal.m4 6 | autom4te.cache 7 | build 8 | config.guess 9 | config.h 10 | config.h.in 11 | config.log 12 | config.nice 13 | config.status 14 | config.sub 15 | configure 16 | configure.ac 17 | configure.in 18 | install-sh 19 | libtool 20 | ltmain.sh 21 | Makefile 22 | Makefile.fragments 23 | Makefile.global 24 | Makefile.objects 25 | missing 26 | mkinstalldirs 27 | modules 28 | run-tests.php 29 | tests 30 | tests/ 31 | tests/*/*.diff 32 | tests/*/*.out 33 | tests/*/*.php 34 | tests/*/*.exp 35 | tests/*/*.log 36 | tests/*/*.sh 37 | *.pid 38 | *.log -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 序言 2 | WarriorMan是一款php的协程高性能socket扩展,适合对 [Workerman](https://www.workerman.net/) 或者 [swoole](https://github.com/swoole/swoole-src) 有一定的了解的同学使用。 3 | 4 | ## WarriorMan是什么 5 | WarriorMan是一个完全用c语言编写的php扩展,仿照 [Workerman](https://www.workerman.net/) 制作,解决Workerman的一些短板,为Workerman插上协程的翅膀。 6 | 7 | ## WarriorMan与WorkerMan的不同 8 | ### 缺点 9 | 1 WarriorMan没有WorkerMan稳定。 10 | 2 WarriorMan扩展是用纯C编写,阅读调试有一定难度。 11 | ### 优点 12 | 1 WarriorMan提供协程调度方法,默认的事件回调也是通过协程调度实现,可以在IO操作方面节省大量时间。 13 | 2 WarriorMan因为HOOK了PHP TCP Socket 类型的 stream,所以常见的`Redis`、`PDO`、`Mysqli`以及用 PHP 的[streams](https://www.php.net/streams)系列函数操作 TCP 连接的操作,都默认支持协程调度,减少了编程复杂度。 14 | 15 | 3 会逐步提供更多底层方法,为开发者提供更多的灵活度。 16 | 17 | ## WarriorMan适合什么样的人 18 | 如果你初次接触socket长连接编程,建议使用 [Workerman](https://www.workerman.net/) 框架开发。 19 | 如果你的项目业务逻辑很清晰,没有频繁的IO操作,建议使用 [Workerman](https://www.workerman.net/) 框架开发。 20 | 如果你的项目IO操作很频繁,可以考虑使用WarriorMan 21 | 如果你对C语言感兴趣,对协程原理感兴趣,可以考虑使用WarriorMan 22 | 如果你是一个热于折腾的人,并且可以主导自己的项目,可以考虑使用WarriorMan 23 | 如果你对php扩展开发有经验,请一定尝试使用WarriorMan 24 | 25 | ## 压力测试 26 | [压力测试](https://www.kancloud.cn/wwwoooshizha/warriorman/1839724) 27 | [压力测试-数据库](https://www.kancloud.cn/wwwoooshizha/warriorman/1839725) 28 | 29 | ### 作者希望 30 | 作者在这里希望大家可以尝试使用WarriorMan,尝试学习WarriorMan源码,源码中有大量中文注释,这对提升自己编程水平以及更好的理解Workerman和Swoole很有帮助。 31 | 32 | ## 环境 33 | PHP7 or Higher 34 | 35 | ## 安装 36 | ``` 37 | 1 首先修改make.sh,将里面路径修改为自己php的路径 38 | 2 执行./make.sh 39 | 3 最后别忘了将workerman.so添加到php.ini 40 | ``` 41 | ### A tcp server 42 | ```php 43 | use Warriorman\Worker; 44 | use Warriorman\Runtime; 45 | 46 | Worker::rename(); // 为了防止命名空间冲突 47 | Runtime::enableCoroutine(); // hook相关函数 48 | 49 | $worker = new Worker("tcp://0.0.0.0:8080"); 50 | 51 | 52 | $worker->onMessage = function ($connection, $data) { 53 | $responseStr = "hello world"; 54 | $connection->send($responseStr); 55 | }; 56 | 57 | Worker::runAll(); 58 | ``` 59 | 60 | ## 文档 61 | WarriorMan:[https://www.kancloud.cn/wwwoooshizha/warriorman/content](https://www.kancloud.cn/wwwoooshizha/warriorman/content) 62 | 文档是直接用了WorkerMan和Swoole的部分文档 63 | 64 | ## 交流 65 | :> 66 | 67 | ## 特别鸣谢 68 | [Workerman](https://github.com/walkor/Workerman) 69 | [Swoole](https://github.com/swoole/swoole-src) 70 | [Study](https://github.com/php-extension-research/study) 71 | 72 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_ENABLE(workerman, whether to enable workerman support, 2 | Make sure that the comment is aligned: 3 | [ --enable-workerman Enable workerman support]) 4 | 5 | # AC_CANONICAL_HOST 6 | 7 | if test "$PHP_WM" != "no"; then 8 | PHP_ADD_LIBRARY(pthread) 9 | WM_ASM_DIR="thirdparty/boost/asm/" 10 | CFLAGS="-Wall -pthread $CFLAGS" 11 | 12 | dnl 这段是用来判断我们机器所使用的操作系统是什么类型的,然后把操作系统的类型赋值给变量WM_OS。 13 | dnl 因为,我们的这个扩展只打算支持Linux,所以,我这个里面只写了Linux。 14 | AS_CASE([$host_os], 15 | [linux*], [WM_OS="LINUX"], 16 | [] 17 | ) 18 | dnl 这段是判断CPU的类型,然后赋值给变量WM_CPU。 19 | AS_CASE([$host_cpu], 20 | [x86_64*], [WM_CPU="x86_64"], 21 | [x86*], [WM_CPU="x86"], 22 | [i?86*], [WM_CPU="x86"], 23 | [arm*], [WM_CPU="arm"], 24 | [aarch64*], [WM_CPU="arm64"], 25 | [arm64*], [WM_CPU="arm64"], 26 | [] 27 | ) 28 | 29 | dnl 这段是判断应该用什么类型的汇编文件 30 | if test "$WM_CPU" = "x86_64"; then 31 | if test "$WM_OS" = "LINUX"; then 32 | WM_CONTEXT_ASM_FILE="x86_64_sysv_elf_gas.S" 33 | fi 34 | elif test "$WM_CPU" = "x86"; then 35 | if test "$WM_OS" = "LINUX"; then 36 | WM_CONTEXT_ASM_FILE="i386_sysv_elf_gas.S" 37 | fi 38 | elif test "$WM_CPU" = "arm"; then 39 | if test "$WM_OS" = "LINUX"; then 40 | WM_CONTEXT_ASM_FILE="arm_aapcs_elf_gas.S" 41 | fi 42 | elif test "$WM_CPU" = "arm64"; then 43 | if test "$WM_OS" = "LINUX"; then 44 | WM_CONTEXT_ASM_FILE="arm64_aapcs_elf_gas.S" 45 | fi 46 | elif test "$WM_CPU" = "mips32"; then 47 | if test "$WM_OS" = "LINUX"; then 48 | WM_CONTEXT_ASM_FILE="mips32_o32_elf_gas.S" 49 | fi 50 | fi 51 | 52 | dnl 把我们需要编译的所有文件已字符串的方式存入到变量workerman_source_file里面。 53 | workerman_source_file="\ 54 | src/core/base.c \ 55 | src/core/log.c \ 56 | src/core/socket.c \ 57 | src/core/timer.c \ 58 | src/core/wm_string.c \ 59 | src/core/file.c \ 60 | src/core/array.c \ 61 | src/coroutine/channel.c \ 62 | src/coroutine/context.c \ 63 | src/coroutine/coroutine.c \ 64 | src/coroutine/socket.c \ 65 | src/worker/loop.c \ 66 | src/worker/signal.c \ 67 | src/worker/connection.c \ 68 | src/worker.c \ 69 | src/runtime.c \ 70 | php_coroutine.c \ 71 | php_workerman.c \ 72 | php_channel.c \ 73 | php_worker.c \ 74 | php_connection.c \ 75 | php_runtime.c \ 76 | php_timer.c \ 77 | ${WM_ASM_DIR}make_${WM_CONTEXT_ASM_FILE} \ 78 | ${WM_ASM_DIR}jump_${WM_CONTEXT_ASM_FILE} 79 | " 80 | 81 | dnl 声明这个扩展的名称、需要的源文件名、此扩展的编译形式。其中$ext_shared代表此扩展是动态库,使用cxx的原因是,我们的这个扩展使用C++来编写。 82 | dnl PHP_NEW_EXTENSION(workerman, $workerman_source_file, $ext_shared,,, cxx) 83 | PHP_NEW_EXTENSION(workerman, $workerman_source_file, $ext_shared) 84 | 85 | dnl 用来添加额外的包含头文件的目录。 86 | PHP_ADD_INCLUDE([$ext_srcdir]) 87 | PHP_ADD_INCLUDE([$ext_srcdir/include]) 88 | PHP_ADD_INCLUDE([$ext_srcdir/include/worker]) 89 | 90 | dnl 把我们的workerman扩展目录里面的*.h、config.h、include/*.h、thirdparty/*.h复制到: php-config --include-dir 91 | dnl 下的ext/workerman里面。这个是在执行make install的时候会进行复制。我们待会会看到。 92 | PHP_INSTALL_HEADERS([ext/workerman], [*.h config.h include/*.h include/worker/*.h thirdparty/*.h]) 93 | 94 | dnl 我们使用c,把下面的c++相关注释了 95 | CFLAGS="-Wall -pthread $CFLAGS" 96 | CFLAGS="$CFLAGS -std=gnu99" 97 | 98 | 99 | dnl 我们使用了C++,所以我们需要指明一下。(没有这句会编译出错) 100 | dnl PHP_REQUIRE_CXX() 101 | 102 | dnl 编译C++时候,用到的编译选项。 103 | dnl CXXFLAGS="$CXXFLAGS -Wall -Wno-unused-function -Wno-deprecated -Wno-deprecated-declarations" 104 | dnl 编译C++时候,用到的编译选项。 105 | dnl if test "$WM_OS" = "CYGWIN" || test "$WM_OS" = "MINGW"; then 106 | dnl CXXFLAGS="$CXXFLAGS -std=gnu++11" 107 | dnl else 108 | dnl CXXFLAGS="$CXXFLAGS -std=c++11" 109 | dnl fi 110 | 111 | dnl 指定这个扩展需要被编译到的文件的目录。因为我们需要编译boost提供的代码,所以需要进行指定。 112 | PHP_ADD_BUILD_DIR($ext_builddir/thirdparty/boost) 113 | PHP_ADD_BUILD_DIR($ext_builddir/thirdparty/boost/asm) 114 | fi -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | ARG_ENABLE('workerman', 'workerman support', 'no'); 2 | 3 | if (PHP_WORKERMAN != 'no') { 4 | AC_DEFINE('HAVE_WORKERMAN', 1, 'workerman support enabled'); 5 | 6 | EXTENSION('workerman', 'workerman.c', null, '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1'); 7 | } 8 | -------------------------------------------------------------------------------- /examples/Workerman/Autoloader.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman; 15 | 16 | /** 17 | * Autoload. 18 | */ 19 | class Autoloader { 20 | 21 | /** 22 | * Autoload root path. 23 | * 24 | * @var string 25 | */ 26 | protected static $_autoloadRootPath = ''; 27 | 28 | /** 29 | * Set autoload root path. 30 | * 31 | * @param string $root_path 32 | * @return void 33 | */ 34 | public static function setRootPath($root_path) { 35 | self::$_autoloadRootPath = $root_path; 36 | } 37 | 38 | /** 39 | * Load files by namespace. 40 | * 41 | * @param string $name 42 | * @return boolean 43 | */ 44 | public static function loadByNamespace($name) { 45 | $class_path = \str_replace('\\', \DIRECTORY_SEPARATOR, $name); 46 | if (\strpos($name, 'Workerman\\') === 0) { 47 | $class_file = __DIR__ . \substr($class_path, \strlen('Workerman')) . '.php'; 48 | } else { 49 | if (self::$_autoloadRootPath) { 50 | $class_file = self::$_autoloadRootPath . \DIRECTORY_SEPARATOR . $class_path . '.php'; 51 | } 52 | if (empty($class_file) || ! \is_file($class_file)) { 53 | $class_file = __DIR__ . \DIRECTORY_SEPARATOR . '..' . \DIRECTORY_SEPARATOR . "$class_path.php"; 54 | } 55 | } 56 | 57 | if (\is_file($class_file)) { 58 | require_once ($class_file); 59 | if (\class_exists($name, false)) { 60 | return true; 61 | } 62 | } 63 | return false; 64 | } 65 | } 66 | 67 | \spl_autoload_register('\Workerman\Autoloader::loadByNamespace'); -------------------------------------------------------------------------------- /examples/Workerman/Db/MysqlPool.php: -------------------------------------------------------------------------------- 1 | config['host'], $this->config['port'], $this->config['username'], $this->config['password'], $this->config['db_name']); 12 | // if ($db->connected == false) { 13 | // dd("createDb error : " . $db->connect_error); 14 | // return false; 15 | // } 16 | return $db; 17 | } 18 | 19 | protected function checkDb($db) 20 | { 21 | return true; 22 | // return $db->connected; 23 | } 24 | 25 | protected function closeDb($db) 26 | { 27 | $db->closeConnection(); 28 | // return $db->connected; 29 | } 30 | } -------------------------------------------------------------------------------- /examples/Workerman/Protocols/Frame.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols; 15 | 16 | use Workerman\Connection\TcpConnection; 17 | 18 | /** 19 | * Frame Protocol. 20 | */ 21 | class Frame 22 | { 23 | /** 24 | * Check the integrity of the package. 25 | * 26 | * @param string $buffer 27 | * @param TcpConnection $connection 28 | * @return int 29 | */ 30 | public static function input($buffer, TcpConnection $connection) 31 | { 32 | if (\strlen($buffer) < 4) { 33 | return 0; 34 | } 35 | $unpack_data = \unpack('Ntotal_length', $buffer); 36 | return $unpack_data['total_length']; 37 | } 38 | 39 | /** 40 | * Decode. 41 | * 42 | * @param string $buffer 43 | * @return string 44 | */ 45 | public static function decode($buffer) 46 | { 47 | return \substr($buffer, 4); 48 | } 49 | 50 | /** 51 | * Encode. 52 | * 53 | * @param string $buffer 54 | * @return string 55 | */ 56 | public static function encode($buffer) 57 | { 58 | $total_length = 4 + \strlen($buffer); 59 | return \pack('N', $total_length) . $buffer; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/Workerman/Protocols/Http/Chunk.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols\Http; 15 | 16 | 17 | /** 18 | * Class Chunk 19 | * @package Workerman\Protocols\Http 20 | */ 21 | class Chunk 22 | { 23 | /** 24 | * Chunk buffer. 25 | * 26 | * @var string 27 | */ 28 | protected $_buffer = null; 29 | 30 | /** 31 | * Chunk constructor. 32 | * @param $buffer 33 | */ 34 | public function __construct($buffer) 35 | { 36 | $this->_buffer = $buffer; 37 | } 38 | 39 | /** 40 | * __toString 41 | * 42 | * @return string 43 | */ 44 | public function __toString() 45 | { 46 | return \dechex(\strlen($this->_buffer))."\r\n$this->_buffer\r\n"; 47 | } 48 | } -------------------------------------------------------------------------------- /examples/Workerman/Protocols/Http/ServerSentEvents.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols\Http; 15 | 16 | /** 17 | * Class ServerSentEvents 18 | * @package Workerman\Protocols\Http 19 | */ 20 | class ServerSentEvents 21 | { 22 | /** 23 | * Data. 24 | * @var array 25 | */ 26 | protected $_data = null; 27 | 28 | /** 29 | * ServerSentEvents constructor. 30 | * $data for example ['event'=>'ping', 'data' => 'some thing', 'id' => 1000, 'retry' => 5000] 31 | * @param array $data 32 | */ 33 | public function __construct(array $data) 34 | { 35 | $this->_data = $data; 36 | } 37 | 38 | /** 39 | * __toString. 40 | * 41 | * @return string 42 | */ 43 | public function __toString() 44 | { 45 | $buffer = ''; 46 | $data = $this->_data; 47 | if (isset($data[''])) { 48 | $buffer = ": {$data['']}\n"; 49 | } 50 | if (isset($data['event'])) { 51 | $buffer .= "event: {$data['event']}\n"; 52 | } 53 | if (isset($data['data'])) { 54 | $buffer .= 'data: ' . \str_replace("\n", "\ndata: ", $data['data']) . "\n\n"; 55 | } 56 | if (isset($data['id'])) { 57 | $buffer .= "id: {$data['id']}\n"; 58 | } 59 | if (isset($data['retry'])) { 60 | $buffer .= "retry: {$data['retry']}\n"; 61 | } 62 | return $buffer; 63 | } 64 | } -------------------------------------------------------------------------------- /examples/Workerman/Protocols/Http/Session/FileSessionHandler.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols\Http\Session; 15 | 16 | /** 17 | * Class FileSessionHandler 18 | * @package Workerman\Protocols\Http\Session 19 | */ 20 | class FileSessionHandler implements \SessionHandlerInterface 21 | { 22 | /** 23 | * Session save path. 24 | * 25 | * @var string 26 | */ 27 | protected static $_sessionSavePath = null; 28 | 29 | /** 30 | * Session file prefix. 31 | * 32 | * @var string 33 | */ 34 | protected static $_sessionFilePrefix = 'session_'; 35 | 36 | /** 37 | * Init. 38 | */ 39 | public static function init() { 40 | $save_path = @\session_save_path(); 41 | if (!$save_path || \strpos($save_path, 'tcp://') === 0) { 42 | $save_path = \sys_get_temp_dir(); 43 | } 44 | static::sessionSavePath($save_path); 45 | } 46 | 47 | /** 48 | * FileSessionHandler constructor. 49 | * @param array $config 50 | */ 51 | public function __construct($config = array()) { 52 | if (isset($config['save_path'])) { 53 | static::sessionSavePath($config['save_path']); 54 | } 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | */ 60 | public function open($save_path, $name) 61 | { 62 | return true; 63 | } 64 | 65 | /** 66 | * {@inheritdoc} 67 | */ 68 | public function read($session_id) 69 | { 70 | $session_file = static::sessionFile($session_id); 71 | \clearstatcache(); 72 | if (\is_file($session_file)) { 73 | $data = \file_get_contents($session_file); 74 | return $data ? $data : ''; 75 | } 76 | return ''; 77 | } 78 | 79 | /** 80 | * {@inheritdoc} 81 | */ 82 | public function write($session_id, $session_data) 83 | { 84 | $temp_file = static::$_sessionSavePath.uniqid(mt_rand(), true); 85 | if (!\file_put_contents($temp_file, $session_data)) { 86 | return false; 87 | } 88 | return \rename($temp_file, static::sessionFile($session_id)); 89 | } 90 | 91 | /** 92 | * {@inheritdoc} 93 | */ 94 | public function close() 95 | { 96 | return true; 97 | } 98 | 99 | /** 100 | * {@inheritdoc} 101 | */ 102 | public function destroy($session_id) 103 | { 104 | $session_file = static::sessionFile($session_id); 105 | if (\is_file($session_file)) { 106 | \unlink($session_file); 107 | } 108 | return true; 109 | } 110 | 111 | /** 112 | * {@inheritdoc} 113 | */ 114 | public function gc($maxlifetime) { 115 | $time_now = \time(); 116 | foreach (\glob(static::$_sessionSavePath . static::$_sessionFilePrefix . '*') as $file) { 117 | if(\is_file($file) && $time_now - \filemtime($file) > $maxlifetime) { 118 | \unlink($file); 119 | } 120 | } 121 | } 122 | 123 | /** 124 | * Get session file path. 125 | * 126 | * @param $session_id 127 | * @return string 128 | */ 129 | protected static function sessionFile($session_id) { 130 | return static::$_sessionSavePath.static::$_sessionFilePrefix.$session_id; 131 | } 132 | 133 | /** 134 | * Get or set session file path. 135 | * 136 | * @param $path 137 | * @return string 138 | */ 139 | public static function sessionSavePath($path) { 140 | if ($path) { 141 | if ($path[\strlen($path)-1] !== DIRECTORY_SEPARATOR) { 142 | $path .= DIRECTORY_SEPARATOR; 143 | } 144 | static::$_sessionSavePath = $path; 145 | if (!\is_dir($path)) { 146 | \mkdir($path, 0777, true); 147 | } 148 | } 149 | return $path; 150 | } 151 | } 152 | 153 | FileSessionHandler::init(); -------------------------------------------------------------------------------- /examples/Workerman/Protocols/Http/Session/RedisSessionHandler.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols\Http\Session; 15 | 16 | /** 17 | * Class RedisSessionHandler 18 | * @package Workerman\Protocols\Http\Session 19 | */ 20 | class RedisSessionHandler extends \SessionHandler 21 | { 22 | 23 | /** 24 | * @var \Redis 25 | */ 26 | protected $_redis; 27 | 28 | /** 29 | * @var int 30 | */ 31 | protected $_maxLifeTime; 32 | 33 | /** 34 | * RedisSessionHandler constructor. 35 | * @param $config = [ 36 | * 'host' => '127.0.0.1', 37 | * 'port' => 6379, 38 | * 'timeout' => 2, 39 | * 'auth' => '******', 40 | * 'database' => 2, 41 | * 'prefix' => 'redis_session_', 42 | * ] 43 | */ 44 | public function __construct($config) 45 | { 46 | if (false === extension_loaded('redis')) { 47 | throw new \RuntimeException('Please install redis extension.'); 48 | } 49 | $this->_maxLifeTime = (int)ini_get('session.gc_maxlifetime'); 50 | 51 | if (!isset($config['timeout'])) { 52 | $config['timeout'] = 2; 53 | } 54 | 55 | $this->_redis = new \Redis(); 56 | if (false === $this->_redis->connect($config['host'], $config['port'], $config['timeout'])) { 57 | throw new \RuntimeException("Redis connect {$config['host']}:{$config['port']} fail."); 58 | } 59 | if (!empty($config['auth'])) { 60 | $this->_redis->auth($config['auth']); 61 | } 62 | if (!empty($config['database'])) { 63 | $this->_redis->select($config['database']); 64 | } 65 | if (empty($config['prefix'])) { 66 | $config['prefix'] = 'redis_session_'; 67 | } 68 | $this->_redis->setOption(\Redis::OPT_PREFIX, $config['prefix']); 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | */ 74 | public function open($save_path, $name) 75 | { 76 | return true; 77 | } 78 | 79 | /** 80 | * {@inheritdoc} 81 | */ 82 | public function read($session_id) 83 | { 84 | return $this->_redis->get($session_id); 85 | } 86 | 87 | /** 88 | * {@inheritdoc} 89 | */ 90 | public function write($session_id, $session_data) 91 | { 92 | return true === $this->_redis->setex($session_id, $this->_maxLifeTime, $session_data); 93 | } 94 | 95 | /** 96 | * {@inheritdoc} 97 | */ 98 | public function destroy($session_id) 99 | { 100 | $this->_redis->del($session_id); 101 | return true; 102 | } 103 | 104 | /** 105 | * {@inheritdoc} 106 | */ 107 | public function close() 108 | { 109 | return true; 110 | } 111 | 112 | /** 113 | * {@inheritdoc} 114 | */ 115 | public function gc($maxlifetime) 116 | { 117 | return true; 118 | } 119 | } -------------------------------------------------------------------------------- /examples/Workerman/Protocols/Http/mime.types: -------------------------------------------------------------------------------- 1 | 2 | types { 3 | text/html html htm shtml; 4 | text/css css; 5 | text/xml xml; 6 | image/gif gif; 7 | image/jpeg jpeg jpg; 8 | application/javascript js; 9 | application/atom+xml atom; 10 | application/rss+xml rss; 11 | 12 | text/mathml mml; 13 | text/plain txt; 14 | text/vnd.sun.j2me.app-descriptor jad; 15 | text/vnd.wap.wml wml; 16 | text/x-component htc; 17 | 18 | image/png png; 19 | image/tiff tif tiff; 20 | image/vnd.wap.wbmp wbmp; 21 | image/x-icon ico; 22 | image/x-jng jng; 23 | image/x-ms-bmp bmp; 24 | image/svg+xml svg svgz; 25 | image/webp webp; 26 | 27 | application/font-woff woff; 28 | application/java-archive jar war ear; 29 | application/json json; 30 | application/mac-binhex40 hqx; 31 | application/msword doc; 32 | application/pdf pdf; 33 | application/postscript ps eps ai; 34 | application/rtf rtf; 35 | application/vnd.apple.mpegurl m3u8; 36 | application/vnd.ms-excel xls; 37 | application/vnd.ms-fontobject eot; 38 | application/vnd.ms-powerpoint ppt; 39 | application/vnd.wap.wmlc wmlc; 40 | application/vnd.google-earth.kml+xml kml; 41 | application/vnd.google-earth.kmz kmz; 42 | application/x-7z-compressed 7z; 43 | application/x-cocoa cco; 44 | application/x-java-archive-diff jardiff; 45 | application/x-java-jnlp-file jnlp; 46 | application/x-makeself run; 47 | application/x-perl pl pm; 48 | application/x-pilot prc pdb; 49 | application/x-rar-compressed rar; 50 | application/x-redhat-package-manager rpm; 51 | application/x-sea sea; 52 | application/x-shockwave-flash swf; 53 | application/x-stuffit sit; 54 | application/x-tcl tcl tk; 55 | application/x-x509-ca-cert der pem crt; 56 | application/x-xpinstall xpi; 57 | application/xhtml+xml xhtml; 58 | application/xspf+xml xspf; 59 | application/zip zip; 60 | 61 | application/octet-stream bin exe dll; 62 | application/octet-stream deb; 63 | application/octet-stream dmg; 64 | application/octet-stream iso img; 65 | application/octet-stream msi msp msm; 66 | 67 | application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; 68 | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; 69 | application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; 70 | 71 | audio/midi mid midi kar; 72 | audio/mpeg mp3; 73 | audio/ogg ogg; 74 | audio/x-m4a m4a; 75 | audio/x-realaudio ra; 76 | 77 | video/3gpp 3gpp 3gp; 78 | video/mp2t ts; 79 | video/mp4 mp4; 80 | video/mpeg mpeg mpg; 81 | video/quicktime mov; 82 | video/webm webm; 83 | video/x-flv flv; 84 | video/x-m4v m4v; 85 | video/x-mng mng; 86 | video/x-ms-asf asx asf; 87 | video/x-ms-wmv wmv; 88 | video/x-msvideo avi; 89 | font/ttf ttf; 90 | } 91 | -------------------------------------------------------------------------------- /examples/Workerman/Protocols/ProtocolInterface.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols; 15 | 16 | use Workerman\Connection\ConnectionInterface; 17 | 18 | /** 19 | * Protocol interface 20 | */ 21 | interface ProtocolInterface 22 | { 23 | /** 24 | * Check the integrity of the package. 25 | * Please return the length of package. 26 | * If length is unknow please return 0 that mean wating more data. 27 | * If the package has something wrong please return false the connection will be closed. 28 | * 29 | * @param string $recv_buffer 30 | * @param ConnectionInterface $connection 31 | * @return int|false 32 | */ 33 | public static function input($recv_buffer, ConnectionInterface $connection); 34 | 35 | /** 36 | * Decode package and emit onMessage($message) callback, $message is the result that decode returned. 37 | * 38 | * @param string $recv_buffer 39 | * @param ConnectionInterface $connection 40 | * @return mixed 41 | */ 42 | public static function decode($recv_buffer, ConnectionInterface $connection); 43 | 44 | /** 45 | * Encode package brefore sending to client. 46 | * 47 | * @param mixed $data 48 | * @param ConnectionInterface $connection 49 | * @return string 50 | */ 51 | public static function encode($data, ConnectionInterface $connection); 52 | } 53 | -------------------------------------------------------------------------------- /examples/Workerman/Protocols/Text.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols; 15 | 16 | /** 17 | * Text Protocol. 18 | */ 19 | class Text { 20 | 21 | /** 22 | * Check the integrity of the package. 23 | * 24 | * @param string $buffer 25 | * @param ConnectionInterface $connection 26 | * @return int 27 | */ 28 | public static function input($buffer = NULL, $connection = NULL) { 29 | var_dump("input"); 30 | return strlen($buffer); 31 | // Judge whether the package length exceeds the limit. 32 | if (isset($connection->maxPackageSize) && \strlen($buffer) >= $connection->maxPackageSize) { 33 | $connection->close(); 34 | return 0; 35 | } 36 | // Find the position of "\n". 37 | $pos = \strpos($buffer, "\n"); 38 | // No "\n", packet length is unknown, continue to wait for the data so return 0. 39 | if ($pos === false) { 40 | return 0; 41 | } 42 | // Return the current package length. 43 | return $pos + 1; 44 | } 45 | 46 | /** 47 | * Encode. 48 | * 49 | * @param string $buffer 50 | * @return string 51 | */ 52 | public static function encode($buffer) { 53 | var_dump("encode"); 54 | // Add "\n" 55 | return $buffer . "\n"; 56 | } 57 | 58 | /** 59 | * Decode. 60 | * 61 | * @param string $buffer 62 | * @return string 63 | */ 64 | public static function decode($buffer) { 65 | var_dump("decode"); 66 | // Remove "\n" 67 | return \rtrim($buffer, "\r\n"); 68 | } 69 | } -------------------------------------------------------------------------------- /examples/http_server.php: -------------------------------------------------------------------------------- 1 | count = 4; 16 | // 设置协议 17 | $http_worker->protocol = "\Workerman\Protocols\Http"; 18 | 19 | // 接收到浏览器发送的数据时回复hello world给浏览器 20 | $http_worker->onMessage = function ($connection, $data) { 21 | // 向浏览器发送hello world 22 | $connection->send('hello world'); 23 | }; 24 | 25 | // 运行worker 26 | Worker::runAll(); 27 | -------------------------------------------------------------------------------- /examples/start.php: -------------------------------------------------------------------------------- 1 | count = 1; 13 | $worker->name = "tcpServer"; // 设置名字 14 | $worker->protocol = "\Workerman\Protocols\Http"; // 设置协议 15 | $worker->mysqlPoll = NULL; 16 | $worker->onWorkerStart = function ($worker) { 17 | $config = array(); 18 | $config["host"] = "192.168.2.103"; 19 | $config["port"] = 3306; 20 | $config["username"] = "www"; 21 | $config["password"] = "www"; 22 | $config["db_name"] = "test"; 23 | 24 | $config["min"] = 2; 25 | $config["max"] = 100; 26 | $config["spareTime"] = 1; 27 | 28 | $worker->mysqlPoll = new MysqlPool($config); 29 | 30 | var_dump("onWorkerStart ->" . $worker->workerId . " id=" . $worker->id); 31 | }; 32 | 33 | $worker->onWorkerReload = function ($worker) { 34 | var_dump("onWorkerReload ->" . $worker->id); 35 | }; 36 | $worker->onConnect = function ($connection) use ($worker) { 37 | $connection->set(array( 38 | "maxSendBufferSize" => 102400 39 | )); 40 | $ip = $connection->getRemoteIp(); 41 | $port = $connection->getRemotePort(); 42 | echo "new connection id {$connection->id} ip=$ip port=$port\n"; 43 | }; 44 | $worker->onMessage = function ($connection, $data) use ($worker) { 45 | $db = $worker->mysqlPoll->get(); 46 | $responseStr = json_encode($db->query("select now()")); 47 | $worker->mysqlPoll->put($db); 48 | $connection->close($responseStr); 49 | }; 50 | 51 | $worker->onBufferFull = function ($connection) { 52 | echo "bufferFull and do not send again\n"; 53 | }; 54 | 55 | $worker->onError = function ($connection, $code, $msg) { 56 | var_dump($code); 57 | var_dump($msg); 58 | echo "connection error ,id {$connection->id} \n"; 59 | }; 60 | 61 | $worker->onClose = function ($connection) { 62 | echo "connection closed\n"; 63 | }; 64 | 65 | // 监听另外一个端口 66 | $worker2 = new Worker("tcp://0.0.0.0:8081"); 67 | $worker2->count = 1; 68 | $worker2->onMessage = function ($connection, $data) { 69 | $responseStr = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Keep-Alive\r\nContent-Length: 11\r\n\r\nhello worlb\r\n"; 70 | $connection->send($responseStr); 71 | }; 72 | 73 | // 监听另外一个端口 74 | $worker3 = new Worker("udp://0.0.0.0:8080"); 75 | $worker3->onMessage = function ($connection, $data) { 76 | var_dump("udp:" . $data); 77 | $connection->send("hello world"); 78 | $ip = $connection->getRemoteIp(); 79 | $port = $connection->getRemotePort(); 80 | echo "new connection id {$connection->id} ip=$ip port=$port\n"; 81 | }; 82 | 83 | Worker::runAll(); 84 | -------------------------------------------------------------------------------- /examples/start_ab.php: -------------------------------------------------------------------------------- 1 | count = 8; 13 | $worker->name = "ab_test"; // 设置名字 14 | $worker->mysqlPoll = NULL; 15 | $worker->onWorkerStart = function ($worker) { 16 | $config = array(); 17 | $config["host"] = "172.21.112.1"; 18 | $config["port"] = 3306; 19 | $config["username"] = "www"; 20 | $config["password"] = "www"; 21 | $config["db_name"] = "test"; 22 | 23 | $config["min"] = 10; 24 | $config["max"] = 30; 25 | $config["spareTime"] = 1; 26 | $worker->mysqlPoll = new MysqlPool($config); 27 | }; 28 | 29 | $worker->onMessage = function ($connection, $data) use ($worker) { 30 | $db = $worker->mysqlPoll->get(); 31 | $db->query("select now()"); 32 | $worker->mysqlPoll->put($db); 33 | $responseStr = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Keep-Alive\r\nContent-Length: 11\r\n\r\nhello worlb\r\n"; 34 | $connection->send($responseStr); 35 | }; 36 | 37 | Worker::runAll(); 38 | -------------------------------------------------------------------------------- /examples/swoole.php: -------------------------------------------------------------------------------- 1 | handle('/', function ($request, $response) { 9 | // $response->end("

Index

"); 10 | // }); 11 | // $server->start(); 12 | // }); 13 | 14 | $server = new Swoole\Server("127.0.0.1", 8081); 15 | 16 | $server->on('receive', function ($server, $fd, $reactor_id, $data) { 17 | $responseStr = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Keep-Alive\r\nContent-Length: 11\r\n\r\nhello worlb\r\n"; 18 | $server->send($fd, $responseStr); 19 | }); 20 | 21 | 22 | $server->start(); -------------------------------------------------------------------------------- /examples/test_channel.php: -------------------------------------------------------------------------------- 1 | push("hello world"); 11 | var_dump($ret); 12 | }); 13 | 14 | Warriorman::create(function () use ($chan) { 15 | var_dump("push pop"); 16 | $ret = $chan->pop(); 17 | var_dump($ret); 18 | }); 19 | 20 | if (! defined("RUN_TEST")) { 21 | worker_event_wait(); 22 | } 23 | -------------------------------------------------------------------------------- /examples/test_hook_tcp.php: -------------------------------------------------------------------------------- 1 | [ 12 | // 'so_reuseaddr' => true, 13 | // 'backlog' => 128 14 | // ] 15 | // ]); 16 | // $socket = stream_socket_server('tcp://0.0.0.0:8080', $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctx); 17 | // if (! $socket) { 18 | // echo "$errstr ($errno)" . PHP_EOL; 19 | // exit(1); 20 | // } 21 | // var_dump($socket); 22 | 23 | 24 | $fp = stream_socket_client("tcp://127.0.0.1:8080", $errno, $errstr); 25 | if (!$fp) { 26 | echo 'error'; 27 | } else { 28 | fwrite($fp,$message); 29 | fclose($fp); 30 | var_dump('--success--'); 31 | } 32 | 33 | 34 | }); 35 | 36 | if (! defined("RUN_TEST")) { 37 | worker_event_wait(); 38 | } -------------------------------------------------------------------------------- /examples/test_require.php: -------------------------------------------------------------------------------- 1 | count = 4; 12 | // 每个进程启动后打印当前进程id编号即 $worker1->id 13 | $worker1->onWorkerStart = function ($worker1) { 14 | echo "worker1->id={$worker1->id}\n"; 15 | }; 16 | 17 | // worker实例2有两个进程,进程id编号将分别为0、1 18 | $worker2 = new Worker('tcp://0.0.0.0:8686'); 19 | // 设置启动2个进程 20 | $worker2->count = 2; 21 | // 每个进程启动后打印当前进程id编号即 $worker2->id 22 | $worker2->onWorkerStart = function ($worker2) { 23 | echo "worker2->id={$worker2->id}\n"; 24 | }; 25 | 26 | // 运行worker 27 | Worker::runAll(); -------------------------------------------------------------------------------- /examples/test_sleep.php: -------------------------------------------------------------------------------- 1 | count = 4; 14 | // 设置协议 15 | $ws_worker->protocol = "\Workerman\Protocols\Websocket"; 16 | 17 | // 接收到浏览器发送的数据时回复hello world给浏览器 18 | $ws_worker->onMessage = function ($connection, $data) { 19 | // 向浏览器发送hello world 20 | $connection->send('hello world'); 21 | }; 22 | 23 | // 运行worker 24 | Worker::runAll(); 25 | -------------------------------------------------------------------------------- /examples/思路: -------------------------------------------------------------------------------- 1 | 开始按照workerman文档制作函数,并且制作差异文档 2 | 完善udp协议 OK 3 | 定时器 OK 4 | 5 | 检查内存泄漏 6 | _DONT_UNLOAD_MODULES=1 USE_ZEND_ALLOC=0 valgrind --leak-check=full --show-reachable=yes --track-origins=yes --log-file=/mnt/d/a.log php start.php start 7 | -------------------------------------------------------------------------------- /include/array.h: -------------------------------------------------------------------------------- 1 | #ifndef WM_ARRAY_H 2 | #define WM_ARRAY_H 3 | 4 | typedef struct _wmArray { 5 | void **pages; 6 | uint16_t page_num; //当前的页数 7 | uint16_t page_size; //每页的数量多少 8 | uint32_t item_size; //每个元素的大小 9 | uint32_t item_num; //有多少元素了 10 | uint32_t offset; 11 | } wmArray; 12 | 13 | #define wmArray_page(array, n) ((n) / (array)->page_size) 14 | #define wmArray_offset(array, n) ((n) % (array)->page_size) 15 | 16 | wmArray *wmArray_new(int page_size, size_t item_size); 17 | void wmArray_free(wmArray *array); 18 | void *wmArray_find(wmArray *array, uint32_t n); 19 | int wmArray_set(wmArray *array, uint32_t n, void *data); 20 | void *wmArray_alloc(wmArray *array, uint32_t n); 21 | int wmArray_add(wmArray *array, void *data); 22 | int wmArray_extend(wmArray *array); 23 | void wmArray_clear(wmArray *array); 24 | void wmArray_printf(wmArray *array); 25 | 26 | #endif /* WM_ARRAY_H */ 27 | -------------------------------------------------------------------------------- /include/asm_context.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_CONTEXT_H 2 | #define ASM_CONTEXT_H 3 | 4 | typedef void* fcontext_t; 5 | 6 | extern intptr_t jump_fcontext(fcontext_t *ofc, fcontext_t nfc, intptr_t vp, bool preserve_fpu) asm("jump_fcontext"); 7 | extern fcontext_t make_fcontext(void *sp, size_t size, void (*fn)(intptr_t)) asm("make_fcontext"); 8 | 9 | #endif /* ASM_CONTEXT_H */ 10 | -------------------------------------------------------------------------------- /include/channel.h: -------------------------------------------------------------------------------- 1 | #ifndef _WM_CHANNEL_H 2 | #define _WM_CHANNEL_H 3 | /** 4 | * 协程化channel 5 | */ 6 | #include "base.h" 7 | 8 | typedef struct { 9 | uint32_t capacity; //容量 10 | //生产者协程等待队列 11 | wmQueue *producer_queue; 12 | //消费者协程等待队列 13 | wmQueue *consumer_queue; 14 | //这个里面存着,存入channle中的数据 15 | wmQueue *data_queue; 16 | } wmChannel; 17 | 18 | wmChannel* wmChannel_create(uint32_t _capacity); 19 | bool wmChannel_push(wmChannel* channel, void *data, double timeout);//插入 20 | void* wmChannel_pop(wmChannel* channel, double timeout);//弹出 21 | int wmChannel_num(wmChannel* channel);//协程内多少元素 22 | void wmChannel_clear(wmChannel* channel);//清空这个协程的所有元素 23 | void wmChannel_free(wmChannel* channel);//销毁 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/context.h: -------------------------------------------------------------------------------- 1 | #ifndef WM_CONTEXT_H 2 | #define WM_CONTEXT_H 3 | 4 | #include "base.h" 5 | #include "asm_context.h" 6 | 7 | typedef fcontext_t coroutine_context_t; 8 | typedef void (*coroutine_func_t)(void*); 9 | 10 | /** 11 | * 协程context结构体 12 | */ 13 | typedef struct { 14 | coroutine_func_t fn_; 15 | uint32_t stack_size_; 16 | void *private_data_; 17 | char* stack_; 18 | //指向汇编 19 | coroutine_context_t ctx_; 20 | coroutine_context_t swap_ctx_; 21 | bool end_; 22 | } wmContext; 23 | 24 | void wmContext_init(wmContext *ctx, size_t stack_size, coroutine_func_t fn, void* private_data); 25 | bool wmContext_swap_out(wmContext *ctx); 26 | bool wmContext_swap_in(wmContext *ctx); 27 | void wmContext_destroy(wmContext *ctx); 28 | 29 | #endif /* WM_CONTEXT_H */ 30 | -------------------------------------------------------------------------------- /include/coroutine.h: -------------------------------------------------------------------------------- 1 | #ifndef WM_COROUTINE_H 2 | #define WM_COROUTINE_H 3 | 4 | #include "base.h" 5 | #include "context.h" 6 | 7 | //协程参数结构体 8 | typedef struct { 9 | zend_fcall_info_cache *fci_cache; 10 | zval *argv; 11 | uint32_t argc; 12 | } php_coro_args; 13 | 14 | // 协程状态信息结构体 15 | typedef struct _Coroutine { 16 | //格式不可以动 17 | zval *vm_stack_top; // 是协程栈栈顶 18 | zval *vm_stack_end; // 是协程栈栈底。 19 | zend_vm_stack vm_stack; // 是协程栈指针。 20 | size_t vm_stack_page_size; //是协程栈页大小。 21 | zend_execute_data *execute_data; // 是当前协程栈的栈帧。 22 | //格式不可以动 23 | 24 | //以下是coroutine结构 25 | wmContext ctx; 26 | long cid; //协程类ID 27 | struct _Coroutine *origin; //唤起协程,记录哪个协程,创建的这个协程 28 | wmStack *defer_tasks; //所有的defer 29 | 30 | coroutine_func_t _defer; //c语言级别defer 31 | void *_defer_data; //c语言级别defer 32 | } wmCoroutine; 33 | 34 | long wmCoroutine_create(zend_fcall_info_cache *fci_cache, uint32_t argc, zval *argv); 35 | wmCoroutine* wmCoroutine_get_by_cid(long _cid); 36 | void wmCoroutine_yield(); 37 | bool wmCoroutine_resume(wmCoroutine *task); 38 | void vm_stack_destroy(); 39 | void wmCoroutine_defer(php_fci_fcc *defer_fci_fcc); 40 | void wmCoroutine_sleep(double seconds); 41 | void wmCoroutine_set_callback(long cid, coroutine_func_t _defer, void *_defer_data); 42 | wmCoroutine* wmCoroutine_get_current(); 43 | void wmCoroutine_init(); 44 | void wmCoroutine_shutdown(); 45 | int wmCoroutine_getTotalNum(); //获取一共有多少个协程 46 | 47 | #endif /* WM_COROUTINE_H */ 48 | -------------------------------------------------------------------------------- /include/file.h: -------------------------------------------------------------------------------- 1 | #ifndef WM_FILE_H 2 | #define WM_FILE_H 3 | 4 | int wm_tmpfile(char *filename); 5 | long wm_file_get_size(FILE *fp); 6 | long wm_file_size(const char *filename); 7 | wmString* wm_file_get_contents(const char *filename); 8 | int wm_file_put_contents(const char *filename, const char *content, size_t length, bool append); 9 | 10 | #endif /* WM_FILE_H */ 11 | -------------------------------------------------------------------------------- /include/hash.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 对khash进行简单的封装 3 | */ 4 | #ifndef WM_HASH_H_ 5 | #define WM_HASH_H_ 6 | 7 | #include "header.h" 8 | #include "khash.h" 9 | 10 | #ifdef kcalloc 11 | #undef kcalloc 12 | #undef kmalloc 13 | #undef krealloc 14 | #undef kfree 15 | #endif 16 | 17 | #define kcalloc(N,Z) wm_calloc(N,Z) 18 | #define kmalloc(Z) wm_malloc(Z) 19 | #define krealloc(P,Z) wm_realloc(P,Z) 20 | #define kfree(P) wm_free(P) 21 | 22 | KHASH_MAP_INIT_INT(WM_HASH_INT_INT, int); //键值都是int的hashmap 23 | KHASH_MAP_INIT_INT(WM_HASH_INT_STR, void*); //键是int,值是void类型指针 24 | 25 | #define wmHash_INT_PTR khash_t(WM_HASH_INT_STR) 26 | #define wmHashKey khiter_t 27 | #define wmHash_init kh_init 28 | #define wmHash_put kh_put 29 | #define wmHash_get kh_get 30 | #define wmHash_del kh_del 31 | #define wmHash_exist kh_exist 32 | #define wmHash_value kh_value 33 | #define wmHash_key kh_key 34 | #define wmHash_begin kh_begin 35 | #define wmHash_end kh_end 36 | #define wmHash_destroy kh_destroy 37 | 38 | 39 | #define WM_HASH_ADD(TYPE,map,key,value) \ 40 | ({ \ 41 | int _p; \ 42 | int ret; \ 43 | _p = wmHash_put(TYPE, map, key, &ret); \ 44 | if (ret) {wmHash_value(map, _p) = value;} else {_p = -1;}\ 45 | _p; \ 46 | })\ 47 | 48 | #define WM_HASH_DEL(TYPE,map,key) \ 49 | ({ \ 50 | int _p; \ 51 | _p = wmHash_get(TYPE, map, key); \ 52 | if (_p!=wmHash_end(map)) {wmHash_del(TYPE, map, _p);} else {_p = -1;}\ 53 | _p; \ 54 | })\ 55 | 56 | #define WM_HASH_GET(TYPE,map,key) \ 57 | ({ \ 58 | void* _p; \ 59 | int iter = wmHash_get(TYPE, map, key); \ 60 | if (iter!=wmHash_end(map)) {_p=wmHash_value(map, iter);} else {_p = NULL;}\ 61 | _p; \ 62 | })\ 63 | 64 | #endif 65 | 66 | -------------------------------------------------------------------------------- /include/header.h: -------------------------------------------------------------------------------- 1 | #ifndef WORKERMAN_HEADER_H_ 2 | #define WORKERMAN_HEADER_H_ 3 | 4 | #include "php.h" 5 | #include "php_ini.h" 6 | #include "php_network.h" 7 | #include "php_streams.h" 8 | #include "ext/standard/info.h" 9 | 10 | #ifdef HAVE_CONFIG_H 11 | #include "config.h" 12 | #endif 13 | 14 | // include standard library 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | 53 | //php库 54 | #include "zend_closures.h" 55 | #include "zend_exceptions.h" 56 | #include "zend_object_handlers.h" 57 | #include "zend_interfaces.h" 58 | 59 | //公共配置 60 | #include "workerman_config.h" 61 | //公共方法 62 | #include "helper.h" 63 | 64 | 65 | #endif /* WORKERMAN_HEADER_H_ */ 66 | -------------------------------------------------------------------------------- /include/helper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 一些基础的公共方法 3 | */ 4 | #ifndef WM_HELPER_H 5 | #define WM_HELPER_H 6 | 7 | /** 8 | * 把数字转换成字符串 9 | */ 10 | static inline int wm_itoa(char *buf, long value) { 11 | long i = 0, j; 12 | long sign_mask; 13 | unsigned long nn; 14 | 15 | sign_mask = value >> (sizeof(long) * 8 - 1); 16 | nn = (value + sign_mask) ^ sign_mask; 17 | do { 18 | buf[i++] = nn % 10 + '0'; 19 | } while (nn /= 10); 20 | 21 | buf[i] = '-'; 22 | i += sign_mask & 1; 23 | buf[i] = '\0'; 24 | 25 | int s_len = i; 26 | char swap; 27 | 28 | for (i = 0, j = s_len - 1; i < j; ++i, --j) { 29 | swap = buf[i]; 30 | buf[i] = buf[j]; 31 | buf[j] = swap; 32 | } 33 | buf[s_len] = 0; 34 | return s_len; 35 | } 36 | 37 | /** 38 | * 随机 39 | */ 40 | static inline int wm_rand(int min, int max) { 41 | static int _seed = 0; 42 | assert(max > min); 43 | 44 | if (_seed == 0) { 45 | _seed = time(NULL); 46 | srand(_seed); 47 | } 48 | 49 | int _rand = rand(); 50 | _rand = min + (int) ((double) ((double) (max) - (min) + 1.0) * ((_rand) / ((RAND_MAX) + 1.0))); 51 | return _rand; 52 | } 53 | 54 | //获取当前时间 55 | static inline void wmGetTime(long *seconds, long *microseconds) { 56 | struct timeval tv; 57 | gettimeofday(&tv, NULL); 58 | *seconds = tv.tv_sec; 59 | *microseconds = tv.tv_usec; 60 | } 61 | 62 | //只获取毫秒 63 | static inline void wmGetMilliTime(long *microseconds) { 64 | struct timeval tv; 65 | gettimeofday(&tv, NULL); 66 | *microseconds = tv.tv_sec * 1000 + (long) tv.tv_usec / 1000; 67 | } 68 | 69 | //只获取微妙 70 | static inline void wmGetMicroTime(long *microseconds) { 71 | struct timeval tv; 72 | gettimeofday(&tv, NULL); 73 | *microseconds = tv.tv_usec; 74 | } 75 | 76 | static inline uint64_t touint64(int fd, int id) { 77 | uint64_t ret = 0; 78 | ret |= ((uint64_t) fd) << 32; 79 | ret |= ((uint64_t) id); 80 | 81 | return ret; 82 | } 83 | 84 | static inline void fromuint64(uint64_t v, int *fd, int *id) { 85 | *fd = (int) (v >> 32); 86 | *id = (int) (v & 0xffffffff); 87 | } 88 | 89 | /** 90 | * 格式化字符串 91 | */ 92 | static inline size_t wm_snprintf(char *buf, size_t size, const char *format, ...) { 93 | va_list args; 94 | va_start(args, format); 95 | int retval = vsnprintf(buf, size, format, args); 96 | va_end(args); 97 | if (retval < 0) { 98 | retval = 0; 99 | buf[0] = '\0'; 100 | } else if (retval >= size) { 101 | retval = size - 1; 102 | buf[retval] = '\0'; 103 | } 104 | return retval; 105 | } 106 | 107 | /** 108 | * 获得格式化后的时间 109 | */ 110 | static inline void wm_get_date(char* date, int date_len) { 111 | time_t rawtime; 112 | struct tm * timeinfo; 113 | time(&rawtime); 114 | timeinfo = localtime(&rawtime); 115 | strftime(date, date_len, "%Y-%m-%d %H:%M:%S", timeinfo); 116 | } 117 | 118 | /** 119 | * copy from php src file: xp_socket.c 120 | */ 121 | static inline char *parse_ip_address_ex(const char *str, size_t str_len, int *portno, int get_err, zend_string **err) { 122 | char *colon; 123 | char *host = NULL; 124 | 125 | #ifdef HAVE_IPV6 126 | char *p; 127 | 128 | if (*(str) == '[' && str_len > 1) 129 | { 130 | /* IPV6 notation to specify raw address with port (i.e. [fe80::1]:80) */ 131 | p = (char *)memchr(str + 1, ']', str_len - 2); 132 | if (!p || *(p + 1) != ':') 133 | { 134 | if (get_err) 135 | { 136 | *err = strpprintf(0, "Failed to parse IPv6 address \"%s\"", str); 137 | } 138 | return NULL; 139 | } 140 | *portno = atoi(p + 2); 141 | return estrndup(str + 1, p - str - 1); 142 | } 143 | #endif 144 | if (str_len) { 145 | colon = (char *) memchr(str, ':', str_len - 1); 146 | } else { 147 | colon = NULL; 148 | } 149 | if (colon) { 150 | *portno = atoi(colon + 1); 151 | host = estrndup(str, colon - str); 152 | } else { 153 | if (get_err) { 154 | *err = strpprintf(0, "Failed to parse address \"%s\"", str); 155 | } 156 | return NULL; 157 | } 158 | 159 | return host; 160 | } 161 | 162 | /** 163 | * copy from php src file: xp_socket.c 164 | */ 165 | static inline char *parse_ip_address(php_stream_xport_param *xparam, int *portno) { 166 | return parse_ip_address_ex(xparam->inputs.name, xparam->inputs.namelen, portno, xparam->want_errortext, &xparam->outputs.error_text); 167 | } 168 | 169 | #endif /* WM_HELPER_H */ 170 | -------------------------------------------------------------------------------- /include/list.h: -------------------------------------------------------------------------------- 1 | #ifndef LIST_H 2 | #define LIST_H 3 | 4 | /** 5 | * 循环双向链表结点 6 | */ 7 | typedef struct _wmListNode { 8 | struct _wmListNode *next; 9 | struct _wmListNode *prev; 10 | } wmListNode; 11 | 12 | // 初始化链表头:前后都指向自己 13 | static inline void wmList_init(wmListNode *head) { 14 | head->prev = head; 15 | head->next = head; 16 | } 17 | 18 | // 插入结点到链表的前面,因为是循环链表,其实是在head的后面 19 | static inline void wmList_add_front(wmListNode *head, wmListNode *node) { 20 | node->prev = head; 21 | node->next = head->next; 22 | head->next->prev = node; 23 | head->next = node; 24 | } 25 | 26 | // 插入结点到链表的后面,因为是循环链表,所以其实是在head的前面 27 | static inline void wmList_add_back(wmListNode *head, wmListNode *node) { 28 | node->prev = head->prev; 29 | node->next = head; 30 | node->prev->next = node; 31 | head->prev = node; 32 | } 33 | 34 | // 判断链表是否为空:循环链表为空是头的下一个和上一个都指向自己 35 | static inline int wmList_is_empty(wmListNode *head) { 36 | return head == head->next; 37 | } 38 | 39 | // 从链表中移除自己,同时会重设结点 40 | static inline void wmList_remote(wmListNode *node) { 41 | node->next->prev = node->prev; 42 | node->prev->next = node->next; 43 | wmList_init(node); 44 | } 45 | 46 | // 将链表1的结点取出来,放到链表2 47 | static inline void wmList_splice(wmListNode *head1, wmListNode *head2) { 48 | if (!wmList_is_empty(head1)) { 49 | wmListNode *first = head1->next; // 第1个结点 50 | wmListNode *last = head1->prev; // 最后1个结点 51 | wmListNode *at = head2->next; // 插在第2个链表的这个结点前面 52 | first->prev = head2; 53 | head2->next = first; 54 | last->next = at; 55 | at->prev = last; 56 | wmList_init(head1); 57 | } 58 | } 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /include/log.h: -------------------------------------------------------------------------------- 1 | #ifndef LOG_H_ 2 | #define LOG_H_ 3 | 4 | #include "header.h" 5 | 6 | #define WM_LOG_BUFFER_SIZE 1024 7 | #define WM_LOG_DATE_WMRLEN 64 8 | 9 | #define WM_DEBUG_MSG_SIZE 512 10 | #define WM_TRACE_MSG_SIZE 512 11 | #define WM_WARN_MSG_SIZE 512 12 | #define WM_ERROR_MSG_SIZE 512 13 | 14 | extern char wm_debug[WM_DEBUG_MSG_SIZE]; 15 | extern char wm_trace[WM_TRACE_MSG_SIZE]; 16 | extern char wm_warn[WM_WARN_MSG_SIZE]; 17 | extern char wm_error[WM_ERROR_MSG_SIZE]; 18 | 19 | enum wmCode { 20 | /** 21 | * connection error 22 | */ 23 | WM_ERROR_SESSION_CLOSED_BY_SERVER = 1001, //代表连接是被服务器关闭的, 24 | WM_ERROR_SESSION_CLOSED_BY_CLIENT = 1002, //代表连接是被客户端关闭的。 25 | WM_ERROR_SESSION_CLOSED = 1003, //代表连接是被客户端关闭的。 26 | WM_ERROR_SEND_FAIL = 1004, //发送失败 27 | WM_ERROR_SEND_BUFFER_FULL = 1005, //发送区满了 28 | WM_ERROR_READ_FAIL = 1006, //接收失败 29 | WM_ERROR_LOOP_FAIL = 1007, //LOOP相关错误 30 | WM_ERROR_PROTOCOL_FAIL = 1008, //错误的协议 31 | }; 32 | 33 | #define wmDebug(wmr, ...) \ 34 | snprintf(wm_debug, WM_DEBUG_MSG_SIZE, "%s: " wmr " in %s on line %d.", __func__, ##__VA_ARGS__, __FILE__, __LINE__); \ 35 | wmLog_put(WM_LOG_DEBUG, wm_debug); 36 | 37 | #define wmTrace(wmr, ...) \ 38 | snprintf(wm_trace, WM_TRACE_MSG_SIZE, "%s: " wmr " in %s on line %d.", __func__, ##__VA_ARGS__, __FILE__, __LINE__); \ 39 | wmLog_put(WM_LOG_TRACE, wm_trace); 40 | 41 | #define wmWarn(wmr, ...) \ 42 | snprintf(wm_error, WM_ERROR_MSG_SIZE, "%s: " wmr " in %s on line %d.", __func__, ##__VA_ARGS__, __FILE__, __LINE__); \ 43 | wmLog_put(WM_LOG_WARNING, wm_error); 44 | 45 | #define wmError(wmr, ...) \ 46 | snprintf(wm_error, WM_ERROR_MSG_SIZE, "%s: " wmr " in %s on line %d.", __func__, ##__VA_ARGS__, __FILE__, __LINE__); \ 47 | wmLog_put(WM_LOG_ERROR, wm_error); \ 48 | exit(-1); 49 | 50 | enum wmLog_level { 51 | WM_LOG_DEBUG = 0, WM_LOG_TRACE, WM_LOG_INFO, WM_LOG_NOTICE, WM_LOG_WARNING, WM_LOG_ERROR, 52 | }; 53 | 54 | void wmLog_put(int level, char *cnt); 55 | 56 | const char* wmCode_str(int code); 57 | 58 | #endif /* LOG_H_ */ 59 | -------------------------------------------------------------------------------- /include/queue.h: -------------------------------------------------------------------------------- 1 | #ifndef _WM_QUEUE_H 2 | #define _WM_QUEUE_H 3 | 4 | #include "workerman_config.h" 5 | #include "list.h" 6 | 7 | // 定时器结点 8 | typedef struct { 9 | wmListNode *next; // 下一个结点 10 | wmListNode *prev; // 上一个结点 11 | void *data; // 用户数据 12 | } wmQueueNode; 13 | 14 | // 队列结构体 15 | typedef struct { 16 | uint32_t num; //队列元素个数 17 | wmQueueNode head; //队列头,头是不包含元素的 18 | } wmQueue; 19 | 20 | // 初始化队列 21 | static inline wmQueue* wmQueue_create() { 22 | wmQueue* queue = (wmQueue *) wm_malloc(sizeof(wmQueue)); 23 | bzero(queue, sizeof(wmQueue)); 24 | 25 | queue->num = 0; 26 | wmList_init((wmListNode *) &queue->head); 27 | return queue; 28 | } 29 | 30 | // push 31 | static inline void wmQueue_push(wmQueue* queue, void *data) { 32 | wmQueueNode* node = (wmQueueNode *) wm_malloc(sizeof(wmQueueNode)); 33 | bzero(node, sizeof(wmQueueNode)); 34 | wmList_init((wmListNode *) node); 35 | //保存用户数据 36 | node->data = data; 37 | //添加到整个双向列表的最后 38 | wmList_add_back((wmListNode *) (&queue->head), (wmListNode *) node); 39 | queue->num++; 40 | } 41 | 42 | // pop 43 | static inline void * wmQueue_pop(wmQueue* queue) { 44 | //如果没有元素了 45 | if (wmList_is_empty((wmListNode *) (&queue->head)) || queue->num == 0) { 46 | return NULL; 47 | } 48 | wmListNode* next = queue->head.next; 49 | wmList_remote(next); 50 | //释放 51 | wm_free(((wmQueueNode*) next)); 52 | //减少记数 53 | queue->num--; 54 | return ((wmQueueNode*) next)->data; 55 | } 56 | 57 | //获取长度 58 | static inline int wmQueue_len(wmQueue* queue) { 59 | return queue->num; 60 | } 61 | 62 | //清空队列 63 | static inline void wmQueue_clear(wmQueue* queue) { 64 | if (queue == NULL || queue->num == 0) { 65 | return; 66 | } 67 | wmListNode* head = (wmListNode *) &queue->head; 68 | while (!wmList_is_empty(head)) { 69 | wmQueueNode* _wqn = (wmQueueNode*) head->next; 70 | wmList_remote(head->next); 71 | wm_free(_wqn); 72 | } 73 | queue->num = 0; 74 | } 75 | 76 | //销毁 77 | static inline void wmQueue_destroy(wmQueue* queue) { 78 | wmQueue_clear(queue); 79 | wm_free(queue); 80 | queue = NULL; 81 | } 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /include/runtime.h: -------------------------------------------------------------------------------- 1 | #ifndef WM_RUNTIME_H 2 | #define WM_RUNTIME_H 3 | 4 | #include "base.h" 5 | 6 | void wmRuntime_init(); 7 | void wmRuntime_shutdown(); 8 | 9 | php_stream *wmRuntime_socket_create(const char *proto, size_t protolen, const char *resourcename, size_t resourcenamelen, // 10 | const char *persistent_id, int options, int flags, struct timeval *timeout, php_stream_context *context STREAMS_DC 11 | ); 12 | #endif /* WM_RUNTIME_H */ 13 | -------------------------------------------------------------------------------- /include/socket.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 基础的socket操作 3 | */ 4 | #ifndef _SOCKET_H 5 | #define _SOCKET_H 6 | 7 | 8 | int wm_socket_create(int domain, int type, int protocol); //创建套接字 9 | int wm_socket_set_nonblock(int sock); //设置为非阻塞 10 | int wm_socket_listen(int sock, int backlog); //监听 11 | int wm_socket_bind(int sock, char *host, int port); 12 | int wm_socket_connect(int sock, char *host, int port); 13 | 14 | /** 15 | * 获取客户端连接,sa是为了获取客户端信息 16 | */ 17 | int wm_socket_accept(int sock, struct sockaddr_in *sa, socklen_t *len); 18 | /** 19 | * 获取客户端数据 20 | */ 21 | ssize_t wm_socket_recv(int sock, void *buf, size_t len, int flag); 22 | 23 | /** 24 | * 发送数据 25 | */ 26 | ssize_t wm_socket_send(int sock, const void *buf, size_t len, int flag); 27 | /** 28 | * 关闭 29 | */ 30 | int wm_socket_close(int fd); 31 | 32 | /** 33 | * 设置端口复用 34 | */ 35 | int wm_socket_reuse_port(int fd); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /include/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef _STACK_H 2 | #define _STACK_H 3 | 4 | #include "workerman_config.h" 5 | 6 | #define WM_STACK_INIT_LEN 10 7 | #define WM_STACK_CRE 2 8 | 9 | /** 10 | * 栈节点 11 | */ 12 | typedef struct _wmStack_Node { 13 | void* data; //数据域 14 | } wmStack_Node; 15 | 16 | //栈结构 17 | typedef struct _wmStack { 18 | wmStack_Node* node; //栈的数据域 19 | int num; //栈内有几个元素 20 | int size; //栈的总大小 21 | } wmStack; 22 | 23 | //创建栈 24 | static inline wmStack* wmStack_create() { 25 | long i = 0; 26 | wmStack* s = NULL; 27 | s = (wmStack*) wm_malloc(sizeof(wmStack)); 28 | if (s == NULL) { 29 | return s; 30 | } 31 | //分配栈空间 32 | s->node = (wmStack_Node *) wm_malloc(WM_STACK_INIT_LEN * sizeof(wmStack_Node)); 33 | //判断是否分配空间 34 | if (s->node == NULL) { 35 | wm_free(s); 36 | //php_error_docref(NULL, E_WARNING, "wmStack_create error"); 37 | php_printf("wmStack_create error \n"); 38 | s = NULL; 39 | return s; 40 | } 41 | s->num = 0; 42 | s->size = WM_STACK_INIT_LEN; 43 | //将数据域置为空 44 | for (i = 0; i < s->size; i++) { 45 | s->node[i].data = NULL; 46 | } 47 | return s; 48 | } 49 | 50 | //入栈 51 | static inline int wmStack_push(wmStack *stack, void* data) { 52 | int i = 0; 53 | if (stack == NULL || stack->node == NULL) { 54 | return 0; 55 | } 56 | //如果溢出则增加内存分配 57 | if (stack->num == stack->size) { 58 | //重新调整大小,也就是加WM_STACK_CRE个 59 | stack->node = (wmStack_Node*) realloc(stack->node, (stack->size + WM_STACK_CRE) * sizeof(wmStack_Node)); 60 | if (stack->node == NULL) { 61 | php_printf("wmStack_push error \n"); 62 | return 0; 63 | } 64 | int old_size = stack->size; 65 | stack->size += WM_STACK_CRE; 66 | //将重新分配的数据域置为NULL 67 | for (i = old_size; i < stack->size; i++) { 68 | stack->node[i].data = NULL; 69 | } 70 | } 71 | stack->node[stack->num].data = data; 72 | stack->num++; 73 | return 1; 74 | } 75 | 76 | /** 77 | * //出栈 78 | */ 79 | static inline void* wmStack_pop(wmStack *stack) { 80 | void* data = NULL; 81 | if (stack == NULL || stack->node == NULL) { 82 | return NULL; 83 | } 84 | if (stack->num == 0) { 85 | return NULL; 86 | } 87 | data = stack->node[stack->num - 1].data; //弹出栈顶内容 88 | stack->node[stack->num - 1].data = NULL; //栈顶数据域置空 89 | stack->num--; //栈顶减1 90 | return data; 91 | } 92 | 93 | //获取栈长度 94 | static inline int wmStack_len(wmStack *stack) { 95 | return stack->num; 96 | } 97 | 98 | //清空栈 99 | static inline void wmStack_clear(wmStack *stack) { 100 | long i = 0; 101 | if (stack == NULL || stack->node == NULL) { 102 | return; 103 | } 104 | for (i = stack->num - 1; i >= 0; i--) { 105 | stack->node[i].data = NULL; 106 | } 107 | stack->num = 0; 108 | } 109 | 110 | //销毁栈 111 | static inline void wmStack_destroy(wmStack *stack) { 112 | if (stack == NULL) 113 | return; 114 | if (stack->node != NULL) { 115 | wm_free(stack->node); 116 | } 117 | wm_free(stack); 118 | } 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /include/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMER_H 2 | #define TIMER_H 3 | 4 | /** 5 | * 定时器模块 6 | */ 7 | #include "header.h" 8 | #include "list.h" 9 | 10 | //////////////////////////////////////////////////////////////////////////////////////// 11 | // 时间轮定时器 12 | 13 | // 第1个轮计算格子数所用的基数。2^8 就是第一个表盘的格子数量 14 | //#define TVR_BITS 8 15 | #define TVR_BITS 8 16 | // 第1个轮有多少个刻度(有多少个双向链表) 17 | #define TVR_SIZE (1 << TVR_BITS) 18 | 19 | // 第b个轮计算格子数所用的基数。2^6 就是第一个表盘的格子数量 20 | //#define TVN_BITS 6 21 | #define TVN_BITS 6 22 | // 第n个轮的长度 23 | #define TVN_SIZE (1 << TVN_BITS) 24 | // 掩码:取模或整除用 25 | #define TVR_MASK (TVR_SIZE - 1) 26 | #define TVN_MASK (TVN_SIZE - 1) 27 | 28 | // 定时器回调函数 29 | typedef void (*timer_cb_t)(void*); 30 | 31 | // 定时器结点 32 | typedef struct timernode { 33 | struct linknode *next; // 下一个结点 34 | struct linknode *prev; // 上一个结点 35 | void *userdata; // 用户数据 36 | timer_cb_t callback; // 回调函数 37 | uint32_t expire; // 到期时间 , 这个不是当前时间戳,是定时器滴答总数+传入的时间间隔产生的 38 | unsigned long id; //定时器ID 39 | } wmTimerWheel_Node; 40 | 41 | // 第1个轮 42 | typedef struct tvroot { 43 | wmListNode vec[TVR_SIZE]; 44 | } tvroot_t; 45 | 46 | // 后面几个轮 47 | typedef struct tvnum { 48 | wmListNode vec[TVN_SIZE]; 49 | } tvnum_t; 50 | 51 | // 时间轮定时器 52 | typedef struct timerwheel { 53 | tvroot_t tvroot; // 第1个轮 54 | tvnum_t tv[4]; // 后面4个轮 55 | uint64_t lasttime; // 上一次的时间毫秒 56 | uint32_t currtick; // 当前的tick 57 | uint16_t interval; // 每个时间点的毫秒间隔 58 | uint16_t remainder; // 剩余的毫秒 59 | uint32_t num; // 当前剩余任务数 60 | wmListNode so_long_node; // 超出了最大时间的节点,在每次最大表盘归0的时候尝试插入 61 | } wmTimerWheel; 62 | 63 | // 初始化时间轮,interval为每帧的间隔,currtime为当前时间 64 | void wmTimerWheel_init(wmTimerWheel *tw, uint16_t interval, uint64_t currtime); 65 | // 初始化时间结点:cb为回调,ud为用户数据 66 | void wmTimerWheel_node_init(wmTimerWheel_Node *node, timer_cb_t cb, void *ud); 67 | // 增加时间结点,ticks为触发间隔(注意是以interval为单位) 68 | void wmTimerWheel_add(wmTimerWheel *tw, wmTimerWheel_Node *node, uint32_t ticks); 69 | // 快速添加 70 | wmTimerWheel_Node* wmTimerWheel_add_quick(wmTimerWheel *tw, timer_cb_t cb, void *ud, uint32_t ticks); 71 | // 删除结点 72 | int wmTimerWheel_del(wmTimerWheel_Node *node); 73 | // 更新时间轮 74 | void wmTimerWheel_update(wmTimerWheel *tw, uint64_t currtime); 75 | // 清空时间轮 76 | void wmTimerWheel_clear(wmTimerWheel *tw); 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /include/wm_socket.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 对于socket进行封装 3 | */ 4 | #ifndef _WM_SOCKET_H 5 | #define _WM_SOCKET_H 6 | 7 | #include "header.h" 8 | #include "coroutine.h" 9 | #include "wm_string.h" 10 | #include "timer.h" 11 | 12 | typedef void (*wm_socket_func_t)(void*); 13 | 14 | typedef struct { 15 | int fd; //文件描述符 16 | wmString *write_buffer; //写缓冲区 17 | int maxSendBufferSize; //应用层发送缓冲区 18 | int events; //loop监听了什么事件 19 | bool closed; //连接是否关闭 20 | bool removed; //连接是否close 21 | void *owner; //拥有人,比如connection创建的socket,owner就是这个connection 22 | int errCode; //错误码 23 | const char *errMsg; //错误描述 24 | 25 | wmCoroutine *read_co; //read操作的时候,保存当前的协程,以便正确唤醒 26 | wmCoroutine *write_co; //write操作的时候,保存当前的,以便正确唤醒 27 | 28 | /** 29 | * worker和connection类型会自己管理loop。runtime是在read或者write的时候代为管理 30 | */ 31 | int loop_type; //对应wmLoop_type这个枚举 32 | int transport; //什么协议类型,比如TCP UDP等 33 | wm_socket_func_t onBufferWillFull; 34 | char *connect_host; 35 | int connect_port; 36 | 37 | /** 38 | * runtime用 39 | */ 40 | bool shutdown_read; 41 | bool shutdown_write; 42 | 43 | /** 44 | * 判断操作是否超时 45 | */ 46 | wmTimerWheel_Node *read_timer; 47 | wmTimerWheel_Node *write_timer; 48 | 49 | uint32_t read_timeout; //读超时默认时间 50 | 51 | struct sockaddr_in *udp_addr; //只有udp用 52 | wmString *remoteIp; //客户端ip 53 | int remotePort; //客户端端口 54 | } wmSocket; 55 | 56 | wmSocket* wmSocket_create(int transport, int loop_type); 57 | wmSocket* wmSocket_pack(int fd, int transport, int loop_type); 58 | int wmSocket_read(wmSocket *socket, char *buf, int len, uint32_t timeout); 59 | int wmSocket_send(wmSocket *socket, const void *buf, size_t len); 60 | int wmSocket_write(wmSocket *socket, const void *buf, size_t len); //不管缓冲区 61 | int wmSocket_close(wmSocket *socket); 62 | void wmSocket_free(wmSocket *socket); 63 | bool wmSocket_connect(wmSocket *socket, char *_host, int _port, uint32_t timeout); 64 | wmSocket* wmSocket_accept(wmSocket *socket, int new_socket_loop_type, uint32_t timeout); 65 | ssize_t wmSocket_peek(wmSocket *socket, void *__buf, size_t __n); 66 | bool wmSocket_shutdown(wmSocket *socket, int __how); 67 | ssize_t wmSocket_recv(wmSocket *server, wmSocket *socket, void *__buf, size_t __n, uint32_t timeout); 68 | ssize_t wmSocket_recvfrom(wmSocket *socket, void *__buf, size_t __n, struct sockaddr *_addr, socklen_t *_socklen, uint32_t timeout); 69 | #endif 70 | -------------------------------------------------------------------------------- /include/wm_string.h: -------------------------------------------------------------------------------- 1 | #ifndef _WM_STRING_H 2 | #define _WM_STRING_H 3 | 4 | typedef struct { 5 | size_t length; //当前字符串长度 6 | size_t size; //为字符串申请总空间大小 7 | off_t offset; 8 | char *str; 9 | } wmString; 10 | 11 | wmString* wmString_new(size_t size); 12 | void wmString_print(wmString *str); 13 | wmString *wmString_dup2(wmString *src); 14 | wmString *wmString_dup(const char *src_str, size_t length); 15 | int wmString_append(wmString *str, wmString *append_str); 16 | int wmString_append_int(wmString *str, int value); 17 | int wmString_append_ptr(wmString *str, const char *append_str, size_t length); 18 | int wmString_write(wmString *str, size_t offset, wmString *write_str); 19 | int wmString_write_ptr(wmString *str, off_t offset, char *write_str, size_t length); 20 | int wmString_extend(wmString *str, size_t new_size); 21 | char* wmString_alloc(wmString *str, size_t __size); 22 | u_int32_t wmString_utf8_decode(char **p, size_t n); 23 | size_t wmString_utf8_length(char *p, size_t n); 24 | void wmString_random_string(char *buf, size_t size); 25 | void wmString_free(wmString *str); 26 | void wmString_replace(wmString *str, char *find, char *replace); //字符串替换 27 | 28 | #endif /* _WM_STRING_H */ 29 | -------------------------------------------------------------------------------- /include/worker.h: -------------------------------------------------------------------------------- 1 | /** 2 | * worker的头文件 3 | */ 4 | #ifndef _WM_SERVER_H 5 | #define _WM_SERVER_H 6 | 7 | #include "base.h" 8 | #include "wm_socket.h" 9 | 10 | typedef struct _wmWorker { 11 | uint32_t workerId; //这是worker的Id 12 | uint32_t id; //这是worker下面每个进程的id,从0开始 13 | uint32_t fd; //监听端口的fd 14 | zval *_This; //指向当前php实例的指针 15 | php_fci_fcc *onWorkerStart; 16 | php_fci_fcc *onWorkerStop; 17 | php_fci_fcc *onWorkerReload; 18 | php_fci_fcc *onConnect; 19 | php_fci_fcc *onMessage; 20 | php_fci_fcc *onClose; 21 | php_fci_fcc *onBufferFull; 22 | php_fci_fcc *onBufferDrain; 23 | php_fci_fcc *onError; 24 | 25 | int _status; //当前状态 26 | int32_t backlog; //listen队列长度 27 | wmString *socketName; // tcp://127.0.0.1:8080 28 | char *user; //当前用户 29 | int transport; //协议 30 | zend_string *protocol; //具体是什么协议,例如http协议的解析php脚本地址 31 | zend_class_entry *protocol_ce; //具体协议的ce指针 32 | int sock_type; //是什么socket类型,比如tcp,udp等 33 | char *host; //监听地址 34 | int32_t port; //监听端口 35 | int32_t count; //进程数量 36 | wmString *name; //名字 37 | bool stopping; //是否正在停止 38 | 39 | bool reloadable; //是否支持reload,默认是支持的 40 | 41 | wmSocket *socket; //用于监听的fd封装而成 42 | zval connections; //保存着当前进程所有的连接 43 | 44 | bool reusePort;//端口复用,默认是true 45 | } wmWorker; 46 | 47 | //为了通过php对象,找到上面的c++对象 ======= start 48 | typedef struct { 49 | wmWorker *worker; //c对象 这个是create产生的 50 | zend_object std; //php对象 51 | } wmWorkerObject; 52 | 53 | wmWorkerObject* wm_worker_fetch_object(zend_object *obj); 54 | //为了通过php对象,找到上面的c++对象 ======= end 55 | 56 | void wmWorker_init(); 57 | void wmWorker_shutdown(); 58 | wmWorker* wmWorker_create(zval *_This, zend_string *socketName); 59 | void wmWorker_listen(wmWorker *worker); 60 | void wmWorker_resumeAccept(wmWorker *worker); 61 | void wmWorker_run(wmWorker *worker); 62 | void wmWorker_runAll(); //启动服务器 63 | void wmWorker_stopAll(); 64 | void wmWorker_free(wmWorker *worker); 65 | wmWorker* wmWorker_find_by_fd(int fd); 66 | wmWorker* wmWorker_getCurrent(); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /include/worker/connection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 用以保存客户端的连接,并且提供相应处理函数 3 | */ 4 | #ifndef _COROUTINE_SOCKET_H 5 | #define _COROUTINE_SOCKET_H 6 | 7 | #include "base.h" 8 | #include "worker.h" 9 | 10 | /** 11 | * 协程化socket结构体 12 | */ 13 | typedef struct { 14 | //写入php属性中 start 15 | int id; 16 | int fd; 17 | int maxSendBufferSize; //应用层发送缓冲区 18 | int maxPackageSize; //接收的最大包包长 19 | //写入php属性中 end 20 | wmSocket *socket; //创建的socket对象 21 | zval _This; //指向当前PHP类的指针 22 | int _status; //当前连接的状态 23 | int transport; //TCP还是UDP 24 | bool _isPaused; //暂停接收消息,只对tcp起作用,默认是false 25 | wmCoroutine *_pausedCoro; //被暂停的协程 26 | 27 | php_fci_fcc *onMessage; 28 | php_fci_fcc *onClose; 29 | php_fci_fcc *onBufferFull; 30 | php_fci_fcc *onBufferDrain; 31 | php_fci_fcc *onError; 32 | 33 | wmString *read_packet_buffer; //用来保存返回给用户整个包的缓冲区 34 | 35 | wmWorker *worker; //所属于哪一个worker对象 36 | 37 | bool is_sending; //是否正在发送数据,如果是会将send方法保护起来,其他协程无法调用 38 | } wmConnection; 39 | 40 | //为了通过php对象,找到上面的c++对象 41 | typedef struct { 42 | wmConnection *connection; //c对象 这个是create产生的 43 | zend_object std; //php对象 44 | } wmConnectionObject; 45 | 46 | wmConnectionObject* wm_connection_fetch_object(zend_object *obj); 47 | zend_object* wm_connection_create_object(zend_class_entry *ce); 48 | 49 | void wmConnection_init(); 50 | void wmConnection_shutdown(); 51 | wmConnection* wmConnection_create(wmSocket *socket); 52 | wmConnection* wmConnection_create_udp(int fd); 53 | wmConnection* wmConnection_find_by_fd(int fd); 54 | ssize_t wmConnection_recv(wmConnection *socket, int32_t length); 55 | void wmConnection_read(wmConnection *connection); 56 | void wmConnection_recvfrom(wmConnection *connection, wmSocket *socket); 57 | bool wmConnection_send(wmConnection *connection, const void *buf, size_t len, bool raw); 58 | int wmConnection_destroy(wmConnection *connection); 59 | void wmConnection_free(wmConnection *socket); 60 | void wmConnection_closeConnections(); 61 | long wmConnection_getConnectionsNum(); 62 | unsigned long wmConnection_getTotalRequestNum(); 63 | void wmConnection_consumeRecvBuffer(wmConnection *connection, zend_long length); 64 | char* wmConnection_getRemoteIp(wmConnection *connection); 65 | int wmConnection_getRemotePort(wmConnection *connection); 66 | void wmConnection_pauseRecv(wmConnection *connection); 67 | void wmConnection_resumeRecv(wmConnection *connection); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /include/worker/loop.h: -------------------------------------------------------------------------------- 1 | #ifndef _WM_WORKER_LOOP_H 2 | #define _WM_WORKER_LOOP_H 3 | 4 | #include "base.h" 5 | #include "wm_socket.h" 6 | 7 | /** 8 | * 保存触发信号之后的回调方法 9 | */ 10 | typedef bool (*loop_callback_func_t)(wmSocket*, int); 11 | 12 | bool wmWorkerLoop_set_handler(int event, int type, loop_callback_func_t fn); 13 | loop_callback_func_t wmWorkerLoop_get_handler(int event, int type); 14 | bool wmWorkerLoop_add(wmSocket* socket, int event); 15 | bool wmWorkerLoop_remove(wmSocket* socket, int event); 16 | void wmWorkerLoop_loop(); 17 | void wmWorkerLoop_stop(); 18 | bool wmWorkerLoop_del(wmSocket* socket); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/worker/wm_signal.h: -------------------------------------------------------------------------------- 1 | #ifndef _WM_SIGNAL_H 2 | #define _WM_SIGNAL_H 3 | 4 | /** 5 | * 保存触发信号之后的回调方法 6 | */ 7 | typedef void (*signal_func_t)(int); 8 | void wmSignal_add(int sigal, signal_func_t fn); 9 | void wmSignal_wait(); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /include/workerman.h: -------------------------------------------------------------------------------- 1 | /* workerman extension for PHP */ 2 | 3 | #ifndef PHP_WORKERMAN_H 4 | # define PHP_WORKERMAN_H 5 | 6 | #include "header.h" 7 | 8 | extern zend_module_entry workerman_module_entry; 9 | # define phpext_workerman_ptr &workerman_module_entry 10 | 11 | #ifdef PHP_WIN32 12 | # define PHP_WORKERMAN_API __declspec(dllexport) 13 | #elif defined(__GNUC__) && __GNUC__ >= 4 14 | # define PHP_WORKERMAN_API __attribute__ ((visibility("default"))) 15 | #else 16 | # define PHP_WORKERMAN_API 17 | #endif 18 | 19 | #ifdef ZTS 20 | #include "TSRM.h" 21 | #endif 22 | 23 | /** 24 | * Declare any global variables you may need between the BEGIN and END macros here 25 | */ 26 | ZEND_BEGIN_MODULE_GLOBALS(workerman) 27 | 28 | ZEND_END_MODULE_GLOBALS(workerman) 29 | 30 | #endif /* PHP_WORKERMAN_H */ 31 | 32 | -------------------------------------------------------------------------------- /include/workerman_config.h: -------------------------------------------------------------------------------- 1 | #ifndef WM_CONFIG_H_ 2 | #define WM_CONFIG_H_ 3 | 4 | #define PHP_WORKERMAN_VERSION "0.1.0" 5 | 6 | enum wmSocket_type { 7 | WM_SOCK_TCP = 1, // 8 | WM_SOCK_UDP = 2, // 9 | }; 10 | 11 | enum wmSocketError_type { 12 | WM_SOCKET_SUCCESS = 0, // 13 | WM_SOCKET_CLOSE = -1, // 14 | WM_SOCKET_ERROR = -2, // 15 | }; 16 | 17 | enum wmLoop_type { 18 | WM_LOOP_AUTO = 1, // 默认是全自动resume和yield,每次都自动添加和删除事件 19 | WM_LOOP_SEMI_AUTO = 2, // send的时候默认resume和yield,read的监听事件需要自己添加 20 | }; 21 | 22 | enum wmChannel_opcode { 23 | CHANNEL_PUSH = 1, // 24 | CHANNEL_POP = 2, 25 | }; 26 | 27 | /** 28 | * epoll各种监听事件 29 | */ 30 | enum wmEvent_type { 31 | WM_EVENT_NULL = 0, // 32 | WM_EVENT_READ = 1u << 9, // 33 | WM_EVENT_WRITE = 1u << 10, // 34 | WM_EVENT_EPOLLEXCLUSIVE = 1u << 11, //防止惊群效应, 不使用 35 | }; 36 | 37 | /** 38 | * worker的状态 39 | */ 40 | enum wmWorker_status { 41 | WM_WORKER_STATUS_STARTING = 1, // 42 | WM_WORKER_STATUS_RUNNING = 2, // 43 | WM_WORKER_STATUS_SHUTDOWN = 4, // 44 | WM_WORKER_STATUS_RELOADING = 8, // 45 | }; 46 | 47 | //worker_worker.h 48 | #define WM_KILL_WORKER_TIMER_TIME 2000 //2000毫秒后杀死进程 49 | 50 | /** 51 | * Connection的状态 52 | */ 53 | enum wmConnection_status { 54 | WM_CONNECTION_STATUS_INITIAL = 0, //没用上,作为客户端使用 55 | WM_CONNECTION_STATUS_CONNECTING = 1, //没用上,作为客户端使用 56 | WM_CONNECTION_STATUS_ESTABLISHED = 2, //刚建立 57 | WM_CONNECTION_STATUS_CLOSING = 4, //不用 58 | WM_CONNECTION_STATUS_CLOSED = 8 //已关闭 59 | }; 60 | 61 | //worker connection 62 | #define WM_MAX_SEND_BUFFER_SIZE 102400 //默认应用层发送缓冲区大小 1M 63 | #define WM_MAX_PACKAGE_SIZE 1024000 //每个连接能够接收的最大包包长 10M 64 | 65 | //coroutine.h 默认的PHP栈页大小 66 | #define DEFAULT_PHP_STACK_PAGE_SIZE 8192 67 | #define PHP_CORO_TASK_SLOT ((int)((ZEND_MM_ALIGNED_SIZE(sizeof(wmCoroutine)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval)))) 68 | #define DEFAULT_C_STACK_SIZE (2 *1024 * 1024) 69 | 70 | #define WM_MAXEVENTS 1024 //每次epoll可以返回的事件数量上限 71 | #define WM_BUFFER_SIZE_BIG 65536 //默认一次从管道中读字节长度 72 | #define WM_BUFFER_SIZE_DEFAULT 512 //初始化的时候的长度 73 | #define WM_DEFAULT_BACKLOG 102400 //默认listen的时候backlog最大长度,也就是等待accept的队列最大长度 74 | 75 | //file 76 | #define WM_MAX_FILE_CONTENT (64*1024*1024) //文件最大字节数 77 | 78 | //array 79 | #define WM_ARRAY_PAGE_MAX 1024 //wmArray默认的page数是多少,每一次扩展都会申请一页的内存 80 | 81 | //socket 82 | #define WM_SOCKET_MAX_TIMEOUT 2147483647 // 83 | #define WM_SOCKET_DEFAULT_CONNECT_TIMEOUT 1000 // 84 | 85 | #define wm_malloc malloc 86 | #define wm_free free 87 | #define wm_calloc calloc 88 | #define wm_realloc realloc 89 | 90 | #endif /* WM_CONFIG_H_ */ 91 | -------------------------------------------------------------------------------- /make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | /usr/local/php7/bin/phpize --clean 3 | /usr/local/php7/bin/phpize 4 | ./configure --with-php-config=/usr/local/php7/bin/php-config 5 | make clean 6 | make -j4 7 | make install -------------------------------------------------------------------------------- /make2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | make clean 3 | make -j4 4 | make install -------------------------------------------------------------------------------- /php_runtime.c: -------------------------------------------------------------------------------- 1 | /** 2 | * hook一些php的函数 3 | */ 4 | #include "runtime.h" 5 | 6 | extern PHP_METHOD(workerman_coroutine, sleep); 7 | 8 | zend_class_entry workerman_runtime_ce; 9 | zend_class_entry *workerman_runtime_ce_ptr; 10 | 11 | static void hook_func(const char *name, size_t name_len, zif_handler new_handler) { 12 | zend_function *ori_f = (zend_function*) zend_hash_str_find_ptr(EG(function_table), name, name_len); 13 | ori_f->internal_function.handler = new_handler; 14 | } 15 | 16 | ZEND_BEGIN_ARG_INFO_EX(arginfo_workerman_runtime_void, 0, 0, 0) // 17 | ZEND_END_ARG_INFO() 18 | 19 | //开启协程模式,hook相关函数 20 | void wm_enableCoroutine() { 21 | hook_func(ZEND_STRL("sleep"), zim_workerman_coroutine_sleep); 22 | // 使用socket_create这个函数,替换原来的php_stream_generic_socket_factory 23 | php_stream_xport_register("udp", wmRuntime_socket_create); 24 | php_stream_xport_register("tcp", wmRuntime_socket_create); 25 | } 26 | 27 | PHP_METHOD(workerman_runtime, enableCoroutine) { 28 | wm_enableCoroutine(); 29 | } 30 | 31 | static const zend_function_entry workerman_runtime_methods[] = { // 32 | PHP_ME(workerman_runtime, enableCoroutine, arginfo_workerman_runtime_void, ZEND_ACC_PUBLIC| ZEND_ACC_STATIC) 33 | PHP_FE_END // 34 | }; 35 | 36 | /** 37 | * 注册我们的WorkerMan\Server这个类 38 | */ 39 | void workerman_runtime_init() { 40 | 41 | //定义好一个类 42 | INIT_NS_CLASS_ENTRY(workerman_runtime_ce, "Warriorman", "Runtime", workerman_runtime_methods); 43 | //在zedn中注册类 44 | workerman_runtime_ce_ptr = zend_register_internal_class(&workerman_runtime_ce TSRMLS_CC); // 在 Zend Engine 中注册 45 | 46 | } 47 | -------------------------------------------------------------------------------- /php_timer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 定时器类 3 | */ 4 | #include "base.h" 5 | #include "timer.h" 6 | #include "worker.h" 7 | #include "coroutine.h" 8 | 9 | /** 10 | * 保存定時器和timer_id的关系 11 | */ 12 | typedef struct { 13 | long id; 14 | long cid; 15 | int ticks; 16 | bool persistent; //定时器是否循环 17 | wmTimerWheel_Node* timer; 18 | zend_fcall_info_cache fcc; 19 | zend_fcall_info fci; 20 | } php_worker_timer; 21 | 22 | static long last_id = 0; 23 | static wmHash_INT_PTR *timers = NULL; //保存所有定时器 24 | 25 | void php_wmTimer_init() { 26 | timers = wmHash_init(WM_HASH_INT_STR); 27 | } 28 | void php_wmTimer_shutdown() { 29 | wmHash_destroy(WM_HASH_INT_STR, timers); 30 | } 31 | 32 | //添加定时器 33 | ZEND_BEGIN_ARG_INFO_EX(arginfo_workerman_timer_add, 0, 0, 1) // 34 | ZEND_ARG_INFO(0, seconds) 35 | ZEND_ARG_CALLABLE_INFO(0, func, 0) 36 | ZEND_ARG_INFO(0, args1) // 如果是数组,那么后面那个就是持久化配置。如果是持久化配置,后面那个就不解析了 37 | ZEND_ARG_INFO(0, args2)// 38 | ZEND_END_ARG_INFO() 39 | 40 | //删除定时器 41 | ZEND_BEGIN_ARG_INFO_EX(arginfo_workerman_timer_resume, 0, 0, 1) // 42 | ZEND_ARG_INFO(0, timer_id) 43 | ZEND_END_ARG_INFO() 44 | 45 | static void timer_free(php_worker_timer* timer) { 46 | if (timer->timer) { 47 | wmTimerWheel_del(timer->timer); 48 | timer->timer = NULL; 49 | } 50 | zend_fcall_info_args_clear(&timer->fci, 1); 51 | //引用计数-1 52 | wm_zend_fci_cache_discard(&timer->fcc); 53 | 54 | WM_HASH_DEL(WM_HASH_INT_STR, timers, timer->id); 55 | wm_free(timer); 56 | } 57 | 58 | static void timer_add_callback(void* _timer) { 59 | php_worker_timer* timer = (php_worker_timer*) _timer; 60 | timer->timer = NULL; 61 | timer->cid = wmCoroutine_create(&timer->fcc, timer->fci.param_count, timer->fci.params); 62 | if (!timer->persistent || wmWorker_getCurrent()->_status == WM_WORKER_STATUS_RELOADING) { 63 | timer_free(timer); 64 | return; 65 | } 66 | //如果不退出,那么继续循环 67 | timer->timer = wmTimerWheel_add_quick(&WorkerG.timer, timer_add_callback, (void*) timer, timer->ticks); 68 | } 69 | 70 | //协程创建实现 71 | PHP_METHOD(workerman_timer, add) { 72 | double seconds; 73 | zval *args1 = NULL; 74 | zval *args2 = NULL; 75 | //在这里创建一个定时器 76 | php_worker_timer* timer = wm_malloc(sizeof(php_worker_timer)); 77 | timer->timer = NULL; 78 | timer->persistent = true; 79 | //第一个参数表示必传的参数个数,第二个参数表示最多传入的参数个数,-1代表可变参数 80 | ZEND_PARSE_PARAMETERS_START(2, 4) 81 | Z_PARAM_DOUBLE(seconds) 82 | Z_PARAM_FUNC(timer->fci, timer->fcc) 83 | Z_PARAM_OPTIONAL 84 | Z_PARAM_ZVAL(args1) 85 | Z_PARAM_ZVAL(args2) 86 | ZEND_PARSE_PARAMETERS_END_EX(efree(timer); RETURN_FALSE); 87 | if (UNEXPECTED(seconds < 0.001)) { 88 | php_error_docref(NULL, E_WARNING, "Timer must be greater than or equal to 0.001"); 89 | RETURN_FALSE 90 | } 91 | //如果第一个参数数数组的话 92 | if (args1) { 93 | if (Z_TYPE_P(args1) == IS_ARRAY) { 94 | if (args2 && Z_TYPE_P(args2) == IS_FALSE) { 95 | timer->persistent = false; 96 | } 97 | //在这里解析数组 98 | zend_fcall_info_args(&timer->fci, args1); 99 | timer->fci.retval = NULL; 100 | } else if (Z_TYPE_P(args1) == IS_FALSE) { 101 | timer->persistent = false; 102 | } 103 | } 104 | timer->id = ++last_id; 105 | timer->ticks = seconds * 1000; 106 | 107 | //fcc的引用计数+1 108 | wm_zend_fci_cache_persist(&timer->fcc); 109 | 110 | if (WM_HASH_ADD(WM_HASH_INT_STR, timers, timer->id,timer) < 0) { 111 | wmWarn("workerman_timer_add-> fail"); 112 | timer_free(timer); 113 | RETURN_FALSE 114 | } 115 | timer->timer = wmTimerWheel_add_quick(&WorkerG.timer, timer_add_callback, (void*) timer, timer->ticks); 116 | RETURN_LONG(timer->id) 117 | } 118 | 119 | //删除定时器 120 | PHP_METHOD(workerman_timer, del) { 121 | zend_long timer_id = 0; 122 | ZEND_PARSE_PARAMETERS_START(1, 1) 123 | Z_PARAM_LONG(timer_id) 124 | ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); 125 | 126 | php_worker_timer* timer = WM_HASH_GET(WM_HASH_INT_STR, timers, timer_id); 127 | if (!timer) { 128 | wmWarn("timer_id not exist"); 129 | RETURN_FALSE 130 | } 131 | timer_free(timer); 132 | RETURN_TRUE 133 | } 134 | 135 | const zend_function_entry workerman_timer_methods[] = { // 136 | PHP_ME(workerman_timer, add, arginfo_workerman_timer_add, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) // 137 | PHP_ME(workerman_timer, del, arginfo_workerman_timer_resume, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) // 138 | PHP_FE_END // 139 | }; 140 | 141 | /** 142 | * 定义 zend class entry 143 | */ 144 | zend_class_entry workerman_timer_ce; 145 | zend_class_entry *workerman_timer_ce_ptr; 146 | 147 | /** 148 | * 注册我们的Warriorman\Timer这个类 149 | */ 150 | void workerman_timer_init() { 151 | //定义好一个类 152 | INIT_NS_CLASS_ENTRY(workerman_timer_ce, "Warriorman", "Lib\\Timer", workerman_timer_methods); 153 | //在zedn中注册类 154 | workerman_timer_ce_ptr = zend_register_internal_class(&workerman_timer_ce TSRMLS_CC); // 在 Zend Engine 中注册 155 | } 156 | -------------------------------------------------------------------------------- /php_workerman.c: -------------------------------------------------------------------------------- 1 | /* workerman extension for PHP */ 2 | #include "workerman.h" 3 | #include "base.h" 4 | #include "worker.h" 5 | #include "connection.h" 6 | #include "runtime.h" 7 | 8 | //创建协程接口方法声明 9 | PHP_FUNCTION(workerman_coroutine_create); 10 | 11 | //创建协程接口参数声明 12 | ZEND_BEGIN_ARG_INFO_EX(arginfo_workerman_coroutine_create, 0, 0, 1) // 13 | ZEND_ARG_CALLABLE_INFO(0, func, 0) 14 | ZEND_END_ARG_INFO() 15 | 16 | /** 17 | * 模块初始化阶段 18 | * 这个阶段不要使用php内存管理,比如emalloc申请内存。 19 | */ 20 | PHP_MINIT_FUNCTION(workerman) { 21 | //初始化协程定义 22 | workerman_coroutine_init(); 23 | //初始化connection 24 | workerman_connection_init(); 25 | //初始化worker相关 26 | workerman_worker_init(); 27 | //初始化channel 28 | workerman_channel_init(); 29 | //初始化runtime 30 | workerman_runtime_init(); 31 | //初始化定时器 32 | workerman_timer_init(); 33 | return SUCCESS; 34 | } 35 | 36 | /** 37 | * 模块关闭阶段 38 | */ 39 | PHP_MSHUTDOWN_FUNCTION(workerman) { 40 | return SUCCESS; 41 | } 42 | 43 | /** 44 | * 请求初始化阶段 45 | */ 46 | PHP_RINIT_FUNCTION(workerman) { 47 | //初始化base相关 48 | workerman_base_init(); 49 | wmCoroutine_init(); 50 | wmWorker_init(); 51 | wmConnection_init(); 52 | wmRuntime_init(); 53 | php_wmTimer_init(); 54 | return SUCCESS; 55 | } 56 | 57 | /** 58 | * 请求关闭阶段 59 | */ 60 | PHP_RSHUTDOWN_FUNCTION(workerman) { 61 | workerman_base_shutdown(); 62 | wmCoroutine_shutdown(); 63 | wmWorker_shutdown(); 64 | wmConnection_shutdown(); 65 | wmRuntime_shutdown(); 66 | php_wmTimer_shutdown(); 67 | return SUCCESS; 68 | } 69 | 70 | /** 71 | * phpinfo相关信息 72 | */ 73 | PHP_MINFO_FUNCTION(workerman) { 74 | php_info_print_table_start(); 75 | php_info_print_table_header(2, "workerman support", "enabled"); 76 | php_info_print_table_end(); 77 | } 78 | 79 | static const zend_function_entry workerman_functions[] = { // 80 | PHP_FE(workerman_coroutine_create, arginfo_workerman_coroutine_create) // 81 | PHP_FALIAS(work, workerman_coroutine_create, arginfo_workerman_coroutine_create) // 82 | PHP_FE_END }; 83 | 84 | zend_module_entry workerman_module_entry = { 85 | STANDARD_MODULE_HEADER, "workerman", // 86 | workerman_functions, // 87 | PHP_MINIT(workerman), 88 | PHP_MSHUTDOWN(workerman), 89 | PHP_RINIT(workerman), 90 | PHP_RSHUTDOWN(workerman), 91 | PHP_MINFO(workerman), 92 | PHP_WORKERMAN_VERSION, // 93 | STANDARD_MODULE_PROPERTIES // 94 | }; 95 | 96 | #ifdef COMPILE_DL_WORKERMAN 97 | # ifdef ZTS 98 | ZEND_TSRMLS_CACHE_DEFINE() 99 | # endif 100 | ZEND_GET_MODULE(workerman) 101 | #endif 102 | 103 | -------------------------------------------------------------------------------- /src/core/array.c: -------------------------------------------------------------------------------- 1 | #include "header.h" 2 | #include "array.h" 3 | #include "log.h" 4 | 5 | /** 6 | * 创建数组 7 | */ 8 | wmArray *wmArray_new(int page_size, size_t item_size) { 9 | wmArray *array = wm_malloc(sizeof(wmArray)); 10 | if (array == NULL) { 11 | wmWarn("malloc[0] failed"); 12 | return NULL; 13 | } 14 | bzero(array, sizeof(wmArray)); 15 | 16 | //一个数组最多有1024个页 17 | array->pages = wm_malloc(sizeof(void*) * WM_ARRAY_PAGE_MAX); 18 | if (array->pages == NULL) { 19 | wm_free(array); 20 | wmWarn("malloc[1] failed"); 21 | return NULL; 22 | } 23 | 24 | array->item_size = item_size; //每个元素的大小 25 | array->page_size = page_size; //每页的大小 26 | 27 | //先为第一页申请内存 28 | wmArray_extend(array); 29 | 30 | return array; 31 | } 32 | 33 | /** 34 | * Destroy the array 35 | */ 36 | void wmArray_free(wmArray *array) { 37 | int i; 38 | for (i = 0; i < array->page_num; i++) { 39 | wm_free(array->pages[i]); 40 | } 41 | wm_free(array->pages); 42 | wm_free(array); 43 | } 44 | 45 | /** 46 | * 扩展数组 47 | */ 48 | int wmArray_extend(wmArray *array) { 49 | //已经达到最大页数,不给申请内存了 50 | if (array->page_num == WM_ARRAY_PAGE_MAX) { 51 | wmWarn("max page_num is %d", array->page_num); 52 | return false; 53 | } 54 | //给第array->page_num页申请内存 55 | array->pages[array->page_num] = wm_calloc(array->page_size, array->item_size); 56 | if (array->pages[array->page_num] == NULL) { 57 | wmWarn("malloc[1] failed"); 58 | return false; 59 | } 60 | //页数增加 61 | array->page_num++; 62 | return true; 63 | } 64 | 65 | /** 66 | * 通过下标查找元素 67 | */ 68 | void *wmArray_find(wmArray *array, uint32_t n) { 69 | //计算对应的页数 70 | int page = wmArray_page(array, n); 71 | if (page >= array->page_num) { 72 | return NULL; 73 | } 74 | //对应页的指针+位移量 75 | return (char*) array->pages[page] + (wmArray_offset(array, n) * array->item_size); 76 | } 77 | 78 | /** 79 | * 添加元素,返回下标 80 | */ 81 | int wmArray_add(wmArray *array, void *data) { 82 | int n = array->offset++; //下标 83 | int page = wmArray_page(array, n); //对应页数 84 | //如果是新页,申请内存 85 | if (page >= array->page_num && wmArray_extend(array) == false) { 86 | return false; 87 | } 88 | //元素数量 89 | array->item_num++; 90 | memcpy((char*) array->pages[page] + (wmArray_offset(array, n) * array->item_size), data, array->item_size); 91 | return n; 92 | } 93 | 94 | /** 95 | * 替换 96 | */ 97 | int wmArray_set(wmArray *array, uint32_t n, void *data) { 98 | int page = wmArray_page(array, n); 99 | if (page >= array->page_num) { 100 | wmWarn("find index[%d] out of array", n); 101 | return false; 102 | } 103 | memcpy((char*) array->pages[page] + (wmArray_offset(array, n) * array->item_size), data, array->item_size); 104 | return true; 105 | } 106 | 107 | void wmArray_printf(wmArray *array) { 108 | for (int i = 0; i < array->offset; i++) { 109 | int *pid = wmArray_find(array, i); 110 | php_printf("key=%d value=%d \n", i, *pid); 111 | } 112 | } 113 | 114 | /** 115 | * 没找到就申请 116 | */ 117 | void *wmArray_alloc(wmArray *array, uint32_t n) { 118 | while (n >= array->page_num * array->page_size) { 119 | if (wmArray_extend(array) == false) { 120 | return NULL; 121 | } 122 | } 123 | 124 | int page = wmArray_page(array, n); 125 | if (page >= array->page_num) { 126 | wmWarn("find index[%d] out of array", n); 127 | return NULL; 128 | } 129 | return (char*) array->pages[page] + (wmArray_offset(array, n) * array->item_size); 130 | } 131 | 132 | //重新开始 133 | void wmArray_clear(wmArray *array) { 134 | array->offset = 0; 135 | array->item_num = 0; 136 | } 137 | -------------------------------------------------------------------------------- /src/core/file.c: -------------------------------------------------------------------------------- 1 | #include "header.h" 2 | #include "log.h" 3 | #include "wm_string.h" 4 | #include "file.h" 5 | 6 | int wm_tmpfile(char *filename) { 7 | #if defined(HAVE_MKOSTEMP) && defined(HAVE_EPOLL) 8 | int tmp_fd = mkostemp(filename, O_WRONLY | O_CREAT); 9 | #else 10 | int tmp_fd = mkstemp(filename); 11 | #endif 12 | if (tmp_fd < 0) { 13 | wmWarn("mkstemp(%s) failed", filename); 14 | return -1; 15 | } else { 16 | return tmp_fd; 17 | } 18 | } 19 | 20 | long wm_file_get_size(FILE *fp) { 21 | long pos = ftell(fp); 22 | if (fseek(fp, 0L, SEEK_END) < 0) { 23 | return -1; 24 | } 25 | long size = ftell(fp); 26 | if (fseek(fp, pos, SEEK_SET) < 0) { 27 | return -1; 28 | } 29 | return size; 30 | } 31 | 32 | long wm_file_size(const char *filename) { 33 | struct stat file_stat; 34 | if (lstat(filename, &file_stat) < 0) { 35 | wmWarn("lstat(%s) failed", filename); 36 | return -1; 37 | } 38 | if ((file_stat.st_mode & S_IFMT) != S_IFREG) { 39 | wmWarn("file_mode not a S_IFREG (%s) failed", filename); 40 | return -1; 41 | } 42 | return file_stat.st_size; 43 | } 44 | 45 | wmString* wm_file_get_contents(const char *filename) { 46 | long filesize = wm_file_size(filename); 47 | if (filesize < 0) { 48 | return NULL; 49 | } else if (filesize == 0) { 50 | wmTrace("file[%s] is empty", filename); 51 | return NULL; 52 | } else if (filesize > WM_MAX_FILE_CONTENT) { 53 | wmWarn("file[%s] is too large", filename); 54 | return NULL; 55 | } 56 | 57 | int fd = open(filename, O_RDONLY); 58 | if (fd < 0) { 59 | wmWarn("open(%s) failed", filename); 60 | return NULL; 61 | } 62 | wmString *content = wmString_new(filesize); 63 | if (!content) { 64 | close(fd); 65 | return NULL; 66 | } 67 | 68 | int readn = 0; 69 | int n; 70 | 71 | while (readn < filesize) { 72 | n = pread(fd, content->str + readn, filesize - readn, readn); 73 | if (n < 0) { 74 | if (errno == EINTR) { 75 | continue; 76 | } else { 77 | wmWarn("pread(%d, %ld, %d) failed", fd, filesize - readn, readn); 78 | wmString_free(content); 79 | close(fd); 80 | return NULL; 81 | } 82 | } 83 | readn += n; 84 | } 85 | close(fd); 86 | content->length = readn; 87 | return content; 88 | } 89 | 90 | int wm_file_put_contents(const char *filename, const char *content, size_t length, bool append) { 91 | if (length <= 0) { 92 | wmTrace("wm_file_put_contents(%s) content is empty", filename); 93 | return false; 94 | } 95 | if (length > WM_MAX_FILE_CONTENT) { 96 | wmWarn("wm_file_put_contents(%s) content is too large", filename); 97 | return false; 98 | } 99 | 100 | int flags = O_WRONLY | O_CREAT; 101 | if (append) { 102 | flags = flags | O_APPEND; 103 | } else { 104 | flags = flags | O_TRUNC; 105 | } 106 | 107 | int fd = open(filename, flags, 0666); 108 | if (fd < 0) { 109 | wmWarn("open(%s) failed", filename); 110 | return false; 111 | } 112 | 113 | int n, chunk_size, written = 0; 114 | 115 | while (written < length) { 116 | chunk_size = length - written; 117 | if (chunk_size > WM_BUFFER_SIZE_BIG) { 118 | chunk_size = WM_BUFFER_SIZE_BIG; 119 | } 120 | n = write(fd, content + written, chunk_size); 121 | if (n < 0) { 122 | if (errno == EINTR) { 123 | continue; 124 | } else { 125 | wmWarn("write(%d, %d) failed", fd, chunk_size); 126 | close(fd); 127 | return false; 128 | } 129 | } 130 | written += n; 131 | } 132 | close(fd); 133 | return true; 134 | } 135 | -------------------------------------------------------------------------------- /src/core/log.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | 3 | char wm_debug[WM_DEBUG_MSG_SIZE]; 4 | char wm_trace[WM_TRACE_MSG_SIZE]; 5 | char wm_warn[WM_WARN_MSG_SIZE]; 6 | char wm_error[WM_ERROR_MSG_SIZE]; 7 | 8 | void wmLog_put(int level, char *cnt) { 9 | const char *level_wmr; 10 | char date_wmr[WM_LOG_DATE_WMRLEN]; 11 | char log_wmr[WM_LOG_BUFFER_SIZE]; 12 | int n; 13 | time_t t; 14 | struct tm *p; 15 | 16 | switch (level) { 17 | case WM_LOG_DEBUG: 18 | level_wmr = "DEBUG"; 19 | break; 20 | case WM_LOG_NOTICE: 21 | level_wmr = "NOTICE"; 22 | break; 23 | case WM_LOG_ERROR: 24 | level_wmr = "ERROR"; 25 | break; 26 | case WM_LOG_WARNING: 27 | level_wmr = "WARNING"; 28 | break; 29 | case WM_LOG_TRACE: 30 | level_wmr = "TRACE"; 31 | break; 32 | default: 33 | level_wmr = "INFO"; 34 | break; 35 | } 36 | 37 | t = time(NULL); 38 | p = localtime(&t); 39 | snprintf(date_wmr, WM_LOG_DATE_WMRLEN, "%d-%02d-%02d %02d:%02d:%02d", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec); 40 | n = snprintf(log_wmr, WM_LOG_BUFFER_SIZE, "[%s]\t%s\t%s\n", date_wmr, level_wmr, cnt); 41 | if (write(STDOUT_FILENO, log_wmr, n) < 0) { 42 | php_printf("write(log_fd, size=%d) failed. Error: %s[%d].\n", n, strerror(errno), errno); 43 | } 44 | } 45 | 46 | const char* wmCode_str(int code) { 47 | if (code < 1000) { 48 | return strerror(code); 49 | } 50 | switch (code) { 51 | case WM_ERROR_SESSION_CLOSED_BY_SERVER: 52 | return "Session closed by worker"; 53 | break; 54 | case WM_ERROR_SESSION_CLOSED_BY_CLIENT: 55 | return "Session closed by client"; 56 | break; 57 | case WM_ERROR_SESSION_CLOSED: 58 | return "Session has closed"; 59 | break; 60 | case WM_ERROR_SEND_FAIL: 61 | return "send buffer full and drop package"; 62 | break; 63 | case WM_ERROR_READ_FAIL: 64 | return "read buffer error"; 65 | break; 66 | case WM_ERROR_LOOP_FAIL: 67 | return "loop error"; 68 | break; 69 | case WM_ERROR_SEND_BUFFER_FULL: 70 | return "send buffer full"; 71 | break; 72 | case WM_ERROR_PROTOCOL_FAIL: 73 | return "protocol fail"; 74 | break; 75 | default: 76 | snprintf(wm_error, sizeof(wm_error), "Unknown error: %d", code); 77 | return wm_error; 78 | break; 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /src/core/socket.c: -------------------------------------------------------------------------------- 1 | #include "header.h" 2 | #include "log.h" 3 | #include "socket.h" 4 | 5 | /** 6 | * 创建套接字 7 | */ 8 | int wm_socket_create(int domain, int type, int protocol) { 9 | int sock; 10 | sock = socket(domain, type, protocol); 11 | if (sock < 0) { 12 | wmWarn("Error has occurred: (errno %d) %s", errno, strerror(errno)); 13 | } 14 | return sock; 15 | } 16 | 17 | /** 18 | * 设置为非阻塞模式 19 | */ 20 | int wm_socket_set_nonblock(int sock) { 21 | int flags; 22 | //用来获取这个socket原来的一些属性。 23 | flags = fcntl(sock, F_GETFL, 0); 24 | if (flags < 0) { 25 | wmWarn("Error has occurred: (errno %d) %s", errno, strerror(errno)); 26 | return -1; 27 | } 28 | //在原来的属性上加上非阻塞的属性。 29 | flags = fcntl(sock, F_SETFL, flags | O_NONBLOCK); 30 | if (flags < 0) { 31 | wmWarn("Error has occurred: (errno %d) %s", errno, strerror(errno)); 32 | return -1; 33 | } 34 | return 0; 35 | } 36 | 37 | /** 38 | * 对bind()函数进行了封装 39 | */ 40 | int wm_socket_bind(int sock, char *host, int port) { 41 | int ret; 42 | struct sockaddr_in servaddr; 43 | 44 | //初始化servaddr 45 | bzero(&servaddr, sizeof(servaddr)); 46 | //将host转换为网络结构体sockaddr_in 47 | inet_aton(host, &(servaddr.sin_addr)); 48 | servaddr.sin_family = AF_INET; 49 | servaddr.sin_port = htons(port); 50 | //把socket和地址,端口绑定 51 | ret = bind(sock, (struct sockaddr*) &servaddr, sizeof(servaddr)); 52 | if (ret < 0) { 53 | return -1; 54 | } 55 | 56 | return ret; 57 | } 58 | 59 | /** 60 | * 对connect进行封装 61 | */ 62 | int wm_socket_connect(int sock, char *host, int port) { 63 | if (port <= 0 || port >= 65536) { 64 | wmWarn("Invalid port [%d]", port); 65 | return -1; 66 | } 67 | 68 | int ret; 69 | struct sockaddr_in servaddr; 70 | 71 | //初始化servaddr 72 | bzero(&servaddr, sizeof(servaddr)); 73 | //将host转换为网络结构体sockaddr_in 74 | inet_aton(host, &(servaddr.sin_addr)); 75 | servaddr.sin_family = AF_INET; 76 | servaddr.sin_port = htons(port); 77 | //把socket和地址,端口绑定 78 | ret = connect(sock, (struct sockaddr*) &servaddr, sizeof(servaddr)); 79 | if (ret < 0) { 80 | return -1; 81 | } 82 | return ret; 83 | } 84 | 85 | int wm_socket_listen(int sock, int backlog) { 86 | int ret; 87 | 88 | ret = listen(sock, backlog); 89 | if (ret < 0) { 90 | wmWarn("Error has occurred: (errno %d) %s", errno, strerror(errno)); 91 | } 92 | return ret; 93 | } 94 | 95 | int wm_socket_accept(int sock, struct sockaddr_in *sa, socklen_t *len) { 96 | int connfd; 97 | connfd = accept(sock, (struct sockaddr*) sa, len); 98 | //errno != EAGAIN 不能再读了 99 | if (connfd < 0 && errno != EAGAIN) { 100 | wmWarn("Error has occurred: (errno %d) %s", errno, strerror(errno)); 101 | } 102 | return connfd; 103 | } 104 | 105 | ssize_t wm_socket_recv(int sock, void *buf, size_t len, int flag) { 106 | ssize_t ret; 107 | 108 | /** 109 | * 成功返回发送的字节数;失败返回-1,同时errno被设置 110 | * 111 | * flags 一般设置为0,此时send为阻塞式发送 112 | * 即发送不成功会一直阻塞,直到被某个信号终端终止,或者直到发送成功为止。 113 | * 指定MSG_NOSIGNAL,表示当连接被关闭时不会产生SIGPIPE信号 114 | * 指定MSG_DONTWAIT 表示非阻塞发送 115 | * 指定MSG_OOB 表示带外数据 116 | */ 117 | ret = recv(sock, buf, len, flag); 118 | if (ret < 0 && errno != EAGAIN) { 119 | //wmWarn("Error has occurred: (errno %d) %s", errno, strerror(errno)); 120 | } 121 | return ret; 122 | } 123 | 124 | ssize_t wm_socket_send(int sock, const void *buf, size_t len, int flag) { 125 | ssize_t ret; 126 | 127 | ret = send(sock, buf, len, flag); 128 | if (ret < 0 && errno != EAGAIN) { 129 | //wmWarn("Error has occurred: (fd=%d,errno %d) %s", sock, errno, strerror(errno)); 130 | } 131 | return ret; 132 | } 133 | 134 | int wm_socket_close(int fd) { 135 | int ret; 136 | ret = close(fd); 137 | if (ret < 0) { 138 | //wmWarn("Error has occurred: (fd=%d,errno %d) %s", fd, errno, strerror(errno)); 139 | } 140 | return ret; 141 | } 142 | 143 | int wm_socket_reuse_port(int fd) { 144 | int reusePort = 1; 145 | int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &reusePort, sizeof(reusePort)); 146 | if (ret < 0) { 147 | wmWarn("Error has occurred: (fd=%d,errno %d) %s", fd, errno, strerror(errno)); 148 | } 149 | return ret; 150 | } 151 | -------------------------------------------------------------------------------- /src/coroutine/channel.c: -------------------------------------------------------------------------------- 1 | #include "channel.h" 2 | #include "coroutine.h" 3 | 4 | static void sleep_timeout(void *param); 5 | 6 | //这个结构体,是用来控制协程,不在错误的时间co->resume的 7 | typedef struct { 8 | wmCoroutine* co; 9 | bool type; //是否需要被唤醒 10 | } WmChannelCoroutineType; 11 | 12 | wmChannel* wmChannel_create(uint32_t _capacity) { 13 | wmChannel* channel = (wmChannel *) wm_malloc(sizeof(wmChannel)); 14 | bzero(channel, sizeof(wmChannel)); 15 | channel->capacity = _capacity; 16 | channel->producer_queue = wmQueue_create(); 17 | channel->consumer_queue = wmQueue_create(); 18 | channel->data_queue = wmQueue_create(); 19 | return channel; 20 | } 21 | 22 | //插入 23 | bool wmChannel_push(wmChannel* channel, void *data, double timeout) { 24 | //获取当前协程 25 | wmCoroutine *co = wmCoroutine_get_current(); 26 | //如果当前channel内容,已到channel上限 27 | if (channel->data_queue->num == channel->capacity) { 28 | WmChannelCoroutineType* wct = NULL; 29 | //如果设置了超时时间 30 | if (timeout > 0) { 31 | wct = (WmChannelCoroutineType *) wm_malloc(sizeof(WmChannelCoroutineType)); 32 | wct->co = co; 33 | wct->type = true; 34 | //就添加到定时器中,定时器到时间,会把当前这个协程再唤醒 35 | wmTimerWheel_add_quick(&WorkerG.timer, sleep_timeout, (void*) wct, timeout * 1000); 36 | } 37 | //把当前协程,加入生产者协程等待队列中 38 | wmQueue_push(channel->producer_queue, co); 39 | //协程暂时yield,等待定时器超时时间结束,或者消费者通知 40 | wmCoroutine_yield(co); 41 | //协程已经醒了,就不需要被唤醒了 42 | if (wct) { 43 | wct->type = false; 44 | } 45 | } 46 | 47 | // 定时器结束,或者未设置timeout 48 | 49 | /** 50 | * 这个时候如果channel还是满的,那直接返回false,我存不进去 51 | */ 52 | if (channel->data_queue->num == channel->capacity) { 53 | return false; 54 | } 55 | 56 | //如果没满的话,就把数据加入channel队列中,这个时候channel中已经有数据了 57 | wmQueue_push(channel->data_queue, data); 58 | 59 | /** 60 | * 那就通知消费者,来消费 61 | */ 62 | 63 | while (channel->consumer_queue->num > 0) { 64 | //唤醒一个消费者 65 | co = (wmCoroutine*) wmQueue_pop(channel->consumer_queue); 66 | if (!co) { 67 | continue; 68 | } 69 | wmCoroutine_resume(co); 70 | break; 71 | } 72 | //消费者协程退出控制权的话,那么这边也返回 73 | return true; 74 | } 75 | 76 | //弹出 77 | void* wmChannel_pop(wmChannel* channel, double timeout) { 78 | //获取当前协程 79 | wmCoroutine *co = wmCoroutine_get_current(); 80 | //准备接受pop的数据 81 | void *data; 82 | 83 | //如果当前channel已经空了,也就是弹不出来了 84 | if (channel->data_queue->num == 0) { 85 | WmChannelCoroutineType* wct = NULL; 86 | //如果设置了超时时间 87 | if (timeout > 0) { 88 | wct = (WmChannelCoroutineType *) wm_malloc(sizeof(WmChannelCoroutineType)); 89 | wct->co = co; 90 | wct->type = true; 91 | //就添加到定时器中,定时器到时间,会把这个协程再唤醒 92 | wmTimerWheel_add_quick(&WorkerG.timer, sleep_timeout, (void*) wct, timeout * 1000); 93 | } 94 | //加入消费者等待队列中 95 | wmQueue_push(channel->consumer_queue, co); 96 | //协程暂时yield,等待定时器超时时间结束 97 | wmCoroutine_yield(co); 98 | //协程已经醒了,就不需要被定时器唤醒了 99 | if (wct) { 100 | wct->type = false; 101 | } 102 | } 103 | 104 | //协程timeout恢复运行的时候.如果还是没有等到channel数据,那么返回空 105 | if (channel->data_queue->num == 0) { 106 | return NULL; 107 | } 108 | 109 | //取一个数据 110 | data = wmQueue_pop(channel->data_queue); 111 | 112 | /** 113 | * 通知生产者 114 | */ 115 | while (channel->producer_queue->num > 0) { 116 | //然后如果有生产者协程在等待,那么就resume那个生产者协程。 117 | //最后,等生产者协程执行完毕,或者生产者协程主动yield,才会回到消费者协程,最后返回data。 118 | co = (wmCoroutine*) wmQueue_pop(channel->producer_queue); 119 | //如果这个生产者,等不及已经退出了 120 | if (!co) { 121 | continue; 122 | } 123 | wmCoroutine_resume(co); 124 | break; 125 | } 126 | return data; 127 | } 128 | 129 | /** 130 | * 协程内多少元素 131 | */ 132 | int wmChannel_num(wmChannel* channel) { 133 | return channel->data_queue->num; 134 | } 135 | 136 | void wmChannel_clear(wmChannel* channel) { 137 | zval *data; 138 | while (wmChannel_num(channel) > 0) { 139 | data = (zval *) wmQueue_pop(channel->data_queue); 140 | zval_ptr_dtor(data); 141 | efree(data); 142 | } 143 | data = NULL; 144 | } 145 | 146 | void wmChannel_free(wmChannel* channel) { 147 | wmChannel_clear(channel); 148 | //唤醒所有,告诉他们不用等了。channel死了 149 | wmCoroutine* co; 150 | while (channel->consumer_queue->num > 0) { 151 | co = (wmCoroutine*) wmQueue_pop(channel->consumer_queue); 152 | if (!co) { 153 | continue; 154 | } 155 | wmCoroutine_resume(co); 156 | } 157 | while (channel->producer_queue->num > 0) { 158 | co = (wmCoroutine*) wmQueue_pop(channel->producer_queue); 159 | if (!co) { 160 | continue; 161 | } 162 | wmCoroutine_resume(co); 163 | } 164 | wm_free(channel->data_queue); 165 | wm_free(channel->consumer_queue); 166 | wm_free(channel->producer_queue); 167 | wm_free(channel); 168 | channel = NULL; 169 | } 170 | 171 | /** 172 | * 超时 173 | */ 174 | void sleep_timeout(void *param) { 175 | WmChannelCoroutineType * wct = ((WmChannelCoroutineType *) param); 176 | wmCoroutine * co = wct->co; 177 | bool type = wct->type; 178 | wm_free(wct); 179 | wct = NULL; 180 | //是否需要被唤醒 181 | if (type) { 182 | //让协程恢复原来的执行状态 183 | wmCoroutine_resume(co); 184 | } 185 | } 186 | 187 | -------------------------------------------------------------------------------- /src/coroutine/context.c: -------------------------------------------------------------------------------- 1 | #include "header.h" 2 | #include "context.h" 3 | 4 | static void wmContext_func(void *arg); 5 | 6 | /** 7 | * 初始化Context 8 | */ 9 | void wmContext_init(wmContext *ctx, size_t stack_size, coroutine_func_t fn, void* private_data) { 10 | ctx->end_ = false; 11 | ctx->stack_size_ = stack_size; 12 | ctx->private_data_ = private_data; 13 | ctx->fn_ = fn; 14 | ctx->swap_ctx_ = NULL; 15 | //是创建一个C栈(实际上是从堆中分配的内存)。 16 | ctx->stack_ = (char*) wm_malloc(ctx->stack_size_); 17 | 18 | //传入模拟的stack的结束指针位置 19 | //代码是把堆模拟成栈的行为。与之前PHP栈的操作类似。 20 | void* sp = (void*) ((char*) ctx->stack_ + ctx->stack_size_); 21 | 22 | //这行代码是设置这个最底层的协程的上下文ctx_,比如栈地址,栈大小,协程的入口函数context_func。 23 | //而make_fcontext这个设置上下文的函数式用的boost.asm里面的库。 24 | ctx->ctx_ = make_fcontext(sp, ctx->stack_size_, (void (*)(intptr_t)) &wmContext_func); // 25 | } 26 | 27 | /** 28 | * 执行php协程,并且切换上下文 29 | */ 30 | void wmContext_func(void *arg) { 31 | 32 | wmContext *_this = (wmContext *) arg; 33 | //调用了fn,也就是WorkerCoroutine::create_func 34 | _this->fn_(_this->private_data_); 35 | 36 | //swap_out的作用是让出当前协程的上下文,去加载其他协程的上下文。 37 | //就是当我们跑完了这个协程,需要恢复其他的协程的上下文,让其他的协程继续运行。我们要应该把当前执行的php方法栈弹出,出栈操作.我们在run里面操作 38 | _this->end_ = true; 39 | 40 | //执行完在这里直接让出控制权 41 | wmContext_swap_out(_this); 42 | } 43 | 44 | /** 45 | * 切换到新栈,并且保存老栈 46 | * 保存当前c栈上下文到swap_ctx_的位置,然后从ctx_切换上下文 47 | */ 48 | bool wmContext_swap_in(wmContext *ctx) { 49 | jump_fcontext(&ctx->swap_ctx_, ctx->ctx_, (intptr_t) ctx, true); 50 | return true; 51 | } 52 | 53 | /** 54 | * 切换到父栈 55 | * 从ctx->swap_ctx_处恢复上下文,swap_ctx_就是父C栈 56 | * 把当前C栈上下文保存在ctx_中,然后切换到swap_ctx_ 57 | */ 58 | bool wmContext_swap_out(wmContext *ctx) { 59 | jump_fcontext(&ctx->ctx_, ctx->swap_ctx_, (intptr_t) ctx, true); 60 | return true; 61 | } 62 | 63 | //每次删除所创建的对象时执行 64 | void wmContext_destroy(wmContext *ctx) { 65 | if (ctx->stack_) { 66 | //施放内存 67 | wm_free(ctx->stack_); 68 | ctx->stack_ = NULL; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/worker/signal.c: -------------------------------------------------------------------------------- 1 | #include "header.h" 2 | #include "wm_signal.h" 3 | #include "socket.h" 4 | #include "loop.h" 5 | 6 | /** 7 | * 创建的信号通道 8 | * 载epoll版本信号 9 | * [0] 是读 10 | * [1] 是写 11 | */ 12 | static int signal_fd[2] = { 0, 0 }; 13 | static signal_func_t signal_handler_array[64]; 14 | static char signals[1024]; 15 | 16 | /** 17 | * 一旦出现信号,写入signal_fd中 18 | */ 19 | void sig_handler(int signalno) { 20 | //保留原来的errno,在函数最后回复,以保证函数的可重入性 21 | int save_errno = errno; 22 | int msg = signalno; 23 | 24 | //将信号值写入管代,通知主循环。 25 | //向1里面写,从0里面读 26 | if (wm_socket_send(signal_fd[1], (char*) &msg, 1, 0) <= 0) { 27 | php_printf("The message sent to the server failed\n"); 28 | } 29 | errno = save_errno; 30 | } 31 | 32 | /** 33 | * 等待&处理signal信号 34 | */ 35 | void wmSignal_wait() { 36 | wmSocket *socket = wmSocket_pack(signal_fd[0], WM_SOCK_TCP, WM_LOOP_SEMI_AUTO); 37 | //监听read事件 38 | wmWorkerLoop_add(socket, WM_EVENT_READ); 39 | while (1) { 40 | int ret = wmSocket_read(socket, signals, 1024, WM_SOCKET_MAX_TIMEOUT); 41 | if (ret < 0 && errno != ETIMEDOUT) { 42 | break; 43 | } 44 | //每个信号值占1字节,所以按字节来逐个接收信号 45 | for (int i = 0; i < ret; ++i) { 46 | int signal = signals[i]; 47 | if (signal_handler_array[signal] != 0) { 48 | signal_handler_array[signal](signals[i]); 49 | } 50 | } 51 | } 52 | wmError("signal socket closed. server exist") 53 | 54 | } 55 | 56 | void wmSignal_add(int signal, signal_func_t fn) { 57 | if (signal_fd[0] == 0) { 58 | //创建一对互相连接的,全双工管道 59 | if (socketpair(PF_UNIX, SOCK_STREAM, 0, signal_fd) == -1) { 60 | wmError("socketpair"); 61 | } 62 | /* sockpair函数创建的管道是全双工的,不区分读写端 63 | * 此处我们假设pipe_fd[1]为写端,非阻塞 64 | * pipe_fd[0]为读端 65 | */ 66 | wm_socket_set_nonblock(signal_fd[0]); 67 | wm_socket_set_nonblock(signal_fd[1]); 68 | } 69 | 70 | struct sigaction act; 71 | bzero(&act, sizeof(act)); 72 | act.sa_handler = sig_handler; //设置信号处理函数 73 | sigfillset(&act.sa_mask); //初始化信号屏蔽集 74 | act.sa_flags |= SA_RESTART; //由此信号中断的系统调用自动重启动 75 | 76 | //初始化信号处理函数 77 | if (sigaction(signal, &act, NULL) == -1) { 78 | php_printf("capture signal,but to deal with failure\n"); 79 | return; 80 | } 81 | //加入信号数组中 82 | signal_handler_array[signal] = fn; 83 | } 84 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_arm64_aapcs_elf_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Edward Nevill 2015 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | /******************************************************* 8 | * * 9 | * ------------------------------------------------- * 10 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 11 | * ------------------------------------------------- * 12 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * 13 | * ------------------------------------------------- * 14 | * | d8 | d9 | d10 | d11 | * 15 | * ------------------------------------------------- * 16 | * ------------------------------------------------- * 17 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 18 | * ------------------------------------------------- * 19 | * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * 20 | * ------------------------------------------------- * 21 | * | d12 | d13 | d14 | d15 | * 22 | * ------------------------------------------------- * 23 | * ------------------------------------------------- * 24 | * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * 25 | * ------------------------------------------------- * 26 | * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * 27 | * ------------------------------------------------- * 28 | * | x19 | x20 | x21 | x22 | * 29 | * ------------------------------------------------- * 30 | * ------------------------------------------------- * 31 | * | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | * 32 | * ------------------------------------------------- * 33 | * | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| * 34 | * ------------------------------------------------- * 35 | * | x23 | x24 | x25 | x26 | * 36 | * ------------------------------------------------- * 37 | * ------------------------------------------------- * 38 | * | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * 39 | * ------------------------------------------------- * 40 | * | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| * 41 | * ------------------------------------------------- * 42 | * | x27 | x28 | FP | LR | * 43 | * ------------------------------------------------- * 44 | * ------------------------------------------------- * 45 | * | 40 | 41 | 42 | 43 | | | * 46 | * ------------------------------------------------- * 47 | * | 0xa0| 0xa4| 0xa8| 0xac| | | * 48 | * ------------------------------------------------- * 49 | * | PC | align | | | * 50 | * ------------------------------------------------- * 51 | * * 52 | *******************************************************/ 53 | 54 | .cpu generic+fp+simd 55 | .text 56 | .align 2 57 | .global jump_fcontext 58 | .type jump_fcontext, %function 59 | jump_fcontext: 60 | # prepare stack for GP + FPU 61 | sub sp, sp, #0xb0 62 | 63 | # Because gcc may save integer registers in fp registers across a 64 | # function call we cannot skip saving the fp registers. 65 | # 66 | # Do not reinstate this test unless you fully understand what you 67 | # are doing. 68 | # 69 | # # test if fpu env should be preserved 70 | # cmp w3, #0 71 | # b.eq 1f 72 | 73 | # save d8 - d15 74 | stp d8, d9, [sp, #0x00] 75 | stp d10, d11, [sp, #0x10] 76 | stp d12, d13, [sp, #0x20] 77 | stp d14, d15, [sp, #0x30] 78 | 79 | 1: 80 | # save x19-x30 81 | stp x19, x20, [sp, #0x40] 82 | stp x21, x22, [sp, #0x50] 83 | stp x23, x24, [sp, #0x60] 84 | stp x25, x26, [sp, #0x70] 85 | stp x27, x28, [sp, #0x80] 86 | stp x29, x30, [sp, #0x90] 87 | 88 | # save LR as PC 89 | str x30, [sp, #0xa0] 90 | 91 | # store RSP (pointing to context-data) in first argument (x0). 92 | # STR cannot have sp as a target register 93 | mov x4, sp 94 | str x4, [x0] 95 | 96 | # restore RSP (pointing to context-data) from A2 (x1) 97 | mov sp, x1 98 | 99 | # # test if fpu env should be preserved 100 | # cmp w3, #0 101 | # b.eq 2f 102 | 103 | # load d8 - d15 104 | ldp d8, d9, [sp, #0x00] 105 | ldp d10, d11, [sp, #0x10] 106 | ldp d12, d13, [sp, #0x20] 107 | ldp d14, d15, [sp, #0x30] 108 | 109 | 2: 110 | # load x19-x30 111 | ldp x19, x20, [sp, #0x40] 112 | ldp x21, x22, [sp, #0x50] 113 | ldp x23, x24, [sp, #0x60] 114 | ldp x25, x26, [sp, #0x70] 115 | ldp x27, x28, [sp, #0x80] 116 | ldp x29, x30, [sp, #0x90] 117 | 118 | # use third arg as return value after jump 119 | # and as first arg in context function 120 | mov x0, x2 121 | 122 | # load pc 123 | ldr x4, [sp, #0xa0] 124 | 125 | # restore stack from GP + FPU 126 | add sp, sp, #0xb0 127 | 128 | ret x4 129 | .size jump_fcontext,.-jump_fcontext 130 | # Mark that we don't need executable stack. 131 | .section .note.GNU-stack,"",%progbits 132 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_arm64_aapcs_macho_gas.S: -------------------------------------------------------------------------------- 1 | /******************************************************* 2 | * * 3 | * ------------------------------------------------- * 4 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 5 | * ------------------------------------------------- * 6 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * 7 | * ------------------------------------------------- * 8 | * | d8 | d9 | d10 | d11 | * 9 | * ------------------------------------------------- * 10 | * ------------------------------------------------- * 11 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 12 | * ------------------------------------------------- * 13 | * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * 14 | * ------------------------------------------------- * 15 | * | d12 | d13 | d14 | d15 | * 16 | * ------------------------------------------------- * 17 | * ------------------------------------------------- * 18 | * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * 19 | * ------------------------------------------------- * 20 | * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * 21 | * ------------------------------------------------- * 22 | * | x19 | x20 | x21 | x22 | * 23 | * ------------------------------------------------- * 24 | * ------------------------------------------------- * 25 | * | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | * 26 | * ------------------------------------------------- * 27 | * | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| * 28 | * ------------------------------------------------- * 29 | * | x23 | x24 | x25 | x26 | * 30 | * ------------------------------------------------- * 31 | * ------------------------------------------------- * 32 | * | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * 33 | * ------------------------------------------------- * 34 | * | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| * 35 | * ------------------------------------------------- * 36 | * | x27 | x28 | FP | LR | * 37 | * ------------------------------------------------- * 38 | * ------------------------------------------------- * 39 | * | 40 | 41 | 42 | 43 | | | * 40 | * ------------------------------------------------- * 41 | * | 0xa0| 0xa4| 0xa8| 0xac| | | * 42 | * ------------------------------------------------- * 43 | * | PC | align | | | * 44 | * ------------------------------------------------- * 45 | * * 46 | *******************************************************/ 47 | 48 | .text 49 | .globl _jump_fcontext 50 | .balign 16 51 | _jump_fcontext: 52 | ; prepare stack for GP + FPU 53 | sub sp, sp, #0xb0 54 | 55 | #if (defined(__VFP_FP__) && !defined(__SOFTFP__)) 56 | ; test if fpu env should be preserved 57 | cmp w3, #0 58 | b.eq 1f 59 | 60 | ; save d8 - d15 61 | stp d8, d9, [sp, #0x00] 62 | stp d10, d11, [sp, #0x10] 63 | stp d12, d13, [sp, #0x20] 64 | stp d14, d15, [sp, #0x30] 65 | 66 | 1: 67 | #endif 68 | 69 | ; save x19-x30 70 | stp x19, x20, [sp, #0x40] 71 | stp x21, x22, [sp, #0x50] 72 | stp x23, x24, [sp, #0x60] 73 | stp x25, x26, [sp, #0x70] 74 | stp x27, x28, [sp, #0x80] 75 | stp fp, lr, [sp, #0x90] 76 | 77 | ; save LR as PC 78 | str lr, [sp, #0xa0] 79 | 80 | ; store RSP (pointing to context-data) in first argument (x0). 81 | ; STR cannot have sp as a target register 82 | mov x4, sp 83 | str x4, [x0] 84 | 85 | ; restore RSP (pointing to context-data) from A2 (x1) 86 | mov sp, x1 87 | 88 | #if (defined(__VFP_FP__) && !defined(__SOFTFP__)) 89 | ; test if fpu env should be preserved 90 | cmp w3, #0 91 | b.eq 2f 92 | 93 | ; load d8 - d15 94 | ldp d8, d9, [sp, #0x00] 95 | ldp d10, d11, [sp, #0x10] 96 | ldp d12, d13, [sp, #0x20] 97 | ldp d14, d15, [sp, #0x30] 98 | 99 | 2: 100 | #endif 101 | 102 | ; load x19-x30 103 | ldp x19, x20, [sp, #0x40] 104 | ldp x21, x22, [sp, #0x50] 105 | ldp x23, x24, [sp, #0x60] 106 | ldp x25, x26, [sp, #0x70] 107 | ldp x27, x28, [sp, #0x80] 108 | ldp fp, lr, [sp, #0x90] 109 | 110 | ; use third arg as return value after jump 111 | ; and as first arg in context function 112 | mov x0, x2 113 | 114 | ; load pc 115 | ldr x4, [sp, #0xa0] 116 | 117 | ; restore stack from GP + FPU 118 | add sp, sp, #0xb0 119 | 120 | ret x4 121 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_arm_aapcs_elf_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /******************************************************* 9 | * * 10 | * ------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ------------------------------------------------- * 13 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * 14 | * ------------------------------------------------- * 15 | * | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | * 16 | * ------------------------------------------------- * 17 | * ------------------------------------------------- * 18 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 19 | * ------------------------------------------------- * 20 | * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * 21 | * ------------------------------------------------- * 22 | * | s24 | s25 | s26 | s27 | s28 | s29 | s30 | s31 | * 23 | * ------------------------------------------------- * 24 | * ------------------------------------------------- * 25 | * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * 26 | * ------------------------------------------------- * 27 | * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * 28 | * ------------------------------------------------- * 29 | * | v1 | v2 | v3 | v4 | v5 | v6 | v7 | v8 | * 30 | * ------------------------------------------------- * 31 | * ------------------------------------------------- * 32 | * | 24 | 25 | | * 33 | * ------------------------------------------------- * 34 | * | 0x60| 0x64| | * 35 | * ------------------------------------------------- * 36 | * | lr | pc | | * 37 | * ------------------------------------------------- * 38 | * * 39 | *******************************************************/ 40 | 41 | .text 42 | .globl jump_fcontext 43 | .align 2 44 | .type jump_fcontext,%function 45 | jump_fcontext: 46 | @ save LR as PC 47 | push {lr} 48 | @ save V1-V8,LR 49 | push {v1-v8,lr} 50 | 51 | @ prepare stack for FPU 52 | sub sp, sp, #64 53 | 54 | #if (defined(__VFP_FP__) && !defined(__SOFTFP__)) 55 | @ test if fpu env should be preserved 56 | cmp a4, #0 57 | beq 1f 58 | 59 | @ save S16-S31 60 | vstmia sp, {d8-d15} 61 | 62 | 1: 63 | #endif 64 | 65 | @ store RSP (pointing to context-data) in A1 66 | str sp, [a1] 67 | 68 | @ restore RSP (pointing to context-data) from A2 69 | mov sp, a2 70 | 71 | #if (defined(__VFP_FP__) && !defined(__SOFTFP__)) 72 | @ test if fpu env should be preserved 73 | cmp a4, #0 74 | beq 2f 75 | 76 | @ restore S16-S31 77 | vldmia sp, {d8-d15} 78 | 2: 79 | #endif 80 | 81 | @ prepare stack for FPU 82 | add sp, sp, #64 83 | 84 | @ use third arg as return value after jump 85 | @ and as first arg in context function 86 | mov a1, a3 87 | 88 | @ restore v1-V8,LR,PC 89 | pop {v1-v8,lr,pc} 90 | .size jump_fcontext,.-jump_fcontext 91 | 92 | @ Mark that we don't need executable stack. 93 | .section .note.GNU-stack,"",%progbits 94 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_arm_aapcs_macho_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /******************************************************* 9 | * * 10 | * ------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ------------------------------------------------- * 13 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * 14 | * ------------------------------------------------- * 15 | * | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | * 16 | * ------------------------------------------------- * 17 | * ------------------------------------------------- * 18 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 19 | * ------------------------------------------------- * 20 | * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * 21 | * ------------------------------------------------- * 22 | * | s24 | s25 | s26 | s27 | s28 | s29 | s30 | s31 | * 23 | * ------------------------------------------------- * 24 | * ------------------------------------------------- * 25 | * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * 26 | * ------------------------------------------------- * 27 | * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * 28 | * ------------------------------------------------- * 29 | * | sjlj| v1 | v2 | v3 | v4 | v5 | v6 | v7 | 30 | * ------------------------------------------------- * 31 | * ------------------------------------------------- * 32 | * | 24 | 25 | 26 | | * 33 | * ------------------------------------------------- * 34 | * | 0x60| 0x64| 0x68| | * 35 | * ------------------------------------------------- * 36 | * | v8 | lr | pc | | * 37 | * ------------------------------------------------- * 38 | * * 39 | * *****************************************************/ 40 | 41 | .text 42 | .globl _jump_fcontext 43 | .align 2 44 | _jump_fcontext: 45 | @ save LR as PC 46 | push {lr} 47 | @ save V1-V8,LR 48 | push {v1-v8,lr} 49 | 50 | @ locate TLS to save/restore SjLj handler 51 | mrc p15, 0, v2, c13, c0, #3 52 | bic v2, v2, #3 53 | 54 | @ load TLS[__PTK_LIBC_DYLD_Unwind_SjLj_Key] 55 | ldr v1, [v2, #72] 56 | @ save SjLj handler 57 | push {v1} 58 | 59 | @ prepare stack for FPU 60 | sub sp, sp, #64 61 | 62 | #if (defined(__VFP_FP__) && !defined(__SOFTFP__)) 63 | @ test if fpu env should be preserved 64 | cmp a4, #0 65 | beq 1f 66 | 67 | @ save S16-S31 68 | vstmia sp, {d8-d15} 69 | 70 | 1: 71 | #endif 72 | 73 | @ store RSP (pointing to context-data) in A1 74 | str sp, [a1] 75 | 76 | @ restore RSP (pointing to context-data) from A2 77 | mov sp, a2 78 | 79 | #if (defined(__VFP_FP__) && !defined(__SOFTFP__)) 80 | @ test if fpu env should be preserved 81 | cmp a4, #0 82 | beq 2f 83 | 84 | @ restore S16-S31 85 | vldmia sp, {d8-d15} 86 | 87 | 2: 88 | #endif 89 | 90 | @ prepare stack for FPU 91 | add sp, sp, #64 92 | 93 | @ restore SjLj handler 94 | pop {v1} 95 | @ store SjLj handler in TLS 96 | str v1, [v2, #72] 97 | 98 | @ use third arg as return value after jump 99 | @ and as first arg in context function 100 | mov a1, a3 101 | 102 | @ restore v1-V8,LR,PC 103 | pop {v1-v8,lr,pc} 104 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_arm_aapcs_pe_armasm.asm: -------------------------------------------------------------------------------- 1 | ;/* 2 | ; Copyright Oliver Kowalke 2009. 3 | ; Distributed under the Boost Software License, Version 1.0. 4 | ; (See accompanying file LICENSE_1_0.txt or copy at 5 | ; http://www.boost.org/LICENSE_1_0.txt) 6 | ;*/ 7 | 8 | ; ******************************************************* 9 | ; * * 10 | ; * ------------------------------------------------- * 11 | ; * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | ; * ------------------------------------------------- * 13 | ; * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * 14 | ; * ------------------------------------------------- * 15 | ; * | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | * 16 | ; * ------------------------------------------------- * 17 | ; * ------------------------------------------------- * 18 | ; * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 19 | ; * ------------------------------------------------- * 20 | ; * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * 21 | ; * ------------------------------------------------- * 22 | ; * | s24 | s25 | s26 | s27 | s28 | s29 | s30 | s31 | * 23 | ; * ------------------------------------------------- * 24 | ; * ------------------------------------------------- * 25 | ; * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * 26 | ; * ------------------------------------------------- * 27 | ; * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * 28 | ; * ------------------------------------------------- * 29 | ; * |deall|limit| base| v1 | v2 | v3 | v4 | v5 | * 30 | ; * ------------------------------------------------- * 31 | ; * ------------------------------------------------- * 32 | ; * | 24 | 25 | 26 | 27 | 28 | | * 33 | ; * ------------------------------------------------- * 34 | ; * | 0x60| 0x64| 0x68| 0x6c| 0x70| | * 35 | ; * ------------------------------------------------- * 36 | ; * | v6 | v7 | v8 | lr | pc | | * 37 | ; * ------------------------------------------------- * 38 | ; * * 39 | ; ******************************************************* 40 | 41 | AREA |.text|, CODE 42 | ALIGN 4 43 | EXPORT jump_fcontext 44 | 45 | jump_fcontext PROC 46 | @ save LR as PC 47 | push {lr} 48 | @ save V1-V8,LR 49 | push {v1-v8,lr} 50 | 51 | @ prepare stack for FPU 52 | sub sp, sp, #0x4c 53 | 54 | @ test if fpu env should be preserved 55 | cmp a4, #0 56 | beq 1f 57 | 58 | @ save S16-S31 59 | vstmia sp, {d8-d15} 60 | 61 | 1: 62 | ; load TIB to save/restore thread size and limit. 63 | ; we do not need preserve CPU flag and can use it's arg register 64 | mrc p15, #0, v1, c13, c0, #2 65 | 66 | ; save current stack base 67 | ldr a5, [v1,#0x04] 68 | str a5, [sp,#0x48] 69 | ; save current stack limit 70 | ldr a5, [v1,#0x08] 71 | str a5, [sp,#0x44] 72 | ; save current deallocation stack 73 | ldr a5, [v1,#0xe0c] 74 | str a5, [sp,#0x40] 75 | 76 | @ store RSP (pointing to context-data) in A1 77 | str sp, [a1] 78 | 79 | @ restore RSP (pointing to context-data) from A2 80 | mov sp, a2 81 | 82 | @ test if fpu env should be preserved 83 | cmp a4, #0 84 | beq 2f 85 | 86 | @ restore S16-S31 87 | vldmia sp, {d8-d15} 88 | 89 | 2: 90 | ; restore stack base 91 | ldr a5, [sp,#0x48] 92 | str a5, [v1,#0x04] 93 | ; restore stack limit 94 | ldr a5, [sp,#0x44] 95 | str a5, [v1,#0x08] 96 | ; restore deallocation stack 97 | ldr a5, [sp,#0x40] 98 | str a5, [v1,#0xe0c] 99 | 100 | @ prepare stack for FPU 101 | add sp, sp, #0x4c 102 | 103 | ; use third arg as return value after jump 104 | ; and as first arg in context function 105 | mov a1, a3 106 | 107 | @ restore v1-V8,LR 108 | pop {v1-v8,lr} 109 | pop {pc} 110 | 111 | ENDP 112 | END 113 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_combined_sysv_macho_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sergue E. Leontiev 2013. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | // Stub file for universal binary 9 | 10 | #if defined(__i386__) 11 | #include "jump_i386_sysv_macho_gas.S" 12 | #elif defined(__x86_64__) 13 | #include "jump_x86_64_sysv_macho_gas.S" 14 | #elif defined(__ppc__) 15 | #include "jump_ppc32_sysv_macho_gas.S" 16 | #elif defined(__ppc64__) 17 | #include "jump_ppc64_sysv_macho_gas.S" 18 | #else 19 | #error "No arch's" 20 | #endif 21 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_i386_ms_pe_gas.asm: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Copyright Thomas Sailer 2013. 4 | Distributed under the Boost Software License, Version 1.0. 5 | (See accompanying file LICENSE_1_0.txt or copy at 6 | http://www.boost.org/LICENSE_1_0.txt) 7 | */ 8 | 9 | /******************************************************************** 10 | --------------------------------------------------------------------------------- 11 | | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | --------------------------------------------------------------------------------- 13 | | 0h | 04h | 08h | 0ch | 010h | 014h | 018h | 01ch | 14 | --------------------------------------------------------------------------------- 15 | | fc_mxcsr|fc_x87_cw| fc_strg |fc_deallo| limit | base | fc_seh | EDI | 16 | --------------------------------------------------------------------------------- 17 | --------------------------------------------------------------------------------- 18 | | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | --------------------------------------------------------------------------------- 20 | | 020h | 024h | 028h | 02ch | 030h | 034h | 038h | 03ch | 21 | --------------------------------------------------------------------------------- 22 | | ESI | EBX | EBP | EIP | EXIT | | SEH NXT |SEH HNDLR| 23 | --------------------------------------------------------------------------------- 24 | * *****************************************************************/ 25 | 26 | .file "jump_i386_ms_pe_gas.asm" 27 | .text 28 | .p2align 4,,15 29 | .globl _jump_fcontext 30 | .def _jump_fcontext; .scl 2; .type 32; .endef 31 | _jump_fcontext: 32 | /* fourth arg of jump_fcontext() == flag indicating preserving FPU */ 33 | movl 0x10(%esp), %ecx 34 | 35 | pushl %ebp /* save EBP */ 36 | pushl %ebx /* save EBX */ 37 | pushl %esi /* save ESI */ 38 | pushl %edi /* save EDI */ 39 | 40 | /* load NT_TIB */ 41 | movl %fs:(0x18), %edx 42 | 43 | /* load current SEH exception list */ 44 | movl (%edx), %eax 45 | push %eax 46 | 47 | /* load current stack base */ 48 | movl 0x04(%edx), %eax 49 | push %eax 50 | 51 | /* load current stack limit */ 52 | movl 0x08(%edx), %eax 53 | push %eax 54 | 55 | /* load current dealloction stack */ 56 | movl 0xe0c(%edx), %eax 57 | push %eax 58 | 59 | /* load fiber local storage */ 60 | movl 0x10(%edx), %eax 61 | push %eax 62 | 63 | /* prepare stack for FPU */ 64 | leal -0x08(%esp), %esp 65 | 66 | /* test for flag preserve_fpu */ 67 | testl %ecx, %ecx 68 | je 1f 69 | 70 | /* save MMX control word */ 71 | stmxcsr (%esp) 72 | /* save x87 control word */ 73 | fnstcw 0x04(%esp) 74 | 75 | 1: 76 | /* first arg of jump_fcontext() == context jumping from */ 77 | movl 0x30(%esp), %eax 78 | 79 | /* store ESP (pointing to context-data) in EAX */ 80 | movl %esp, (%eax) 81 | 82 | /* second arg of jump_fcontext() == context jumping to */ 83 | movl 0x34(%esp), %edx 84 | 85 | /* third arg of jump_fcontext() == value to be returned after jump */ 86 | movl 0x38(%esp), %eax 87 | 88 | /* restore ESP (pointing to context-data) from EDX */ 89 | movl %edx, %esp 90 | 91 | /* test for flag preserve_fpu */ 92 | testl %ecx, %ecx 93 | je 2f 94 | 95 | /* restore MMX control- and status-word */ 96 | ldmxcsr (%esp) 97 | /* restore x87 control-word */ 98 | fldcw 0x04(%esp) 99 | 100 | 2: 101 | /* prepare stack for FPU */ 102 | leal 0x08(%esp), %esp 103 | 104 | /* load NT_TIB into ECX */ 105 | movl %fs:(0x18), %edx 106 | 107 | /* restore fiber local storage */ 108 | popl %ecx 109 | movl %ecx, 0x10(%edx) 110 | 111 | /* restore current deallocation stack */ 112 | popl %ecx 113 | movl %ecx, 0xe0c(%edx) 114 | 115 | /* restore current stack limit */ 116 | popl %ecx 117 | movl %ecx, 0x08(%edx) 118 | 119 | /* restore current stack base */ 120 | popl %ecx 121 | movl %ecx, 0x04(%edx) 122 | 123 | /* restore current SEH exception list */ 124 | popl %ecx 125 | movl %ecx, (%edx) 126 | 127 | popl %edi /* save EDI */ 128 | popl %esi /* save ESI */ 129 | popl %ebx /* save EBX */ 130 | popl %ebp /* save EBP */ 131 | 132 | /* restore return-address */ 133 | popl %edx 134 | 135 | /* use value in EAX as return-value after jump */ 136 | /* use value in EAX as first arg in context function */ 137 | movl %eax, 0x04(%esp) 138 | 139 | /* indirect jump to context */ 140 | jmp *%edx 141 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_i386_ms_pe_masm.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Copyright Oliver Kowalke 2009. 3 | ; Distributed under the Boost Software License, Version 1.0. 4 | ; (See accompanying file LICENSE_1_0.txt or copy at 5 | ; http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | ; --------------------------------------------------------------------------------- 8 | ; | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | ; --------------------------------------------------------------------------------- 10 | ; | 0h | 04h | 08h | 0ch | 010h | 014h | 018h | 01ch | 11 | ; --------------------------------------------------------------------------------- 12 | ; | fc_mxcsr|fc_x87_cw| fc_strg |fc_deallo| limit | base | fc_seh | EDI | 13 | ; --------------------------------------------------------------------------------- 14 | ; --------------------------------------------------------------------------------- 15 | ; | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ; --------------------------------------------------------------------------------- 17 | ; | 020h | 024h | 028h | 02ch | 030h | 034h | 038h | 03ch | 18 | ; --------------------------------------------------------------------------------- 19 | ; | ESI | EBX | EBP | EIP | EXIT | | SEH NXT |SEH HNDLR| 20 | ; --------------------------------------------------------------------------------- 21 | 22 | .386 23 | .XMM 24 | .model flat, c 25 | .code 26 | 27 | jump_fcontext PROC BOOST_CONTEXT_EXPORT 28 | ; fourth arg of jump_fcontext() == flag indicating preserving FPU 29 | mov ecx, [esp+010h] 30 | 31 | push ebp ; save EBP 32 | push ebx ; save EBX 33 | push esi ; save ESI 34 | push edi ; save EDI 35 | 36 | assume fs:nothing 37 | ; load NT_TIB into ECX 38 | mov edx, fs:[018h] 39 | assume fs:error 40 | 41 | ; load current SEH exception list 42 | mov eax, [edx] 43 | push eax 44 | 45 | ; load current stack base 46 | mov eax, [edx+04h] 47 | push eax 48 | 49 | ; load current stack limit 50 | mov eax, [edx+08h] 51 | push eax 52 | 53 | ; load current deallocation stack 54 | mov eax, [edx+0e0ch] 55 | push eax 56 | 57 | ; load fiber local storage 58 | mov eax, [edx+010h] 59 | push eax 60 | 61 | ; prepare stack for FPU 62 | lea esp, [esp-08h] 63 | 64 | ; test for flag preserve_fpu 65 | test ecx, ecx 66 | je nxt1 67 | 68 | ; save MMX control- and status-word 69 | stmxcsr [esp] 70 | ; save x87 control-word 71 | fnstcw [esp+04h] 72 | 73 | nxt1: 74 | ; first arg of jump_fcontext() == context jumping from 75 | mov eax, [esp+030h] 76 | 77 | ; store ESP (pointing to context-data) in EAX 78 | mov [eax], esp 79 | 80 | ; second arg of jump_fcontext() == context jumping to 81 | mov edx, [esp+034h] 82 | 83 | ; third arg of jump_fcontext() == value to be returned after jump 84 | mov eax, [esp+038h] 85 | 86 | ; restore ESP (pointing to context-data) from EDX 87 | mov esp, edx 88 | 89 | ; test for flag preserve_fpu 90 | test ecx, ecx 91 | je nxt2 92 | 93 | ; restore MMX control- and status-word 94 | ldmxcsr [esp] 95 | ; restore x87 control-word 96 | fldcw [esp+04h] 97 | 98 | nxt2: 99 | ; prepare stack for FPU 100 | lea esp, [esp+08h] 101 | 102 | assume fs:nothing 103 | ; load NT_TIB into ECX 104 | mov edx, fs:[018h] 105 | assume fs:error 106 | 107 | ; restore fiber local storage 108 | pop ecx 109 | mov [edx+010h], ecx 110 | 111 | ; restore current deallocation stack 112 | pop ecx 113 | mov [edx+0e0ch], ecx 114 | 115 | ; restore current stack limit 116 | pop ecx 117 | mov [edx+08h], ecx 118 | 119 | ; restore current stack base 120 | pop ecx 121 | mov [edx+04h], ecx 122 | 123 | ; restore current SEH exception list 124 | pop ecx 125 | mov [edx], ecx 126 | 127 | pop edi ; save EDI 128 | pop esi ; save ESI 129 | pop ebx ; save EBX 130 | pop ebp ; save EBP 131 | 132 | ; restore return-address 133 | pop edx 134 | 135 | ; use value in EAX as return-value after jump 136 | ; use value in EAX as first arg in context function 137 | mov [esp+04h], eax 138 | 139 | ; indirect jump to context 140 | jmp edx 141 | jump_fcontext ENDP 142 | END 143 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_i386_sysv_elf_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /**************************************************************************************** 9 | * * 10 | * ---------------------------------------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ---------------------------------------------------------------------------------- * 13 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * 14 | * ---------------------------------------------------------------------------------- * 15 | * | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | EXIT | * 16 | * ---------------------------------------------------------------------------------- * 17 | * * 18 | ****************************************************************************************/ 19 | 20 | .text 21 | .globl jump_fcontext 22 | .align 2 23 | .type jump_fcontext,@function 24 | jump_fcontext: 25 | /* fourth arg of jump_fcontext() == flag indicating preserving FPU */ 26 | movl 0x10(%esp), %ecx 27 | 28 | pushl %ebp /* save EBP */ 29 | pushl %ebx /* save EBX */ 30 | pushl %esi /* save ESI */ 31 | pushl %edi /* save EDI */ 32 | 33 | /* prepare stack for FPU */ 34 | leal -0x8(%esp), %esp 35 | 36 | /* test for flag preserve_fpu */ 37 | test %ecx, %ecx 38 | je 1f 39 | 40 | /* save MMX control- and status-word */ 41 | stmxcsr (%esp) 42 | /* save x87 control-word */ 43 | fnstcw 0x4(%esp) 44 | 45 | 1: 46 | /* first arg of jump_fcontext() == context jumping from */ 47 | movl 0x1c(%esp), %eax 48 | 49 | /* store ESP (pointing to context-data) in EAX */ 50 | movl %esp, (%eax) 51 | 52 | /* second arg of jump_fcontext() == context jumping to */ 53 | movl 0x20(%esp), %edx 54 | 55 | /* third arg of jump_fcontext() == value to be returned after jump */ 56 | movl 0x24(%esp), %eax 57 | 58 | /* restore ESP (pointing to context-data) from EDX */ 59 | movl %edx, %esp 60 | 61 | /* test for flag preserve_fpu */ 62 | test %ecx, %ecx 63 | je 2f 64 | 65 | /* restore MMX control- and status-word */ 66 | ldmxcsr (%esp) 67 | /* restore x87 control-word */ 68 | fldcw 0x4(%esp) 69 | 2: 70 | /* prepare stack for FPU */ 71 | leal 0x8(%esp), %esp 72 | 73 | popl %edi /* restore EDI */ 74 | popl %esi /* restore ESI */ 75 | popl %ebx /* restore EBX */ 76 | popl %ebp /* restore EBP */ 77 | 78 | /* restore return-address */ 79 | popl %edx 80 | 81 | /* use value in EAX as return-value after jump */ 82 | /* use value in EAX as first arg in context function */ 83 | movl %eax, 0x4(%esp) 84 | 85 | /* indirect jump to context */ 86 | jmp *%edx 87 | .size jump_fcontext,.-jump_fcontext 88 | 89 | /* Mark that we don't need executable stack. */ 90 | .section .note.GNU-stack,"",%progbits 91 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_i386_sysv_macho_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /**************************************************************************************** 9 | * * 10 | * ---------------------------------------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ---------------------------------------------------------------------------------- * 13 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * 14 | * ---------------------------------------------------------------------------------- * 15 | * | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | EXIT | * 16 | * ---------------------------------------------------------------------------------- * 17 | * * 18 | ****************************************************************************************/ 19 | 20 | .text 21 | .globl _jump_fcontext 22 | .align 2 23 | _jump_fcontext: 24 | /* fourth arg of jump_fcontext() == flag indicating preserving FPU */ 25 | movl 0x10(%esp), %ecx 26 | 27 | pushl %ebp /* save EBP */ 28 | pushl %ebx /* save EBX */ 29 | pushl %esi /* save ESI */ 30 | pushl %edi /* save EDI */ 31 | 32 | /* prepare stack for FPU */ 33 | leal -0x8(%esp), %esp 34 | 35 | /* test for flag preserve_fpu */ 36 | test %ecx, %ecx 37 | je 1f 38 | 39 | /* save MMX control- and status-word */ 40 | stmxcsr (%esp) 41 | /* save x87 control-word */ 42 | fnstcw 0x4(%esp) 43 | 44 | 1: 45 | /* first arg of jump_fcontext() == context jumping from */ 46 | movl 0x1c(%esp), %eax 47 | 48 | /* store ESP (pointing to context-data) in EAX */ 49 | movl %esp, (%eax) 50 | 51 | /* second arg of jump_fcontext() == context jumping to */ 52 | movl 0x20(%esp), %edx 53 | 54 | /* third arg of jump_fcontext() == value to be returned after jump */ 55 | movl 0x24(%esp), %eax 56 | 57 | /* restore ESP (pointing to context-data) from EDX */ 58 | movl %edx, %esp 59 | 60 | /* test for flag preserve_fpu */ 61 | test %ecx, %ecx 62 | je 2f 63 | 64 | /* restore MMX control- and status-word */ 65 | ldmxcsr (%esp) 66 | /* restore x87 control-word */ 67 | fldcw 0x4(%esp) 68 | 2: 69 | /* prepare stack for FPU */ 70 | leal 0x8(%esp), %esp 71 | 72 | popl %edi /* restore EDI */ 73 | popl %esi /* restore ESI */ 74 | popl %ebx /* restore EBX */ 75 | popl %ebp /* restore EBP */ 76 | 77 | /* restore return-address */ 78 | popl %edx 79 | 80 | /* use value in EAX as return-value after jump */ 81 | /* use value in EAX as first arg in context function */ 82 | movl %eax, 0x4(%esp) 83 | 84 | /* indirect jump to context */ 85 | jmp *%edx 86 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_i386_x86_64_sysv_macho_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sergue E. Leontiev 2013. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | // Stub file for universal binary 9 | 10 | #if defined(__i386__) 11 | #include "jump_i386_sysv_macho_gas.S" 12 | #elif defined(__x86_64__) 13 | #include "jump_x86_64_sysv_macho_gas.S" 14 | #else 15 | #error "No arch's" 16 | #endif 17 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_mips32_o32_elf_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /******************************************************* 9 | * * 10 | * ------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ------------------------------------------------- * 13 | * | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | * 14 | * ------------------------------------------------- * 15 | * | F20 | F22 | F24 | F26 | * 16 | * ------------------------------------------------- * 17 | * ------------------------------------------------- * 18 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 19 | * ------------------------------------------------- * 20 | * | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | * 21 | * ------------------------------------------------- * 22 | * | F28 | F30 | S0 | S1 | S2 | S3 | * 23 | * ------------------------------------------------- * 24 | * ------------------------------------------------- * 25 | * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | | * 26 | * ------------------------------------------------- * 27 | * | 64 | 68 | 72 | 76 | 80 | 84 | 88 | | * 28 | * ------------------------------------------------- * 29 | * | S4 | S5 | S6 | S7 | FP | RA | PC | | * 30 | * ------------------------------------------------- * 31 | * * 32 | * *****************************************************/ 33 | 34 | .text 35 | .globl jump_fcontext 36 | .align 2 37 | .type jump_fcontext,@function 38 | .ent jump_fcontext 39 | jump_fcontext: 40 | # reserve space on stack 41 | addiu $sp, $sp, -92 42 | 43 | sw $s0, 48($sp) # save S0 44 | sw $s1, 52($sp) # save S1 45 | sw $s2, 56($sp) # save S2 46 | sw $s3, 60($sp) # save S3 47 | sw $s4, 64($sp) # save S4 48 | sw $s5, 68($sp) # save S5 49 | sw $s6, 72($sp) # save S6 50 | sw $s7, 76($sp) # save S7 51 | sw $fp, 80($sp) # save FP 52 | sw $ra, 84($sp) # save RA 53 | sw $ra, 88($sp) # save RA as PC 54 | 55 | #if defined(__mips_hard_float) 56 | # test if fpu env should be preserved 57 | beqz $a3, 1f 58 | 59 | s.d $f20, ($sp) # save F20 60 | s.d $f22, 8($sp) # save F22 61 | s.d $f24, 16($sp) # save F24 62 | s.d $f26, 24($sp) # save F26 63 | s.d $f28, 32($sp) # save F28 64 | s.d $f30, 40($sp) # save F30 65 | 66 | 1: 67 | #endif 68 | 69 | # store SP (pointing to context-data) in A0 70 | sw $sp, ($a0) 71 | 72 | # restore SP (pointing to context-data) from A1 73 | move $sp, $a1 74 | 75 | 76 | #if defined(__mips_hard_float) 77 | # test if fpu env should be preserved 78 | beqz $a3, 2f 79 | 80 | l.d $f20, ($sp) # restore F20 81 | l.d $f22, 8($sp) # restore F22 82 | l.d $f24, 16($sp) # restore F24 83 | l.d $f26, 24($sp) # restore F26 84 | l.d $f28, 32($sp) # restore F28 85 | l.d $f30, 40($sp) # restore F30 86 | 87 | 2: 88 | #endif 89 | 90 | lw $s0, 48($sp) # restore S0 91 | lw $s1, 52($sp) # restore S1 92 | lw $s2, 56($sp) # restore S2 93 | lw $s3, 60($sp) # restore S3 94 | lw $s4, 64($sp) # restore S4 95 | lw $s5, 68($sp) # restore S5 96 | lw $s6, 72($sp) # restore S6 97 | lw $s7, 76($sp) # restore S7 98 | lw $fp, 80($sp) # restore FP 99 | lw $ra, 84($sp) # restore RA 100 | 101 | # load PC 102 | lw $t9, 88($sp) 103 | 104 | # adjust stack 105 | addiu $sp, $sp, 92 106 | 107 | # use third arg as return value after jump 108 | move $v0, $a2 109 | # use third arg as first arg in context function 110 | move $a0, $a2 111 | 112 | # jump to context 113 | jr $t9 114 | .end jump_fcontext 115 | .size jump_fcontext, .-jump_fcontext 116 | 117 | /* Mark that we don't need executable stack. */ 118 | .section .note.GNU-stack,"",%progbits 119 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_ppc32_ppc64_sysv_macho_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sergue E. Leontiev 2013. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | // Stub file for universal binary 9 | 10 | #if defined(__ppc__) 11 | #include "jump_ppc32_sysv_macho_gas.S" 12 | #elif defined(__ppc64__) 13 | #include "jump_ppc64_sysv_macho_gas.S" 14 | #else 15 | #error "No arch's" 16 | #endif 17 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_ppc32_sysv_xcoff_gas.S: -------------------------------------------------------------------------------- 1 | .globl .jump_fcontext 2 | .globl jump_fcontext[DS] 3 | .align 2 4 | .csect jump_fcontext[DS] 5 | jump_fcontext: 6 | .long .jump_fcontext 7 | .jump_fcontext: 8 | # reserve space on stack 9 | subi 1, 1, 240 10 | 11 | stw 13, 152(1) # save R13 12 | stw 14, 156(1) # save R14 13 | stw 15, 160(1) # save R15 14 | stw 16, 164(1) # save R16 15 | stw 17, 168(1) # save R17 16 | stw 18, 172(1) # save R18 17 | stw 19, 176(1) # save R19 18 | stw 20, 180(1) # save R20 19 | stw 21, 184(1) # save R21 20 | stw 22, 188(1) # save R22 21 | stw 23, 192(1) # save R23 22 | stw 24, 196(1) # save R24 23 | stw 25, 200(1) # save R25 24 | stw 26, 204(1) # save R26 25 | stw 27, 208(1) # save R27 26 | stw 28, 212(1) # save R28 27 | stw 29, 216(1) # save R29 28 | stw 30, 220(1) # save R30 29 | stw 31, 224(1) # save R31 30 | 31 | # save CR 32 | mfcr 0 33 | stw 0, 228(1) 34 | # save LR 35 | mflr 0 36 | stw 0, 232(1) 37 | # save LR as PC 38 | stw 0, 236(1) 39 | 40 | # test if fpu env should be preserved 41 | cmpwi 7, 6, 0 42 | beq 7, label1 43 | 44 | stfd 14, 0(1) # save F14 45 | stfd 15, 8(1) # save F15 46 | stfd 16, 16(1) # save F16 47 | stfd 17, 24(1) # save F17 48 | stfd 18, 32(1) # save F18 49 | stfd 19, 40(1) # save F19 50 | stfd 20, 48(1) # save F20 51 | stfd 21, 56(1) # save F21 52 | stfd 22, 64(1) # save F22 53 | stfd 23, 72(1) # save F23 54 | stfd 24, 80(1) # save F24 55 | stfd 25, 88(1) # save F25 56 | stfd 26, 96(1) # save F26 57 | stfd 27, 104(1) # save F27 58 | stfd 28, 112(1) # save F28 59 | stfd 29, 120(1) # save F29 60 | stfd 30, 128(1) # save F30 61 | stfd 31, 136(1) # save F31 62 | mffs 0 # load FPSCR 63 | stfd 0, 144(1) # save FPSCR 64 | 65 | label1: 66 | # store RSP (pointing to context-data) in R3 67 | stw 1, 0(3) 68 | 69 | # restore RSP (pointing to context-data) from R4 70 | mr 1, 4 71 | 72 | # test if fpu env should be preserved 73 | cmpwi 7, 6, 0 74 | beq 7, label2 75 | 76 | lfd 14, 0(1) # restore F14 77 | lfd 15, 8(1) # restore F15 78 | lfd 16, 16(1) # restore F16 79 | lfd 17, 24(1) # restore F17 80 | lfd 18, 32(1) # restore F18 81 | lfd 19, 40(1) # restore F19 82 | lfd 20, 48(1) # restore F20 83 | lfd 21, 56(1) # restore F21 84 | lfd 22, 64(1) # restore F22 85 | lfd 23, 72(1) # restore F23 86 | lfd 24, 80(1) # restore F24 87 | lfd 25, 88(1) # restore F25 88 | lfd 26, 96(1) # restore F26 89 | lfd 27, 104(1) # restore F27 90 | lfd 28, 112(1) # restore F28 91 | lfd 29, 120(1) # restore F29 92 | lfd 30, 128(1) # restore F30 93 | lfd 31, 136(1) # restore F31 94 | lfd 0, 144(1) # load FPSCR 95 | mtfsf 0xff, 0 # restore FPSCR 96 | 97 | label2: 98 | lwz 13, 152(1) # restore R13 99 | lwz 14, 156(1) # restore R14 100 | lwz 15, 160(1) # restore R15 101 | lwz 16, 164(1) # restore R16 102 | lwz 17, 168(1) # restore R17 103 | lwz 18, 172(1) # restore R18 104 | lwz 19, 176(1) # restore R19 105 | lwz 20, 180(1) # restore R20 106 | lwz 21, 184(1) # restore R21 107 | lwz 22, 188(1) # restore R22 108 | lwz 23, 192(1) # restore R23 109 | lwz 24, 196(1) # restore R24 110 | lwz 25, 200(1) # restore R25 111 | lwz 26, 204(1) # restore R26 112 | lwz 27, 208(1) # restore R27 113 | lwz 28, 212(1) # restore R28 114 | lwz 29, 216(1) # restore R29 115 | lwz 30, 220(1) # restore R30 116 | lwz 31, 224(1) # restore R31 117 | 118 | # restore CR 119 | lwz 0, 228(1) 120 | mtcr 0 121 | # restore LR 122 | lwz 0, 232(1) 123 | mtlr 0 124 | 125 | # load PC 126 | lwz 0, 236(1) 127 | # restore CTR 128 | mtctr 0 129 | 130 | # adjust stack 131 | addi 1, 1, 240 132 | 133 | # use third arg as return value after jump 134 | # use third arg as first arg in context function 135 | mr 3, 5 136 | 137 | # jump to context 138 | bctr 139 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_ppc64_sysv_xcoff_gas.S: -------------------------------------------------------------------------------- 1 | .align 2 2 | .globl .jump_fcontext 3 | .jump_fcontext: 4 | # reserve space on stack 5 | subi 1, 1, 328 6 | 7 | std 13, 152(1) # save R13 8 | std 14, 160(1) # save R14 9 | std 15, 168(1) # save R15 10 | std 16, 176(1) # save R16 11 | std 17, 184(1) # save R17 12 | std 18, 192(1) # save R18 13 | std 19, 200(1) # save R19 14 | std 20, 208(1) # save R20 15 | std 21, 216(1) # save R21 16 | std 22, 224(1) # save R22 17 | std 23, 232(1) # save R23 18 | std 24, 240(1) # save R24 19 | std 25, 248(1) # save R25 20 | std 26, 256(1) # save R26 21 | std 27, 264(1) # save R27 22 | std 28, 272(1) # save R28 23 | std 29, 280(1) # save R29 24 | std 30, 288(1) # save R30 25 | std 31, 296(1) # save R31 26 | 27 | # save CR 28 | mfcr 0 29 | std 0, 304(1) 30 | # save LR 31 | mflr 0 32 | std 0, 312(1) 33 | # save LR as PC 34 | std 0, 320(1) 35 | 36 | # test if fpu env should be preserved 37 | cmpwi 7, 6, 0 38 | beq 7, label1 39 | 40 | stfd 14, 0(1) # save F14 41 | stfd 15, 8(1) # save F15 42 | stfd 16, 16(1) # save F16 43 | stfd 17, 24(1) # save F17 44 | stfd 18, 32(1) # save F18 45 | stfd 19, 40(1) # save F19 46 | stfd 20, 48(1) # save F20 47 | stfd 21, 56(1) # save F21 48 | stfd 22, 64(1) # save F22 49 | stfd 23, 72(1) # save F23 50 | stfd 24, 80(1) # save F24 51 | stfd 25, 88(1) # save F25 52 | stfd 26, 96(1) # save F26 53 | stfd 27, 104(1) # save F27 54 | stfd 28, 112(1) # save F28 55 | stfd 29, 120(1) # save F29 56 | stfd 30, 128(1) # save F30 57 | stfd 31, 136(1) # save F31 58 | mffs 0 # load FPSCR 59 | stfd 0, 144(1) # save FPSCR 60 | 61 | label1: 62 | # store RSP (pointing to context-data) in R3 63 | stw 1, 0(3) 64 | 65 | # restore RSP (pointing to context-data) from R4 66 | mr 1, 4 67 | 68 | # test if fpu env should be preserved 69 | cmpwi 7, 6, 0 70 | beq 7, label2 71 | 72 | lfd 14, 0(1) # restore F14 73 | lfd 15, 8(1) # restore F15 74 | lfd 16, 16(1) # restore F16 75 | lfd 17, 24(1) # restore F17 76 | lfd 18, 32(1) # restore F18 77 | lfd 19, 40(1) # restore F19 78 | lfd 20, 48(1) # restore F20 79 | lfd 21, 56(1) # restore F21 80 | lfd 22, 64(1) # restore F22 81 | lfd 23, 72(1) # restore F23 82 | lfd 24, 80(1) # restore F24 83 | lfd 25, 88(1) # restore F25 84 | lfd 26, 96(1) # restore F26 85 | lfd 27, 104(1) # restore F27 86 | lfd 28, 112(1) # restore F28 87 | lfd 29, 120(1) # restore F29 88 | lfd 30, 128(1) # restore F30 89 | lfd 31, 136(1) # restore F31 90 | lfd 0, 144(1) # load FPSCR 91 | mtfsf 0xff, 0 # restore FPSCR 92 | 93 | label2: 94 | ld 13, 152(1) # restore R13 95 | ld 14, 160(1) # restore R14 96 | ld 15, 168(1) # restore R15 97 | ld 16, 176(1) # restore R16 98 | ld 17, 184(1) # restore R17 99 | ld 18, 192(1) # restore R18 100 | ld 19, 200(1) # restore R19 101 | ld 20, 208(1) # restore R20 102 | ld 21, 216(1) # restore R21 103 | ld 22, 224(1) # restore R22 104 | ld 23, 232(1) # restore R23 105 | ld 24, 240(1) # restore R24 106 | ld 25, 248(1) # restore R25 107 | ld 26, 256(1) # restore R26 108 | ld 27, 264(1) # restore R27 109 | ld 28, 272(1) # restore R28 110 | ld 29, 280(1) # restore R29 111 | ld 30, 288(1) # restore R30 112 | ld 31, 296(1) # restore R31 113 | 114 | # restore CR 115 | ld 0, 304(1) 116 | mtcr 0 117 | # restore LR 118 | ld 0, 312(1) 119 | mtlr 0 120 | 121 | # load PC 122 | ld 0, 320(1) 123 | # restore CTR 124 | mtctr 0 125 | 126 | # adjust stack 127 | addi 1, 1, 328 128 | 129 | # use third arg as return value after jump 130 | # use third arg as first arg in context function 131 | mr 3, 5 132 | 133 | # jump to context 134 | bctr 135 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_x86_64_sysv_elf_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /**************************************************************************************** 9 | * * 10 | * ---------------------------------------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ---------------------------------------------------------------------------------- * 13 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * 14 | * ---------------------------------------------------------------------------------- * 15 | * | fc_mxcsr|fc_x87_cw| R12 | R13 | R14 | * 16 | * ---------------------------------------------------------------------------------- * 17 | * ---------------------------------------------------------------------------------- * 18 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 19 | * ---------------------------------------------------------------------------------- * 20 | * | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | * 21 | * ---------------------------------------------------------------------------------- * 22 | * | R15 | RBX | RBP | RIP | * 23 | * ---------------------------------------------------------------------------------- * 24 | * ---------------------------------------------------------------------------------- * 25 | * | 16 | 17 | | * 26 | * ---------------------------------------------------------------------------------- * 27 | * | 0x40 | 0x44 | | * 28 | * ---------------------------------------------------------------------------------- * 29 | * | EXIT | | * 30 | * ---------------------------------------------------------------------------------- * 31 | * * 32 | ****************************************************************************************/ 33 | 34 | .text 35 | .globl jump_fcontext 36 | .type jump_fcontext,@function 37 | .align 16 38 | jump_fcontext: 39 | pushq %rbp /* save RBP */ 40 | pushq %rbx /* save RBX */ 41 | pushq %r15 /* save R15 */ 42 | pushq %r14 /* save R14 */ 43 | pushq %r13 /* save R13 */ 44 | pushq %r12 /* save R12 */ 45 | 46 | /* prepare stack for FPU */ 47 | leaq -0x8(%rsp), %rsp 48 | 49 | /* test for flag preserve_fpu */ 50 | cmp $0, %rcx 51 | je 1f 52 | 53 | /* save MMX control- and status-word */ 54 | stmxcsr (%rsp) 55 | /* save x87 control-word */ 56 | fnstcw 0x4(%rsp) 57 | 58 | 1: 59 | /* store RSP (pointing to context-data) in RDI */ 60 | movq %rsp, (%rdi) 61 | 62 | /* restore RSP (pointing to context-data) from RSI */ 63 | movq %rsi, %rsp 64 | 65 | /* test for flag preserve_fpu */ 66 | cmp $0, %rcx 67 | je 2f 68 | 69 | /* restore MMX control- and status-word */ 70 | ldmxcsr (%rsp) 71 | /* restore x87 control-word */ 72 | fldcw 0x4(%rsp) 73 | 74 | 2: 75 | /* prepare stack for FPU */ 76 | leaq 0x8(%rsp), %rsp 77 | 78 | popq %r12 /* restrore R12 */ 79 | popq %r13 /* restrore R13 */ 80 | popq %r14 /* restrore R14 */ 81 | popq %r15 /* restrore R15 */ 82 | popq %rbx /* restrore RBX */ 83 | popq %rbp /* restrore RBP */ 84 | 85 | /* restore return-address */ 86 | popq %r8 87 | 88 | /* use third arg as return-value after jump */ 89 | movq %rdx, %rax 90 | /* use third arg as first arg in context function */ 91 | movq %rdx, %rdi 92 | 93 | /* indirect jump to context */ 94 | jmp *%r8 95 | .size jump_fcontext,.-jump_fcontext 96 | 97 | /* Mark that we don't need executable stack. */ 98 | .section .note.GNU-stack,"",%progbits 99 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/jump_x86_64_sysv_macho_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /**************************************************************************************** 9 | * * 10 | * ---------------------------------------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ---------------------------------------------------------------------------------- * 13 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * 14 | * ---------------------------------------------------------------------------------- * 15 | * | fc_mxcsr|fc_x87_cw| R12 | R13 | R14 | * 16 | * ---------------------------------------------------------------------------------- * 17 | * ---------------------------------------------------------------------------------- * 18 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 19 | * ---------------------------------------------------------------------------------- * 20 | * | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | * 21 | * ---------------------------------------------------------------------------------- * 22 | * | R15 | RBX | RBP | RIP | * 23 | * ---------------------------------------------------------------------------------- * 24 | * ---------------------------------------------------------------------------------- * 25 | * | 16 | 17 | | * 26 | * ---------------------------------------------------------------------------------- * 27 | * | 0x40 | 0x44 | | * 28 | * ---------------------------------------------------------------------------------- * 29 | * | EXIT | | * 30 | * ---------------------------------------------------------------------------------- * 31 | * * 32 | ****************************************************************************************/ 33 | 34 | .text 35 | .globl _jump_fcontext 36 | .align 8 37 | _jump_fcontext: 38 | pushq %rbp /* save RBP */ 39 | pushq %rbx /* save RBX */ 40 | pushq %r15 /* save R15 */ 41 | pushq %r14 /* save R14 */ 42 | pushq %r13 /* save R13 */ 43 | pushq %r12 /* save R12 */ 44 | 45 | /* prepare stack for FPU */ 46 | leaq -0x8(%rsp), %rsp 47 | 48 | /* test for flag preserve_fpu */ 49 | cmp $0, %rcx 50 | je 1f 51 | 52 | /* save MMX control- and status-word */ 53 | stmxcsr (%rsp) 54 | /* save x87 control-word */ 55 | fnstcw 0x4(%rsp) 56 | 57 | 1: 58 | /* store RSP (pointing to context-data) in RDI */ 59 | movq %rsp, (%rdi) 60 | 61 | /* restore RSP (pointing to context-data) from RSI */ 62 | movq %rsi, %rsp 63 | 64 | /* test for flag preserve_fpu */ 65 | cmp $0, %rcx 66 | je 2f 67 | 68 | /* restore MMX control- and status-word */ 69 | ldmxcsr (%rsp) 70 | /* restore x87 control-word */ 71 | fldcw 0x4(%rsp) 72 | 73 | 2: 74 | /* prepare stack for FPU */ 75 | leaq 0x8(%rsp), %rsp 76 | 77 | popq %r12 /* restrore R12 */ 78 | popq %r13 /* restrore R13 */ 79 | popq %r14 /* restrore R14 */ 80 | popq %r15 /* restrore R15 */ 81 | popq %rbx /* restrore RBX */ 82 | popq %rbp /* restrore RBP */ 83 | 84 | /* restore return-address */ 85 | popq %r8 86 | 87 | /* use third arg as return-value after jump */ 88 | movq %rdx, %rax 89 | /* use third arg as first arg in context function */ 90 | movq %rdx, %rdi 91 | 92 | /* indirect jump to context */ 93 | jmp *%r8 94 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_arm64_aapcs_elf_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Edward Nevill 2015 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | /******************************************************* 8 | * * 9 | * ------------------------------------------------- * 10 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 11 | * ------------------------------------------------- * 12 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * 13 | * ------------------------------------------------- * 14 | * | d8 | d9 | d10 | d11 | * 15 | * ------------------------------------------------- * 16 | * ------------------------------------------------- * 17 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 18 | * ------------------------------------------------- * 19 | * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * 20 | * ------------------------------------------------- * 21 | * | d12 | d13 | d14 | d15 | * 22 | * ------------------------------------------------- * 23 | * ------------------------------------------------- * 24 | * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * 25 | * ------------------------------------------------- * 26 | * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * 27 | * ------------------------------------------------- * 28 | * | x19 | x20 | x21 | x22 | * 29 | * ------------------------------------------------- * 30 | * ------------------------------------------------- * 31 | * | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | * 32 | * ------------------------------------------------- * 33 | * | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| * 34 | * ------------------------------------------------- * 35 | * | x23 | x24 | x25 | x26 | * 36 | * ------------------------------------------------- * 37 | * ------------------------------------------------- * 38 | * | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * 39 | * ------------------------------------------------- * 40 | * | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| * 41 | * ------------------------------------------------- * 42 | * | x27 | x28 | FP | LR | * 43 | * ------------------------------------------------- * 44 | * ------------------------------------------------- * 45 | * | 40 | 41 | 42 | 43 | | | * 46 | * ------------------------------------------------- * 47 | * | 0xa0| 0xa4| 0xa8| 0xac| | | * 48 | * ------------------------------------------------- * 49 | * | PC | align | | | * 50 | * ------------------------------------------------- * 51 | * * 52 | *******************************************************/ 53 | 54 | .cpu generic+fp+simd 55 | .text 56 | .align 2 57 | .global make_fcontext 58 | .type make_fcontext, %function 59 | make_fcontext: 60 | # shift address in x0 (allocated stack) to lower 16 byte boundary 61 | and x0, x0, ~0xF 62 | 63 | # reserve space for context-data on context-stack 64 | sub x0, x0, #0xb0 65 | 66 | # third arg of make_fcontext() == address of context-function 67 | # store address as a PC to jump in 68 | str x2, [x0, #0xa0] 69 | 70 | # save address of finish as return-address for context-function 71 | # will be entered after context-function returns (LR register) 72 | adr x1, finish 73 | str x1, [x0, #0x98] 74 | 75 | ret x30 // return pointer to context-data (x0) 76 | 77 | finish: 78 | # exit code is zero 79 | mov x0, #0 80 | # exit application 81 | bl _exit 82 | 83 | .size make_fcontext,.-make_fcontext 84 | # Mark that we don't need executable stack. 85 | .section .note.GNU-stack,"",%progbits 86 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_arm64_aapcs_macho_gas.S: -------------------------------------------------------------------------------- 1 | /******************************************************* 2 | * * 3 | * ------------------------------------------------- * 4 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 5 | * ------------------------------------------------- * 6 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * 7 | * ------------------------------------------------- * 8 | * | d8 | d9 | d10 | d11 | * 9 | * ------------------------------------------------- * 10 | * ------------------------------------------------- * 11 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 12 | * ------------------------------------------------- * 13 | * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * 14 | * ------------------------------------------------- * 15 | * | d12 | d13 | d14 | d15 | * 16 | * ------------------------------------------------- * 17 | * ------------------------------------------------- * 18 | * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * 19 | * ------------------------------------------------- * 20 | * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * 21 | * ------------------------------------------------- * 22 | * | x19 | x20 | x21 | x22 | * 23 | * ------------------------------------------------- * 24 | * ------------------------------------------------- * 25 | * | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | * 26 | * ------------------------------------------------- * 27 | * | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| * 28 | * ------------------------------------------------- * 29 | * | x23 | x24 | x25 | x26 | * 30 | * ------------------------------------------------- * 31 | * ------------------------------------------------- * 32 | * | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * 33 | * ------------------------------------------------- * 34 | * | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| * 35 | * ------------------------------------------------- * 36 | * | x27 | x28 | FP | LR | * 37 | * ------------------------------------------------- * 38 | * ------------------------------------------------- * 39 | * | 40 | 41 | 42 | 43 | | | * 40 | * ------------------------------------------------- * 41 | * | 0xa0| 0xa4| 0xa8| 0xac| | | * 42 | * ------------------------------------------------- * 43 | * | PC | align | | | * 44 | * ------------------------------------------------- * 45 | * * 46 | *******************************************************/ 47 | 48 | 49 | .text 50 | .globl _make_fcontext 51 | .balign 16 52 | 53 | _make_fcontext: 54 | ; shift address in x0 (allocated stack) to lower 16 byte boundary 55 | and x0, x0, ~0xF 56 | 57 | ; reserve space for context-data on context-stack 58 | sub x0, x0, #0xb0 59 | 60 | ; third arg of make_fcontext() == address of context-function 61 | ; store address as a PC to jump in 62 | str x2, [x0, #0xa0] 63 | 64 | ; compute abs address of label finish 65 | ; 0x0c = 3 instructions * size (4) before label 'finish' 66 | 67 | ; TODO: Numeric offset since llvm still does not support labels in ADR. Fix: 68 | ; http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140407/212336.html 69 | adr x1, 0x0c 70 | 71 | ; save address of finish as return-address for context-function 72 | ; will be entered after context-function returns (LR register) 73 | str x1, [x0, #0x98] 74 | 75 | ret lr ; return pointer to context-data (x0) 76 | 77 | finish: 78 | ; exit code is zero 79 | mov x0, #0 80 | ; exit application 81 | bl __exit 82 | 83 | 84 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_arm_aapcs_elf_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /******************************************************* 9 | * * 10 | * ------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ------------------------------------------------- * 13 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * 14 | * ------------------------------------------------- * 15 | * | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | * 16 | * ------------------------------------------------- * 17 | * ------------------------------------------------- * 18 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 19 | * ------------------------------------------------- * 20 | * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * 21 | * ------------------------------------------------- * 22 | * | s24 | s25 | s26 | s27 | s28 | s29 | s30 | s31 | * 23 | * ------------------------------------------------- * 24 | * ------------------------------------------------- * 25 | * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * 26 | * ------------------------------------------------- * 27 | * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * 28 | * ------------------------------------------------- * 29 | * | v1 | v2 | v3 | v4 | v5 | v6 | v7 | v8 | * 30 | * ------------------------------------------------- * 31 | * ------------------------------------------------- * 32 | * | 24 | 25 | | * 33 | * ------------------------------------------------- * 34 | * | 0x60| 0x64| | * 35 | * ------------------------------------------------- * 36 | * | lr | pc | | * 37 | * ------------------------------------------------- * 38 | * * 39 | *******************************************************/ 40 | 41 | .text 42 | .globl make_fcontext 43 | .align 2 44 | .type make_fcontext,%function 45 | make_fcontext: 46 | @ shift address in A1 to lower 16 byte boundary 47 | bic a1, a1, #15 48 | 49 | @ reserve space for context-data on context-stack 50 | sub a1, a1, #104 51 | 52 | @ third arg of make_fcontext() == address of context-function 53 | str a3, [a1,#100] 54 | 55 | @ compute abs address of label finish 56 | adr a2, finish 57 | @ save address of finish as return-address for context-function 58 | @ will be entered after context-function returns 59 | str a2, [a1,#96] 60 | 61 | bx lr @ return pointer to context-data 62 | 63 | finish: 64 | @ exit code is zero 65 | mov a1, #0 66 | @ exit application 67 | bl _exit@PLT 68 | .size make_fcontext,.-make_fcontext 69 | 70 | @ Mark that we don't need executable stack. 71 | .section .note.GNU-stack,"",%progbits 72 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_arm_aapcs_macho_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /******************************************************* 9 | * * 10 | * ------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ------------------------------------------------- * 13 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * 14 | * ------------------------------------------------- * 15 | * | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | * 16 | * ------------------------------------------------- * 17 | * ------------------------------------------------- * 18 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 19 | * ------------------------------------------------- * 20 | * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * 21 | * ------------------------------------------------- * 22 | * | s24 | s25 | s26 | s27 | s28 | s29 | s30 | s31 | * 23 | * ------------------------------------------------- * 24 | * ------------------------------------------------- * 25 | * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * 26 | * ------------------------------------------------- * 27 | * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * 28 | * ------------------------------------------------- * 29 | * | sjlj| v1 | v2 | v3 | v4 | v5 | v6 | v7 | * 30 | * ------------------------------------------------- * 31 | * ------------------------------------------------- * 32 | * | 24 | 25 | 26 | | * 33 | * ------------------------------------------------- * 34 | * | 0x60| 0x64| 0x68| | * 35 | * ------------------------------------------------- * 36 | * | v8 | lr | pc | | * 37 | * ------------------------------------------------- * 38 | * * 39 | *******************************************************/ 40 | 41 | .text 42 | .globl _make_fcontext 43 | .align 2 44 | _make_fcontext: 45 | @ shift address in A1 to lower 16 byte boundary 46 | bic a1, a1, #15 47 | 48 | @ reserve space for context-data on context-stack 49 | sub a1, a1, #108 50 | 51 | @ third arg of make_fcontext() == address of context-function 52 | str a3, [a1,#104] 53 | 54 | @ compute abs address of label finish 55 | adr a2, finish 56 | @ save address of finish as return-address for context-function 57 | @ will be entered after context-function returns 58 | str a2, [a1,#100] 59 | 60 | bx lr @ return pointer to context-data 61 | 62 | finish: 63 | @ exit code is zero 64 | mov a1, #0 65 | @ exit application 66 | bl __exit 67 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_arm_aapcs_pe_armasm.asm: -------------------------------------------------------------------------------- 1 | ;/* 2 | ; Copyright Oliver Kowalke 2009. 3 | ; Distributed under the Boost Software License, Version 1.0. 4 | ; (See accompanying file LICENSE_1_0.txt or copy at 5 | ; http://www.boost.org/LICENSE_1_0.txt) 6 | ;*/ 7 | 8 | ; ******************************************************* 9 | ; * * 10 | ; * ------------------------------------------------- * 11 | ; * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | ; * ------------------------------------------------- * 13 | ; * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * 14 | ; * ------------------------------------------------- * 15 | ; * | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | * 16 | ; * ------------------------------------------------- * 17 | ; * ------------------------------------------------- * 18 | ; * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 19 | ; * ------------------------------------------------- * 20 | ; * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * 21 | ; * ------------------------------------------------- * 22 | ; * | s24 | s25 | s26 | s27 | s28 | s29 | s30 | s31 | * 23 | ; * ------------------------------------------------- * 24 | ; * ------------------------------------------------- * 25 | ; * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * 26 | ; * ------------------------------------------------- * 27 | ; * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * 28 | ; * ------------------------------------------------- * 29 | ; * |deall|limit| base| v1 | v2 | v3 | v4 | v5 | * 30 | ; * ------------------------------------------------- * 31 | ; * ------------------------------------------------- * 32 | ; * | 24 | 25 | 26 | 27 | 28 | | * 33 | ; * ------------------------------------------------- * 34 | ; * | 0x60| 0x64| 0x68| 0x6c| 0x70| | * 35 | ; * ------------------------------------------------- * 36 | ; * | v6 | v7 | v8 | lr | pc | | * 37 | ; * ------------------------------------------------- * 38 | ; * * 39 | ; ******************************************************* 40 | 41 | 42 | AREA |.text|, CODE 43 | ALIGN 4 44 | EXPORT make_fcontext 45 | IMPORT _exit 46 | 47 | make_fcontext PROC 48 | ; first arg of make_fcontext() == top of context-stack 49 | ; save top of context-stack (base) A4 50 | mov a4, a1 51 | 52 | ; shift address in A1 to lower 16 byte boundary 53 | bic a1, a1, #0x0f 54 | 55 | ; reserve space for context-data on context-stack 56 | sub a1, a1, #0x74 57 | 58 | ; save top address of context_stack as 'base' 59 | str a4, [a1,#0x48] 60 | ; second arg of make_fcontext() == size of context-stack 61 | ; compute bottom address of context-stack (limit) 62 | sub a4, a4, a2 63 | ; save bottom address of context-stack as 'limit' 64 | str a4, [a1,#0x44] 65 | ; save bottom address of context-stack as 'dealloction stack' 66 | str a4, [a1,#0x40] 67 | 68 | ; third arg of make_fcontext() == address of context-function 69 | str a3, [a1,#0x70] 70 | 71 | ; compute abs address of label finish 72 | adr a2, finish 73 | ; save address of finish as return-address for context-function 74 | ; will be entered after context-function returns 75 | str a2, [a1,#0x6c] 76 | 77 | bx lr ; return pointer to context-data 78 | 79 | finish 80 | ; exit code is zero 81 | mov a1, #0 82 | ; exit application 83 | bl _exit 84 | 85 | ENDP 86 | END 87 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_combined_sysv_macho_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sergue E. Leontiev 2013. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | // Stub file for universal binary 9 | 10 | #if defined(__i386__) 11 | #include "make_i386_sysv_macho_gas.S" 12 | #elif defined(__x86_64__) 13 | #include "make_x86_64_sysv_macho_gas.S" 14 | #elif defined(__ppc__) 15 | #include "make_ppc32_sysv_macho_gas.S" 16 | #elif defined(__ppc64__) 17 | #include "make_ppc64_sysv_macho_gas.S" 18 | #else 19 | #error "No arch's" 20 | #endif 21 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_i386_ms_pe_masm.asm: -------------------------------------------------------------------------------- 1 | 2 | ; Copyright Oliver Kowalke 2009. 3 | ; Distributed under the Boost Software License, Version 1.0. 4 | ; (See accompanying file LICENSE_1_0.txt or copy at 5 | ; http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | ; --------------------------------------------------------------------------------- 8 | ; | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | ; --------------------------------------------------------------------------------- 10 | ; | 0h | 04h | 08h | 0ch | 010h | 014h | 018h | 01ch | 11 | ; --------------------------------------------------------------------------------- 12 | ; | fc_mxcsr|fc_x87_cw| fc_strg |fc_deallo| limit | base | fc_seh | EDI | 13 | ; --------------------------------------------------------------------------------- 14 | ; --------------------------------------------------------------------------------- 15 | ; | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ; --------------------------------------------------------------------------------- 17 | ; | 020h | 024h | 028h | 02ch | 030h | 034h | 038h | 03ch | 18 | ; --------------------------------------------------------------------------------- 19 | ; | ESI | EBX | EBP | EIP | EXIT | | SEH NXT |SEH HNDLR| 20 | ; --------------------------------------------------------------------------------- 21 | 22 | .386 23 | .XMM 24 | .model flat, c 25 | ; standard C library function 26 | _exit PROTO, value:SDWORD 27 | .code 28 | 29 | make_fcontext PROC BOOST_CONTEXT_EXPORT 30 | ; first arg of make_fcontext() == top of context-stack 31 | mov eax, [esp+04h] 32 | 33 | ; reserve space for first argument of context-function 34 | ; EAX might already point to a 16byte border 35 | lea eax, [eax-08h] 36 | 37 | ; shift address in EAX to lower 16 byte boundary 38 | and eax, -16 39 | 40 | ; reserve space for context-data on context-stack 41 | ; size for fc_mxcsr .. EIP + return-address for context-function 42 | ; on context-function entry: (ESP -0x4) % 8 == 0 43 | ; additional space is required for SEH 44 | lea eax, [eax-03ch] 45 | 46 | ; first arg of make_fcontext() == top of context-stack 47 | mov ecx, [esp+04h] 48 | ; save top address of context stack as 'base' 49 | mov [eax+014h], ecx 50 | ; second arg of make_fcontext() == size of context-stack 51 | mov edx, [esp+08h] 52 | ; negate stack size for LEA instruction (== substraction) 53 | neg edx 54 | ; compute bottom address of context stack (limit) 55 | lea ecx, [ecx+edx] 56 | ; save bottom address of context-stack as 'limit' 57 | mov [eax+010h], ecx 58 | ; save bottom address of context-stack as 'dealloction stack' 59 | mov [eax+0ch], ecx 60 | 61 | ; third arg of make_fcontext() == address of context-function 62 | mov ecx, [esp+0ch] 63 | mov [eax+02ch], ecx 64 | 65 | ; save MMX control- and status-word 66 | stmxcsr [eax] 67 | ; save x87 control-word 68 | fnstcw [eax+04h] 69 | 70 | ; compute abs address of label finish 71 | mov ecx, finish 72 | ; save address of finish as return-address for context-function 73 | ; will be entered after context-function returns 74 | mov [eax+030h], ecx 75 | 76 | ; traverse current seh chain to get the last exception handler installed by Windows 77 | ; note that on Windows Server 2008 and 2008 R2, SEHOP is activated by default 78 | ; the exception handler chain is tested for the presence of ntdll.dll!FinalExceptionHandler 79 | ; at its end by RaiseException all seh-handlers are disregarded if not present and the 80 | ; program is aborted 81 | assume fs:nothing 82 | ; load NT_TIB into ECX 83 | mov ecx, fs:[0h] 84 | assume fs:error 85 | 86 | walk: 87 | ; load 'next' member of current SEH into EDX 88 | mov edx, [ecx] 89 | ; test if 'next' of current SEH is last (== 0xffffffff) 90 | inc edx 91 | jz found 92 | dec edx 93 | ; exchange content; ECX contains address of next SEH 94 | xchg edx, ecx 95 | ; inspect next SEH 96 | jmp walk 97 | 98 | found: 99 | ; load 'handler' member of SEH == address of last SEH handler installed by Windows 100 | mov ecx, [ecx+04h] 101 | ; save address in ECX as SEH handler for context 102 | mov [eax+03ch], ecx 103 | ; set ECX to -1 104 | mov ecx, 0ffffffffh 105 | ; save ECX as next SEH item 106 | mov [eax+038h], ecx 107 | ; load address of next SEH item 108 | lea ecx, [eax+038h] 109 | ; save next SEH 110 | mov [eax+018h], ecx 111 | 112 | ret ; return pointer to context-data 113 | 114 | finish: 115 | ; exit code is zero 116 | xor eax, eax 117 | mov [esp], eax 118 | ; exit application 119 | call _exit 120 | hlt 121 | make_fcontext ENDP 122 | END 123 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_i386_sysv_elf_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /**************************************************************************************** 9 | * * 10 | * ---------------------------------------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ---------------------------------------------------------------------------------- * 13 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * 14 | * ---------------------------------------------------------------------------------- * 15 | * | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | EXIT | * 16 | * ---------------------------------------------------------------------------------- * 17 | * * 18 | ****************************************************************************************/ 19 | 20 | .text 21 | .globl make_fcontext 22 | .align 2 23 | .type make_fcontext,@function 24 | make_fcontext: 25 | /* first arg of make_fcontext() == top of context-stack */ 26 | movl 0x4(%esp), %eax 27 | 28 | /* reserve space for first argument of context-function 29 | rax might already point to a 16byte border */ 30 | leal -0x8(%eax), %eax 31 | 32 | /* shift address in EAX to lower 16 byte boundary */ 33 | andl $-16, %eax 34 | 35 | /* reserve space for context-data on context-stack */ 36 | /* size for fc_mxcsr .. EIP + return-address for context-function */ 37 | /* on context-function entry: (ESP -0x4) % 8 == 0 */ 38 | leal -0x20(%eax), %eax 39 | 40 | /* third arg of make_fcontext() == address of context-function */ 41 | movl 0xc(%esp), %edx 42 | movl %edx, 0x18(%eax) 43 | 44 | /* save MMX control- and status-word */ 45 | stmxcsr (%eax) 46 | /* save x87 control-word */ 47 | fnstcw 0x4(%eax) 48 | 49 | /* compute abs address of label finish */ 50 | call 1f 51 | /* address of label 1 */ 52 | 1: popl %ecx 53 | /* compute abs address of label finish */ 54 | addl $finish-1b, %ecx 55 | /* save address of finish as return-address for context-function */ 56 | /* will be entered after context-function returns */ 57 | movl %ecx, 0x1c(%eax) 58 | 59 | ret /* return pointer to context-data */ 60 | 61 | finish: 62 | call 2f 63 | /* address of label 2 */ 64 | 2: popl %ebx 65 | /* compute address of GOT and store it in EBX */ 66 | addl $_GLOBAL_OFFSET_TABLE_+[.-2b], %ebx 67 | 68 | /* exit code is zero */ 69 | xorl %eax, %eax 70 | movl %eax, (%esp) 71 | /* exit application */ 72 | call _exit@PLT 73 | hlt 74 | .size make_fcontext,.-make_fcontext 75 | 76 | /* Mark that we don't need executable stack. */ 77 | .section .note.GNU-stack,"",%progbits 78 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_i386_sysv_macho_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /**************************************************************************************** 9 | * * 10 | * ---------------------------------------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ---------------------------------------------------------------------------------- * 13 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * 14 | * ---------------------------------------------------------------------------------- * 15 | * | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | EXIT | * 16 | * ---------------------------------------------------------------------------------- * 17 | * * 18 | ****************************************************************************************/ 19 | 20 | .text 21 | .globl _make_fcontext 22 | .align 2 23 | _make_fcontext: 24 | /* first arg of make_fcontext() == top of context-stack */ 25 | movl 0x4(%esp), %eax 26 | 27 | /* reserve space for first argument of context-function 28 | rax might already point to a 16byte border */ 29 | leal -0x8(%eax), %eax 30 | 31 | /* shift address in EAX to lower 16 byte boundary */ 32 | andl $-16, %eax 33 | 34 | /* reserve space for context-data on context-stack */ 35 | /* size for fc_mxcsr .. EIP + return-address for context-function */ 36 | /* on context-function entry: (ESP -0x4) % 8 == 0 */ 37 | leal -0x20(%eax), %eax 38 | 39 | /* thrid arg of make_fcontext() == address of context-function */ 40 | movl 0xc(%esp), %edx 41 | movl %edx, 0x18(%eax) 42 | 43 | /* save MMX control- and status-word */ 44 | stmxcsr (%eax) 45 | /* save x87 control-word */ 46 | fnstcw 0x4(%eax) 47 | 48 | /* compute abs address of label finish */ 49 | call 1f 50 | /* address of label 1 */ 51 | 1: popl %ecx 52 | /* compute abs address of label finish */ 53 | addl $finish-1b, %ecx 54 | /* save address of finish as return-address for context-function */ 55 | /* will be entered after context-function returns */ 56 | movl %ecx, 0x1c(%eax) 57 | 58 | ret /* return pointer to context-data */ 59 | 60 | finish: 61 | /* exit code is zero */ 62 | xorl %eax, %eax 63 | movl %eax, (%esp) 64 | /* exit application */ 65 | call __exit 66 | hlt 67 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_i386_x86_64_sysv_macho_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sergue E. Leontiev 2013. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | // Stub file for universal binary 9 | 10 | #if defined(__i386__) 11 | #include "make_i386_sysv_macho_gas.S" 12 | #elif defined(__x86_64__) 13 | #include "make_x86_64_sysv_macho_gas.S" 14 | #else 15 | #error "No arch's" 16 | #endif 17 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_mips32_o32_elf_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /******************************************************* 9 | * * 10 | * ------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ------------------------------------------------- * 13 | * | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | * 14 | * ------------------------------------------------- * 15 | * | F20 | F22 | F24 | F26 | * 16 | * ------------------------------------------------- * 17 | * ------------------------------------------------- * 18 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 19 | * ------------------------------------------------- * 20 | * | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | * 21 | * ------------------------------------------------- * 22 | * | F28 | F30 | S0 | S1 | S2 | S3 | * 23 | * ------------------------------------------------- * 24 | * ------------------------------------------------- * 25 | * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | | * 26 | * ------------------------------------------------- * 27 | * | 64 | 68 | 72 | 76 | 80 | 84 | 88 | | * 28 | * ------------------------------------------------- * 29 | * | S4 | S5 | S6 | S7 | FP | RA | PC | | * 30 | * ------------------------------------------------- * 31 | * * 32 | * *****************************************************/ 33 | 34 | .text 35 | .globl make_fcontext 36 | .align 2 37 | .type make_fcontext,@function 38 | .ent make_fcontext 39 | make_fcontext: 40 | #ifdef __PIC__ 41 | .set noreorder 42 | .cpload $t9 43 | .set reorder 44 | #endif 45 | # first arg of make_fcontext() == top address of context-stack 46 | move $v0, $a0 47 | 48 | # shift address in A0 to lower 16 byte boundary 49 | move $v1, $v0 50 | li $v0, -16 # 0xfffffffffffffff0 51 | and $v0, $v1, $v0 52 | 53 | # reserve space for context-data on context-stack 54 | # including 48 byte of shadow space (sp % 16 == 0) 55 | addiu $v0, $v0, -140 56 | 57 | # third arg of make_fcontext() == address of context-function 58 | sw $a2, 88($v0) 59 | # save global pointer in context-data 60 | # S0 will contain address of global pointer 61 | sw $gp, 48($v0) 62 | 63 | # compute abs address of label finish 64 | la $t9, finish 65 | # save address of finish as return-address for context-function 66 | # will be entered after context-function returns 67 | sw $t9, 84($v0) 68 | 69 | jr $ra # return pointer to context-data 70 | 71 | finish: 72 | # allocate stack space (contains shadow space for subroutines) 73 | addiu $sp, $sp, -32 74 | # save return address 75 | sw $ra, 28($sp) 76 | 77 | # restore GP (global pointer) 78 | move $gp, $s0 79 | # exit code is zero 80 | move $a0, $zero 81 | # address of exit 82 | lw $t9, %call16(_exit)($gp) 83 | # exit application 84 | jalr $t9 85 | .end make_fcontext 86 | .size make_fcontext, .-make_fcontext 87 | 88 | /* Mark that we don't need executable stack. */ 89 | .section .note.GNU-stack,"",%progbits 90 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_ppc32_ppc64_sysv_macho_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sergue E. Leontiev 2013. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | // Stub file for universal binary 9 | 10 | #if defined(__ppc__) 11 | #include "make_ppc32_sysv_macho_gas.S" 12 | #elif defined(__ppc64__) 13 | #include "make_ppc64_sysv_macho_gas.S" 14 | #else 15 | #error "No arch's" 16 | #endif 17 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_ppc32_sysv_xcoff_gas.S: -------------------------------------------------------------------------------- 1 | .globl make_fcontext[DS] 2 | .globl .make_fcontext[PR] 3 | .align 2 4 | .csect make_fcontext[DS] 5 | make_fcontext: 6 | .long .make_fcontext[PR] 7 | .csect .make_fcontext[PR], 3 8 | #.make_fcontext: 9 | # save return address into R6 10 | mflr 6 11 | 12 | # first arg of make_fcontext() == top address of context-function 13 | # shift address in R3 to lower 16 byte boundary 14 | clrrwi 3, 3, 4 15 | 16 | # reserve space for context-data on context-stack 17 | # including 64 byte of linkage + parameter area (R1 % 16 == 0) 18 | subi 3, 3, 304 19 | 20 | # third arg of make_fcontext() == address of context-function 21 | stw 5, 236(3) 22 | 23 | # load LR 24 | mflr 0 25 | # jump to label 1 26 | bl .Label 27 | .Label: 28 | # load LR into R4 29 | mflr 4 30 | # compute abs address of label .L_finish 31 | addi 4, 4, .L_finish - .Label 32 | # restore LR 33 | mtlr 0 34 | # save address of finish as return-address for context-function 35 | # will be entered after context-function returns 36 | stw 4, 232(3) 37 | 38 | # restore return address from R6 39 | mtlr 6 40 | 41 | blr # return pointer to context-data 42 | 43 | .L_finish: 44 | # save return address into R0 45 | mflr 0 46 | # save return address on stack, set up stack frame 47 | stw 0, 4(1) 48 | # allocate stack space, R1 % 16 == 0 49 | stwu 1, -16(1) 50 | 51 | # exit code is zero 52 | li 3, 0 53 | # exit application 54 | bl ._exit 55 | nop 56 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_ppc64_sysv_xcoff_gas.S: -------------------------------------------------------------------------------- 1 | .globl make_fcontext[DS] 2 | .globl .make_fcontext[PR] 3 | .align 2 4 | .csect .make_fcontext[PR], 3 5 | .globl _make_fcontext 6 | #._make_fcontext: 7 | # save return address into R6 8 | mflr 6 9 | 10 | # first arg of make_fcontext() == top address of context-function 11 | # shift address in R3 to lower 16 byte boundary 12 | clrrwi 3, 3, 4 13 | 14 | # reserve space for context-data on context-stack 15 | # including 64 byte of linkage + parameter area (R1 % 16 == 0) 16 | subi 3, 3, 392 17 | 18 | # third arg of make_fcontext() == address of context-function 19 | stw 5, 320(3) 20 | 21 | # load LR 22 | mflr 0 23 | # jump to label 1 24 | bl .Label 25 | .Label: 26 | # load LR into R4 27 | mflr 4 28 | # compute abs address of label .L_finish 29 | addi 4, 4, .L_finish - .Label 30 | # restore LR 31 | mtlr 0 32 | # save address of finish as return-address for context-function 33 | # will be entered after context-function returns 34 | stw 4, 312(3) 35 | 36 | # restore return address from R6 37 | mtlr 6 38 | 39 | blr # return pointer to context-data 40 | 41 | .L_finish: 42 | # save return address into R0 43 | mflr 0 44 | # save return address on stack, set up stack frame 45 | stw 0, 8(1) 46 | # allocate stack space, R1 % 16 == 0 47 | stwu 1, -32(1) 48 | 49 | # exit code is zero 50 | li 3, 0 51 | # exit application 52 | bl ._exit 53 | nop 54 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_sparc64_sysv_elf_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Martin Husemann 2013. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /******************************************************************* 9 | * * 10 | * ------------------------------------------------------------- * 11 | * | Offset (in 4 or 8 byte units) | Content | * 12 | * ------------------------------------------------------------- * 13 | * | 0 | %sp | * 14 | * ------------------------------------------------------------- * 15 | * | 1 | %pc | * 16 | * ------------------------------------------------------------- * 17 | * | 2 | %i7 (return address) | * 18 | * ------------------------------------------------------------- * 19 | * | 3 | %g1 | * 20 | * ------------------------------------------------------------- * 21 | * | 4 | %g2 | * 22 | * ------------------------------------------------------------- * 23 | * | 5 | %g3 | * 24 | * ------------------------------------------------------------- * 25 | * | 6 | %g6 | * 26 | * ------------------------------------------------------------- * 27 | * | 7 | %g7 | * 28 | * ------------------------------------------------------------- * 29 | * The local and in registers are stored on the stack. * 30 | *******************************************************************/ 31 | 32 | #define OFF(N) (8*(N)) 33 | #define CCFSZ 176 // C Compiler Frame Size 34 | #define BIAS (2048-1) // Stack offset for 64 bit programs 35 | #define FC_SZ 448 // sizeof(fcontext_t) 36 | #define FC_STK 384 // offsetof(fcontext_t, fc_stack) 37 | #define FC_FPU 0 // offsetof(fcontext_t, fc_fp) 38 | #define FC_FSR 264 // offsetof(fcontext_t, fc_fp.fp_fsr) 39 | #define FC_FPRS 256 // offsetof(fcontext_t, fc_fp.fp_fprs) 40 | #define FC_GREG 320 // offsetof(fcontext_t, fc_greg) 41 | #define BLOCK_SIZE 64 42 | 43 | .register %g2,#ignore 44 | .register %g3,#ignore 45 | .register %g6,#ignore 46 | 47 | .text 48 | .globl make_fcontext 49 | .align 4 50 | .type make_fcontext,@function 51 | // fcontext_t * 52 | // make_fcontext( void * sp, std::size_t size, void (* fn)( intptr_t) ) 53 | make_fcontext: 54 | save %sp, -CCFSZ, %sp 55 | // %i0 initial stack pointer 56 | // %i1 stack size limit 57 | // %i2 function pointer for context start function 58 | 59 | sub %i0, FC_SZ, %i4 // allocate fcontext_t at on the new stack and keep pointer as return value 60 | andn %i4, BLOCK_SIZE-1, %i5 // force block ops usable alignement and keep pointer to fcontext in %i5 61 | 62 | stx %i0, [%i5+FC_STK+OFF(0)] // save fs_stack.sp 63 | stx %i1, [%i5+FC_STK+OFF(1)] // save fs_stack.size 64 | sub %i5, CCFSZ+BIAS, %o1 // leave space for one register window (and offset stack for 64bit) 65 | stx %o1, [%i5+FC_GREG+OFF(0)] // save new stack pointer 66 | stx %i2, [%i5+FC_GREG+OFF(1)] // save new %pc (function pointer) 67 | stx %g1, [%i5+FC_GREG+OFF(3)] 68 | stx %g2, [%i5+FC_GREG+OFF(4)] 69 | stx %g3, [%i5+FC_GREG+OFF(5)] 70 | stx %g6, [%i5+FC_GREG+OFF(6)] 71 | stx %g7, [%i5+FC_GREG+OFF(7)] 72 | 73 | // synthesize "return address": jump to finish 74 | 1: rd %pc, %i4 75 | add %i4, finish-1b-8, %i4 76 | stx %i4, [%i5+FC_GREG+OFF(2)] 77 | 78 | ret 79 | restore %g0, %i5, %o0 // return fcontext_t 80 | 81 | finish: 82 | mov %g0, %o0 83 | call _exit 84 | nop 85 | 86 | .size make_fcontext,.-make_fcontext 87 | 88 | /* Mark that we don't need executable stack. */ 89 | .section .note.GNU-stack,"",%progbits 90 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_sparc_sysv_elf_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Martin Husemann 2013. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /******************************************************************* 9 | * * 10 | * ------------------------------------------------------------- * 11 | * | Offset (in 4 or 8 byte units) | Content | * 12 | * ------------------------------------------------------------- * 13 | * | 0 | %sp | * 14 | * ------------------------------------------------------------- * 15 | * | 1 | %pc | * 16 | * ------------------------------------------------------------- * 17 | * | 2 | %i7 (return address) | * 18 | * ------------------------------------------------------------- * 19 | * | 3 | %g1 | * 20 | * ------------------------------------------------------------- * 21 | * | 4 | %g2 | * 22 | * ------------------------------------------------------------- * 23 | * | 5 | %g3 | * 24 | * ------------------------------------------------------------- * 25 | * | 6 | %g6 | * 26 | * ------------------------------------------------------------- * 27 | * | 7 | %g7 | * 28 | * ------------------------------------------------------------- * 29 | * The local and in registers are stored on the stack. * 30 | *******************************************************************/ 31 | 32 | #define OFF(N) (4*(N)) 33 | #define CCFSZ 96 34 | #define FC_SZ 176 35 | #define FC_stK 168 // offsetof(fcontext_t, fc_stack) 36 | #define FC_FPU 0 // offsetof(fcontext_t, fc_fp) 37 | #define FC_FSR 128 // offsetof(fcontext_t, fc_fp.fp_fsr) 38 | #define FC_GREG 136 // offsetof(fcontext_t, fc_greg) 39 | #define BLOCK_SIZE 8 40 | 41 | .text 42 | .globl make_fcontext 43 | .align 4 44 | .type make_fcontext,@function 45 | // fcontext_t * 46 | // make_fcontext( void * sp, std::size_t size, void (* fn)( intptr_t) ) 47 | make_fcontext: 48 | save %sp, -CCFSZ, %sp 49 | // %i0 initial stack pointer 50 | // %i1 stack size limit 51 | // %i2 function pointer for context start function 52 | 53 | sub %i0, FC_SZ, %i4 // allocate fcontext_t at on the new stack and keep pointer as return value 54 | andn %i4, BLOCK_SIZE-1, %i5 // force block ops usable alignement and keep pointer to fcontext in %i5 55 | 56 | st %i0, [%i5+FC_stK+OFF(0)] // save fs_stack.sp 57 | st %i1, [%i5+FC_stK+OFF(1)] // save fs_stack.size 58 | sub %i5, CCFSZ, %o1 // leave space for one register window 59 | st %o1, [%i5+FC_GREG+OFF(0)] // save new stack pointer 60 | st %i2, [%i5+FC_GREG+OFF(1)] // save new %pc (function pointer) 61 | st %g1, [%i5+FC_GREG+OFF(3)] 62 | st %g2, [%i5+FC_GREG+OFF(4)] 63 | st %g3, [%i5+FC_GREG+OFF(5)] 64 | st %g6, [%i5+FC_GREG+OFF(6)] 65 | st %g7, [%i5+FC_GREG+OFF(7)] 66 | 67 | // synthesize "return address": jump to finish 68 | mov %i7, %l0 69 | 2: call 3f 70 | nop 71 | 3: add finish-2b-8, %o7, %i4 72 | st %i4, [%i5+FC_GREG+OFF(2)] 73 | 74 | ret 75 | restore %g0, %i5, %o0 // return fcontext_t 76 | 77 | finish: 78 | mov %g0, %o0 79 | call _exit 80 | nop 81 | 82 | .size make_fcontext,.-make_fcontext 83 | 84 | /* Mark that we don't need executable stack. */ 85 | .section .note.GNU-stack,"",%progbits 86 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_x86_64_sysv_elf_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /**************************************************************************************** 9 | * * 10 | * ---------------------------------------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ---------------------------------------------------------------------------------- * 13 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * 14 | * ---------------------------------------------------------------------------------- * 15 | * | fc_mxcsr|fc_x87_cw| R12 | R13 | R14 | * 16 | * ---------------------------------------------------------------------------------- * 17 | * ---------------------------------------------------------------------------------- * 18 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 19 | * ---------------------------------------------------------------------------------- * 20 | * | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | * 21 | * ---------------------------------------------------------------------------------- * 22 | * | R15 | RBX | RBP | RIP | * 23 | * ---------------------------------------------------------------------------------- * 24 | * ---------------------------------------------------------------------------------- * 25 | * | 16 | 17 | | * 26 | * ---------------------------------------------------------------------------------- * 27 | * | 0x40 | 0x44 | | * 28 | * ---------------------------------------------------------------------------------- * 29 | * | EXIT | | * 30 | * ---------------------------------------------------------------------------------- * 31 | * * 32 | ****************************************************************************************/ 33 | 34 | .text 35 | .globl make_fcontext 36 | .type make_fcontext,@function 37 | .align 16 38 | make_fcontext: 39 | /* first arg of make_fcontext() == top of context-stack */ 40 | movq %rdi, %rax 41 | 42 | /* shift address in RAX to lower 16 byte boundary */ 43 | andq $-16, %rax 44 | 45 | /* reserve space for context-data on context-stack */ 46 | /* size for fc_mxcsr .. RIP + return-address for context-function */ 47 | /* on context-function entry: (RSP -0x8) % 16 == 0 */ 48 | leaq -0x48(%rax), %rax 49 | 50 | /* third arg of make_fcontext() == address of context-function */ 51 | movq %rdx, 0x38(%rax) 52 | 53 | /* save MMX control- and status-word */ 54 | stmxcsr (%rax) 55 | /* save x87 control-word */ 56 | fnstcw 0x4(%rax) 57 | 58 | /* compute abs address of label finish */ 59 | leaq finish(%rip), %rcx 60 | /* save address of finish as return-address for context-function */ 61 | /* will be entered after context-function returns */ 62 | movq %rcx, 0x40(%rax) 63 | 64 | ret /* return pointer to context-data */ 65 | 66 | finish: 67 | /* exit code is zero */ 68 | xorq %rdi, %rdi 69 | /* exit application */ 70 | call _exit@PLT 71 | hlt 72 | .size make_fcontext,.-make_fcontext 73 | 74 | /* Mark that we don't need executable stack. */ 75 | .section .note.GNU-stack,"",%progbits 76 | -------------------------------------------------------------------------------- /thirdparty/boost/asm/make_x86_64_sysv_macho_gas.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Oliver Kowalke 2009. 3 | Distributed under the Boost Software License, Version 1.0. 4 | (See accompanying file LICENSE_1_0.txt or copy at 5 | http://www.boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | /**************************************************************************************** 9 | * * 10 | * ---------------------------------------------------------------------------------- * 11 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * 12 | * ---------------------------------------------------------------------------------- * 13 | * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * 14 | * ---------------------------------------------------------------------------------- * 15 | * | fc_mxcsr|fc_x87_cw| R12 | R13 | R14 | * 16 | * ---------------------------------------------------------------------------------- * 17 | * ---------------------------------------------------------------------------------- * 18 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * 19 | * ---------------------------------------------------------------------------------- * 20 | * | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | * 21 | * ---------------------------------------------------------------------------------- * 22 | * | R15 | RBX | RBP | RIP | * 23 | * ---------------------------------------------------------------------------------- * 24 | * ---------------------------------------------------------------------------------- * 25 | * | 16 | 17 | | * 26 | * ---------------------------------------------------------------------------------- * 27 | * | 0x40 | 0x44 | | * 28 | * ---------------------------------------------------------------------------------- * 29 | * | EXIT | | * 30 | * ---------------------------------------------------------------------------------- * 31 | * * 32 | ****************************************************************************************/ 33 | 34 | .text 35 | .globl _make_fcontext 36 | .align 8 37 | _make_fcontext: 38 | /* first arg of make_fcontext() == top of context-stack */ 39 | movq %rdi, %rax 40 | 41 | /* shift address in RAX to lower 16 byte boundary */ 42 | movabs $-16, %r8 43 | andq %r8, %rax 44 | 45 | /* reserve space for context-data on context-stack */ 46 | /* size for fc_mxcsr .. RIP + return-address for context-function */ 47 | /* on context-function entry: (RSP -0x8) % 16 == 0 */ 48 | leaq -0x48(%rax), %rax 49 | 50 | /* third arg of make_fcontext() == address of context-function */ 51 | movq %rdx, 0x38(%rax) 52 | 53 | /* save MMX control- and status-word */ 54 | stmxcsr (%rax) 55 | /* save x87 control-word */ 56 | fnstcw 0x4(%rax) 57 | 58 | /* compute abs address of label finish */ 59 | leaq finish(%rip), %rcx 60 | /* save address of finish as return-address for context-function */ 61 | /* will be entered after context-function returns */ 62 | movq %rcx, 0x40(%rax) 63 | 64 | ret /* return pointer to context-data */ 65 | 66 | finish: 67 | /* exit code is zero */ 68 | xorq %rdi, %rdi 69 | /* exit application */ 70 | call __exit 71 | hlt 72 | --------------------------------------------------------------------------------