Core: added support for more than 64 CPUs in worker_cpu_affinity.

This commit is contained in:
Vladimir Homutov 2016-02-18 13:58:49 +03:00
parent b5d7d3f024
commit faa96e82d2
6 changed files with 83 additions and 59 deletions

View File

@ -1270,16 +1270,16 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#if (NGX_HAVE_CPU_AFFINITY) #if (NGX_HAVE_CPU_AFFINITY)
ngx_core_conf_t *ccf = conf; ngx_core_conf_t *ccf = conf;
u_char ch; u_char ch, *p;
uint64_t *mask;
ngx_str_t *value; ngx_str_t *value;
ngx_uint_t i, n; ngx_uint_t i, n;
ngx_cpuset_t *mask;
if (ccf->cpu_affinity) { if (ccf->cpu_affinity) {
return "is duplicate"; return "is duplicate";
} }
mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(uint64_t)); mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(ngx_cpuset_t));
if (mask == NULL) { if (mask == NULL) {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
@ -1299,7 +1299,12 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
} }
ccf->cpu_affinity_auto = 1; ccf->cpu_affinity_auto = 1;
mask[0] = (uint64_t) -1 >> (64 - ngx_min(64, ngx_ncpu));
CPU_ZERO(&mask[0]);
for (i = 0; i < (ngx_uint_t) ngx_min(ngx_ncpu, CPU_SETSIZE); i++) {
CPU_SET(i, &mask[0]);
}
n = 2; n = 2;
} else { } else {
@ -1308,30 +1313,34 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
for ( /* void */ ; n < cf->args->nelts; n++) { for ( /* void */ ; n < cf->args->nelts; n++) {
if (value[n].len > 64) { if (value[n].len > CPU_SETSIZE) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"worker_cpu_affinity\" supports up to 64 CPUs only"); "\"worker_cpu_affinity\" supports up to %d CPUs only",
CPU_SETSIZE);
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
mask[n - 1] = 0; i = 0;
CPU_ZERO(&mask[n - 1]);
for (i = 0; i < value[n].len; i++) { for (p = value[n].data + value[n].len - 1;
p >= value[n].data;
ch = value[n].data[i]; p--)
{
ch = *p;
if (ch == ' ') { if (ch == ' ') {
continue; continue;
} }
mask[n - 1] <<= 1; i++;
if (ch == '0') { if (ch == '0') {
continue; continue;
} }
if (ch == '1') { if (ch == '1') {
mask[n - 1] |= 1; CPU_SET(i - 1, &mask[n - 1]);
continue; continue;
} }
@ -1353,43 +1362,57 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
} }
uint64_t ngx_cpuset_t *
ngx_get_cpu_affinity(ngx_uint_t n) ngx_get_cpu_affinity(ngx_uint_t n)
{ {
uint64_t mask; #if (NGX_HAVE_CPU_AFFINITY)
ngx_uint_t i; ngx_uint_t i, j;
ngx_cpuset_t *mask;
ngx_core_conf_t *ccf; ngx_core_conf_t *ccf;
static ngx_cpuset_t result;
ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
ngx_core_module); ngx_core_module);
if (ccf->cpu_affinity == NULL) { if (ccf->cpu_affinity == NULL) {
return 0; return NULL;
} }
if (ccf->cpu_affinity_auto) { if (ccf->cpu_affinity_auto) {
mask = ccf->cpu_affinity[ccf->cpu_affinity_n - 1]; mask = &ccf->cpu_affinity[ccf->cpu_affinity_n - 1];
if (mask == 0) { for (i = 0, j = n; /* void */ ; i++) {
return 0;
}
for (i = 0; /* void */ ; i++) { if (CPU_ISSET(i % CPU_SETSIZE, mask) && j-- == 0) {
if ((mask & ((uint64_t) 1 << (i % 64))) && n-- == 0) {
break; break;
} }
if (i == CPU_SETSIZE && j == n) {
/* empty mask */
return NULL;
}
/* void */ /* void */
} }
return (uint64_t) 1 << (i % 64); CPU_ZERO(&result);
CPU_SET(i % CPU_SETSIZE, &result);
return &result;
} }
if (ccf->cpu_affinity_n > n) { if (ccf->cpu_affinity_n > n) {
return ccf->cpu_affinity[n]; return &ccf->cpu_affinity[n];
} }
return ccf->cpu_affinity[ccf->cpu_affinity_n - 1]; return &ccf->cpu_affinity[ccf->cpu_affinity_n - 1];
#else
return NULL;
#endif
} }

View File

@ -94,7 +94,7 @@ typedef struct {
ngx_uint_t cpu_affinity_auto; ngx_uint_t cpu_affinity_auto;
ngx_uint_t cpu_affinity_n; ngx_uint_t cpu_affinity_n;
uint64_t *cpu_affinity; ngx_cpuset_t *cpu_affinity;
char *username; char *username;
ngx_uid_t user; ngx_uid_t user;
@ -121,7 +121,7 @@ ngx_int_t ngx_signal_process(ngx_cycle_t *cycle, char *sig);
void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user); void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user);
char **ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last); char **ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last);
ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv); ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv);
uint64_t ngx_get_cpu_affinity(ngx_uint_t n); ngx_cpuset_t *ngx_get_cpu_affinity(ngx_uint_t n);
ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name,
size_t size, void *tag); size_t size, void *tag);

View File

@ -784,9 +784,9 @@ static void
ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker) ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
{ {
sigset_t set; sigset_t set;
uint64_t cpu_affinity;
ngx_int_t n; ngx_int_t n;
ngx_uint_t i; ngx_uint_t i;
ngx_cpuset_t *cpu_affinity;
struct rlimit rlmt; struct rlimit rlmt;
ngx_core_conf_t *ccf; ngx_core_conf_t *ccf;
ngx_listening_t *ls; ngx_listening_t *ls;

View File

@ -10,29 +10,20 @@
#if (NGX_HAVE_CPUSET_SETAFFINITY) #if (NGX_HAVE_CPUSET_SETAFFINITY)
#include <sys/cpuset.h>
void void
ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log) ngx_setaffinity(ngx_cpuset_t *cpu_affinity, ngx_log_t *log)
{ {
cpuset_t mask;
ngx_uint_t i; ngx_uint_t i;
ngx_log_error(NGX_LOG_NOTICE, log, 0, for (i = 0; i < CPU_SETSIZE; i++) {
"cpuset_setaffinity(0x%08Xl)", cpu_affinity); if (CPU_ISSET(i, cpu_affinity)) {
ngx_log_error(NGX_LOG_NOTICE, log, 0,
CPU_ZERO(&mask); "cpuset_setaffinity(): using cpu #%ui", i);
i = 0;
do {
if (cpu_affinity & 1) {
CPU_SET(i, &mask);
} }
i++; }
cpu_affinity >>= 1;
} while (cpu_affinity);
if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
sizeof(cpuset_t), &mask) == -1) sizeof(cpuset_t), cpu_affinity) == -1)
{ {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
"cpuset_setaffinity() failed"); "cpuset_setaffinity() failed");
@ -42,25 +33,18 @@ ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log)
#elif (NGX_HAVE_SCHED_SETAFFINITY) #elif (NGX_HAVE_SCHED_SETAFFINITY)
void void
ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log) ngx_setaffinity(ngx_cpuset_t *cpu_affinity, ngx_log_t *log)
{ {
cpu_set_t mask;
ngx_uint_t i; ngx_uint_t i;
ngx_log_error(NGX_LOG_NOTICE, log, 0, for (i = 0; i < CPU_SETSIZE; i++) {
"sched_setaffinity(0x%08Xl)", cpu_affinity); if (CPU_ISSET(i, cpu_affinity)) {
ngx_log_error(NGX_LOG_NOTICE, log, 0,
CPU_ZERO(&mask); "sched_setaffinity(): using cpu #%ui", i);
i = 0;
do {
if (cpu_affinity & 1) {
CPU_SET(i, &mask);
} }
i++; }
cpu_affinity >>= 1;
} while (cpu_affinity);
if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { if (sched_setaffinity(0, sizeof(cpu_set_t), cpu_affinity) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
"sched_setaffinity() failed"); "sched_setaffinity() failed");
} }

View File

@ -11,12 +11,26 @@
#define NGX_HAVE_CPU_AFFINITY 1 #define NGX_HAVE_CPU_AFFINITY 1
void ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log); #if (NGX_HAVE_SCHED_SETAFFINITY)
typedef cpu_set_t ngx_cpuset_t;
#elif (NGX_HAVE_CPUSET_SETAFFINITY)
#include <sys/cpuset.h>
typedef cpuset_t ngx_cpuset_t;
#endif
void ngx_setaffinity(ngx_cpuset_t *cpu_affinity, ngx_log_t *log);
#else #else
#define ngx_setaffinity(cpu_affinity, log) #define ngx_setaffinity(cpu_affinity, log)
typedef uint64_t ngx_cpuset_t;
#endif #endif

View File

@ -21,6 +21,9 @@ typedef DWORD ngx_pid_t;
(sizeof("ngx_cache_manager_mutex_") + NGX_INT32_LEN) (sizeof("ngx_cache_manager_mutex_") + NGX_INT32_LEN)
typedef uint64_t ngx_cpuset_t;
typedef struct { typedef struct {
HANDLE handle; HANDLE handle;
ngx_pid_t pid; ngx_pid_t pid;