1999-11-09 Roland McGrath <roland@baalperazim.frob.com>
[kopensolaris-gnu/glibc.git] / sysdeps / mach / hurd / i386 / intr-msg.h
1 /* Machine-dependent details of interruptible RPC messaging.  i386 version.
2    Copyright (C) 1995, 1996, 1997, 1999 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 Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    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    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20
21 /* Note that we must mark OPTION and TIMEOUT as outputs of this operation,
22    to indicate that the signal thread might mutate them as part
23    of sending us to a signal handler.  */
24 #define INTR_MSG_TRAP(msg, option, send_size, rcv_size, rcv_name, timeout, notify) \
25 ({                                                                            \
26   error_t err;                                                                \
27   asm (".globl _hurd_intr_rpc_msg_do_trap\n"                                  \
28        ".globl _hurd_intr_rpc_msg_in_trap\n"                                  \
29        ".globl _hurd_intr_rpc_msg_cx_sp\n"                                    \
30        ".globl _hurd_intr_rpc_msg_sp_restored\n"                              \
31        "                                movl %%esp, %%ecx\n"                  \
32        "                                leal %3, %%esp\n"                     \
33        "_hurd_intr_rpc_msg_cx_sp:       movl $-25, %%eax\n"                   \
34        "_hurd_intr_rpc_msg_do_trap:     lcall $7, $0 # status in %0\n"        \
35        "_hurd_intr_rpc_msg_in_trap:     movl %%ecx, %%esp\n"                  \
36        "_hurd_intr_rpc_msg_sp_restored:"                                      \
37        : "=a" (err), "=m" (option), "=m" (timeout)                            \
38        : "m" ((&msg)[-1]), "1" (option), "2" (timeout)                        \
39        : "%ecx");                                                             \
40   err;                                                                        \
41 })
42
43
44 static void inline
45 INTR_MSG_BACK_OUT (struct i386_thread_state *state)
46 {
47   extern const void _hurd_intr_rpc_msg_cx_sp;
48   if (state->eip >= (natural_t) &_hurd_intr_rpc_msg_cx_sp)
49     state->uesp = state->ecx;
50   else
51     state->ecx = state->uesp;
52 }
53 \f
54 #include "hurdfault.h"
55
56 static inline int
57 SYSCALL_EXAMINE (struct i386_thread_state *state, int *callno)
58 {
59   struct { unsigned int c[2]; } *p = (void *) (state->eip - 7);
60   int result;
61   if (_hurdsig_catch_memory_fault (p))
62     return 0;
63   if (result = p->c[0] == 0x0000009a && (p->c[1] & 0x00ffffff) == 0x00000700)
64     /* The PC is just after an `lcall $7,$0' instruction.
65        This is a system call in progress; %eax holds the call number.  */
66     *callno = state->eax;
67   _hurdsig_end_catch_fault ();
68   return result;
69 }
70
71
72 struct mach_msg_trap_args
73   {
74     void *retaddr;              /* Address mach_msg_trap will return to.  */
75     /* This is the order of arguments to mach_msg_trap.  */
76     mach_msg_header_t *msg;
77     mach_msg_option_t option;
78     mach_msg_size_t send_size;
79     mach_msg_size_t rcv_size;
80     mach_port_t rcv_name;
81     mach_msg_timeout_t timeout;
82     mach_port_t notify;
83   };
84
85
86 static inline int
87 MSG_EXAMINE (struct i386_thread_state *state, int *msgid,
88              mach_port_t *rcv_name, mach_port_t *send_name,
89              mach_msg_option_t *option, mach_msg_timeout_t *timeout)
90 {
91   const struct mach_msg_trap_args *args = (const void *) state->uesp;
92   mach_msg_header_t *msg;
93
94   if (_hurdsig_catch_memory_fault (args))
95     return -1;
96   msg = args->msg;
97   *option = args->option;
98   *timeout = args->timeout;
99   *rcv_name = args->rcv_name;
100   _hurdsig_end_catch_fault ();
101
102   if (msg == 0)
103     {
104       *send_name = MACH_PORT_NULL;
105       *msgid = 0;
106     }
107   else
108     {
109       if (_hurdsig_catch_memory_fault (msg))
110         return -1;
111       *send_name = msg->msgh_remote_port;
112       *msgid = msg->msgh_id;
113       _hurdsig_end_catch_fault ();
114     }
115
116   return 0;
117 }