├── EXPERIMENTAL ├── CREDITS ├── config.w32 ├── tests ├── 002.phpt └── 001.phpt ├── affinity.php ├── api.php ├── README.MD ├── config.m4 ├── php_affinity.h └── affinity.c /EXPERIMENTAL: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | affinity -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | // vim:ft=javascript 3 | 4 | // If your extension references something external, use ARG_WITH 5 | // ARG_WITH("affinity", "for affinity support", "no"); 6 | 7 | // Otherwise, use ARG_ENABLE 8 | // ARG_ENABLE("affinity", "enable affinity support", "no"); 9 | 10 | if (PHP_AFFINITY != "no") { 11 | EXTENSION("affinity", "affinity.c"); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /tests/002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for affinity presence 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 18 | --EXPECT-- 19 | set success 20 | get success 21 | getcpucores success 22 | -------------------------------------------------------------------------------- /affinity.php: -------------------------------------------------------------------------------- 1 | "; 3 | 4 | if(!extension_loaded('affinity')) { 5 | dl('affinity.' . PHP_SHLIB_SUFFIX); 6 | } 7 | $module = 'affinity'; 8 | $functions = get_extension_funcs($module); 9 | echo "Functions available in the test extension:$br\n"; 10 | foreach($functions as $func) { 11 | echo $func."$br\n"; 12 | } 13 | echo "$br\n"; 14 | $function = 'confirm_' . $module . '_compiled'; 15 | if (extension_loaded($module)) { 16 | $str = $function($module); 17 | } else { 18 | $str = "Module $module is not compiled into PHP"; 19 | } 20 | echo "$str\n"; 21 | ?> 22 | -------------------------------------------------------------------------------- /tests/001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for affinity presence 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 20 | --EXPECT-- 21 | affinity extension is available 22 | -------------------------------------------------------------------------------- /api.php: -------------------------------------------------------------------------------- 1 | 4 | * @blog http://www.huyanping.cn 5 | * @license https://opensource.org/licenses/MIT MIT 6 | * @datetime: 2015/11/20 12:11 7 | */ 8 | 9 | /** 10 | * set CPU affinity 11 | * 12 | * @param $cpu_id 13 | * @return bool 14 | */ 15 | function setaffinity($cpu_id){ 16 | $num = getcpucores(); 17 | if($cpu_id >= $num){ 18 | return false; 19 | } 20 | $set = system_call($cpu_id); 21 | if($set === -1){ 22 | return false; 23 | } 24 | 25 | return true; 26 | } 27 | 28 | /** 29 | * get CPU affinity 30 | * 31 | * @return bool 32 | */ 33 | function getaffinity(){ 34 | $cpu_id = system_call(); 35 | if($cpu_id === -1){ 36 | return false; 37 | } 38 | return $cpu_id; 39 | } 40 | 41 | 42 | /** 43 | * get number of CPU 44 | * 45 | * @return bool 46 | */ 47 | function getcpucores(){ 48 | $nums = system_call(); 49 | if($nums === -1){ 50 | return false; 51 | } 52 | return $nums; 53 | } -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | php-affinity 2 | ================== 3 | A PHP extension which provides functions to modify CPU affinity 4 | 5 | Introduce 6 | ------------------ 7 | Affinity extension provides three functions: 8 | + getaffinity get CPU number which current process is running in. 9 | + setaffinity change the process to another CPU 10 | + getcpucores get number of CPU cores 11 | 12 | simple-fork-php framework 13 | ------------------------- 14 | [simple-fork-php](https://github.com/huyanping/simple-fork-php "simple-fork-php") 15 | is A multi-processes management framework. 16 | Its interfaces are like `Thread` and `Runnable` in java. 17 | It is useful for someone who wants to write multi-processes programs. 18 | 19 | Install 20 | --------------------- 21 | ```shell 22 | wget https://github.com/huyanping/php-affinity/archive/0.1.tar.gz 23 | tar zxvf 0.1.tar.gz 24 | cd affinity 25 | phpize 26 | ./configure --with-php-config=/path/to/php-config 27 | make && make test && make install 28 | ``` 29 | 30 | API 31 | --------------------- 32 | ```php 33 | /** 34 | * set CPU affinity 35 | * 36 | * @param $cpu_id 37 | * @return bool 38 | */ 39 | function setaffinity($cpu_id){ 40 | $num = getcpucores(); 41 | if($cpu_id >= $num){ 42 | return false; 43 | } 44 | $set = system_call($cpu_id); 45 | if($set === -1){ 46 | return false; 47 | } 48 | 49 | return true; 50 | } 51 | 52 | /** 53 | * get CPU affinity 54 | * 55 | * @return bool 56 | */ 57 | function getaffinity(){ 58 | $cpu_id = system_call(); 59 | if($cpu_id === -1){ 60 | return false; 61 | } 62 | return $cpu_id; 63 | } 64 | 65 | 66 | /** 67 | * get number of CPU 68 | * 69 | * @return bool 70 | */ 71 | function getcpucores(){ 72 | $nums = system_call(); 73 | if($nums === -1){ 74 | return false; 75 | } 76 | return $nums; 77 | } 78 | ``` -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl $Id$ 2 | dnl config.m4 for extension affinity 3 | 4 | dnl Comments in this file start with the string 'dnl'. 5 | dnl Remove where necessary. This file will not work 6 | dnl without editing. 7 | 8 | dnl If your extension references something external, use with: 9 | 10 | dnl PHP_ARG_WITH(affinity, for affinity support, 11 | dnl Make sure that the comment is aligned: 12 | dnl [ --with-affinity Include affinity support]) 13 | 14 | dnl Otherwise use enable: 15 | 16 | PHP_ARG_ENABLE(affinity, whether to enable affinity support, 17 | Make sure that the comment is aligned: 18 | [ --enable-affinity Enable affinity support]) 19 | 20 | if test "$PHP_AFFINITY" != "no"; then 21 | dnl Write more examples of tests here... 22 | 23 | dnl # --with-affinity -> check with-path 24 | dnl SEARCH_PATH="/usr/local /usr" # you might want to change this 25 | dnl SEARCH_FOR="/include/affinity.h" # you most likely want to change this 26 | dnl if test -r $PHP_AFFINITY/$SEARCH_FOR; then # path given as parameter 27 | dnl AFFINITY_DIR=$PHP_AFFINITY 28 | dnl else # search default path list 29 | dnl AC_MSG_CHECKING([for affinity files in default path]) 30 | dnl for i in $SEARCH_PATH ; do 31 | dnl if test -r $i/$SEARCH_FOR; then 32 | dnl AFFINITY_DIR=$i 33 | dnl AC_MSG_RESULT(found in $i) 34 | dnl fi 35 | dnl done 36 | dnl fi 37 | dnl 38 | dnl if test -z "$AFFINITY_DIR"; then 39 | dnl AC_MSG_RESULT([not found]) 40 | dnl AC_MSG_ERROR([Please reinstall the affinity distribution]) 41 | dnl fi 42 | 43 | dnl # --with-affinity -> add include path 44 | dnl PHP_ADD_INCLUDE($AFFINITY_DIR/include) 45 | 46 | dnl # --with-affinity -> check for lib and symbol presence 47 | dnl LIBNAME=affinity # you may want to change this 48 | dnl LIBSYMBOL=affinity # you most likely want to change this 49 | 50 | dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, 51 | dnl [ 52 | dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $AFFINITY_DIR/$PHP_LIBDIR, AFFINITY_SHARED_LIBADD) 53 | dnl AC_DEFINE(HAVE_AFFINITYLIB,1,[ ]) 54 | dnl ],[ 55 | dnl AC_MSG_ERROR([wrong affinity lib version or lib not found]) 56 | dnl ],[ 57 | dnl -L$AFFINITY_DIR/$PHP_LIBDIR -lm 58 | dnl ]) 59 | dnl 60 | dnl PHP_SUBST(AFFINITY_SHARED_LIBADD) 61 | 62 | PHP_NEW_EXTENSION(affinity, affinity.c, $ext_shared) 63 | fi 64 | -------------------------------------------------------------------------------- /php_affinity.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2015 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | /* $Id$ */ 20 | 21 | #ifndef PHP_AFFINITY_H 22 | #define PHP_AFFINITY_H 23 | 24 | extern zend_module_entry affinity_module_entry; 25 | #define phpext_affinity_ptr &affinity_module_entry 26 | 27 | #define PHP_AFFINITY_VERSION "0.1.0" /* Replace with version number for your extension */ 28 | 29 | #ifdef PHP_WIN32 30 | # define PHP_AFFINITY_API __declspec(dllexport) 31 | #elif defined(__GNUC__) && __GNUC__ >= 4 32 | # define PHP_AFFINITY_API __attribute__ ((visibility("default"))) 33 | #else 34 | # define PHP_AFFINITY_API 35 | #endif 36 | 37 | #ifdef ZTS 38 | #include "TSRM.h" 39 | #endif 40 | 41 | PHP_MINIT_FUNCTION(affinity); 42 | PHP_MSHUTDOWN_FUNCTION(affinity); 43 | PHP_RINIT_FUNCTION(affinity); 44 | PHP_RSHUTDOWN_FUNCTION(affinity); 45 | PHP_MINFO_FUNCTION(affinity); 46 | 47 | PHP_FUNCTION(setaffinity); /* For testing, remove later. */ 48 | PHP_FUNCTION(getaffinity); /* For testing, remove later. */ 49 | PHP_FUNCTION(getcpucores); /* For testing, remove later. */ 50 | 51 | /* 52 | Declare any global variables you may need between the BEGIN 53 | and END macros here: 54 | 55 | ZEND_BEGIN_MODULE_GLOBALS(affinity) 56 | long global_value; 57 | char *global_string; 58 | ZEND_END_MODULE_GLOBALS(affinity) 59 | */ 60 | 61 | /* In every utility function you add that needs to use variables 62 | in php_affinity_globals, call TSRMLS_FETCH(); after declaring other 63 | variables used by that function, or better yet, pass in TSRMLS_CC 64 | after the last function argument and declare your utility function 65 | with TSRMLS_DC after the last declared argument. Always refer to 66 | the globals in your function as AFFINITY_G(variable). You are 67 | encouraged to rename these macros something shorter, see 68 | examples in any other php module directory. 69 | */ 70 | 71 | #ifdef ZTS 72 | #define AFFINITY_G(v) TSRMG(affinity_globals_id, zend_affinity_globals *, v) 73 | #else 74 | #define AFFINITY_G(v) (affinity_globals.v) 75 | #endif 76 | 77 | #endif /* PHP_AFFINITY_H */ 78 | 79 | 80 | /* 81 | * Local variables: 82 | * tab-width: 4 83 | * c-basic-offset: 4 84 | * End: 85 | * vim600: noet sw=4 ts=4 fdm=marker 86 | * vim<600: noet sw=4 ts=4 87 | */ 88 | -------------------------------------------------------------------------------- /affinity.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2015 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | /* $Id$ */ 20 | 21 | #ifdef HAVE_CONFIG_H 22 | #include "config.h" 23 | #endif 24 | 25 | #include "php.h" 26 | #include "php_ini.h" 27 | #include "ext/standard/info.h" 28 | #include "php_affinity.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #define __USE_GNU 37 | #include 38 | #include 39 | #include 40 | 41 | /* If you declare any globals in php_affinity.h uncomment this: 42 | ZEND_DECLARE_MODULE_GLOBALS(affinity) 43 | */ 44 | 45 | /* True global resources - no need for thread safety here */ 46 | static int le_affinity; 47 | 48 | /* {{{ affinity_functions[] 49 | * 50 | * Every user visible function must have an entry in affinity_functions[]. 51 | */ 52 | const zend_function_entry affinity_functions[] = { 53 | PHP_FE(setaffinity, NULL) /* For testing, remove later. */ 54 | PHP_FE(getaffinity, NULL) /* For testing, remove later. */ 55 | PHP_FE(getcpucores, NULL) /* For testing, remove later. */ 56 | PHP_FE_END /* Must be the last line in affinity_functions[] */ 57 | }; 58 | /* }}} */ 59 | 60 | /* {{{ affinity_module_entry 61 | */ 62 | zend_module_entry affinity_module_entry = { 63 | #if ZEND_MODULE_API_NO >= 20010901 64 | STANDARD_MODULE_HEADER, 65 | #endif 66 | "affinity", 67 | affinity_functions, 68 | PHP_MINIT(affinity), 69 | PHP_MSHUTDOWN(affinity), 70 | PHP_RINIT(affinity), /* Replace with NULL if there's nothing to do at request start */ 71 | PHP_RSHUTDOWN(affinity), /* Replace with NULL if there's nothing to do at request end */ 72 | PHP_MINFO(affinity), 73 | #if ZEND_MODULE_API_NO >= 20010901 74 | PHP_AFFINITY_VERSION, 75 | #endif 76 | STANDARD_MODULE_PROPERTIES 77 | }; 78 | /* }}} */ 79 | 80 | #ifdef COMPILE_DL_AFFINITY 81 | ZEND_GET_MODULE(affinity) 82 | #endif 83 | 84 | /* {{{ PHP_INI 85 | */ 86 | /* Remove comments and fill if you need to have entries in php.ini 87 | PHP_INI_BEGIN() 88 | STD_PHP_INI_ENTRY("affinity.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_affinity_globals, affinity_globals) 89 | STD_PHP_INI_ENTRY("affinity.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_affinity_globals, affinity_globals) 90 | PHP_INI_END() 91 | */ 92 | /* }}} */ 93 | 94 | /* {{{ php_affinity_init_globals 95 | */ 96 | /* Uncomment this function if you have INI entries 97 | static void php_affinity_init_globals(zend_affinity_globals *affinity_globals) 98 | { 99 | affinity_globals->global_value = 0; 100 | affinity_globals->global_string = NULL; 101 | } 102 | */ 103 | /* }}} */ 104 | 105 | /* {{{ PHP_MINIT_FUNCTION 106 | */ 107 | PHP_MINIT_FUNCTION(affinity) 108 | { 109 | /* If you have INI entries, uncomment these lines 110 | REGISTER_INI_ENTRIES(); 111 | */ 112 | return SUCCESS; 113 | } 114 | /* }}} */ 115 | 116 | /* {{{ PHP_MSHUTDOWN_FUNCTION 117 | */ 118 | PHP_MSHUTDOWN_FUNCTION(affinity) 119 | { 120 | /* uncomment this line if you have INI entries 121 | UNREGISTER_INI_ENTRIES(); 122 | */ 123 | return SUCCESS; 124 | } 125 | /* }}} */ 126 | 127 | /* Remove if there's nothing to do at request start */ 128 | /* {{{ PHP_RINIT_FUNCTION 129 | */ 130 | PHP_RINIT_FUNCTION(affinity) 131 | { 132 | return SUCCESS; 133 | } 134 | /* }}} */ 135 | 136 | /* Remove if there's nothing to do at request end */ 137 | /* {{{ PHP_RSHUTDOWN_FUNCTION 138 | */ 139 | PHP_RSHUTDOWN_FUNCTION(affinity) 140 | { 141 | return SUCCESS; 142 | } 143 | /* }}} */ 144 | 145 | /* {{{ PHP_MINFO_FUNCTION 146 | */ 147 | PHP_MINFO_FUNCTION(affinity) 148 | { 149 | php_info_print_table_start(); 150 | php_info_print_table_header(2, "affinity support", "enabled"); 151 | php_info_print_table_end(); 152 | 153 | /* Remove comments if you have entries in php.ini 154 | DISPLAY_INI_ENTRIES(); 155 | */ 156 | } 157 | /* }}} */ 158 | 159 | PHP_FUNCTION(getcpucores){ 160 | int num = sysconf(_SC_NPROCESSORS_CONF); 161 | RETURN_LONG(num); 162 | } 163 | 164 | PHP_FUNCTION(setaffinity) 165 | { 166 | long cpu_id = 0; 167 | 168 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &cpu_id) == FAILURE) { 169 | RETURN_NULL(); 170 | } 171 | 172 | int num = sysconf(_SC_NPROCESSORS_CONF); 173 | if(cpu_id >= num){ 174 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "cpu_id more than the total number of CPU"); 175 | RETURN_FALSE; 176 | } 177 | 178 | cpu_set_t mask; 179 | CPU_ZERO(&mask); 180 | CPU_SET(cpu_id, &mask); 181 | 182 | if(sched_setaffinity(0, sizeof(mask), &mask) == -1){ 183 | RETURN_FALSE; 184 | } 185 | 186 | RETURN_TRUE; 187 | } 188 | 189 | PHP_FUNCTION(getaffinity) 190 | { 191 | int num = sysconf(_SC_NPROCESSORS_CONF); 192 | cpu_set_t get; 193 | CPU_ZERO(&get); 194 | 195 | if(sched_getaffinity(0, sizeof(get), &get) == -1){ 196 | RETURN_FALSE; 197 | } 198 | int i; 199 | for(i=0; i