diff options
author | Eugene V. Lyubimkin <jackyf@debian.org> | 2011-01-16 19:36:07 +0200 |
---|---|---|
committer | Daniel Lange <DLange@git.local> | 2016-04-11 13:00:28 +0200 |
commit | 6e8d31964ea33edd470001ee13070e844b269e11 (patch) | |
tree | 48b41783f978b511ccfb25260c83717160c8d63b /plpa-1.3.2/src/libplpa/plpa_dispatch.c | |
parent | 6e545da37e2482b15007df28c549afa072a5198d (diff) | |
parent | 283707c5e5bc436b78ea23bf5500cb6b16a01148 (diff) | |
download | debian_htop-6e8d31964ea33edd470001ee13070e844b269e11.tar.gz debian_htop-6e8d31964ea33edd470001ee13070e844b269e11.tar.bz2 debian_htop-6e8d31964ea33edd470001ee13070e844b269e11.zip |
Imported Debian patch 0.9-1debian/0.9-1
Diffstat (limited to 'plpa-1.3.2/src/libplpa/plpa_dispatch.c')
-rw-r--r-- | plpa-1.3.2/src/libplpa/plpa_dispatch.c | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/plpa-1.3.2/src/libplpa/plpa_dispatch.c b/plpa-1.3.2/src/libplpa/plpa_dispatch.c new file mode 100644 index 0000000..13dc820 --- /dev/null +++ b/plpa-1.3.2/src/libplpa/plpa_dispatch.c @@ -0,0 +1,193 @@ +/* -*- c -*- + * + * Copyright (c) 2004-2006 The Trustees of Indiana University. + * All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2007-2008 Cisco Systems, Inc. All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "plpa_config.h" +#include "plpa.h" +#include "plpa_internal.h" + +#include <errno.h> +#include <sys/syscall.h> +#include <unistd.h> + +/** + * Call the kernel's setaffinity, massaging the user's input + * parameters as necessary + */ +int PLPA_NAME(sched_setaffinity)(pid_t pid, size_t cpusetsize, + const PLPA_NAME(cpu_set_t) *cpuset) +{ + int ret; + size_t i; + PLPA_NAME(cpu_set_t) tmp; + PLPA_NAME(api_type_t) api; + + /* Check to see that we're initialized */ + if (!PLPA_NAME(initialized)) { + if (0 != (ret = PLPA_NAME(init)())) { + return ret; + } + } + + /* Check for bozo arguments */ + if (NULL == cpuset) { + return EINVAL; + } + + /* Probe the API type */ + if (0 != (ret = PLPA_NAME(api_probe)(&api))) { + return ret; + } + switch (api) { + case PLPA_NAME_CAPS(PROBE_OK): + /* This shouldn't happen, but check anyway */ + if (cpusetsize > sizeof(*cpuset)) { + return EINVAL; + } + + /* If the user-supplied bitmask is smaller than what the + kernel wants, zero out a temporary buffer of the size that + the kernel wants and copy the user-supplied bitmask to the + lower part of the temporary buffer. This could be done + more efficiently, but we're looking for clarity/simplicity + of code here -- this is not intended to be + performance-critical. */ + if (cpusetsize < PLPA_NAME(len)) { + memset(&tmp, 0, sizeof(tmp)); + for (i = 0; i < cpusetsize * 8; ++i) { + if (PLPA_CPU_ISSET(i, cpuset)) { + PLPA_CPU_SET(i, &tmp); + } + } + } + + /* If the user-supplied bitmask is larger than what the kernel + will accept, scan it and see if there are any set bits in + the part larger than what the kernel will accept. If so, + return EINVAL. Otherwise, copy the part that the kernel + will accept into a temporary and use that. Again, + efficinency is not the issue of this code -- clarity is. */ + else if (cpusetsize > PLPA_NAME(len)) { + for (i = PLPA_NAME(len) * 8; i < cpusetsize * 8; ++i) { + if (PLPA_CPU_ISSET(i, cpuset)) { + return EINVAL; + } + } + /* No upper-level bits are set, so now copy over the bits + that the kernel will look at */ + memset(&tmp, 0, sizeof(tmp)); + for (i = 0; i < PLPA_NAME(len) * 8; ++i) { + if (PLPA_CPU_ISSET(i, cpuset)) { + PLPA_CPU_SET(i, &tmp); + } + } + } + + /* Otherwise, the user supplied a buffer that is exactly the + right size. Just for clarity of code, copy the user's + buffer into the temporary and use that. */ + else { + memcpy(&tmp, cpuset, cpusetsize); + } + + /* Now do the syscall */ + ret = syscall(__NR_sched_setaffinity, pid, PLPA_NAME(len), &tmp); + + /* Return 0 upon success. According to + http://www.open-mpi.org/community/lists/plpa-users/2006/02/0016.php, + all the kernel implementations return >= 0 upon success. */ + return (ret >= 0) ? 0 : ret; + break; + + case PLPA_NAME_CAPS(PROBE_NOT_SUPPORTED): + /* Process affinity not supported here */ + return ENOSYS; + break; + + default: + /* Something went wrong */ + /* JMS: would be good to have something other than EINVAL here + -- suggestions? */ + return EINVAL; + break; + } +} + + +/** + * Call the kernel's getaffinity, massaging the user's input + * parameters as necessary + */ +int PLPA_NAME(sched_getaffinity)(pid_t pid, size_t cpusetsize, + PLPA_NAME(cpu_set_t) *cpuset) +{ + int ret; + PLPA_NAME(api_type_t) api; + + /* Check to see that we're initialized */ + if (!PLPA_NAME(initialized)) { + if (0 != (ret = PLPA_NAME(init)())) { + return ret; + } + } + + /* Check for bozo arguments */ + if (NULL == cpuset) { + return EINVAL; + } + /* Probe the API type */ + if (0 != (ret = PLPA_NAME(api_probe)(&api))) { + return ret; + } + switch (api) { + case PLPA_NAME_CAPS(PROBE_OK): + /* This shouldn't happen, but check anyway */ + if (PLPA_NAME(len) > sizeof(*cpuset)) { + return EINVAL; + } + + /* If the user supplied a buffer that is too small, then don't + even bother */ + if (cpusetsize < PLPA_NAME(len)) { + return EINVAL; + } + + /* Now we know that the user's buffer is >= the size required + by the kernel. If it's >, then zero it out so that the + bits at the top are cleared (since they won't be set by the + kernel) */ + if (cpusetsize > PLPA_NAME(len)) { + memset(cpuset, 0, cpusetsize); + } + + /* Now do the syscall */ + ret = syscall(__NR_sched_getaffinity, pid, PLPA_NAME(len), cpuset); + + /* Return 0 upon success. According to + http://www.open-mpi.org/community/lists/plpa-users/2006/02/0016.php, + all the kernel implementations return >= 0 upon success. */ + return (ret >= 0) ? 0 : ret; + break; + + case PLPA_NAME_CAPS(PROBE_NOT_SUPPORTED): + /* Process affinity not supported here */ + return ENOSYS; + break; + + default: + /* Something went wrong */ + return EINVAL; + break; + } +} + |