/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 2005 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Magnus Määttä <magnus@php.net> | +----------------------------------------------------------------------+ */ /* $ Id: $ */ #include "php_realtime.h" #include <sched.h> #include <sys/mman.h> #if HAVE_REALTIME ZEND_DECLARE_MODULE_GLOBALS(realtime) /* {{{ realtime_functions[] */ function_entry realtime_functions[] = { PHP_FE(realtime_mlockall, NULL) PHP_FE(realtime_munlockall, NULL) PHP_FE(realtime_sched_getscheduler, NULL) PHP_FE(realtime_sched_setscheduler, NULL) PHP_FE(realtime_sched_get_priority_max, NULL) PHP_FE(realtime_sched_get_priority_min, NULL) PHP_FE(realtime_sched_getaffinity, NULL) PHP_FE(realtime_sched_setaffinity, NULL) PHP_FE(realtime_sched_rr_get_interval, NULL) PHP_FE(realtime_sched_yield, NULL) PHP_FE(realtime_get_last_error, NULL) PHP_FE(realtime_strerror, NULL) { NULL, NULL, NULL } }; /* }}} */ /* {{{ realtime_module_entry */ zend_module_entry realtime_module_entry = { STANDARD_MODULE_HEADER, "realtime", realtime_functions, PHP_MINIT(realtime), NULL, NULL, NULL, PHP_MINFO(realtime), "0.1", STANDARD_MODULE_PROPERTIES }; /* }}} */ #ifdef COMPILE_DL_REALTIME ZEND_GET_MODULE(realtime) #endif static void php_realtime_init_globals(zend_realtime_globals *realtime_globals TSRMLS_DC) { realtime_globals->last_error = 0; } /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(realtime) { ZEND_INIT_MODULE_GLOBALS(realtime, php_realtime_init_globals, NULL); REGISTER_LONG_CONSTANT("REALTIME_MCL_CURRENT", MCL_CURRENT, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("REALTIME_MCL_FUTURE", MCL_FUTURE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("REALTIME_SCHED_OTHER", SCHED_OTHER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("REALTIME_SCHED_RR", SCHED_RR, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("REALTIME_SCHED_FIFO", SCHED_FIFO, CONST_CS | CONST_PERSISTENT); return SUCCESS; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(realtime) { php_info_print_table_start(); php_info_print_table_row(2, "Revision", "$Revision: 1.1 $"); php_info_print_table_end(); } /* }}} */ /* {{{ bool realtime_mlockall(int flags) Lock all pages mapped into the address space of the calling process. */ PHP_FUNCTION(realtime_mlockall) { long flags; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &flags) == FAILURE) { WRONG_PARAM_COUNT; } if (!mlockall(flags)) { RETURN_TRUE; } else { REALTIME_G(last_error) = errno; RETURN_FALSE; } } /* }}} */ /* {{{ bool realtime_munlockall() Unlock all pages mapped into the address space of the calling process. */ PHP_FUNCTION(realtime_munlockall) { if (ZEND_NUM_ARGS() TSRMLS_CC != 0) { WRONG_PARAM_COUNT; } if (!munlockall()) { RETURN_TRUE; } else { REALTIME_G(last_error) = errno; RETURN_FALSE; } } /* }}} */ /* {{{ proto int realtime_sched_setscheduler([int pid]) Get scheduling algorithm */ PHP_FUNCTION(realtime_sched_getscheduler) { int retval; long pid = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &pid) == FAILURE) { WRONG_PARAM_COUNT; } retval = sched_getscheduler(pid); if (retval >= 0) { RETURN_LONG(retval); } else { REALTIME_G(last_error) = errno; RETURN_FALSE; } } /* }}} */ /* {{{ proto bool realtime_sched_setscheduler(int policy, int priority [, int pid]) Set scheduling algorithm/parameters */ PHP_FUNCTION(realtime_sched_setscheduler) { long pid = 0; long policy, priority; struct sched_param php_param; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|l", &policy, &priority, &pid) == FAILURE) { WRONG_PARAM_COUNT; } php_param.sched_priority = priority; if (!sched_setscheduler(pid, policy, &php_param)) { RETURN_TRUE; } else { REALTIME_G(last_error) = errno; RETURN_FALSE; } } /* }}} */ /* {{{ proto int realtime_sched_get_priority_max(int policy) Get the maximum priority value that can be used with the scheduling algorithm identified by policy. */ PHP_FUNCTION(realtime_sched_get_priority_max) { int retval = 0; long sched; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &sched) == FAILURE) { WRONG_PARAM_COUNT; } retval = sched_get_priority_max(sched); if (retval < 0) { REALTIME_G(last_error) = errno; } RETURN_LONG(retval); } /* }}} */ /* {{{ proto int realtime_sched_setscheduler(int policy) Get the minimum priority value that can be used with the scheduling algorithm identified by policy. */ PHP_FUNCTION(realtime_sched_get_priority_min) { int retval = 0; long policy; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &policy) == FAILURE) { WRONG_PARAM_COUNT; } retval = sched_get_priority_max(policy); if (retval < 0) { REALTIME_G(last_error) = errno; RETURN_FALSE; } RETURN_LONG(retval); } /* }}} */ /* {{{ proto int realtime_sched_getaffinity(int pid) Get a process's CPU affinity mask. */ PHP_FUNCTION(realtime_sched_getaffinity) { long pid = 0; long mask = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &pid) == FAILURE) { WRONG_PARAM_COUNT; } if (!sched_getaffinity(0, sizeof(mask), &mask)) { RETURN_LONG(mask); } else { REALTIME_G(last_error) = errno; RETURN_FALSE; } } /* }}} */ /* {{{ proto int realtime_sched_getaffinity(array cpus [,int pid]) Set a process's CPU affinity mask. */ PHP_FUNCTION(realtime_sched_setaffinity) { zval **tmp; HashPosition pos; HashTable *array_hash; long pid, mask = 0; zval *array; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &pid) == FAILURE) { WRONG_PARAM_COUNT; } array_hash = Z_ARRVAL_P(array); for (zend_hash_internal_pointer_reset_ex(array_hash, &pos); zend_hash_get_current_data_ex(array_hash, (void **) &tmp, &pos) == SUCCESS; zend_hash_move_forward_ex(array_hash, &pos)) { if (Z_TYPE_PP(tmp) == IS_LONG) { mask |= (long) pow(2, Z_LVAL_PP(tmp)); } } if (!sched_setaffinity(pid, sizeof(mask), &mask)) { RETURN_TRUE; } else { REALTIME_G(last_error) = errno; RETURN_FALSE; } } /* }}} */ /* {{{ proto array realtime_sched_rr_get_interval([int pid]) Get the SCHED_RR interval for the named process */ PHP_FUNCTION(realtime_sched_rr_get_interval) { long pid = 0; struct timespec php_rr_interval; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &pid) == FAILURE) { WRONG_PARAM_COUNT; } if (!sched_rr_get_interval(pid, &php_rr_interval)) { array_init(return_value); add_assoc_long_ex(return_value, "seconds", 8, php_rr_interval.tv_sec); add_assoc_long_ex(return_value, "nanoseconds", 12, php_rr_interval.tv_nsec); return; } else { REALTIME_G(last_error) = errno; RETURN_FALSE; } } /* }}} */ /* {{{ proto int realtime_sched_yield(void) Move the process to the end of the work queue. */ PHP_FUNCTION(realtime_sched_yield) { if (ZEND_NUM_ARGS() TSRMLS_CC != 0) { WRONG_PARAM_COUNT; } if (!sched_yield()) { RETURN_TRUE; } else { REALTIME_G(last_error) = errno; RETURN_FALSE; } } /* }}} */ /* {{{ proto int realtime_get_last_error(void) Retrieve the error number set by the last realtime function which failed. */ PHP_FUNCTION(realtime_get_last_error) { if (ZEND_NUM_ARGS() TSRMLS_CC != 0) { WRONG_PARAM_COUNT; } RETURN_LONG(REALTIME_G(last_error)); } /* }}} */ /* {{{ proto int realtime_strerror(int errno) Retrieve the system error message associated with the given errno. */ PHP_FUNCTION(realtime_strerror) { long error; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &error) == FAILURE) { WRONG_PARAM_COUNT; } RETURN_STRING(strerror(error), 1); } #endif /* HAVE_REALTIME */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */