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

Bug#435546: gcc-4.1: Wrong loop code generation using O2



Package: gcc-4.1
Version: 4.1.2-13
Severity: important

void do_pin_processes(int pids[], int n, char pin)
{
  int i;
  for (i = 0; i < n; i++) {
    printf("%d\n", i);
    do_pin_process(pids[i], pin);
  }
}

When I compile the attached program with the following flags the
compiler generates a infinite loop in the function do_pin_processes (the
i variable is not incremented):

gcc -DHAVE_CONFIG_H -I. -I.. -I../include   -pg -g -g -O2 -MT pin-main.o
-MD -MP -MF .deps/pin-main.Tpo -c -o pin-main.o `test -f 'main.c' ||
echo
'./'`main.c
mv -f .deps/pin-main.Tpo .deps/pin-main.Po
gcc -DHAVE_CONFIG_H -I. -I.. -I../include   -pg -g -g -O2 -MT pin-pin.o
-MD -MP -MF .deps/pin-pin.Tpo -c -o pin-pin.o `test -f 'pin.c' || echo
'./'`pin.c
mv -f .deps/pin-pin.Tpo .deps/pin-pin.Po
gcc -DHAVE_CONFIG_H -I. -I.. -I../include   -pg -g -g -O2 -MT
pin-error.o -MD -MP -MF .deps/pin-error.Tpo -c -o pin-error.o `test -f
'error.c' || echo
'./'`error.c
mv -f .deps/pin-error.Tpo .deps/pin-error.Po
gcc -pg -g -g -O2 -pg -g  -o pin pin-main.o pin-pin.o pin-error.o -lpopt

However if I export the CFLAGS variable with -O0 it works properly.

The arguments passed to the program and the obtained outputs are:

(cmd line) $ ./pin -l "1 2 3"

(output bad code) $ Pinning 1 (0): done
0
Pinning 1 (0): done
0
Pinning 1 (0): done
0
Pinning 1 (0): done
0
Pinning 1 (0): done
...

(output correct code) $ 0
Pinning 1 (0): done
1
Pinning 2 (0): failed
Permission denied
2
Pinning 3 (0): failed
Permission denied


I have the same problem if I use gcc-4.2.

Thanks,

Javi
#include <stdio.h>
#include <errno.h>

FILE * error_file;
char err_debug_mode;

__attribute__((constructor)) static void init_error()
{
  error_file = stderr;
  err_debug_mode = 0;
}

__attribute__((destructor)) static void fini_error()
{
  if (error_file != stderr)
    fclose(error_file);
}

int err_set_output_path(char * path)
{
  int ret = 0;

  if (error_file != stderr)
    fclose(error_file);

  error_file = fopen(path, "a+");

  if (!error_file) {
    error_file = stderr;
    ret = errno;
  }

  return ret;
}

int err_set_output_file(FILE * f)
{
  int ret = 0;

  if (error_file != stderr)
    fclose(error_file);

  error_file = f;

  if (!error_file) {
    error_file = stderr;
    ret = errno;
  }

  return ret;
}
/* 
   pin - pin and unpin processes in memory

   Copyright (C) 2007 Javier Cabezas Rodriguez

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  

*/

#include <stdio.h>
#include <sys/types.h>
#include <popt.h>
#include "system.h"
#include "pin.h"
#include "error.h"

#define EXIT_FAILURE 1

/* The name the program was run with, stripped of any leading path. */
char * program_name;

typedef struct {
  char unpin;
  char all;
  char * pids;
} t_cmd_args;

t_cmd_args program_args;

/* Option flags and variables */
static const struct poptOption program_options[] = {
  {"unpin", 'u', POPT_ARG_NONE, 0, 'u', "unpin the listed process/es"},
  {"all", 'a', POPT_ARG_NONE, 0, 'a', "pin/unpin all the processes"},
  {"list", 'l', POPT_ARG_STRING, &program_args.pids, 0, "pin/unpin the processes listed next", "PIDS"},
  POPT_AUTOALIAS
  POPT_AUTOHELP
  POPT_TABLEEND
};

static int parse_args(int argc, char ** argv);

static int get_pids(int ** pids)
{
  int i;
  char error[64];
  char * copy;
  char * str_pid;
  char * end_pid;
  int pid, n = 0;

  copy = strdup(program_args.pids);

  str_pid = strtok(program_args.pids, " \f\n\r\t\v");

  if (!program_args.pids)
    return 0;

  while (str_pid) {
    pid = strtol(str_pid, &end_pid, 10);

    str_pid = strtok(NULL, " \f\n\r\t\v");
    
    if (pid)
      n++;
  }

  *pids = (int *) malloc(n * sizeof(int));
  str_pid = strtok(copy, " \f\n\r\t\v");

  i = 0;
   
  while (str_pid) {
    pid = strtol(str_pid, &end_pid, 10);

    if (!pid) {
      sprintf(error, "Error: %d is not a valid PID", pid);
      ERROR(error);
      str_pid = strtok(NULL, " \f\n\r\t\v");
      continue;
    }

    (*pids)[i] = pid;
    
    str_pid = strtok(NULL, " \f\n\r\t\v");
    i++; 
  }

  free(copy);
  return n;
}

int main(int argc, char * argv[])
{
  int i;

  program_name = argv[0];

  i = parse_args(argc, argv);

  /* do the work */
  if (program_args.all) {
    do_pin_all(!program_args.unpin);
  } else {
    int *pids;
    int n = get_pids(&pids);
    do_pin_processes(pids, n, !program_args.unpin);
    free(pids);
  }

  if (program_args.pids)
    free(program_args.pids);

  return 0;
}

static int parse_args(int argc, char ** argv)
{
  int option;

  poptContext context = poptGetContext(
      NULL,
      argc,
      (const char **) argv,
      program_options,
      0);

  if (argc < 2) {
    poptPrintUsage(context, error_file, 0);
    poptFreeContext(context);
    exit(1);
  }

  while ((option = poptGetNextOpt(context)) >= 0) {
    switch (option) {
      case 'u':
        program_args.unpin = 1;
        break;
      case 'a':
        program_args.all = 1;
        break;
      default:
        poptPrintUsage(context, error_file, 0);
        exit(1);
    }
  } 

  if (program_args.all && program_args.pids) {
    ERROR("Error: -l and -a flags are incompatible\n");
    poptPrintUsage(context, error_file, 0);
    exit(1);
  }

  poptFreeContext(context);
}
/* 
   pin - pin and unpin processes in memory

   Copyright (C) 2007 Javier Cabezas Rodriguez

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  

*/

#include <stdio.h>
#include "error.h"

static inline char is_pinned(int pid)
{
  char path[32];
  char error[64];

  char pinned;
  char read;

  sprintf(path, "/proc/%d/pinned", pid);
  FILE * f = fopen(path, "r");

  if (!f) {
    printf("failed\n");
    STDERROR();
    return;
  }

  read = fscanf(f, "%d", &pinned);
  if (!read || read == EOF) {
    printf("failed\n");
    sprintf(error, "Error reading from %s", path);
    ERROR(error);
    fclose(f);
    return;
  }

  if (fclose(f) == EOF) {
    printf("failed\n");
    STDERROR();
    return;
  }
}

static void do_pin(int pid)
{
  char path[32];
  char error[64];

  printf("Pinning %d (%d): ", pid, is_pinned(pid));

  sprintf(path, "/proc/%d/pinned", pid);
  FILE * f = fopen(path, "a");

  if (!f) {
    printf("failed\n");
    STDERROR();
    return;
  }

  if (fprintf(f, "1") <= 0) {
    printf("failed\n");
    sprintf(error, "Error writing to %s", path);
    ERROR(error);
    fclose(f);
    return;
  }

  if (fclose(f) == EOF) {
    printf("failed\n");
    STDERROR();
    return;
  }

  printf("done\n");
}

static void do_unpin(int pid)
{
  char path[32];
  char error[64];

  printf("Unpinning %d (%d): ", pid, is_pinned(pid));

  sprintf(path, "/proc/%d/pinned", pid);
  FILE * f = fopen(path, "a");

  if (!f) {
    printf("failed\n");
    STDERROR();
    return;
  }

  if (fprintf(f, "0") <= 0) {
    printf("failed\n");
    sprintf(error, "Error writing to %s", path);
    ERROR(error);
    fclose(f);
    return;
  }

  if (fclose(f) == EOF) {
    printf("failed\n");
    STDERROR();
    return;
  }

  printf("done\n");
}

void do_pin_process(int pid, char pin)
{
  if (pin)
    do_pin(pid);
  else
    do_unpin(pid);
}

void do_pin_processes(int pids[], int n, char pin)
{
  int i;
  for (i = 0; i < n; i++) {
    printf("%d\n", i);
    do_pin_process(pids[i], pin);
  }
}

void do_pin_all(char pin)
{
}

Attachment: signature.asc
Description: Esta parte del mensaje =?ISO-8859-1?Q?est=E1?= firmada digitalmente


Reply to: