continua (next page) Index of UNOFFICIAL Circumvesuviana Home Page Linux pages main index

What to do if the fan is broken and you have to render a radiose POVray image? Have a look at the program below: given a process-id, checks the ACPI processor temperature every three seconds, and stops the process when the temperature is high (that is, near to starting the fan) and restarts it when the temperature is sufficiently low.
More info in the News section of my Asus notebook and Linux page!
Ecco, lo sapevo: cosa si fa quando la ventola del processore del notebook fa una CACIARA della miseria e volete renderizzare una radiosa immagine col POVray?

L'ideale sarebbe un programmino che controlla continuamente la temperatura del processore (diciamo ogni tre secondi): quando la temperatura diventa troppo alta (diciamo tre gradi prima dell'accensione automatica della ventola, cioè a 72ºC) allora ferma temporaneamente il processo indicato aspettando che la temperatura scenda in misura sufficiente (almeno 14-15 gradi, visto che appena si riavvia il processo, talvolta c'è un "balzo" anche di dieci-dodici gradi in su).

Bene: il programmino ideale è qui sotto (sono umile e me ne vanto!). L'ho usato per il rendering di immagini complesse sia di notte che di giorno, con l'ACPI di Linux 2.4.19; col freddo di ottobre ottenevo un uso totale della CPU (e senza avviare la ventola) compreso tra il quindici e il sessanta per cento del tempo di funzionamento (quest'ultimo caso è quando mettevo il notebook sul davanzale, il cui freddissimo marmo e lo spiffero ghiacciato contribuivano egregiamente al raffreddamento. Quasi quasi progetto un radiatore con raffreddamento ad acqua e liquido antigelo...).

Esempio d'uso: lancio POVray e col comando ps vedo il suo process-id (per esempio 3387) e poi lancio il programmino qui sotto (per esempio con "semifreddo 3387"): quando termina il povray, terminerà anche semifreddo.


/*
//      semifreddo.c
//      2002-10-04
//      http://www.alfonsomartone.itb.it -- under GNU GPL license
//
//      lets a cpu-hungry program run only when temperature is low
//      (veeeeeeery good if your cpu fan is broken...!)
*/

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/times.h>

int pid=0,                       // process id in analysis
    t,                           // program start time (in jiffies())
    lastt,                       // begin of the last hot/cold time section
    lasttemp,                    // last temperature found by gettemp()

    hot=0, cold=0,               // time jiffies used in "hot" and "cold" mode

    maxtemp=72,                  // "too hot" temperature
    runtemp=58;                  // "sufficiently cold" temperature


#define error(fmt...) { fprintf(stderr,"\n"); fprintf(stderr,fmt); \
                        fprintf(stderr,"\n\n"); exit(1); }

#define jiffies() times(NULL)

int gettemp()                    // get CPU temperature from ACPI
{
  int temp=0;
  char buf[200];
  FILE *fp=fopen("/proc/acpi/thermal/0/status", "r");

  if(fp==NULL)
    error("cannot get ACPI temperature status");

  if(fscanf(fp, "%s %d", buf, &temp)!=2)
    error("cannot read ACPI temperature status");

  fclose(fp);
  lasttemp=(temp-2732)/10;       // convert deciKelvin to Celsius
  return lasttemp;
}


int unaccessible()               // check if process still exists
{
  FILE *fp;
  char buf[100];
  sprintf(buf, "/proc/%d/stat", pid);
  fp=fopen(buf, "r");
  if(!fp) return 1;
  fclose(fp);
  return 0;
}


void output(char *s)
{
  int n=jiffies()-t;
  if(!n) n++;
  printf("\n%8ld.%02d  t=%-3d  %s", n/100, n%100, lasttemp, s);
  fflush(stdout);
}


void refriger()
{
  if(unaccessible())             // die when hot process ends
  {
    char buf[400];
    int z=jiffies()-t; if(z<100) z=100;

    sprintf(buf, "the end: hot=%d.%02ds, cold=%d.%02ds (%d%% of %ds)\n\n",
      hot/100, hot%100, cold/100, cold%100, hot/(z/100), (z+50)/100);

    output(buf);
    exit(0);
  }

  sleep(3);                      // wait three seconds before updating...
}


int main(int argc, char **argv)
{
  int j;

  if(argc!=2)
    error("usage: %s pid\n(maxtemp=%d, runtemp=%d)",
      argv[0], maxtemp, runtemp);

  if(sscanf(argv[1], "%d", &pid)!=1)
    error("invalid pid (%s)", argv[1]);

  if(unaccessible())
    error("pid %d does not exist", pid);

  t=lastt=jiffies();
  gettemp();
  output("starting");

  for(;;)
  {
    if(gettemp()<maxtemp)
    {
      output("running");
      refriger();
      continue;
    }

    j = jiffies();
    hot += j-lastt;
    lastt = j;
    output("too hot: stopping");
    if(kill(pid, SIGSTOP)) perror("sending SIGSTOP");

    while(gettemp()>runtemp) { output("waiting"); refriger(); }

    j = jiffies();
    cold += j-lastt;
    lastt = j;
    output("end of hot section: restarting");
    if(kill(pid, SIGCONT)) perror("sending SIGCONT");
  }
}

// ---


Scorcio di Monte Faito (ai piedi della penisola sorrentina)

send e-mail - continua (next page)