about summary refs log tree commit diff
path: root/sysdeps/mach/hurd/mig-reply.c
blob: 3fdee80e5a9a7c8c191c29b28f49e3c1799349f2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* Copyright (C) 1994-2023 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <https://www.gnu.org/licenses/>.  */

#include <mach.h>
#include <mach/mig_support.h>
#include <tls.h>

/* These functions are called by MiG-generated code.  */

#if !defined (SHARED) || IS_IN (rtld)
mach_port_t __hurd_reply_port0;
#endif

static mach_port_t
get_reply_port (void)
{
#if !defined (SHARED) || IS_IN (rtld)
  if (__LIBC_NO_TLS ())
    return __hurd_reply_port0;
#endif
  return THREAD_GETMEM (THREAD_SELF, reply_port);
}

static void
set_reply_port (mach_port_t port)
{
#if !defined (SHARED) || IS_IN (rtld)
  if (__LIBC_NO_TLS ())
    __hurd_reply_port0 = port;
  else
#endif
    THREAD_SETMEM (THREAD_SELF, reply_port, port);
}

/* Called by MiG to get a reply port.  */
mach_port_t
__mig_get_reply_port (void)
{
  mach_port_t port = get_reply_port ();
  if (__glibc_unlikely (port == MACH_PORT_NULL))
    {
      port = __mach_reply_port ();
      set_reply_port (port);
    }
  return port;
}
weak_alias (__mig_get_reply_port, mig_get_reply_port)
libc_hidden_def (__mig_get_reply_port)

/* Called by MiG to deallocate the reply port.  */
void
__mig_dealloc_reply_port (mach_port_t arg)
{
  error_t err;
  mach_port_t port = get_reply_port ();

  set_reply_port (MACH_PORT_NULL);	/* So the mod_refs RPC won't use it.  */

  /* Normally, ARG should be the same as PORT that we store.  However, if a
     signal has interrupted the RPC, the stored PORT has been deallocated and
     reset to MACH_PORT_NULL (or possibly MACH_PORT_DEAD).  In this case the
     MIG routine still has the old name, which it passes to us here.  We must
     not deallocate (or otherwise touch) it, since it may be already allocated
     to another port right.  Fortunately MIG itself doesn't do anything with
     the reply port on errors either, other than immediately calling this
     function.

     And so:
     1. Assert that things are sane, i.e. and PORT is either invalid or same
        as ARG.
     2. Only deallocate the name if our stored PORT still names it.  In that
        case we're sure the right has not been deallocated / the name reused.
    */

  if (!MACH_PORT_VALID (port))
    return;
  assert (port == arg);

  err = __mach_port_mod_refs (__mach_task_self (), port,
                              MACH_PORT_RIGHT_RECEIVE, -1);
  assert_perror (err);
}
weak_alias (__mig_dealloc_reply_port, mig_dealloc_reply_port)
libc_hidden_def (__mig_dealloc_reply_port)

/* Called by mig interfaces when done with a port.  Used to provide the
   same interface as needed when a custom allocator is used.  */
void
__mig_put_reply_port(mach_port_t port)
{
  /* Do nothing.  */
}
weak_alias (__mig_put_reply_port, mig_put_reply_port)

/* Called at startup with STACK == NULL.  When per-thread variables are set
   up, this is called again with STACK set to the new stack being switched
   to, where per-thread variables should be set up.  */
void
__mig_init (void *stack)
{
  /* Do nothing.  */
}
weak_alias (__mig_init, mig_init)
libc_hidden_def (__mig_init)