1
/*___INFO__MARK_BEGIN__*/
2
/*************************************************************************
4
* The Contents of this file are made available subject to the terms of
5
* the Sun Industry Standards Source License Version 1.2
7
* Sun Microsystems Inc., March, 2001
10
* Sun Industry Standards Source License Version 1.2
11
* =================================================
12
* The contents of this file are subject to the Sun Industry Standards
13
* Source License Version 1.2 (the "License"); You may not use this file
14
* except in compliance with the License. You may obtain a copy of the
15
* License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
17
* Software provided under this License is provided on an "AS IS" basis,
18
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
19
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
20
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
21
* See the License for the specific provisions governing your rights and
22
* obligations concerning the Software.
24
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
26
* Copyright: 2001 by Sun Microsystems, Inc.
28
* All Rights Reserved.
30
************************************************************************/
31
/*___INFO__MARK_END__*/
33
#include <sys/types.h>
39
#if defined(SOLARIS64) || defined(SOLARISAMD64)
40
# include <sys/pset.h>
42
# include <sys/processor.h>
44
# include <sys/sysmp.h>
45
# include <sys/prctl.h>
46
# include <sys/schedctl.h>
49
#include "sge_uidgid.h"
50
#include "sge_nprocs.h"
52
#include "basis_types.h"
53
#include "config_file.h"
54
#include "execution_states.h"
55
#include "err_trace.h"
56
#include "sge_stdio.h"
59
#define PROC_SET_WARNING 1
60
#define PROC_SET_ERROR -1
61
#define PROC_SET_BUSY -2
64
# define SGE_MPSET_MULTIPLIER 100
71
* declaration of sbv_t from sys/runq_private.h
72
* including sys/runq_private.h lead to compile errors.
74
typedef unsigned long long sbv_t;
79
int assign_pid_to_pset(pid_t *pid_list, long num_pids,
80
int pset_id, long flags);
81
int assign_cpu_to_pset(long cpu, int pset_id, long option);
83
int destroy_pset(int pset_id, int number);
84
int create_pset(void);
85
void print_pset_error(int ret);
88
#if defined(__sgi) || defined(ALPHA)
89
static int range2proc_vec(char *, sbv_t *, char *);
92
#if defined(__sgi) || defined(ALPHA) || defined(SOLARIS64) || defined(SOLARISAMD64)
93
static int free_processor_set(char *err_str);
94
static int set_processor_range(char *crange, int proc_set_num, char *err_str);
97
void sge_pset_create_processor_set(void)
99
#if defined(__sgi) || defined(ALPHA) || defined(SOLARIS64) || defined(SOLARISAMD64)
100
char err_str[2*SGE_PATH_MAX+128];
102
/* SGI IRIX processor set stuff */
103
if (strcasecmp("UNDEFINED",get_conf_val("processors"))) {
106
sge_switch2start_user();
107
if ((ret=set_processor_range(get_conf_val("processors"),
108
(int) strtol(get_conf_val("job_id"), NULL, 10),
109
err_str)) != PROC_SET_OK) {
110
sge_switch2admin_user();
111
if (ret == PROC_SET_WARNING) /* not critical - e.g. not root */
112
shepherd_trace("warning: processor set not set in set_processor_range");
113
else { /* critical --> use err_str to indicate error */
114
shepherd_trace("critical error in set_processor_range - bailing out");
115
shepherd_state = SSTATE_PROCSET_NOTSET;
116
shepherd_error(1, err_str);
119
sge_switch2admin_user();
125
void sge_pset_free_processor_set(void)
127
#if defined(__sgi) || defined(ALPHA) || defined(SOLARIS64) || defined(SOLARISAMD64)
128
/* SGI IRIX processor set stuff */
129
if (strcasecmp("UNDEFINED",get_conf_val("processors"))) {
130
char err_str[2*SGE_PATH_MAX+128];
133
sge_switch2start_user();
134
if ((ret=free_processor_set(err_str)) != PROC_SET_OK) {
135
sge_switch2admin_user();
137
case PROC_SET_WARNING: /* not critical - e.g. not root */
138
shepherd_trace("warning: processor set not freed in free_processor_set - "
139
"did no exist, probably");
141
case PROC_SET_ERROR: /* critical - err_str indicates error */
142
shepherd_trace("critical error in free_processor_set - bailing out");
143
shepherd_state = SSTATE_PROCSET_NOTFREED;
144
shepherd_error(1, err_str);
146
case PROC_SET_BUSY: /* still processes running in processor set */
147
shepherd_trace("error in releasing processor set");
148
shepherd_state = SSTATE_PROCSET_NOTFREED;
149
shepherd_error(1, err_str);
151
default: /* should not occur */
153
"internal error after free_processor_set - ret=%d", ret);
154
shepherd_state = SSTATE_PROCSET_NOTFREED;
155
shepherd_error(1, err_str);
159
sge_switch2admin_user();
165
#if defined(__sgi) || defined(ALPHA) || defined(SOLARIS64) || defined(SOLARISAMD64)
166
/****** shepherd/pset/set_processor_range() ***********************************
168
* set_processor_range() -- sets processor range according to string
171
* int set_processor_range(char *crange,
176
* Sets processor range according to string specification.
177
* The unique processor set number will be stored in the file
178
* "processor_set_number" located in the current working directory.
181
* n|[n][-[m]],... , n,m being int >= 0.
182
* no blanks are allowed in between (this is supposed to be
183
* handled by the queue configuration parsing routine)
186
* char *crange - String specifier of the range. Will be
187
* modified via strtok internally.
188
* int proc_set_num - The base for a unique processor set number.
189
* This number is already supposed to be unique.
190
* for the job (currently the job_id).
191
* set_processor_range() manipulates it to make
192
* sure that it is a unique processor set number.
193
* char *err_str - The error message string to be used by the
194
* calling routine retuns value != PROC_SET_OK
195
* Also used for trace messages internally.
196
* Passed to invoked subroutines.
201
* PROC_SET_ERROR - A critical error occurred; either during
202
* execution of sysmp() calls or as returned
203
* from range2proc_vec().
204
* PROC_SET_WARNING - A non-critical error occurred (e.g. the
205
* procedure is executed as unpriveliged user)
206
******************************************************************************/
207
static int set_processor_range(char *crange, int proc_set_num, char *err_str)
211
#if defined(__sgi) || defined(ALPHA)
215
#if defined(__sgi) || defined(ALPHA)
216
if ((ret=range2proc_vec(crange, &proc_vec, err_str)))
221
/* It is not possible to bind processor #0 to other psets than pset #0
222
* So if we get a pset with #0 contained in the range we do nothing.
223
* The process gets not bound to a processor but it is guaranteed
224
* that no other job will get processor #0 exclusively. It is upon
225
* the administrator to prevent overlapping of the psets in different
228
if (!(proc_vec & 1)) { /* processor #0 not contained */
229
if ((proc_set_num = create_pset())<0) {
230
print_pset_error(proc_set_num); /* prints error to stdout */
231
shepherd_trace("MPPS_CREATE: failed to setup a new processor set");
232
return PROC_SET_ERROR;
235
if (assign_cpu_to_pset(proc_vec, proc_set_num, 0)<0) {
236
print_pset_error(proc_set_num); /* prints error to stdout */
237
shepherd_trace("MPPS_CREATE: failed assigning processors to processor set");
238
return PROC_SET_ERROR;
241
/* use default pset (id #0) */
244
#elif defined(SOLARIS64) || defined(SOLARISAMD64)
246
* We do not create a processor set here
247
* The system administrator is responsible to do this
248
* We read one id from crange. This is the processor-set id we should use.
253
if ((tok=strtok(crange, " \t\n"))) {
254
proc_set_num = (int) strtol(tok, &next, 10);
256
sprintf(err_str, "wrong processor set id format: %20.20s", crange);
257
shepherd_trace(err_str);
258
return PROC_SET_ERROR;
264
/* dump to file for later use */
265
if ((fp = fopen("processor_set_number","w"))) {
266
fprintf(fp,"%d\n",proc_set_num);
269
shepherd_trace("MPPS_CREATE: failed creating file processor_set_number");
270
return PROC_SET_ERROR;
274
/* Now let's assign ourselves to the previously created processor set */
277
pid_list[0] = getpid();
278
if (assign_pid_to_pset(pid_list, 1, proc_set_num, PSET_EXCLUSIVE)<0) {
279
print_pset_error(proc_set_num); /* prints error to stdout */
280
shepherd_trace("MPPS_CREATE: failed assigning processors to processor set");
281
return PROC_SET_ERROR;
284
#elif defined(SOLARIS64) || defined(SOLARISAMD64)
288
sprintf(err_str,"pset_bind: try to use processorset %d", proc_set_num);
289
shepherd_trace(err_str);
290
if (pset_bind(proc_set_num, P_PID, P_MYID, NULL)) {
293
shepherd_trace("pset_bind: The location pointed to by opset was not"
294
" NULL and not writable by the user");
295
local_ret = PROC_SET_ERROR;
298
shepherd_trace("pset_bind: invalid processor set was specified");
299
local_ret = PROC_SET_ERROR;
302
shepherd_trace("pset_bind: The effective user of the calling "
303
"process is not super-user");
304
local_ret = PROC_SET_ERROR;
307
sprintf(err_str,"pset_bind: unexpected error - errno=%d", errno);
308
shepherd_trace(err_str);
309
local_ret = PROC_SET_ERROR;
319
shepherd_trace("MPPS_CREATE: failed creating file processor_set_number");
320
return PROC_SET_ERROR;
323
/****** shepherd/pset/free_processor_set() ************************************
325
* free_processor_set() -- Release the previously occupied proc set.
328
* int free_processor_set(char *err_str)
331
* Release the previously occupied processor set. The unique
332
* processor set number is read from the file "processor_set_number"
333
* which has to be located in the current working directory.
336
* char *err_str - The error message string to be used by the calling
337
* routine if return value != PROC_SET_OK. Also used
338
* for trace messages internally
343
* PROC_SET_BUSY - The processor set is still in use, i.e.
344
* processes originating from the job have not
346
* PROC_SET_ERROR - A critical error occurred. During execution
348
* PROC_SET_WARNING - A non-critical error occurred (e.g. the
349
* procedure is executed as unpriviliged user)
350
******************************************************************************/
351
static int free_processor_set(char *err_str)
356
/* read unique processor set number from file */
357
if ((fp = fopen("processor_set_number","r"))) {
358
fscanf(fp, "%d", &proc_set_num);
359
FCLOSE_IGNORE_ERROR(fp);
361
shepherd_trace("MPPS_CREATE: failed reading from file processor_set_number");
362
return PROC_SET_ERROR;
369
pid_list[0] = getpid();
371
/* assign shepherd back to default processor set */
372
if ((ret=assign_pid_to_pset(pid_list, 1, 0, 0))<0) {
373
print_pset_error(ret); /* prints error to stdout */
374
shepherd_trace("MPPS_CREATE: failed assigning processors to processor set");
375
return PROC_SET_ERROR;
378
if ((ret = destroy_pset(proc_set_num, 1))==PROCESSOR_SET_ACTIVE) {
379
print_pset_error(ret);
380
shepherd_trace("MPPS_CREATE: failed assigning processors to processor set");
381
return PROC_SET_ERROR;
384
#elif defined(SOLARIS64) || defined(SOLARISAMD64)
386
* We do not release a processor set here
387
* The system administrator is responsible to do this
393
#if defined(__sgi) || defined(ALPHA)
394
/****** shepherd/pset/range2proc_vec() ****************************************
396
* range2proc_vec() -- Computes bit vector (prcessor set spec.)
399
* static int range2proc_vec(char *crange, sbv_t *proc_vec, char *err_str)
402
* Computes bit vector with bits set corresponding to string
403
* specification of processor range.
406
* char *crange - String specifier of the range. Will be modified
407
* internally. Format:
408
* n|[n][-[m]],... , n,m being int >= 0.
409
* no blanks are allowed in between
410
* sbv_t *proc_vec - a bit vector of type sbv_t with all bits set
411
* contained in the range description and all
413
* char *err_str - The error message string to be used by the
414
* calling routine if return value != PROC_SET_OK.
415
* Also used for trace messages internally.
418
* static int - Error state
420
* PROC_SET_ERROR - Invalid range value in range description.
421
******************************************************************************/
422
static int range2proc_vec(char *crange, sbv_t *proc_vec, char *err_str)
424
char *tok, *next, *p=crange;
429
*proc_vec = (sbv_t) 0;
431
/* compute max number of processors and thus significant length of
434
sbvlen = sge_nprocs() - 1; /* LSB corresponds to proc. 0 */
436
/* loop trough range string with "," as token delimiter
437
* Set processor vector for each token = range definition element.
439
while ((tok=strtok(p,","))) {
442
/* for each token parse range, i.e. find
443
* whether min or max value is set and whether a "-" sign
455
} else { /* should be a number */
456
if (min == -1 && !dash_used ) {
457
min = (int) strtol(tok, &next, 10);
458
if (next == tok || min < 0 || min > sbvlen) {
459
sprintf(err_str, "range2proc_vec: wrong processor range format: %20.20s", crange);
460
shepherd_trace(err_str);
461
return PROC_SET_ERROR;
463
} else if (max == -1 && dash_used ) {
464
max = (int) strtol(tok, &next, 10);
465
if (next == tok || max < 0 || max > sbvlen) {
466
sprintf(err_str, "range2proc_vec: wrong processor range format: %20.20s", crange);
467
shepherd_trace(err_str);
468
return PROC_SET_ERROR;
473
/* proceed either by one char in case of a "-" or by the
474
* width of the number field
482
/* fill out full range specification "n-m" according to findings */
486
if (min == -1) min = 0;
487
if (max == -1) max = sbvlen;
490
/* set processor vector as defined by range specification */
491
for(i=min; i<=max; i++)
492
*proc_vec |= (sbv_t) 1<<i;