File: activeCpu.c

package info (click to toggle)
nws 2.11-3
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 2,700 kB
  • ctags: 2,820
  • sloc: ansic: 28,849; sh: 3,289; java: 1,205; makefile: 697; perl: 12
file content (99 lines) | stat: -rwxr-xr-x 2,775 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/* $Id: activeCpu.c,v 1.10 2003/01/29 05:31:39 graziano Exp $ */

#include "config_nws.h"
#include <stdlib.h>
#include <sys/types.h>    /* pid_t */
#include <sys/wait.h>     /* wait() */
#include <setjmp.h>       /* {long,set}jmp() */
#include <signal.h>       /* signal() */
#include <unistd.h>       /* nice() pipe() */
#include "diagnostic.h"   /* FAIL() */
#include "osutil.h"       /* SetRealTimer() */
#include "spinner.h"      /* spin() */
#include "activeCpu.h"


#define READ_END 0
#define WRITE_END 1
#define SPIN_TIMED_OUT 1


/* The process state, saved before the spinner invocation. */
static sigjmp_buf preSpin;


/* A SIGALRM handler that aborts the spinner call when invoked. */
static void
SpinTimeOut(int sig) {
  longjmp(preSpin, SPIN_TIMED_OUT);
}


int
ActiveCpuGetLoad(unsigned short niceValue,
                 unsigned int maxWait,
                 unsigned int testLength,
                 double *available) {

  int connection[2];
  pid_t childPid;
  unsigned long cpuTime;
  void (*oldHandler)(int);
  unsigned long wallTime;

  if (niceValue != 0) {

    /*
    ** Since we can't ever reduce our nice value, we have to run any niced
    ** spinner in a forked process.  We use a communication channel to report
    ** results from the forked process to the parent.
    */
    if(pipe(connection) != 0) {
      FAIL("ActiveCpuGetLoad: pipe() failed\n");
    }

    childPid = fork();

    if(childPid < 0) {
      FAIL("ActiveCpuGetLoad: fork() failed\n");
    }
    else if(childPid > 0) {
      /* Parent process. */
      close(connection[WRITE_END]);
      read(connection[READ_END], available, sizeof(*available));
      close(connection[READ_END]);
      wait(NULL);
      return(*available >= 0.0);
    }

    /* Child comes here. */
    close(connection[READ_END]);
    nice(niceValue);

  }

  /*
  ** Set an alarm and begin the spin process.  If the alarm goes off before the
  ** spin completes, setjmp() will return (via SpinTimeOut()) SPIN_TIMED_OUT
  ** and we report that no cpu is availble.  This is overly pessimistic; we
  ** should probably look at the rusage ourselves and report the actual amount
  ** of CPU we received.  Also, if we really get *no* CPU time, then we'll
  ** never be able to execute any of this code anyway.
  */
  oldHandler = signal(SIGALRM, SpinTimeOut);
  SetRealTimer(maxWait);
  *available = (setjmp(preSpin) == SPIN_TIMED_OUT) ? 0.0 :
               (spin(testLength, &cpuTime, &wallTime) && (wallTime > 0.0)) ?
               ((float)cpuTime / (float)wallTime) : -1.0;
  RESETREALTIMER;
  (void)signal(SIGALRM, oldHandler);

  if (niceValue != 0) {
    write(connection[WRITE_END], available, sizeof(*available));
    close(connection[WRITE_END]);
    exit(0);
  }

  return(*available >= 0.0);

}