[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: patch for wanna-build (sysinfo/getloadavg)



Robert Millan <zeratul2@wanadoo.es> writes:

> On Thu, Jul 24, 2003 at 12:14:57AM +0100, Roger Leigh wrote:
>> Robert Millan <zeratul2@wanadoo.es> writes:
>> 
>> > Some days ago I posted this small patch for building wanna-build on
>> > GNU, and asked for revision, but didn't get any response.
>> >
>> > It attempts to replace the linux-specific sysinfo() with getloadavg(),
>> > but there's a type conversion issue and i'd like to make sure i did it
>> > correctly, please could anyone verify this:
>> >
>> > --- wanna-build.old/buildd-mail-wrapper.c	1999-07-21 14:53:22.000000000 +0200
>> > +++ wanna-build/buildd-mail-wrapper.c	2003-07-15 21:06:59.000000000 +0200
>> [...]
>> 
>> This seems rather complex!  Why not just do something like:
>>                 waittime = (long) (loadavg[0] / 16384) * 6 + 20;
>> 
>> If you don't need SI_LOAD_SHIFT (Linux-specific??), it can probably be
>> even simpler.
>
> Can I cast a double to long like that? What kind of truncating happens if
> loadavg[0] is bigger than LONG_MAX? Does a division with 2^14 garantee it
> will fit nicely?

I've written a simple test program.  It seems any cast from
double->long will set LONG_MIN/LONG_MAX if it would result in an
double->overflow.  Thus,

+		if (loadavg[0] > LONG_MAX)
+			load = LONG_MAX;
+		else
+			load = (long) loadavg[0];

can be replaced with

load = (long) loadavg[0].

This was tested on Debian unstable (Linux 2.4.21 with glibc 2.3.1).
For some reason, I only ever got LONG_MIN to be returned, even when
the overflow was positive!  I'm not sure if this is a problem with my
code, or a glibc bug, or whatever.

Here's the test program.  You'll need to link with -lreadline.

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>

#include <readline/readline.h>

int main(void)
{
  char *input = NULL;
  double big;
  long fixed;

  while(1)
    {
      if (input)
	{
	  free(input);
	  input = NULL;
	}
      input = readline("Enter a number: ");

      big = strtod(input, NULL);

      if (errno == ERANGE)
	{
	  fprintf(stderr, "Number is out of range: ");
	  if (big == 0)
	    fprintf(stderr, "FP underflow\n");
	  else
	    fprintf(stderr, "FP overflow\n");
	  continue;
	}

      printf("double: %g\n", big);

      fixed = (long) big;

      if (fixed == LONG_MIN || fixed == LONG_MAX)
	{
	  fprintf(stderr, "Number is out of range for type \"long\": ");
	  if (fixed == LONG_MIN)
	    fprintf(stderr, "LONG_MIN");
	  else
	    fprintf(stderr, "LONG_MAX");
	  fprintf(stderr, ": %ld\n", fixed);
	  continue;
	}

      printf("long: %ld\n", fixed);
    }

  return 0;
}


-- 
Roger Leigh

                Printing on GNU/Linux?  http://gimp-print.sourceforge.net/
                GPG Public Key: 0x25BFB848 available on public keyservers



Reply to: