All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bugspray Bot <bugbot@kernel.org>
To: tglx@linutronix.de, bugs@lists.linux.dev, frederic@kernel.org,
	 anna-maria@linutronix.de, linux-kernel@vger.kernel.org
Subject: setitimer works incorrectly
Date: Fri, 13 Sep 2024 22:00:10 +0000	[thread overview]
Message-ID: <20240913-b217598c0-81d4abf24530@bugzilla.kernel.org> (raw)

vladimir.mezentsev writes via Kernel.org Bugzilla:

A small test below shows the problem with the itimer setting on OL8 (x86_64 / aarch64)

% cat sig.c
#include<stdio.h>
#include <stdlib.h>
#include<signal.h>
#include <time.h>
#include <sys/time.h>
#include <string.h>

#ifndef MY_TIMER
#define MY_TIMER 1000
#endif

static time_t start;
static int sigprof_cnt = 0;

time_t
gethrtime (void)
{
  struct timespec tp;
  time_t rc = 0;
  int r = clock_gettime (CLOCK_MONOTONIC, &tp);
  if (r == 0)
    rc = ((time_t) tp.tv_sec) * 1e9 + (time_t) tp.tv_nsec;
  return rc;
}

static void sigprof_handler(int signo, siginfo_t* info, void *context)
{
  if (++sigprof_cnt >= 3)
    exit(0);
  static struct itimerval t;
  memset(&t, 0, sizeof(t));
  if (getitimer(ITIMER_PROF, &t) != 0)
    printf("getitimer failed\n");
  printf("sigprof_handler: it_interval.tv_sec=%lld it_interval.tv_usec=%lld\n"
         "                    it_value.tv_sec=%lld it_value.tv_usec=%lld\n",
    (long long) t.it_interval.tv_sec, (long long) t.it_interval.tv_usec,
    (long long) t.it_value.tv_sec, (long long) t.it_value.tv_usec);
}

volatile long x; /* temp variable for long calculation */

int
main (int argc, char **argv)
{
  long long count = 0;
  start = gethrtime ();

  struct sigaction sa;
  memset(&sa, 0, sizeof(struct sigaction));
  sa.sa_sigaction = sigprof_handler;
  sa.sa_flags = SA_RESTART | SA_SIGINFO;
  sigemptyset(&sa.sa_mask);

  if (sigaction(SIGPROF, &sa, NULL) == -1)
    {
       perror("sigaction");
       return 1;
    }

  static struct itimerval timer;
  memset(&timer, 0, sizeof(timer));
  timer.it_interval.tv_usec = MY_TIMER;
  timer.it_value.tv_usec = MY_TIMER;
  if (setitimer(ITIMER_PROF, &timer, NULL) != 0)
    {
      printf("Timer could not be initialized \n");
      return 1;
    }

  struct itimerval t;
  memset(&t, 0, sizeof(t));
  if (getitimer(ITIMER_PROF, &t) != 0)
    {
      printf("getitimer failed\n");
      return 1;
    }
  printf("After setitimer: it_interval.tv_sec=%lld it_interval.tv_usec=%lld\n"
         "                    it_value.tv_sec=%lld it_value.tv_usec=%lld\n",
    (long long) t.it_interval.tv_sec, (long long) t.it_interval.tv_usec,
    (long long) t.it_value.tv_sec, (long long) t.it_value.tv_usec);

  do
    {
      x = 0;
      for (int j = 0; j < 1000000; j++)
        x = x + 1;
      count++;
    }
  while (start + 1e9 / 4 > gethrtime ());
  printf("count=%lld  x=%lld\n", count, x);
  return 0;
}



It is from man page:
% man setitimer
...
   setitimer()
       If either field in new_value.it_value is nonzero, then the timer is arme to initially expire at the specified time.


But this is not right on x86_64 and aarch64. I run this test on OL8.

On x86_64 / OL8:
% gcc -DMY_TIMER=1000 sig.c; ./a.out
After setitimer: it_interval.tv_sec=0   it_interval.tv_usec=1000
                    it_value.tv_sec=0      it_value.tv_usec=2000 <<<<<< this should be <= 1000 because I set it_value.tv_usec to 1000 in setitimer

sigprof_handler: it_interval.tv_sec=0   it_interval.tv_usec=1000
                    it_value.tv_sec=0      it_value.tv_usec=23
sigprof_handler: it_interval.tv_sec=0   it_interval.tv_usec=1000
                    it_value.tv_sec=0      it_value.tv_usec=27



On aarch64 / OL8:

% gcc -DMY_TIMER=1000 sig.c; ./a.out
After setitimer: it_interval.tv_sec=0   it_interval.tv_usec=1000
                    it_value.tv_sec=0 it_value.tv_usec=5000    <<<<<< Same as on x86_64

sigprof_handler: it_interval.tv_sec=0   it_interval.tv_usec=1000
                    it_value.tv_sec=0 it_value.tv_usec=4000 <<<<<< this must be <= 1000 because it_interval.tv_usec is 1000

sigprof_handler: it_interval.tv_sec=0   it_interval.tv_usec=1000
                    it_value.tv_sec=0      it_value.tv_usec=4000<<<<<< this must be <= 1000 because it_interval.tv_usec is 1000

View: https://bugzilla.kernel.org/show_bug.cgi?id=217598#c0
You can reply to this message to join the discussion.
-- 
Deet-doot-dot, I am a bot.
Kernel.org Bugzilla (bugspray 0.1-dev)


             reply	other threads:[~2024-09-13 22:00 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-13 22:00 Bugspray Bot [this message]
2024-09-13 22:00 ` setitimer works incorrectly Bugspray Bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240913-b217598c0-81d4abf24530@bugzilla.kernel.org \
    --to=bugbot@kernel.org \
    --cc=anna-maria@linutronix.de \
    --cc=bugs@lists.linux.dev \
    --cc=frederic@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.