~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/daemons/shepherd/sge_pset.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*___INFO__MARK_BEGIN__*/
 
2
/*************************************************************************
 
3
 * 
 
4
 *  The Contents of this file are made available subject to the terms of
 
5
 *  the Sun Industry Standards Source License Version 1.2
 
6
 * 
 
7
 *  Sun Microsystems Inc., March, 2001
 
8
 * 
 
9
 * 
 
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
 
16
 * 
 
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.
 
23
 * 
 
24
 *   The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 
25
 * 
 
26
 *   Copyright: 2001 by Sun Microsystems, Inc.
 
27
 * 
 
28
 *   All Rights Reserved.
 
29
 * 
 
30
 ************************************************************************/
 
31
/*___INFO__MARK_END__*/
 
32
 
 
33
#include <sys/types.h>
 
34
#include <stdio.h>
 
35
#include <stdlib.h>
 
36
#include <string.h>
 
37
#include <errno.h>
 
38
 
 
39
#if defined(SOLARIS64) || defined(SOLARISAMD64)
 
40
#   include <sys/pset.h>
 
41
#elif defined(ALPHA)
 
42
#   include <sys/processor.h>
 
43
#elif defined(__sgi)
 
44
#   include <sys/sysmp.h>
 
45
#   include <sys/prctl.h>
 
46
#   include <sys/schedctl.h>
 
47
#endif
 
48
 
 
49
#include "sge_uidgid.h"
 
50
#include "sge_nprocs.h"
 
51
#include "sge_pset.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"
 
57
 
 
58
#define PROC_SET_OK            0
 
59
#define PROC_SET_WARNING       1
 
60
#define PROC_SET_ERROR        -1
 
61
#define PROC_SET_BUSY         -2
 
62
 
 
63
#if defined(__sgi)
 
64
#   define SGE_MPSET_MULTIPLIER   100
 
65
#endif
 
66
 
 
67
#if defined(ALPHA)
 
68
typedef long sbv_t;
 
69
#elif defined(__sgi)
 
70
/* 
 
71
 * declaration of sbv_t from sys/runq_private.h
 
72
 * including sys/runq_private.h lead to compile errors.
 
73
 */
 
74
typedef unsigned long long sbv_t;
 
75
#endif
 
76
 
 
77
#if defined(ALPHA)
 
78
#  if defined(ALPHA4)
 
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);
 
82
#  endif
 
83
int destroy_pset(int pset_id, int number);
 
84
int create_pset(void);
 
85
void print_pset_error(int ret);
 
86
#endif
 
87
 
 
88
#if defined(__sgi) || defined(ALPHA)
 
89
static int range2proc_vec(char *, sbv_t *, char *);
 
90
#endif
 
91
 
 
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);
 
95
#endif
 
96
 
 
97
void sge_pset_create_processor_set(void) 
 
98
{
 
99
#if defined(__sgi) || defined(ALPHA) || defined(SOLARIS64) || defined(SOLARISAMD64)
 
100
   char err_str[2*SGE_PATH_MAX+128];
 
101
 
 
102
   /* SGI IRIX processor set stuff */
 
103
   if (strcasecmp("UNDEFINED",get_conf_val("processors"))) {
 
104
      int ret;
 
105
 
 
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);
 
117
         }
 
118
      } else {
 
119
         sge_switch2admin_user();
 
120
      }
 
121
   }
 
122
#endif
 
123
}
 
124
 
 
125
void sge_pset_free_processor_set(void)
 
126
{
 
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];
 
131
      int ret;
 
132
 
 
133
      sge_switch2start_user();
 
134
      if ((ret=free_processor_set(err_str)) != PROC_SET_OK) {
 
135
         sge_switch2admin_user();
 
136
         switch (ret) {
 
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");
 
140
            break;
 
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);
 
145
            break;
 
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);
 
150
            break;
 
151
         default: /* should not occur */
 
152
            sprintf(err_str,
 
153
               "internal error after free_processor_set - ret=%d", ret);
 
154
            shepherd_state = SSTATE_PROCSET_NOTFREED;
 
155
            shepherd_error(1, err_str);
 
156
            break;
 
157
         }
 
158
      } else {
 
159
         sge_switch2admin_user();
 
160
      }
 
161
   }
 
162
#endif
 
163
}
 
164
 
 
165
#if defined(__sgi) || defined(ALPHA) || defined(SOLARIS64) || defined(SOLARISAMD64)
 
166
/****** shepherd/pset/set_processor_range() ***********************************
 
167
*  NAME
 
168
*     set_processor_range() -- sets processor range according to string 
 
169
*
 
170
*  SYNOPSIS
 
171
*     int set_processor_range(char *crange, 
 
172
*                             int proc_set_num, 
 
173
*                             char *err_str) 
 
174
*
 
175
*  FUNCTION
 
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.
 
179
*
 
180
*     Format:
 
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)
 
184
*
 
185
*  INPUTS
 
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.
 
197
*
 
198
*  RESULT
 
199
*     int - error state
 
200
*        PROC_SET_OK      - Ok
 
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) 
 
208
{
 
209
   int ret;
 
210
   FILE *fp;
 
211
#if defined(__sgi) || defined(ALPHA)
 
212
   sbv_t proc_vec;
 
213
#endif
 
214
 
 
215
#if defined(__sgi) || defined(ALPHA)
 
216
   if ((ret=range2proc_vec(crange, &proc_vec, err_str)))
 
217
      return ret;
 
218
#endif
 
219
 
 
220
#if defined(ALPHA)
 
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
 
226
    * queues 
 
227
    */
 
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;
 
233
      }
 
234
 
 
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;
 
239
      }
 
240
   } else {
 
241
      /* use default pset (id #0) */
 
242
      proc_set_num = 0;
 
243
   }
 
244
#elif defined(SOLARIS64) || defined(SOLARISAMD64)
 
245
   /*
 
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.
 
249
    */
 
250
   if (crange) {
 
251
      char *tok, *next;
 
252
 
 
253
      if ((tok=strtok(crange, " \t\n"))) {
 
254
         proc_set_num = (int) strtol(tok, &next, 10);
 
255
         if (next == tok) {
 
256
            sprintf(err_str, "wrong processor set id format: %20.20s", crange);
 
257
            shepherd_trace(err_str);
 
258
            return PROC_SET_ERROR;
 
259
         }
 
260
      } 
 
261
   }
 
262
#endif
 
263
 
 
264
   /* dump to file for later use */
 
265
   if ((fp = fopen("processor_set_number","w"))) {
 
266
      fprintf(fp,"%d\n",proc_set_num);
 
267
      FCLOSE(fp);
 
268
   } else {
 
269
      shepherd_trace("MPPS_CREATE: failed creating file processor_set_number");
 
270
      return PROC_SET_ERROR;
 
271
   }
 
272
 
 
273
#if defined(ALPHA)
 
274
   /* Now let's assign ourselves to the previously created processor set */
 
275
   if (proc_set_num) {
 
276
      pid_t pid_list[1];
 
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;
 
282
      }
 
283
   }
 
284
#elif defined(SOLARIS64) || defined(SOLARISAMD64)
 
285
   if (proc_set_num) {
 
286
      int local_ret;
 
287
 
 
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)) {
 
291
         switch (errno) {
 
292
         case EFAULT:
 
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;
 
296
            break;
 
297
         case EINVAL:
 
298
            shepherd_trace("pset_bind: invalid processor set was specified");
 
299
            local_ret = PROC_SET_ERROR;
 
300
            break;
 
301
         case EPERM:
 
302
            shepherd_trace("pset_bind: The effective user of the calling "
 
303
               "process is not super-user");
 
304
            local_ret = PROC_SET_ERROR;
 
305
            break;
 
306
         default:
 
307
            sprintf(err_str,"pset_bind: unexpected error - errno=%d", errno);
 
308
            shepherd_trace(err_str);
 
309
            local_ret = PROC_SET_ERROR;
 
310
            break;
 
311
         }
 
312
         return local_ret;
 
313
      }
 
314
   }
 
315
#endif
 
316
 
 
317
   return PROC_SET_OK;
 
318
FCLOSE_ERROR:
 
319
   shepherd_trace("MPPS_CREATE: failed creating file processor_set_number");
 
320
   return PROC_SET_ERROR;
 
321
}
 
322
 
 
323
/****** shepherd/pset/free_processor_set() ************************************
 
324
*  NAME
 
325
*     free_processor_set() -- Release the previously occupied proc set. 
 
326
*
 
327
*  SYNOPSIS
 
328
*     int free_processor_set(char *err_str) 
 
329
*
 
330
*  FUNCTION
 
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.
 
334
*
 
335
*  INPUTS
 
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 
 
339
*
 
340
*  RESULT
 
341
*     int - Error state
 
342
*        PROC_SET_OK      - Ok
 
343
*        PROC_SET_BUSY    - The processor set is still in use, i.e.
 
344
*                           processes originating from the job have not 
 
345
*                           finished.
 
346
*        PROC_SET_ERROR   - A critical error occurred. During execution
 
347
*                           of sysmp() calls.
 
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) 
 
352
{
 
353
   FILE *fp;
 
354
   int proc_set_num;
 
355
 
 
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);
 
360
   } else {
 
361
      shepherd_trace("MPPS_CREATE: failed reading from file processor_set_number");
 
362
      return PROC_SET_ERROR;
 
363
   }
 
364
 
 
365
#if defined(ALPHA)
 
366
   if (proc_set_num) {
 
367
      int ret;
 
368
      pid_t pid_list[1];
 
369
      pid_list[0] = getpid();
 
370
 
 
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;
 
376
      }
 
377
 
 
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;
 
382
      }
 
383
   }
 
384
#elif defined(SOLARIS64) || defined(SOLARISAMD64)
 
385
   /*
 
386
    * We do not release a processor set here
 
387
    * The system administrator is responsible to do this
 
388
    */
 
389
#endif
 
390
   return PROC_SET_OK;
 
391
}
 
392
 
 
393
#if defined(__sgi) || defined(ALPHA) 
 
394
/****** shepherd/pset/range2proc_vec() ****************************************
 
395
*  NAME
 
396
*     range2proc_vec() -- Computes bit vector (prcessor set spec.)
 
397
*
 
398
*  SYNOPSIS
 
399
*     static int range2proc_vec(char *crange, sbv_t *proc_vec, char *err_str) 
 
400
*
 
401
*  FUNCTION
 
402
*     Computes bit vector with bits set corresponding to string 
 
403
*     specification of processor range. 
 
404
*
 
405
*  INPUTS
 
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
 
412
*                       other bits zero. 
 
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. 
 
416
*
 
417
*  RESULT
 
418
*     static int - Error state
 
419
*        PROC_SET_OK    - Ok
 
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) 
 
423
{
 
424
   char *tok, *next, *p=crange;
 
425
   int min, max, i;
 
426
   int dash_used;
 
427
   int sbvlen;
 
428
 
 
429
   *proc_vec = (sbv_t) 0;
 
430
 
 
431
   /* compute max number of processors and thus significant length of
 
432
    * proc_vec
 
433
    */
 
434
   sbvlen = sge_nprocs() - 1; /* LSB corresponds to proc. 0 */
 
435
 
 
436
   /* loop trough range string with "," as token delimiter
 
437
    * Set processor vector for each token = range definition element.
 
438
    */
 
439
   while ((tok=strtok(p,","))) {
 
440
      if (p) p=NULL;
 
441
      
 
442
      /* for each token parse range, i.e. find
 
443
       * whether min or max value is set and whether a "-" sign
 
444
       * was used
 
445
       */
 
446
      min = -1;
 
447
      max = -1;
 
448
      dash_used = 0;
 
449
      while (*tok) {
 
450
         next = NULL;
 
451
         if (*tok == '-') {
 
452
            dash_used = 1;
 
453
            if (min == -1)
 
454
               min = 0;
 
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;
 
462
               }
 
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;
 
469
               }
 
470
            }
 
471
         }
 
472
 
 
473
         /* proceed either by one char in case of a "-" or by the
 
474
          * width of the number field
 
475
          */
 
476
         if (next)
 
477
            tok = next;
 
478
         else
 
479
            tok++;
 
480
      }
 
481
 
 
482
      /* fill out full range specification "n-m" according to findings */
 
483
      if (!dash_used )
 
484
         max = min;
 
485
      else {
 
486
         if (min == -1) min = 0;
 
487
         if (max == -1) max = sbvlen;
 
488
      }
 
489
 
 
490
      /* set processor vector as defined by range specification */
 
491
      for(i=min; i<=max; i++)
 
492
         *proc_vec |= (sbv_t) 1<<i;
 
493
   }
 
494
 
 
495
   return PROC_SET_OK;
 
496
}
 
497
 
 
498
#endif
 
499
 
 
500
#endif