Back to index

glibc  2.9
intr-msg.h
Go to the documentation of this file.
00001 /* Machine-dependent details of interruptible RPC messaging.  i386 version.
00002    Copyright (C) 1995,96,97,99,2001 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 
00021 /* Note that we must mark OPTION and TIMEOUT as outputs of this operation,
00022    to indicate that the signal thread might mutate them as part
00023    of sending us to a signal handler.  */
00024 #define INTR_MSG_TRAP(msg, option, send_size, rcv_size, rcv_name, timeout, notify) \
00025 ({                                                                   \
00026   error_t err;                                                              \
00027   asm (".globl _hurd_intr_rpc_msg_do_trap\n"                                \
00028        ".globl _hurd_intr_rpc_msg_in_trap\n"                                \
00029        ".globl _hurd_intr_rpc_msg_cx_sp\n"                                  \
00030        ".globl _hurd_intr_rpc_msg_sp_restored\n"                     \
00031        "                           movl %%esp, %%ecx\n"              \
00032        "                           leal %3, %%esp\n"                 \
00033        "_hurd_intr_rpc_msg_cx_sp:  movl $-25, %%eax\n"               \
00034        "_hurd_intr_rpc_msg_do_trap:       lcall $7, $0 # status in %0\n"           \
00035        "_hurd_intr_rpc_msg_in_trap:       movl %%ecx, %%esp\n"              \
00036        "_hurd_intr_rpc_msg_sp_restored:"                             \
00037        : "=a" (err), "=m" (option), "=m" (timeout)                          \
00038        : "m" ((&msg)[-1]), "1" (option), "2" (timeout)                      \
00039        : "%ecx");                                                    \
00040   err;                                                               \
00041 })
00042 
00043 
00044 static void inline
00045 INTR_MSG_BACK_OUT (struct i386_thread_state *state)
00046 {
00047   extern const void _hurd_intr_rpc_msg_cx_sp;
00048   if (state->eip >= (natural_t) &_hurd_intr_rpc_msg_cx_sp)
00049     state->uesp = state->ecx;
00050   else
00051     state->ecx = state->uesp;
00052 }
00053 
00054 #include "hurdfault.h"
00055 
00056 /* This cannot be an inline function because it calls setjmp.  */
00057 #define SYSCALL_EXAMINE(state, callno)                                      \
00058 ({                                                                   \
00059   struct { unsigned int c[2]; } *p = (void *) ((state)->eip - 7);           \
00060   int result;                                                        \
00061   if (_hurdsig_catch_memory_fault (p))                                      \
00062     return 0;                                                        \
00063   if (result = p->c[0] == 0x0000009a && (p->c[1] & 0x00ffffff) == 0x00000700) \
00064     /* The PC is just after an `lcall $7,$0' instruction.                   \
00065        This is a system call in progress; %eax holds the call number.  */     \
00066     *(callno) = (state)->eax;                                               \
00067   _hurdsig_end_catch_fault ();                                              \
00068   result;                                                            \
00069 })
00070 
00071 
00072 struct mach_msg_trap_args
00073   {
00074     void *retaddr;          /* Address mach_msg_trap will return to.  */
00075     /* This is the order of arguments to mach_msg_trap.  */
00076     mach_msg_header_t *msg;
00077     mach_msg_option_t option;
00078     mach_msg_size_t send_size;
00079     mach_msg_size_t rcv_size;
00080     mach_port_t rcv_name;
00081     mach_msg_timeout_t timeout;
00082     mach_port_t notify;
00083   };
00084 
00085 
00086 /* This cannot be an inline function because it calls setjmp.  */
00087 #define MSG_EXAMINE(state, msgid, rcvname, send_name, opt, tmout)           \
00088 ({                                                                   \
00089   const struct mach_msg_trap_args *args = (const void *) (state)->uesp;            \
00090   mach_msg_header_t *msg;                                            \
00091   _hurdsig_catch_memory_fault (args) ? -1 :                                 \
00092     ({                                                               \
00093       msg = args->msg;                                                      \
00094       *(opt) = args->option;                                                \
00095       *(tmout) = args->timeout;                                             \
00096       *(rcvname) = args->rcv_name;                                   \
00097       _hurdsig_end_catch_fault ();                                   \
00098       if (msg == 0)                                                  \
00099        {                                                             \
00100          *(send_name) = MACH_PORT_NULL;                              \
00101          *(msgid) = 0;                                                      \
00102        }                                                             \
00103       else                                                           \
00104        {                                                             \
00105          if (_hurdsig_catch_memory_fault (msg))                      \
00106            return -1;                                                       \
00107          *(send_name) = msg->msgh_remote_port;                              \
00108          *(msgid) = msg->msgh_id;                                    \
00109          _hurdsig_end_catch_fault ();                                       \
00110        }                                                             \
00111       0;                                                             \
00112     });                                                                     \
00113 })