2

Taking a course in Operating systems and are new to this (and C), I dont really understand a fact stated in my studying material. The program is suppose to pause execution until a kill-command is issued (ctr+c or kill from the terminal) From the beginning the line was:

while (!done);

but it was suggested to change this:

"Using a while loop to repeatedly check the global variable done is not a very efficient use of the CPU. A better way is to change the loop to:

while (pause()) {
  if (done) break;
};

"

What does the system do during pause()? If it have to check a global variable every loop can it really do something useful? I'm thinking that pause() probably allow the CPU to pick up other work, but doesn't the checking of the variable ruin that?

The complete code is this if it helps:

#include <stdio.h>   // puts(), printf()
#include <signal.h>  // SIGFPE, SIGSEGV, SIGINT
#include <stdlib.h>  // exit(), EXIT_SUCCESS, EXIT_FAIURE
#include <unistd.h>  // getpid(), pause()
#include <stdbool.h> // true, false

sig_atomic_t volatile done = false;

int divide_by_zero() {
  int a = 1;
  int b = 0;
  return a / b;
}

void segfault() {
  int *ptr = NULL;
  *ptr = 42;
}

void signal_handler(int s) {
  switch(s) {
    case SIGFPE:
      fputs("Caught SIGFPE: arithmetic exception, such as division by zero.\n", stderr);
      exit(EXIT_FAILURE);
    case SIGSEGV:
      fputs("Caught SIGSEGV: segfault.\n", stderr);
      exit(EXIT_FAILURE);
      break;
    case SIGINT:
      done = true;
      fputs("Caught SIGINT: interactive attention signal, probably a ctrl+c.\n", stderr);
      break;
    case SIGUSR1:
      puts("Hello!");
      break;
  }
}

int main(void) {

  printf("My PID = %ld\n", (long) getpid());

  // Install signal handlers.
  signal(SIGSEGV, signal_handler);
  signal(SIGFPE,  signal_handler);
  signal(SIGINT, signal_handler);
  signal(SIGUSR1, signal_handler);

  //divide_by_zero();
  //segfault();

  // Wait until a signal is delivered.

  while(pause()) {
      if(done) break;
  };

  puts("I'm done!");

  exit(EXIT_SUCCESS);
}
Meltdown
  • 99
  • 4
  • 3
    Have you read [the documentation for `pause()`](http://man7.org/linux/man-pages/man2/pause.2.html)? Assuming you mean the POSIX-defined function of that name, it causes the calling thread to *sleep* until a signal is delivered to the process. Unlike a busy-waiting loop, sleeping does not consume CPU -- that's pretty much its definition. – John Bollinger Feb 07 '18 at 17:50
  • 2
    No, the checking of variable doesn't ruin that. Infact the pause() in while loop checks for whether the process has not experienced any kind of sleep and if the process is done the condition of if breaks. – HarshitMadhav Feb 07 '18 at 17:55
  • It would be useful to see exactly WHAT your materials said. pause () might be an efficient alternative in some situations but it might be less efficient in others. – user3344003 Feb 08 '18 at 03:23
  • I Think that I get it, the pause() will ofc "sleep" until it is interrupted and after that interrupt is handled it does the check if done. The variable is not checked when the program is paused and therefore the pause is still efficiant. – Meltdown Feb 08 '18 at 12:12

1 Answers1

7

why pause() is efficient ? Because pause() will block the execution of current process while has not received any signal and by doing so that process will moved to suspend state and while this process is in suspend state, at the same time CPU can execute some other processes and by doing this CPU utilized efficiently.

From the Linux manual page of pause(2)

pause() causes the calling process (or thread) to sleep until a signal is delivered that either terminates the process or causes the invocation of a signal-catching function.

The POSIX pause(3p) man page says basically the same thing.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Achal
  • 11,821
  • 2
  • 15
  • 37
  • "in the same time CPU can execute some other processes" or, if there's nothing to do, it can be throttled down and in general be put in lower power modes. That's particularly important if you want your phone or laptop last when running on battery. – Matteo Italia Feb 07 '18 at 17:58
  • @HarshitAgrawal let say there is a `while(!done)` in sub thread and if it doesn't uses any `pause()` and keep on checking the variable, in that case what if `main thread` has `stopped` but that `sub thread` is still `running` ? same scenario can be avoided if pause() used instead of `while(!done)` – Achal Feb 07 '18 at 18:26
  • @HarshitAgrawal Also using only `while(!done)` consumes more CPU than `while(pause())` – Achal Feb 07 '18 at 18:32
  • @achal thank you. I understood the concept very well. Great explanation from your side. I appreciate it. I upvoted the answer :) – HarshitMadhav Feb 07 '18 at 18:50
  • Worth mentioning, context switch does waste some CPU cycles if signal is assured to be raised in less than 2*Context_Switch_time. – Tony Tannous Feb 07 '18 at 22:34