示例#1
0
/* Sleep USECONDS microseconds, or until a previously set timer goes off.  */
int
usleep (useconds_t useconds)
{
  mach_port_t recv;
  struct timeval before, after;

  recv = __mach_reply_port ();

  if (__gettimeofday (&before, NULL) < 0)
    return -1;
  (void) __mach_msg (NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT,
		     0, 0, recv, (useconds + 999) / 1000, MACH_PORT_NULL);
  __mach_port_destroy (mach_task_self (), recv);
  if (__gettimeofday (&after, NULL) < 0)
    return -1;

  return 0;
}
示例#2
0
int
__libc_nanosleep (const struct timespec *requested_time,
	     struct timespec *remaining)
{
  mach_port_t recv;
  struct timeval before, after;

  if (requested_time->tv_sec < 0
      || requested_time->tv_nsec < 0
      || requested_time->tv_nsec >= 1000000000)
    {
      errno = EINVAL;
      return -1;
    }

  const mach_msg_timeout_t ms
    = requested_time->tv_sec * 1000
    + (requested_time->tv_nsec + 999999) / 1000000;

  recv = __mach_reply_port ();

  if (remaining && __gettimeofday (&before, NULL) < 0)
    return -1;
  error_t err = __mach_msg (NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT,
			    0, 0, recv, ms, MACH_PORT_NULL);
  __mach_port_destroy (mach_task_self (), recv);
  if (err == EMACH_RCV_INTERRUPTED)
    {
      if (remaining && __gettimeofday (&after, NULL) >= 0)
	{
	  struct timeval req_time, elapsed, rem;
	  TIMESPEC_TO_TIMEVAL (&req_time, requested_time);
	  timersub (&after, &before, &elapsed);
	  timersub (&req_time, &elapsed, &rem);
	  TIMEVAL_TO_TIMESPEC (&rem, remaining);
	}

      errno = EINTR;
      return -1;
    }

  return 0;
}
示例#3
0
error_t
__hurd_file_name_lookup_retry (error_t (*use_init_port)
				 (int which, error_t (*operate) (file_t)),
			       file_t (*get_dtable_port) (int fd),
			       error_t (*lookup)
				 (file_t dir, char *name,
				  int flags, mode_t mode,
				  retry_type *do_retry, string_t retry_name,
				  mach_port_t *result),
			       enum retry_type doretry,
			       char retryname[1024],
			       int flags, mode_t mode,
			       file_t *result)
{
  error_t err;
  char *file_name;
  int nloops;

  error_t lookup_op (file_t startdir)
    {
      while (file_name[0] == '/')
	file_name++;

      return lookup_error ((*lookup) (startdir, file_name, flags, mode,
				      &doretry, retryname, result));
    }
  error_t reauthenticate (file_t unauth)
    {
      error_t err;
      mach_port_t ref = __mach_reply_port ();
      error_t reauth (auth_t auth)
	{
	  return __auth_user_authenticate (auth, ref,
					   MACH_MSG_TYPE_MAKE_SEND,
					   result);
	}
      err = __io_reauthenticate (unauth, ref, MACH_MSG_TYPE_MAKE_SEND);
      if (! err)
	err = (*use_init_port) (INIT_PORT_AUTH, &reauth);
      __mach_port_destroy (__mach_task_self (), ref);
      __mach_port_deallocate (__mach_task_self (), unauth);
      return err;
    }
示例#4
0
void
_hurdsig_longjmp_from_handler (void *data, jmp_buf env, int val)
{
  struct sigcontext *scp = data;
  struct hurd_sigstate *ss = _hurd_self_sigstate ();
  int onstack;
  inline void cleanup (void)
    {
      /* Destroy the MiG reply port used by the signal handler, and restore
	 the reply port in use by the thread when interrupted.  */
      mach_port_t *reply_port =
	(mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY);
      if (*reply_port)
	{
	  mach_port_t port = *reply_port;
	  /* Assigning MACH_PORT_DEAD here tells libc's mig_get_reply_port
	     not to get another reply port, but avoids mig_dealloc_reply_port
	     trying to deallocate it after the receive fails (which it will,
	     because the reply port will be bogus, regardless).  */
	  *reply_port = MACH_PORT_DEAD;
	  __mach_port_destroy (__mach_task_self (), port);
	}
      *reply_port = scp->sc_reply_port;
    }
示例#5
0
文件: hurdsig.c 项目: VGEAREN/mygit
mach_port_t
_hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
		     struct machine_thread_all_state *state, int *state_change,
		     void (*reply) (void))
{
  extern const void _hurd_intr_rpc_msg_in_trap;
  mach_port_t rcv_port = MACH_PORT_NULL;
  mach_port_t intr_port;

  *state_change = 0;

  intr_port = ss->intr_port;
  if (intr_port == MACH_PORT_NULL)
    /* No interruption needs done.  */
    return MACH_PORT_NULL;

  /* Abort the thread's kernel context, so any pending message send or
     receive completes immediately or aborts.  */
  abort_thread (ss, state, reply);

  if (state->basic.PC < (natural_t) &_hurd_intr_rpc_msg_in_trap)
    {
      /* The thread is about to do the RPC, but hasn't yet entered
	 mach_msg.  Mutate the thread's state so it knows not to try
	 the RPC.  */
      INTR_MSG_BACK_OUT (&state->basic);
      MACHINE_THREAD_STATE_SET_PC (&state->basic,
				   &_hurd_intr_rpc_msg_in_trap);
      state->basic.SYSRETURN = MACH_SEND_INTERRUPTED;
      *state_change = 1;
    }
  else if (state->basic.PC == (natural_t) &_hurd_intr_rpc_msg_in_trap &&
	   /* The thread was blocked in the system call.  After thread_abort,
	      the return value register indicates what state the RPC was in
	      when interrupted.  */
	   state->basic.SYSRETURN == MACH_RCV_INTERRUPTED)
      {
	/* The RPC request message was sent and the thread was waiting for
	   the reply message; now the message receive has been aborted, so
	   the mach_msg call will return MACH_RCV_INTERRUPTED.  We must tell
	   the server to interrupt the pending operation.  The thread must
	   wait for the reply message before running the signal handler (to
	   guarantee that the operation has finished being interrupted), so
	   our nonzero return tells the trampoline code to finish the message
	   receive operation before running the handler.  */

	mach_port_t *reply = interrupted_reply_port_location (ss->thread,
							      state,
							      sigthread);
	error_t err = __interrupt_operation (intr_port, _hurdsig_interrupt_timeout);

	if (err)
	  {
	    if (reply)
	      {
		/* The interrupt didn't work.
		   Destroy the receive right the thread is blocked on.  */
		__mach_port_destroy (__mach_task_self (), *reply);
		*reply = MACH_PORT_NULL;
	      }

	    /* The system call return value register now contains
	       MACH_RCV_INTERRUPTED; when mach_msg resumes, it will retry the
	       call.  Since we have just destroyed the receive right, the
	       retry will fail with MACH_RCV_INVALID_NAME.  Instead, just
	       change the return value here to EINTR so mach_msg will not
	       retry and the EINTR error code will propagate up.  */
	    state->basic.SYSRETURN = EINTR;
	    *state_change = 1;
	  }
	else if (reply)
	  rcv_port = *reply;

	/* All threads whose RPCs were interrupted by the interrupt_operation
	   call above will retry their RPCs unless we clear SS->intr_port.
	   So we clear it for the thread taking a signal when SA_RESTART is
	   clear, so that its call returns EINTR.  */
	if (! signo || !(_hurd_sigstate_actions (ss) [signo].sa_flags & SA_RESTART))
	  ss->intr_port = MACH_PORT_NULL;
      }

  return rcv_port;
}