~ubuntu-branches/ubuntu/trusty/htop/trusty-proposed

« back to all changes in this revision

Viewing changes to plpa-1.1/src/plpa_dispatch.c

  • Committer: Bazaar Package Importer
  • Author(s): Eugene V. Lyubimkin
  • Date: 2011-02-13 10:41:53 UTC
  • mfrom: (10.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20110213104153-0mv3qqddoh38psjk
Tags: 0.9-2
Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- c -*-
2
 
 *
3
 
 * Copyright (c) 2004-2006 The Trustees of Indiana University.
4
 
 *                         All rights reserved.
5
 
 * Copyright (c) 2004-2005 The Regents of the University of California.
6
 
 *                         All rights reserved.
7
 
 * Copyright (c) 2007-2008 Cisco Systems, Inc.  All rights reserved.
8
 
 * $COPYRIGHT$
9
 
 *
10
 
 * Additional copyrights may follow
11
 
 *
12
 
 * $HEADER$
13
 
 */
14
 
 
15
 
#include "plpa_config.h"
16
 
#include "plpa.h"
17
 
#include "plpa_internal.h"
18
 
 
19
 
#include <errno.h>
20
 
#include <sys/syscall.h>
21
 
#include <unistd.h>
22
 
 
23
 
/**
24
 
 * Call the kernel's setaffinity, massaging the user's input
25
 
 * parameters as necessary
26
 
 */
27
 
int PLPA_NAME(sched_setaffinity)(pid_t pid, size_t cpusetsize,
28
 
                                 const PLPA_NAME(cpu_set_t) *cpuset)
29
 
{
30
 
    int ret;
31
 
    size_t i;
32
 
    PLPA_NAME(cpu_set_t) tmp;
33
 
    PLPA_NAME(api_type_t) api;
34
 
 
35
 
    /* Check to see that we're initialized */
36
 
    if (!PLPA_NAME(initialized)) {
37
 
        if (0 != (ret = PLPA_NAME(init)())) {
38
 
            return ret;
39
 
        }
40
 
    }
41
 
 
42
 
    /* Check for bozo arguments */
43
 
    if (NULL == cpuset) {
44
 
        return EINVAL;
45
 
    }
46
 
 
47
 
    /* Probe the API type */
48
 
    if (0 != (ret = PLPA_NAME(api_probe)(&api))) {
49
 
        return ret;
50
 
    }
51
 
    switch (api) {
52
 
    case PLPA_NAME_CAPS(PROBE_OK):
53
 
        /* This shouldn't happen, but check anyway */
54
 
        if (cpusetsize > sizeof(*cpuset)) {
55
 
            return EINVAL;
56
 
        }
57
 
 
58
 
        /* If the user-supplied bitmask is smaller than what the
59
 
           kernel wants, zero out a temporary buffer of the size that
60
 
           the kernel wants and copy the user-supplied bitmask to the
61
 
           lower part of the temporary buffer.  This could be done
62
 
           more efficiently, but we're looking for clarity/simplicity
63
 
           of code here -- this is not intended to be
64
 
           performance-critical. */
65
 
        if (cpusetsize < PLPA_NAME(len)) {
66
 
            memset(&tmp, 0, sizeof(tmp));
67
 
            for (i = 0; i < cpusetsize * 8; ++i) {
68
 
                if (PLPA_CPU_ISSET(i, cpuset)) {
69
 
                    PLPA_CPU_SET(i, &tmp);
70
 
                }
71
 
            }
72
 
        }
73
 
 
74
 
        /* If the user-supplied bitmask is larger than what the kernel
75
 
           will accept, scan it and see if there are any set bits in
76
 
           the part larger than what the kernel will accept.  If so,
77
 
           return EINVAL.  Otherwise, copy the part that the kernel
78
 
           will accept into a temporary and use that.  Again,
79
 
           efficinency is not the issue of this code -- clarity is. */
80
 
        else if (cpusetsize > PLPA_NAME(len)) {
81
 
            for (i = PLPA_NAME(len) * 8; i < cpusetsize * 8; ++i) {
82
 
                if (PLPA_CPU_ISSET(i, cpuset)) {
83
 
                    return EINVAL;
84
 
                }
85
 
            }
86
 
            /* No upper-level bits are set, so now copy over the bits
87
 
               that the kernel will look at */
88
 
            memset(&tmp, 0, sizeof(tmp));
89
 
            for (i = 0; i < PLPA_NAME(len) * 8; ++i) {
90
 
                if (PLPA_CPU_ISSET(i, cpuset)) {
91
 
                    PLPA_CPU_SET(i, &tmp);
92
 
                }
93
 
            }
94
 
        }
95
 
 
96
 
        /* Otherwise, the user supplied a buffer that is exactly the
97
 
           right size.  Just for clarity of code, copy the user's
98
 
           buffer into the temporary and use that. */
99
 
        else {
100
 
            memcpy(&tmp, cpuset, cpusetsize);
101
 
        }
102
 
 
103
 
        /* Now do the syscall */
104
 
        ret = syscall(__NR_sched_setaffinity, pid, PLPA_NAME(len), &tmp);
105
 
 
106
 
        /* Return 0 upon success.  According to
107
 
           http://www.open-mpi.org/community/lists/plpa-users/2006/02/0016.php,
108
 
           all the kernel implementations return >= 0 upon success. */
109
 
        if (ret >= 0) {
110
 
            return 0;
111
 
        } else {
112
 
            return ret;
113
 
        }
114
 
        break;
115
 
 
116
 
    case PLPA_NAME_CAPS(PROBE_NOT_SUPPORTED):
117
 
        /* Process affinity not supported here */
118
 
        return ENOSYS;
119
 
        break;
120
 
 
121
 
    default:
122
 
        /* Something went wrong */
123
 
        /* JMS: would be good to have something other than EINVAL here
124
 
           -- suggestions? */
125
 
        return EINVAL;
126
 
        break;
127
 
    }
128
 
}
129
 
 
130
 
 
131
 
/**
132
 
 * Call the kernel's getaffinity, massaging the user's input
133
 
 * parameters as necessary
134
 
 */
135
 
int PLPA_NAME(sched_getaffinity)(pid_t pid, size_t cpusetsize,
136
 
                                PLPA_NAME(cpu_set_t) *cpuset)
137
 
{
138
 
    int ret;
139
 
    PLPA_NAME(api_type_t) api;
140
 
 
141
 
    /* Check to see that we're initialized */
142
 
    if (!PLPA_NAME(initialized)) {
143
 
        if (0 != (ret = PLPA_NAME(init)())) {
144
 
            return ret;
145
 
        }
146
 
    }
147
 
 
148
 
    /* Check for bozo arguments */
149
 
    if (NULL == cpuset) {
150
 
        return EINVAL;
151
 
    }
152
 
    /* Probe the API type */
153
 
    if (0 != (ret = PLPA_NAME(api_probe)(&api))) {
154
 
        return ret;
155
 
    }
156
 
    switch (api) {
157
 
    case PLPA_NAME_CAPS(PROBE_OK):
158
 
        /* This shouldn't happen, but check anyway */
159
 
        if (PLPA_NAME(len) > sizeof(*cpuset)) {
160
 
            return EINVAL;
161
 
        }
162
 
 
163
 
        /* If the user supplied a buffer that is too small, then don't
164
 
           even bother */
165
 
        if (cpusetsize < PLPA_NAME(len)) {
166
 
            return EINVAL;
167
 
        }
168
 
 
169
 
        /* Now we know that the user's buffer is >= the size required
170
 
           by the kernel.  If it's >, then zero it out so that the
171
 
           bits at the top are cleared (since they won't be set by the
172
 
           kernel) */
173
 
        if (cpusetsize > PLPA_NAME(len)) {
174
 
            memset(cpuset, 0, cpusetsize);
175
 
        }
176
 
 
177
 
        /* Now do the syscall */
178
 
        ret = syscall(__NR_sched_getaffinity, pid, PLPA_NAME(len), cpuset);
179
 
 
180
 
        /* Return 0 upon success.  According to
181
 
           http://www.open-mpi.org/community/lists/plpa-users/2006/02/0016.php,
182
 
           all the kernel implementations return >= 0 upon success. */
183
 
        if (ret >= 0) {
184
 
            return 0;
185
 
        } else {
186
 
            return ret;
187
 
        }
188
 
        break;
189
 
 
190
 
    case PLPA_NAME_CAPS(PROBE_NOT_SUPPORTED):
191
 
        /* Process affinity not supported here */
192
 
        return ENOSYS;
193
 
        break;
194
 
 
195
 
    default:
196
 
        /* Something went wrong */
197
 
        return EINVAL;
198
 
        break;
199
 
    }
200
 
}
201