示例#1
0
/* set affinity for current thread */
static int
eal_thread_set_affinity(void)
{
	int s;
	pthread_t thread;

/*
 * According to the section VERSIONS of the CPU_ALLOC man page:
 *
 * The CPU_ZERO(), CPU_SET(), CPU_CLR(), and CPU_ISSET() macros were added
 * in glibc 2.3.3.
 *
 * CPU_COUNT() first appeared in glibc 2.6.
 *
 * CPU_AND(),     CPU_OR(),     CPU_XOR(),    CPU_EQUAL(),    CPU_ALLOC(),
 * CPU_ALLOC_SIZE(), CPU_FREE(), CPU_ZERO_S(),  CPU_SET_S(),  CPU_CLR_S(),
 * CPU_ISSET_S(),  CPU_AND_S(), CPU_OR_S(), CPU_XOR_S(), and CPU_EQUAL_S()
 * first appeared in glibc 2.7.
 */
#if defined(CPU_ALLOC)
	size_t size;
	cpu_set_t *cpusetp;

	cpusetp = CPU_ALLOC(RTE_MAX_LCORE);
	if (cpusetp == NULL) {
		RTE_LOG(ERR, EAL, "CPU_ALLOC failed\n");
		return -1;
	}

	size = CPU_ALLOC_SIZE(RTE_MAX_LCORE);
	CPU_ZERO_S(size, cpusetp);
	CPU_SET_S(rte_lcore_id(), size, cpusetp);

	thread = pthread_self();
	s = pthread_setaffinity_np(thread, size, cpusetp);
	if (s != 0) {
		RTE_LOG(ERR, EAL, "pthread_setaffinity_np failed\n");
		CPU_FREE(cpusetp);
		return -1;
	}

	CPU_FREE(cpusetp);
#else /* CPU_ALLOC */
	cpuset_t cpuset;
	CPU_ZERO( &cpuset );
	CPU_SET( rte_lcore_id(), &cpuset );

	thread = pthread_self();
	s = pthread_setaffinity_np(thread, sizeof( cpuset ), &cpuset);
	if (s != 0) {
		RTE_LOG(ERR, EAL, "pthread_setaffinity_np failed\n");
		return -1;
	}
#endif
	return 0;
}
示例#2
0
int geopm_sched_woomp(int num_cpu, cpu_set_t *woomp)
{
    /*! @brief Function that returns a cpuset that has bits set for
               all CPUs enabled for the process which are not used by
               OpenMP.  Rather than returning an empty mask, if all
               CPUs allocated for the process are used by OpenMP, then
               the woomp mask will have all bits set. */

    int err = pthread_once(&g_proc_cpuset_once, geopm_proc_cpuset_once);
    int sched_num_cpu = geopm_sched_num_cpu();
    size_t req_alloc_size = CPU_ALLOC_SIZE(num_cpu);

    if (!err && !g_proc_cpuset) {
        err = ENOMEM;
    }
    if (!err && req_alloc_size < g_proc_cpuset_size) {
        err = EINVAL;
    }
    if (!err) {
        /* Copy the process CPU mask into the output. */
        memcpy(woomp, g_proc_cpuset, g_proc_cpuset_size);
        /* Start an OpenMP parallel region and have each thread clear
           its bit from the mask. */
#ifdef _OPENMP
#pragma omp parallel default(shared)
{
#pragma omp critical
{
        int cpu_index = sched_getcpu();
        if (cpu_index != -1 && cpu_index < num_cpu) {
            /* Clear the bit for this OpenMP thread's CPU. */
            CPU_CLR_S(cpu_index, g_proc_cpuset_size, woomp);
        }
        else {
            err = errno ? errno : GEOPM_ERROR_LOGIC;
        }
} /* end pragma omp critical */
} /* end pragma omp parallel */
#endif /* _OPENMP */
    }
    if (!err) {
        for (int i = sched_num_cpu; i < num_cpu; ++i) {
            CPU_CLR_S(i, req_alloc_size, woomp);
        }
    }
    if (err || CPU_COUNT_S(g_proc_cpuset_size, woomp) == 0) {
        /* If all CPUs are used by the OpenMP gang, then leave the
           mask open and allow the Linux scheduler to choose. */
        for (int i = 0; i < num_cpu; ++i) {
            CPU_SET_S(i, g_proc_cpuset_size, woomp);
        }
    }
    return err;
}
示例#3
0
static void geopm_proc_cpuset_once(void)
{
    int err = 0;
    int num_cpu = geopm_sched_num_cpu();
    pthread_t tid;
    pthread_attr_t attr;

    g_proc_cpuset = CPU_ALLOC(num_cpu);
    if (g_proc_cpuset == NULL) {
        err = ENOMEM;
    }
    if (!err) {
        g_proc_cpuset_size = CPU_ALLOC_SIZE(num_cpu);
        for (int i = 0; i < num_cpu; ++i) {
            CPU_SET_S(i, g_proc_cpuset_size, g_proc_cpuset);
        }
        err = pthread_attr_init(&attr);
    }
    if (!err) {
        err = pthread_attr_setaffinity_np(&attr, g_proc_cpuset_size, g_proc_cpuset);
    }
    if (!err) {
        err = pthread_create(&tid, &attr, geopm_proc_cpuset_pthread, NULL);
    }
    if (!err) {
        void *result = NULL;
        err = pthread_join(tid, &result);
        if (!err && result) {
            err = (int)(size_t)result;
        }
    }
    if (err && err != ENOMEM) {
        for (int i = 0; i < num_cpu; ++i) {
            CPU_SET_S(i, g_proc_cpuset_size, g_proc_cpuset);
        }
    }
    if (!err) {
        err = pthread_attr_destroy(&attr);
    }
}
示例#4
0
static int
create_fetcher(struct server *s, int n)
{
    int i;
    struct fetcher *ws, *tmp;
    cpu_set_t cpuinfo;
    pthread_t fpt[FETCHER_NUM];
    if (n < 1)
        return -1;
    ws = malloc(sizeof(struct fetcher) * n);    //associated a worker with main thread
    if (ws == NULL)
        return -1;
    memset(ws, 0, sizeof(struct fetcher) * n);
    s->fetchers = ws;
    for (i = 0; i < n; i++) {
        tmp = ws + i;
        tmp->s = s;
        tmp->idx = i;
        tmp->pkg = 0;
        tmp->send = 0;
        tmp->miss = 0;
        tmp->el = &s->eventlist;
        tmp->qidx = i % QUIZZER_NUM;
        tmp->mc = init_msgcache(100);
        if (tmp->mc == NULL)
            dns_error(0, "get msgcache");
        tmp->loginfo = malloc(sizeof(struct log_info));
        memset(tmp->loginfo, 0, sizeof(struct log_info));
        tmp->loginfo->lastlog = global_now;
        tmp->loginfo->log_type = TYPE_FETCHER;
        tmp->loginfo->logfd = create_new_log(s->logpath, i, TYPE_FETCHER);
        if (tmp->loginfo->logfd < 0)
            dns_error(0, "log file error");
        if (pthread_create(fpt + i, NULL, (void *) run_fetcher, tmp) != 0)
            dns_error(0, "init worker");
    }
    global_out_info->thread_num += i;
    
    for(i = 0;i < FETCHER_NUM ;i ++)
    {
        CPU_ZERO(&cpuinfo);
        CPU_SET_S(i + 1, sizeof(cpuinfo), &cpuinfo);
        if(0 != pthread_setaffinity_np(fpt[i], sizeof(cpu_set_t), &cpuinfo))
        {
            printf("set affinity fetcher failed,  may be the cpu cores num less than (FETCHER_NUM + QUIZZER_NUM + 1)\n");
//             exit(0);
        }
    }
    
    return 0;
}
示例#5
0
int parse_cpu_set_and_warn(
                const char *rvalue,
                cpu_set_t **cpu_set,
                const char *unit,
                const char *filename,
                unsigned line,
                const char *lvalue) {

        const char *whole_rvalue = rvalue;
        _cleanup_cpu_free_ cpu_set_t *c = NULL;
        unsigned ncpus = 0;

        assert(lvalue);
        assert(rvalue);

        for (;;) {
                _cleanup_free_ char *word = NULL;
                unsigned cpu;
                int r;

                r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES);
                if (r < 0) {
                        log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue);
                        return r;
                }
                if (r == 0)
                        break;

                if (!c) {
                        c = cpu_set_malloc(&ncpus);
                        if (!c)
                                return log_oom();
                }

                r = safe_atou(word, &cpu);
                if (r < 0 || cpu >= ncpus) {
                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", rvalue);
                        return -EINVAL;
                }

                CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
        }

        /* On success, sets *cpu_set and returns ncpus for the system. */
        if (c) {
                *cpu_set = c;
                c = NULL;
        }

        return (int) ncpus;
}
示例#6
0
文件: init.c 项目: AlexShiLucky/rtems
static void test_scheduler_get_processors(void)
{
#if defined(__RTEMS_HAVE_SYS_CPUSET_H__)
  rtems_status_code sc;
  rtems_name name = BLUE;
  rtems_id scheduler_id;
  cpu_set_t cpusetone;
  cpu_set_t cpuset;
  size_t big = 2 * CHAR_BIT * sizeof(cpu_set_t);
  size_t cpusetbigsize = CPU_ALLOC_SIZE(big);
  cpu_set_t *cpusetbigone;
  cpu_set_t *cpusetbig;

  CPU_ZERO(&cpusetone);
  CPU_SET(0, &cpusetone);

  sc = rtems_scheduler_ident(name, &scheduler_id);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  sc = rtems_scheduler_get_processor_set(scheduler_id, sizeof(cpuset), NULL);
  rtems_test_assert(sc == RTEMS_INVALID_ADDRESS);

  sc = rtems_scheduler_get_processor_set(invalid_id, sizeof(cpuset), &cpuset);
  rtems_test_assert(sc == RTEMS_INVALID_ID);

  sc = rtems_scheduler_get_processor_set(scheduler_id, 0, &cpuset);
  rtems_test_assert(sc == RTEMS_INVALID_NUMBER);

  sc = rtems_scheduler_get_processor_set(scheduler_id, sizeof(cpuset), &cpuset);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  rtems_test_assert(CPU_EQUAL(&cpuset, &cpusetone));

  cpusetbigone = CPU_ALLOC(big);
  rtems_test_assert(cpusetbigone != NULL);

  cpusetbig = CPU_ALLOC(big);
  rtems_test_assert(cpusetbig != NULL);

  CPU_ZERO_S(cpusetbigsize, cpusetbigone);
  CPU_SET_S(0, cpusetbigsize, cpusetbigone);

  sc = rtems_scheduler_get_processor_set(scheduler_id, cpusetbigsize, cpusetbig);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  rtems_test_assert(CPU_EQUAL_S(cpusetbigsize, cpusetbig, cpusetbigone));

  CPU_FREE(cpusetbig);
  CPU_FREE(cpusetbigone);
#endif /* defined(__RTEMS_HAVE_SYS_CPUSET_H__) */
}
int __be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz,
						 int ignore_rm)
{

	int first_cpu = cluster * cluster_sz; /* first CPU in cluster */
	int last_cpu = first_cpu + cluster_sz - 1;
	int master;
	int num_cpus;
	cpu_set_t *cpu_set;
	size_t sz;
	int i;
	int ret;
	/* TODO: Error check to make sure that tid is not a real-time task. */

	if (cluster_sz == 1) {
		/* we're partitioned */
		return be_migrate_thread_to_partition(tid, cluster);
	}

	master = (ignore_rm) ? -1 : release_master();
	num_cpus = num_online_cpus();

	if (num_cpus == -1 || last_cpu >= num_cpus || first_cpu < 0)
		return -1;

	cpu_set = CPU_ALLOC(num_cpus);
	sz = CPU_ALLOC_SIZE(num_cpus);
	CPU_ZERO_S(sz, cpu_set);

	for (i = first_cpu; i <= last_cpu; ++i) {
		if (i != master) {
			CPU_SET_S(i, sz, cpu_set);
		}
	}

	/* apply to caller */
	if (tid == 0)
		tid = gettid();

	ret = sched_setaffinity(tid, sz, cpu_set);

	CPU_FREE(cpu_set);

	return ret;
}
示例#8
0
int pin_cpu(pid_t pid, unsigned int cpu) {
   size_t size;
   cpu_set_t * setPtr = CPU_ALLOC(1);
   assert (NULL != setPtr && "cpu_set allocation failed!");

   size = CPU_ALLOC_SIZE(1);
   CPU_ZERO_S(size, setPtr);     // clear set
   CPU_SET_S(cpu, size, setPtr); // enable requested cpu in set
   assert(1 == CPU_COUNT_S(size, setPtr));
   assert (CPU_ISSET_S(cpu, size, setPtr));

   int ret = sched_setaffinity(pid, size, setPtr);
   assert (ret == 0 && "sched_setaffinity failed");
   assert (cpu == sched_getcpu() && "Pinning failed");

   CPU_FREE(setPtr);
   return ret;
}
示例#9
0
static void setup(void)
{
	tst_require_root(NULL);
	uid = geteuid();
	ncpus = tst_ncpus_max();

	/* Current mask */
	mask = CPU_ALLOC(ncpus);
	if (mask == NULL)
		tst_brkm(TBROK | TERRNO, cleanup, "CPU_ALLOC(%ld) failed",
			ncpus);
	mask_size = CPU_ALLOC_SIZE(ncpus);
	if (sched_getaffinity(0, mask_size, mask) < 0)
		tst_brkm(TBROK | TERRNO, cleanup, "sched_getaffinity() failed");

	/* Mask with one more cpu than available on the system */
	emask = CPU_ALLOC(ncpus + 1);
	if (emask == NULL)
		tst_brkm(TBROK | TERRNO, cleanup, "CPU_ALLOC(%ld) failed",
			ncpus + 1);
	emask_size = CPU_ALLOC_SIZE(ncpus + 1);
	CPU_ZERO_S(emask_size, emask);
	CPU_SET_S(ncpus, emask_size, emask);

	privileged_pid = tst_fork();
	if (privileged_pid == 0) {
		pause();

		exit(0);
	} else if (privileged_pid < 0) {
		tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
	}

	/* Dropping the root privileges */
	ltpuser = getpwnam(nobody_uid);
	if (ltpuser == NULL)
		tst_brkm(TBROK | TERRNO, cleanup,
			"getpwnam failed for user id %s", nobody_uid);

	SAFE_SETEUID(cleanup, ltpuser->pw_uid);

	/* this pid is not used by the OS */
	free_pid = tst_get_unused_pid(cleanup);
}
示例#10
0
static int bind_cpu(thread_t *thread) {
    size_t setsize;
    cpu_set_t *cur_cpuset;
    cpu_set_t *new_cpuset;

    int ncpus = max_number_of_cpus();

    if (thread == NULL) {
        // if thread is NULL it means the emulator is disabled, return without setting CPU affinity
        //printf("thread self is null");
        return 0;
    }

    if (ncpus == 0) {
    	return 1;
    }

    setsize = CPU_ALLOC_SIZE(ncpus);
    cur_cpuset = CPU_ALLOC(ncpus);
    new_cpuset = CPU_ALLOC(ncpus);
    CPU_ZERO_S(setsize, cur_cpuset);
    CPU_ZERO_S(setsize, new_cpuset);
    CPU_SET_S(thread->cpu_id, setsize, new_cpuset);

    if (pthread_getaffinity_np(thread->pthread, setsize, cur_cpuset) != 0) {
        DBG_LOG(ERROR, "Cannot get thread tid [%d] affinity, pthread: 0x%lx on processor %d\n",
        		thread->tid, thread->pthread, thread->cpu_id);
        return 1;
    }

    if (CPU_EQUAL(cur_cpuset, new_cpuset)) {
        //printf("No need to bind CPU\n");
    	return 0;
    }

    DBG_LOG(INFO, "Binding thread tid [%d] pthread: 0x%lx on processor %d\n", thread->tid, thread->pthread, thread->cpu_id);

    if (pthread_setaffinity_np(thread->pthread, setsize, new_cpuset) != 0) {
        DBG_LOG(ERROR, "Cannot bind thread tid [%d] pthread: 0x%lx on processor %d\n", thread->tid, thread->pthread, thread->cpu_id);
        return 1;
    }

    return 0;
}
示例#11
0
文件: cpuset.c 项目: dolezaljan/rtems
/*
 * _CPU_set_Handler_initialization
 */
void _CPU_set_Handler_initialization()
{
  int i;
  int max_cpus;

  /* We do not support a cpu count over CPU_SETSIZE  */
  max_cpus = _SMP_Get_processor_count();

  /* This should never happen */
  _Assert( max_cpus <= CPU_SETSIZE );

  /*  Initialize the affinity to be the set of all available CPU's   */
  cpuset_default.set     = &cpuset_default.preallocated;
  cpuset_default.setsize = sizeof( *cpuset_default.set );
  CPU_ZERO_S( cpuset_default.setsize, &cpuset_default.preallocated );

  for (i=0; i<max_cpus; i++)
    CPU_SET_S(i, cpuset_default.setsize, cpuset_default.set );
}
示例#12
0
/*
 * _CPU_set_Handler_initialization
 */
void _CPU_set_Handler_initialization()
{
  uint32_t cpu_count;
  uint32_t cpu_index;

  /* We do not support a cpu count over CPU_SETSIZE  */
  cpu_count = _SMP_Get_processor_count();

  /* This should never happen */
  _Assert( cpu_count <= CPU_SETSIZE );

  /*  Initialize the affinity to be the set of all available CPU's   */
  cpuset_default.set     = &cpuset_default.preallocated;
  cpuset_default.setsize = sizeof( *cpuset_default.set );
  CPU_ZERO_S( cpuset_default.setsize, &cpuset_default.preallocated );

  for ( cpu_index=0; cpu_index<cpu_count; cpu_index++ )
    CPU_SET_S( (int) cpu_index, cpuset_default.setsize, cpuset_default.set );
}
示例#13
0
static void geopm_proc_cpuset_once(void)
{
    const char *status_path = "/proc/self/status";
    const int num_cpu = geopm_sched_num_cpu();
    const int num_read = num_cpu / 32 + (num_cpu % 32 ? 1 : 0);

    int err = 0;
    uint32_t *proc_cpuset = NULL;
    FILE *fid = NULL;

    g_proc_cpuset = CPU_ALLOC(num_cpu);
    if (g_proc_cpuset == NULL) {
        err = ENOMEM;
    }
    if (!err) {
        g_proc_cpuset_size = CPU_ALLOC_SIZE(num_cpu);
        proc_cpuset = calloc(num_read, sizeof(*proc_cpuset));
        if (proc_cpuset == NULL) {
            err = ENOMEM;
        }
    }
    if (!err) {
        fid = fopen(status_path, "r");
        if (!fid) {
            err = errno ? errno : GEOPM_ERROR_RUNTIME;
        }
    }
    if (!err) {
        err = geopm_sched_proc_cpuset_helper(num_cpu, proc_cpuset, fid);
        fclose(fid);
    }
    if (!err) {
        memcpy(g_proc_cpuset, proc_cpuset, g_proc_cpuset_size);
    }
    else if (g_proc_cpuset) {
        for (int i = 0; i < num_cpu; ++i) {
            CPU_SET_S(i, g_proc_cpuset_size, g_proc_cpuset);
        }
    }
    if (proc_cpuset) {
        free(proc_cpuset);
    }
}
示例#14
0
inline void pin_RT(int cpu) {
  auto set = CPU_ALLOC(NUM_CPUS);
  auto size = CPU_ALLOC_SIZE(NUM_CPUS);
  CPU_ZERO_S(size, set);
  CPU_SET_S(cpu, size, set);
  if (sched_setaffinity(0, size, set) != 0) {
    fprintf(stderr, "unable to pin to cpu %i\n", cpu);
    exit(EXIT_FAILURE);
  }
  CPU_FREE(set);

  struct sched_param p;
  p.sched_priority = 99;
  if (sched_setscheduler(0, SCHED_FIFO, &p) != 0) {
    fprintf(stderr, "unable to set SCHED_FIFO: %s\n",
      strerror(errno));
    exit(EXIT_FAILURE);
  }
}
示例#15
0
文件: linux.c 项目: rminnich/ftq
int wireme(int core)
{
	cpu_set_t *set;
	int numthreads = core + 1;
	int ret;
	size_t size;
	set = CPU_ALLOC(numthreads);
	size = CPU_ALLOC_SIZE(numthreads);
	CPU_ZERO_S(size, set);
	/* lock us down. */
	CPU_SET_S(core, size, set);
	ret = sched_setaffinity(0, size, set);
	/* just blow up. If they ignore this error the numbers will be crap. */
	if ((ret < 0) && (! ignore_wire_failures)) {
		fprintf(stderr, "wireme: pid %d, core %d, %m\n", getpid(), core);
		exit(1);
	}
	CPU_FREE(set);
	return 0;
}
示例#16
0
bool
gomp_affinity_copy_place (void *p, void *q, long stride)
{
  unsigned long i, max = 8 * gomp_cpuset_size;
  cpu_set_t *destp = (cpu_set_t *) p;
  cpu_set_t *srcp = (cpu_set_t *) q;

  CPU_ZERO_S (gomp_cpuset_size, destp);
  for (i = 0; i < max; i++)
    if (CPU_ISSET_S (i, gomp_cpuset_size, srcp))
      {
	if ((stride < 0 && i + stride > i)
	    || (stride > 0 && (i + stride < i || i + stride >= max)))
	  {
	    gomp_error ("Logical CPU number %lu+%ld out of range", i, stride);
	    return false;
	  }
	CPU_SET_S (i + stride, gomp_cpuset_size, destp);
      }
  return true;
}
示例#17
0
int bind_cpu(int cpu)
{
	cpu_set_t *cmask;
	struct bitmask *bmask;
	size_t ncpu, setsize;
	int ret;

	ncpu = get_num_cpus();

	if (cpu < 0 || cpu >= (int)ncpu) {
		errno = -EINVAL;
		return -1;
	}

	cmask = CPU_ALLOC(ncpu);
	if (cmask == NULL)
		return -1;

	setsize = CPU_ALLOC_SIZE(ncpu);
	CPU_ZERO_S(setsize, cmask);
	CPU_SET_S(cpu, setsize, cmask);

	ret = sched_setaffinity(0, ncpu, cmask);

	CPU_FREE(cmask);

	/* skip NUMA stuff for UMA systems */
	if (numa_max_node() == 0)
		return ret;

	bmask = numa_bitmask_alloc(16);
	assert(bmask);

	numa_bitmask_setbit(bmask, cpu % 2);
	numa_set_membind(bmask);
	numa_bitmask_free(bmask);

	return ret;
}
示例#18
0
/**
 * Try to ping process to a specific CPU. Returns the CPU we are
 * currently running on.
 */
static int pin_to_cpu(int run_cpu)
{
	cpu_set_t *cpusetp;
	size_t size;
	int num_cpus;

	num_cpus = CPU_SETSIZE; /* take default, currently 1024 */
	cpusetp = CPU_ALLOC(num_cpus);
	if (cpusetp == NULL)
		return sched_getcpu();

	size = CPU_ALLOC_SIZE(num_cpus);

	CPU_ZERO_S(size, cpusetp);
	CPU_SET_S(run_cpu, size, cpusetp);
	if (sched_setaffinity(0, size, cpusetp) < 0) {
		CPU_FREE(cpusetp);
		return sched_getcpu();
	}

	/* figure out on which cpus we actually run */
	CPU_FREE(cpusetp);
	return run_cpu;
}
示例#19
0
int cpu_manager::reserve_cpu_for_thread(pthread_t tid, int suggested_cpu /* = NO_CPU */)
{
	lock();
	int cpu = g_n_thread_cpu_core;
	if (cpu != NO_CPU) { //already reserved
		unlock();
		return cpu;
	}

	cpu_set_t* cpu_set = NULL;
	cpu_set = CPU_ALLOC(MAX_CPU);
	if (!cpu_set) {
		unlock();
		__log_err("failed to allocate cpu set");
		return -1;
	}
	size_t cpu_set_size = CPU_ALLOC_SIZE(MAX_CPU);
	CPU_ZERO_S(cpu_set_size, cpu_set);
	if (pthread_getaffinity_np(tid, cpu_set_size, cpu_set)) {
		unlock();
		CPU_FREE(cpu_set);
		__log_err("pthread_getaffinity_np failed for tid=%lu (errno=%d %m)", tid, errno);
		return -1;
	}

	if (CPU_COUNT_S(cpu_set_size, cpu_set) == 0) {
		unlock();
		__log_err("no cpu available for tid=%lu", tid);
		CPU_FREE(cpu_set);
		return -1;
	}

	if (CPU_COUNT_S(cpu_set_size, cpu_set) == 1) { //already attached
		for (cpu = 0; cpu < MAX_CPU && !CPU_ISSET_S(cpu, cpu_set_size, cpu_set); cpu++) {}
	} else { //need to choose one cpu to attach to
		int min_cpu_count = -1;
		for (int i = 0; i < MAX_CPU; i++) {
			if (!CPU_ISSET_S(i, cpu_set_size, cpu_set)) continue;
			if (min_cpu_count < 0 || m_cpu_thread_count[i] < min_cpu_count) {
				min_cpu_count = m_cpu_thread_count[i];
				cpu = i;
			}
		}
		if (suggested_cpu >= 0
			&& CPU_ISSET_S(suggested_cpu, cpu_set_size, cpu_set)
			&& m_cpu_thread_count[suggested_cpu] <= min_cpu_count + 1 ) {
			cpu = suggested_cpu;
		}
		CPU_ZERO_S(cpu_set_size, cpu_set);
		CPU_SET_S(cpu, cpu_set_size, cpu_set);
		__log_dbg("attach tid=%lu running on cpu=%d to cpu=%d", tid, sched_getcpu(), cpu);
		if (pthread_setaffinity_np(tid, cpu_set_size, cpu_set)) {
			unlock();
			CPU_FREE(cpu_set);
			__log_err("pthread_setaffinity_np failed for tid=%lu to cpu=%d (errno=%d %m)", tid, cpu, errno);
			return -1;
		}
	}

	CPU_FREE(cpu_set);
	g_n_thread_cpu_core = cpu;
	m_cpu_thread_count[cpu]++;
	unlock();
	return cpu;
}
示例#20
0
int main(int argc, char **argv)
{
    int fd;

    if (argc < 2) {
        printf("usage: temporary-file-name\n");
        exit(EXIT_SUCCESS);
    }

    /*
     * lseek() 対象の一時ファイルを作成
     */
    const char *filename = argv[1];

    fd = open(filename, O_CREAT|O_RDWR, 0600);

    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    if (ftruncate(fd, LSEEK_FILE_SIZE) < 0) {
        perror("ftruncate");
        exit(EXIT_FAILURE);
    }
    fsync(fd);

    unlink(filename);

    /*
     * アフィニティを確認 
     */
    int max_processors, ret;
    cpu_set_t cpu_set;

    max_processors = (int) sysconf(_SC_NPROCESSORS_CONF);

    if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) != 0) {
        perror("sched_getaffinity");
        exit(EXIT_FAILURE);
    }

    /*
     * 共有メモリを作成
     */
    void *addr;
    addr = mmap(NULL, sizeof(shared_area_t), PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1, 0);
    if (addr == MAP_FAILED) {
        perror("mmap");
        exit(EXIT_FAILURE);
    }

    shared_area_p = (shared_area_t *) addr;

    memset(shared_area_p, sizeof(*shared_area_p), 0);

    /*
     * アフィニティが存在する CPU 毎に子プロセスを作成
     */
    int i;
    for (i = 0 ; i < max_processors ; i++) {
        if (CPU_ISSET(i, &cpu_set)) {
            pid_t pid;

            pid = fork();

            if (pid > 0) {
                /* parent */
                shared_area_p->children[i].pid = pid;
            } else if (pid == 0) {
                /* child */
                cpu_set_t child_cpu_set;

                CPU_ZERO_S(sizeof(child_cpu_set), &child_cpu_set);
                CPU_SET_S(i, sizeof(child_cpu_set), &child_cpu_set);

                if (sched_setaffinity(0, sizeof(child_cpu_set), &child_cpu_set)) {
                    perror("sched_setaffinity");
                    exit(EXIT_FAILURE);
                }

                shared_area_p->children[i].count = do_task(fd, &shared_area_p->start, &shared_area_p->stop);

                exit(EXIT_SUCCESS);
            } else {
                /* error */
                perror("fork");
                exit(EXIT_FAILURE);
            }
        }
    }

    /*
     * 計測
     */
    shared_area_p->start = 1;

    ret = usleep(TEST_DURATION * 1000000);

    if (ret != 0) {
        perror("usleep");
        exit(EXIT_FAILURE);        
    }

    shared_area_p->stop = 1;

    /*
     * 子プロセスの回収と集計
     */
    unsigned long total_count = 0;

    for (i = 0 ; i < max_processors ; i++) {
        pid_t pid = shared_area_p->children[i].pid;
        
        if (pid != 0) {
            pid_t ret;
            int status;

            do {
                ret = waitpid(pid, &status, 0);
            } while (ret == 0);

            if (ret == (pid_t) -1) {
                perror("watipid");
                exit(EXIT_FAILURE);
            }

            assert(pid == ret);

            total_count += shared_area_p->children[i].count;
        }
    }

    printf("TPS: %.3f\n", (double) total_count / TEST_DURATION);

    return 0;
}
示例#21
0
int
create_author(struct server *s, int n)
{
    int i, j;
    struct author *authors = NULL;
    cpu_set_t cpuinfo;
    pthread_t apt[QUIZZER_NUM];
    if (n < 1 || n > 50)
        dns_error(0, "quizzer bad range");
    if ((authors = malloc(sizeof(struct author) * n)) == NULL)
        dns_error(0, "out of memory in quizzer");
    memset(authors, 0, sizeof(struct author) * n);
    s->authors = authors;
    for (i = 0; i < n; i++) {
        authors[i].idx = i;
        authors[i].cudp = s->ludp;
        authors[i].audp = create_listen_ports(i * 1000 + 998, UDP, NULL);
        if (authors[i].audp < 0)
            dns_error(0, "auth fd error");
        set_sock_buff(authors[i].audp, 1);
        authors[i].el = &s->eventlist;
        authors[i].s = s;
        get_random_data(authors[i].randombuffer, RANDOM_SIZE);
        authors[i].rndidx = 0;
        authors[i].dupbefore = 0;
        authors[i].limits = 10;
        authors[i].bdepfd = 0;
        authors[i].fwd = s->forward;
        authors[i].ds = s->datasets;
        authors[i].qnum = 0;
        authors[i].underattack = 0;
        authors[i].timex = 0;
        authors[i].response = 0;
        authors[i].tcpinuse = 0;
        authors[i].rdb = 0;
        authors[i].quizz = 0;
        authors[i].drop = 0;
        authors[i].timeout = 0;
        authors[i].qidx = 0;    //start idx in qoutinfo list
        authors[i].start = QLIST_TABLE_SIZE / QUIZZER_NUM * i;
        if (i == (QUIZZER_NUM - 1))
            authors[i].end = QLIST_TABLE_SIZE;
        else
            authors[i].end = QLIST_TABLE_SIZE / QUIZZER_NUM * (i + 1);
        memset(authors[i].ip, 0, IP_DATA_LEN);
        authors[i].loginfo = malloc(sizeof(struct log_info));
        memset(authors[i].loginfo, 0, sizeof(struct log_info));
        authors[i].loginfo->log_type = TYPE_QUIZZER;
        authors[i].loginfo->logfd = create_new_log(s->logpath, i, TYPE_QUIZZER);
        for (j = 0; j < AUTH_DB_NUM; j++)
            pthread_spin_init(&(authors[i].dblock[j]), 0);
        for (j = 0; j < LIST_SPACE; j++)
            authors[i].list[j] = NULL;
        for (j = 0; j < EP_TCP_FDS; j++)
            authors[i].eptcpfds[j].ret = -1;
        pthread_spin_init(&authors[i].lock, 0);
        authors[i].loginfo->lastlog = global_now;
        if (authors[i].cudp < 0 || authors[i].audp < 0)
            dns_error(0, "create quizzer2");
        if (pthread_create(apt + i, NULL, run_quizzer, (void *) &(authors[i]))
            != 0)
            dns_error(0, "create quizzer");
    }
    global_out_info->thread_num += i;
    
    for(i = 0;i < QUIZZER_NUM ;i ++)
    {
        CPU_ZERO(&cpuinfo);
        CPU_SET_S(i + FETCHER_NUM + 1, sizeof(cpuinfo), &cpuinfo);
        if(0 != pthread_setaffinity_np(apt[i], sizeof(cpu_set_t), &cpuinfo))
        {
            printf("set affinity quizzer failed, may be the cpu cores num less than (FETCHER_NUM + QUIZZER_NUM + 1)\n");
//             exit(0);
        }
    }
    
    return 0;
}
示例#22
0
文件: init.c 项目: AlexShiLucky/rtems
static void test_task_get_set_affinity(void)
{
#if defined(__RTEMS_HAVE_SYS_CPUSET_H__)
  rtems_id self_id = rtems_task_self();
  rtems_id task_id;
  rtems_status_code sc;
  cpu_set_t cpusetone;
  cpu_set_t cpuset;
  size_t big = 2 * CHAR_BIT * sizeof(cpu_set_t);
  size_t cpusetbigsize = CPU_ALLOC_SIZE(big);
  cpu_set_t *cpusetbigone;
  cpu_set_t *cpusetbig;

  CPU_ZERO(&cpusetone);
  CPU_SET(0, &cpusetone);

  sc = rtems_task_create(
    rtems_build_name('T', 'A', 'S', 'K'),
    2,
    RTEMS_MINIMUM_STACK_SIZE,
    RTEMS_DEFAULT_MODES,
    RTEMS_DEFAULT_ATTRIBUTES,
    &task_id
  );
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  sc = rtems_task_get_affinity(RTEMS_SELF, sizeof(cpuset), NULL);
  rtems_test_assert(sc == RTEMS_INVALID_ADDRESS);

  sc = rtems_task_set_affinity(RTEMS_SELF, sizeof(cpuset), NULL);
  rtems_test_assert(sc == RTEMS_INVALID_ADDRESS);

  sc = rtems_task_get_affinity(RTEMS_SELF, 0, &cpuset);
  rtems_test_assert(sc == RTEMS_INVALID_NUMBER);

  sc = rtems_task_set_affinity(RTEMS_SELF, 0, &cpuset);
  rtems_test_assert(sc == RTEMS_INVALID_NUMBER);

  sc = rtems_task_get_affinity(invalid_id, sizeof(cpuset), &cpuset);
  rtems_test_assert(sc == RTEMS_INVALID_ID);

  sc = rtems_task_set_affinity(invalid_id, sizeof(cpuset), &cpuset);
  rtems_test_assert(sc == RTEMS_INVALID_ID);

  sc = rtems_task_get_affinity(RTEMS_SELF, sizeof(cpuset), &cpuset);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  rtems_test_assert(CPU_EQUAL(&cpuset, &cpusetone));

  sc = rtems_task_set_affinity(RTEMS_SELF, sizeof(cpuset), &cpuset);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  sc = rtems_task_set_affinity(self_id, sizeof(cpuset), &cpuset);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  sc = rtems_task_set_affinity(task_id, sizeof(cpuset), &cpuset);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  sc = rtems_task_get_affinity(task_id, sizeof(cpuset), &cpuset);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  rtems_test_assert(CPU_EQUAL(&cpuset, &cpusetone));

  cpusetbigone = CPU_ALLOC(big);
  rtems_test_assert(cpusetbigone != NULL);

  cpusetbig = CPU_ALLOC(big);
  rtems_test_assert(cpusetbig != NULL);

  CPU_ZERO_S(cpusetbigsize, cpusetbigone);
  CPU_SET_S(0, cpusetbigsize, cpusetbigone);

  sc = rtems_task_get_affinity(task_id, cpusetbigsize, cpusetbig);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  rtems_test_assert(CPU_EQUAL_S(cpusetbigsize, cpusetbig, cpusetbigone));

  sc = rtems_task_set_affinity(task_id, cpusetbigsize, cpusetbig);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  sc = rtems_task_delete(task_id);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  CPU_FREE(cpusetbig);
  CPU_FREE(cpusetbigone);
#endif /* defined(__RTEMS_HAVE_SYS_CPUSET_H__) */
}
示例#23
0
int set_thread_affinity(int cpuid) {
  unsigned long mask = 0xffffffff;
  unsigned int len = sizeof(mask);

#ifdef _WIN32
  HANDLE hThread;
#endif	
  
#ifdef _WIN32
  SET_MASK(cpuid)
  hThread = GetCurrentThread();
  if (SetThreadAffinityMask(hThread, mask) == 0) {
    return -1;
  }
#elif  CMK_HAS_PTHREAD_SETAFFINITY
#ifdef CPU_ALLOC
 if ( cpuid >= CPU_SETSIZE ) {
  cpu_set_t *cpusetp;
  pthread_t thread;
  size_t size;
  int num_cpus;
  num_cpus = cpuid + 1;
  cpusetp = CPU_ALLOC(num_cpus);
  if (cpusetp == NULL) {
    perror("set_thread_affinity CPU_ALLOC");
    return -1;
  }
  size = CPU_ALLOC_SIZE(num_cpus);
  thread = pthread_self();
  CPU_ZERO_S(size, cpusetp);
  CPU_SET_S(cpuid, size, cpusetp);
  if (errno = pthread_setaffinity_np(thread, size, cpusetp)) {
    perror("pthread_setaffinity dynamically allocated");
    CPU_FREE(cpusetp);
    return -1;
  }
  CPU_FREE(cpusetp);
 } else
#endif
 {
  int s, j;
  cpu_set_t cpuset;
  pthread_t thread;

  thread = pthread_self();

  CPU_ZERO(&cpuset);
  CPU_SET(cpuid, &cpuset);

  if (errno = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset)) {
    perror("pthread_setaffinity");
    return -1;
  }
 }
#elif CMK_HAS_BINDPROCESSOR
  if (bindprocessor(BINDTHREAD, thread_self(), cpuid) != 0)
    return -1;
#else
  return set_cpu_affinity(cpuid);
#endif

  return 0;
}
示例#24
0
文件: init.c 项目: WattTech/rtems
static void test(uint32_t cpu_count)
{
  rtems_status_code sc;
  uint32_t t;
  uint32_t c;
  rtems_task_argument idx;
  cpu_set_t cpu_set;

  /* Semaphore to signal end of test */
  sc = rtems_semaphore_create(rtems_build_name('D', 'o', 'n', 'e'), 0,
      RTEMS_LOCAL |
      RTEMS_NO_INHERIT_PRIORITY |
      RTEMS_NO_PRIORITY_CEILING |
      RTEMS_FIFO, 0, &finished_sem);

  /*
   * Create a set of tasks per CPU. Chain them together using
   * semaphores so that only one task can be active at any given
   * time.
   */
  for ( c = 0; c < cpu_count; c++ ) {
    for ( t = 0; t < TASKS_PER_CPU; t++ ) {
      idx = c * TASKS_PER_CPU + t;

      sc = rtems_task_create(rtems_build_name('T', 'A', '0' + c, '0' + t),
          TASK_PRIO,
          RTEMS_MINIMUM_STACK_SIZE,
          RTEMS_DEFAULT_MODES,
          RTEMS_DEFAULT_ATTRIBUTES,
          &task_data[idx].id);
      rtems_test_assert(sc == RTEMS_SUCCESSFUL);

      sc = rtems_semaphore_create(rtems_build_name('S', 'E', '0' + c, '0' + t),
          0,
          RTEMS_LOCAL |
          RTEMS_SIMPLE_BINARY_SEMAPHORE |
          RTEMS_NO_INHERIT_PRIORITY |
          RTEMS_NO_PRIORITY_CEILING |
          RTEMS_FIFO, 0, &task_data[idx].task_sem);
      rtems_test_assert(sc == RTEMS_SUCCESSFUL);

      task_data[(idx + 1) % (cpu_count * TASKS_PER_CPU)].prev_sem =
          task_data[idx].task_sem;

      CPU_ZERO_S(sizeof(cpu_set_t), &cpu_set);
      CPU_SET_S(c, sizeof(cpu_set_t), &cpu_set);

      sc = rtems_task_set_affinity(task_data[idx].id, sizeof(cpu_set_t),
          &cpu_set);
      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
    }
  }

  /* Start the tasks */
  for ( idx = 0; idx < cpu_count * TASKS_PER_CPU; idx++ ) {
    sc = rtems_task_start(task_data[idx].id, task, idx);
    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
  }

  /* Start chain */
  sc = rtems_semaphore_release(task_data[0].task_sem);

  /* Wait until chain has completed */
  for ( idx = 0; idx < cpu_count * TASKS_PER_CPU; idx++ ) {
    rtems_semaphore_obtain(finished_sem, 0, 0);
    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
  }

}
示例#25
0
文件: threads.c 项目: DrDonk/cpuid
int thread_bind_native(__unused_variable struct cpuid_state_t *state, __unused_variable uint32_t id)
{
#ifdef TARGET_OS_WINDOWS

	BOOL ret;
	HANDLE hThread = GetCurrentThread();
#if _WIN32_WINNT >= 0x0601
	GROUP_AFFINITY affinity;

	ZeroMemory(&affinity, sizeof(GROUP_AFFINITY));

	affinity.Group = id / 64;
	affinity.Mask = 1 << (id % 64);

	ret = SetThreadGroupAffinity(hThread, &affinity, NULL);
#else
	DWORD mask;

	if (id > 32)
		return 1;

	mask = (1 << id);

	ret = SetThreadAffinityMask(hThread, mask);
#endif

	return (ret != FALSE) ? 0 : 1;

#elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_FREEBSD)

	int ret;

#ifdef CPU_SET_S
	size_t setsize = CPU_ALLOC_SIZE(MAX_CPUS);
	CPUSET_T *set = CPU_ALLOC(MAX_CPUS);
	pthread_t pth;

	pth = pthread_self();

	CPU_ZERO_S(setsize, set);
	CPU_SET_S(id, setsize, set);
	ret = pthread_setaffinity_np(pth, setsize, set);
	CPU_FREE(set);
#else
	size_t bits_per_set = sizeof(CPUSET_T) * 8;
	size_t bits_per_subset = sizeof(CPUSET_MASK_T) * 8;
	size_t setsize = sizeof(CPUSET_T) * (MAX_CPUS / bits_per_set);
	size_t set_id, subset_id;
	unsigned long long mask;
	CPUSET_T *set = malloc(setsize);
	pthread_t pth;

	pth = pthread_self();

	for (set_id = 0; set_id < (MAX_CPUS / bits_per_set); set_id++)
		CPU_ZERO(&set[set_id]);

	set_id = id / bits_per_set;
	id %= bits_per_set;

	subset_id = id / bits_per_subset;
	id %= bits_per_subset;

	mask = 1ULL << (unsigned long long)id;

	((unsigned long *)set[set_id].__bits)[subset_id] |= mask;
	ret = pthread_setaffinity_np(pth, setsize, set);
	free(set);
#endif

	return (ret == 0) ? 0 : 1;

#elif defined(TARGET_OS_MACOSX)

#ifdef USE_CHUD
	return (utilBindThreadToCPU(id) == 0) ? 0 : 1;
#else
	return 1;
#endif

#else
#error "thread_bind_native() not defined for this platform"
#endif
}
示例#26
0
int virProcessSetAffinity(pid_t pid, virBitmapPtr map)
{
    size_t i;
    VIR_DEBUG("Set process affinity on %lld\n", (long long)pid);
# ifdef CPU_ALLOC
    /* New method dynamically allocates cpu mask, allowing unlimted cpus */
    int numcpus = 1024;
    size_t masklen;
    cpu_set_t *mask;

    /* Not only may the statically allocated cpu_set_t be too small,
     * but there is no way to ask the kernel what size is large enough.
     * So you have no option but to pick a size, try, catch EINVAL,
     * enlarge, and re-try.
     *
     * http://lkml.org/lkml/2009/7/28/620
     */
 realloc:
    masklen = CPU_ALLOC_SIZE(numcpus);
    mask = CPU_ALLOC(numcpus);

    if (!mask) {
        virReportOOMError();
        return -1;
    }

    CPU_ZERO_S(masklen, mask);
    for (i = 0; i < virBitmapSize(map); i++) {
        if (virBitmapIsBitSet(map, i))
            CPU_SET_S(i, masklen, mask);
    }

    if (sched_setaffinity(pid, masklen, mask) < 0) {
        CPU_FREE(mask);
        if (errno == EINVAL &&
            numcpus < (1024 << 8)) { /* 262144 cpus ought to be enough for anyone */
            numcpus = numcpus << 2;
            goto realloc;
        }
        virReportSystemError(errno,
                             _("cannot set CPU affinity on process %d"), pid);
        return -1;
    }
    CPU_FREE(mask);
# else
    /* Legacy method uses a fixed size cpu mask, only allows up to 1024 cpus */
    cpu_set_t mask;

    CPU_ZERO(&mask);
    for (i = 0; i < virBitmapSize(map); i++) {
        if (virBitmapIsBitSet(map, i))
            CPU_SET(i, &mask);
    }

    if (sched_setaffinity(pid, sizeof(mask), &mask) < 0) {
        virReportSystemError(errno,
                             _("cannot set CPU affinity on process %d"), pid);
        return -1;
    }
# endif

    return 0;
}
示例#27
0
文件: threads.c 项目: tycho/cpuid
int thread_bind_native(__unused_variable struct cpuid_state_t *state, uint32_t id)
{
#ifdef TARGET_OS_WINDOWS

	BOOL ret = FALSE;
	HANDLE hThread = GetCurrentThread();

#if _WIN32_WINNT < 0x0601
	if (is_windows7_or_greater()) {
#endif
		DWORD threadsInGroup = 0;
		WORD groupId, groupCount;
		GROUP_AFFINITY affinity;
		ZeroMemory(&affinity, sizeof(GROUP_AFFINITY));

		groupCount = GetActiveProcessorGroupCount();

		for (groupId = 0; groupId < groupCount; groupId++) {
			threadsInGroup = GetActiveProcessorCount(groupId);
			if (id < threadsInGroup)
				break;
			id -= threadsInGroup;
		}

		if (groupId < groupCount && id < threadsInGroup) {
			affinity.Group = groupId;
			affinity.Mask = 1ULL << id;

			ret = SetThreadGroupAffinity(hThread, &affinity, NULL);
		}
#if _WIN32_WINNT < 0x0601
	} else {
		DWORD mask;

		if (id > 32)
			return 1;

		mask = (1 << id);

		ret = SetThreadAffinityMask(hThread, mask);
	}
#endif

	if (state && ret != FALSE)
		state->cpu_bound_index = id;

	return (ret != FALSE) ? 0 : 1;

#elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_FREEBSD)

	int ret;

#ifdef CPU_SET_S
	size_t setsize = CPU_ALLOC_SIZE(MAX_CPUS);
	CPUSET_T *set = CPU_ALLOC(MAX_CPUS);
	pthread_t pth;

	pth = pthread_self();

	CPU_ZERO_S(setsize, set);
	CPU_SET_S(id, setsize, set);
	ret = pthread_setaffinity_np(pth, setsize, set);
	CPU_FREE(set);
#else
	size_t bits_per_set = sizeof(CPUSET_T) * 8;
	size_t bits_per_subset = sizeof(CPUSET_MASK_T) * 8;
	size_t setsize = sizeof(CPUSET_T) * (MAX_CPUS / bits_per_set);
	size_t set_id, subset_id;
	unsigned long long mask;
	CPUSET_T *set = malloc(setsize);
	pthread_t pth;

	pth = pthread_self();

	for (set_id = 0; set_id < (MAX_CPUS / bits_per_set); set_id++)
		CPU_ZERO(&set[set_id]);

	set_id = id / bits_per_set;
	id %= bits_per_set;

	subset_id = id / bits_per_subset;
	id %= bits_per_subset;

	mask = 1ULL << (unsigned long long)id;

	((unsigned long *)set[set_id].__bits)[subset_id] |= mask;
	ret = pthread_setaffinity_np(pth, setsize, set);
	free(set);
#endif

	if (state && ret == 0)
		state->cpu_bound_index = id;

	return (ret == 0) ? 0 : 1;

#elif defined(TARGET_OS_SOLARIS)

	/*
	 * This requires permissions, so can easily fail.
	 */
	if (processor_bind(P_LWPID, P_MYID, id, NULL) != 0) {
		fprintf(stderr, "warning: failed to bind to CPU%u: %s\n",
			id, strerror(errno));
		return 1;
	}

	if (state)
		state->cpu_bound_index = id;
	return 0;
#elif defined(TARGET_OS_MACOSX)
	int ret = 1;

#ifdef USE_CHUD
	ret = (utilBindThreadToCPU(id) == 0) ? 0 : 1;
#endif

	if (state && ret == 0)
		state->cpu_bound_index = id;

	return ret == 0 ? 0 : 1;
#else
#error "thread_bind_native() not defined for this platform"
#endif
}