(root)/
glibc-2.38/
sysdeps/
mach/
htl/
pt-timedblock.c
       1  /* Block a thread with a timeout.  Mach version.
       2     Copyright (C) 2000-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library;  if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <assert.h>
      20  #include <errno.h>
      21  #include <time.h>
      22  #include <sys/time.h>
      23  
      24  #include <mach.h>
      25  #include <mach/message.h>
      26  
      27  #include <pt-internal.h>
      28  
      29  #ifndef MSG_OPTIONS
      30  # define MSG_OPTIONS 0
      31  #endif
      32  
      33  /* Block THREAD.  */
      34  error_t
      35  __pthread_timedblock (struct __pthread *thread,
      36  		      const struct timespec *abstime, clockid_t clock_id)
      37  {
      38    error_t err;
      39    mach_msg_header_t msg;
      40    mach_msg_timeout_t timeout;
      41    struct timespec now;
      42  
      43    /* We have an absolute time and now we have to convert it to a
      44       relative time.  Arg.  */
      45  
      46    err = __clock_gettime (clock_id, &now);
      47    assert (!err);
      48  
      49    if (now.tv_sec > abstime->tv_sec
      50        || (now.tv_sec == abstime->tv_sec && now.tv_nsec > abstime->tv_nsec))
      51      return ETIMEDOUT;
      52  
      53    timeout = (abstime->tv_sec - now.tv_sec) * 1000;
      54  
      55    if (abstime->tv_nsec >= now.tv_nsec)
      56      timeout += (abstime->tv_nsec - now.tv_nsec + 999999) / 1000000;
      57    else
      58      /* Need to do a carry.  */
      59      timeout -= (now.tv_nsec - abstime->tv_nsec + 999999) / 1000000;
      60  
      61    err = __mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT | MSG_OPTIONS, 0,
      62  		    sizeof msg, thread->wakeupmsg.msgh_remote_port,
      63  		    timeout, MACH_PORT_NULL);
      64    if (err == EMACH_RCV_TIMED_OUT)
      65      return ETIMEDOUT;
      66    if ((MSG_OPTIONS & MACH_RCV_INTERRUPT) && err == MACH_RCV_INTERRUPTED)
      67      return EINTR;
      68  
      69    assert_perror (err);
      70    return 0;
      71  }