Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Jul 2008 11:13:14 -0400
From:      "Michael B Allen" <ioplex@gmail.com>
To:        freebsd-hackers <freebsd-hackers@freebsd.org>
Subject:   Pls sanity check my semtimedop(2) implementation
Message-ID:  <78c6bd860807130813p4c28f930g1f3094241aa1f1b1@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
Hi,

Below is a semtimedop(2) implementation that I'm using for FreeBSD. I
was hoping someone could look it over and tell me if they think the
implementation is sound.

The code seems to work ok but when stressing the FreeBSD build of my app
I have managed to provoke errors related to concurrency (usually when a
SIGALRM goes off). The Linux build works flawlessesly so I'm wondering
about this one critical function that is different.

Is there any reason why I would want to use ITIMER_VIRTUAL /
SIGVTALRM instead of ITIMER_REAL / SIGALRM?

Or perhaps I should be using a different implementation entirely?

Mike

int
_semtimedop(int semid,
       struct sembuf *array,
       size_t nops,
       struct timespec *_timeout)
{
   struct timeval timeout, before, after;
   struct itimerval value, ovalue;
   struct sigaction sa, osa;
   int ret;

   if (_timeout) {
       timeout.tv_sec = _timeout->tv_sec;
       timeout.tv_usec = _timeout->tv_nsec / 1000;

       if (gettimeofday(&before, NULL) == -1) {
           return -1;
       }

       memset(&value, 0, sizeof value);
       value.it_value = timeout;

       memset(&sa, 0, sizeof sa);
       /* signal_print writes the signal info to a log file
        */
       sa.sa_sigaction = signal_print;
       sa.sa_flags = SA_SIGINFO;
       sigemptyset(&sa.sa_mask);
       sigaction(SIGALRM, &sa, &osa);

       if (setitimer(ITIMER_REAL, &value, &ovalue) == -1) {
           sigaction(SIGALRM, &osa, NULL);
           return -1;
       }
   }

   ret = semop(semid, array, nops);

   if (_timeout) {
       sigaction(SIGALRM, &osa, NULL);

       if (setitimer(ITIMER_REAL, &ovalue, NULL) == -1) {
           return -1;
       }
   }

   if (ret == -1) {
       if (_timeout) {
           struct timeval elapsed;

           if (gettimeofday(&after, NULL) == -1) {
               return -1;
           }

           _timeval_diff(&after, &before, &elapsed);

           if (timercmp(&elapsed, &timeout, >=))
               errno = EAGAIN;
       }

       return -1;
   }

   return 0;
}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?78c6bd860807130813p4c28f930g1f3094241aa1f1b1>