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

[nptl] Re: NPTL Issue getrusage() / times



Hello, 

> > accordingly to SUSv3, getrusage() and times() should return the timing 
> > (user and system time) information for the *process*. That is the sum 
> > over all thread's time.
> > 
> > With NPTL, the timing is thread-wise only. That is, the timing is 
> > given only for the thread that calls getrusage(), resp. times(). 
> > This deviates from SUSv3.
> 
> According to this message:
> http://sources.redhat.com/ml/libc-alpha/2004-10/msg00013.html
> the glibc is claimed to return the usage for the process. So, if it
> appears that it is not the case, there surely is a bug!

Hmm... I must admit that I only tested with the default glibc provided in 
FC2, which is not necessarily a *branding new* one... 


> > I would definitively keep that neat feature of obtaining timing 
> > thread-wise, but not with the standard getrusage(), resp. times().
> 
> Yeah, the POSIX function have to conform to the POSIX spec; otherwise it
> makes no sense :)
> 
> > 
> > If you like, I can devise a test program proving my claim.
> 
> It would be great. If you have no time for this, please let me know,
> I'll try to figure out a way to check this. Anyway, at the moment, I
> don't really can imagine how to prove this... Can you give me some more
> information on a design for such a test?

You _can't_ prove that the computation is done correctly. But you _can_
prove when it is obviously wrong. For instance, if the main thread spent 300
ticks before starting a thread, then calling /times()/ in that thread should
returns something greater or equal to 300 ticks... 

In attachement, you'll find the corresponding test program. 

Cheers,
Loic. 

-- 
--
// Sender address goes to /dev/null (!!) 
// Use my 32/64 bits, ANSI C89, compliant email-address instead:   

unsigned y[]=
{0,34432,26811,16721,41866,63119,61007,48155,26147,10986};
void x(z){putchar(z);}; unsigned t; 
main(i){if(i<10){t=(y[i]*47560)%65521;x(t>>8);x(t&255);main(++i);}}

+++ GMX DSL Premiumtarife 3 Monate gratis* + WLAN-Router 0,- EUR* +++
Clevere DSL-Nutzer wechseln jetzt zu GMX: http://www.gmx.net/de/go/dsl
/*
 *----------------------------------------------------------------------------
 * Copyright (c) 2004, Loic Domaigne. All rights reserved.
 * Created by: Loic Domaigne.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2.5 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write the Free Software Foundation, Inc., 59
 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
 *
 *---------------------------------------------------------------------------
 *
 * This program tests that virtual times returns by time() is process-wise 
 * (that is, the sum of of timings over all threads). If the test succeed
 * it terminates returning 0, otherwise 1. 
 * 
 * #------------------------#
 * #  To compile            #
 * #------------------------#
 * $ gcc -W -Wall -pthread test_times.c -o test_times
 *
 * #------------------------#
 * #  To call the program:  #
 * #------------------------#
 * $ ./test_times 
 * 
 * #------------------------#
 * #  Program Tunings:      #
 * #------------------------#
 * You might tune:
 *
 *  o the number of ticks VTIME_THRESHOLD the process should spent in
 *    computation (in order to have a non-zero time). 
 *
 * Example:
 * $ gcc -W -Wall -pthread -DVTIME_THRESHOLD=50 test_times.c -o test_times
 */
#include <assert.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/times.h>

#ifndef _U_
#define _U_ __attribute__((unused))
#endif 


#ifndef VTIME_THRESHOLD
#define VTIME_THRESHOLD 300 
#endif 

#define CHUNK_SIZE 1000000
#define BAD_CLOCK ( (clock_t) -1 )

double        s=0.0;
unsigned long n=1;
unsigned long global_vt=0;


/*****************************************************************************
 * do_computation- perform computation in order to spent some time.   
 *****************************************************************************
 *
 * This function computes the sum_{i=1}^n 1/(n^2) until at least VT_THRESHOLD
 * time ticks has been elapsed. 
 *
 *****************************************************************************/
void
do_computation(void)
{
  struct tms    now;
  unsigned long count;
  
  do {
    for (count=0; count<CHUNK_SIZE; count++) {
      s += 1.0/((double)n*n);
      ++n; 
    }
    assert ( times (&now) != BAD_CLOCK );
    global_vt = now.tms_utime + now.tms_stime; 
  }
  while ( global_vt < VTIME_THRESHOLD);  
}


/*****************************************************************************
 * testThread- Check current virtual times.   
 *****************************************************************************
 *
 * This thread just call times() and check that the times elapsed 
 * (user + system) is greater or equal the times saved in global_vt.  
 *
 *****************************************************************************/
void*
myThread(void* unused _U_)
{
  struct tms    now;
  unsigned long my_vt; 
  int           success;

  assert ( times (&now) != BAD_CLOCK );
  my_vt   = now.tms_utime + now.tms_stime; 
  success = (my_vt >= global_vt);
  return (void*) success; 
}


/*###########################################################################*/
/*## MAIN PROCESS ENTRY POINT                                              ##*/
/*###########################################################################*/
int
main()
{
  int       status;
  int       success; 
  void*     retVal;
  pthread_t thrId;

  /*
   * spent about VTIME_THRESHOLD ticks in computation.
   */
  do_computation();
  
  /*
   * here, global_vt should have a value of about VTIME_THRESHOLD. 
   *
   * Create a thread which checks that times() is process-wide.
   * In other words,  times of that thread should be >= global_vt. 
   */
  status  = pthread_create (&thrId, NULL, myThread, NULL);
  assert (status==0);
  status  = pthread_join(thrId, &retVal);
  assert (status==0);

  /*
   * Test succeed or failed? 
   */
  success = (int) retVal; 
  printf ("Test: %s\n",
	  (success)? "PASS":"FAIL"
	  );
  return (success==0)? 1:0;
}