]>
Commit | Line | Data |
---|---|---|
28f540f4 | 1 | /* Lightweight user references for ports. |
dff8da6b | 2 | Copyright (C) 1993-2024 Free Software Foundation, Inc. |
c84142e8 UD |
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 | |
41bdb6e2 AJ |
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. | |
c84142e8 UD |
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 | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
c84142e8 | 14 | |
41bdb6e2 | 15 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 | 16 | License along with the GNU C Library; if not, see |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
28f540f4 RM |
18 | |
19 | #ifndef _HURD_PORT_H | |
20 | ||
21 | #define _HURD_PORT_H 1 | |
22 | #include <features.h> | |
23 | ||
24 | #include <mach.h> | |
25 | #include <hurd/userlink.h> | |
26 | #include <spin-lock.h> | |
28f540f4 RM |
27 | |
28 | ||
29 | /* Structure describing a cell containing a port. With the lock held, a | |
30 | user extracts PORT, and attaches his own link (in local storage) to the | |
31 | USERS chain. PORT can then safely be used. When PORT is no longer | |
32 | needed, with the lock held, the user removes his link from the chain. | |
33 | If his link is the last, and PORT has changed since he fetched it, the | |
34 | user deallocates the port he used. See <hurd/userlink.h>. */ | |
35 | ||
36 | struct hurd_port | |
37 | { | |
38 | spin_lock_t lock; /* Locks rest. */ | |
39 | struct hurd_userlink *users; /* Chain of users; see below. */ | |
40 | mach_port_t port; /* Port. */ | |
41 | }; | |
42 | ||
43 | ||
44 | /* Evaluate EXPR with the variable `port' bound to the port in PORTCELL. */ | |
67a78072 | 45 | /* Also see HURD_PORT_USE_CANCEL. */ |
28f540f4 RM |
46 | |
47 | #define HURD_PORT_USE(portcell, expr) \ | |
48 | ({ struct hurd_port *const __p = (portcell); \ | |
49 | struct hurd_userlink __link; \ | |
50 | const mach_port_t port = _hurd_port_get (__p, &__link); \ | |
51 | __typeof(expr) __result = (expr); \ | |
52 | _hurd_port_free (__p, &__link, port); \ | |
53 | __result; }) | |
54 | ||
55 | ||
6f9dc08b | 56 | #ifndef _HURD_PORT_H_EXTERN_INLINE |
b037a293 | 57 | #define _HURD_PORT_H_EXTERN_INLINE __extern_inline |
28f540f4 RM |
58 | #endif |
59 | ||
60 | ||
61 | /* Initialize *PORT to INIT. */ | |
62 | ||
28f6186f ST |
63 | extern void _hurd_port_init (struct hurd_port *port, mach_port_t init); |
64 | ||
65 | #if defined __USE_EXTERN_INLINES && defined _LIBC | |
2f8902cc | 66 | # if IS_IN (libc) |
6f9dc08b | 67 | _HURD_PORT_H_EXTERN_INLINE void |
28f540f4 RM |
68 | _hurd_port_init (struct hurd_port *port, mach_port_t init) |
69 | { | |
70 | __spin_lock_init (&port->lock); | |
71 | port->users = NULL; | |
72 | port->port = init; | |
73 | } | |
2f8902cc | 74 | # endif |
28f6186f | 75 | #endif |
28f540f4 RM |
76 | |
77 | ||
1474b80f RM |
78 | /* Cleanup function for non-local exits. */ |
79 | extern void _hurd_port_cleanup (void *, jmp_buf, int); | |
80 | ||
28f540f4 RM |
81 | /* Get a reference to *PORT, which is locked. |
82 | Pass return value and LINK to _hurd_port_free when done. */ | |
83 | ||
28f6186f ST |
84 | extern mach_port_t |
85 | _hurd_port_locked_get (struct hurd_port *port, | |
86 | struct hurd_userlink *link); | |
87 | ||
88 | #if defined __USE_EXTERN_INLINES && defined _LIBC | |
2f8902cc | 89 | # if IS_IN (libc) |
6f9dc08b | 90 | _HURD_PORT_H_EXTERN_INLINE mach_port_t |
28f540f4 RM |
91 | _hurd_port_locked_get (struct hurd_port *port, |
92 | struct hurd_userlink *link) | |
93 | { | |
94 | mach_port_t result; | |
95 | result = port->port; | |
96 | if (result != MACH_PORT_NULL) | |
1474b80f RM |
97 | { |
98 | link->cleanup = &_hurd_port_cleanup; | |
62d6c330 | 99 | link->cleanup_data = (void *) (uintptr_t) result; |
1474b80f RM |
100 | _hurd_userlink_link (&port->users, link); |
101 | } | |
28f540f4 RM |
102 | __spin_unlock (&port->lock); |
103 | return result; | |
104 | } | |
2f8902cc | 105 | # endif |
28f6186f | 106 | #endif |
28f540f4 RM |
107 | |
108 | /* Same, but locks PORT first. */ | |
109 | ||
28f6186f ST |
110 | extern mach_port_t |
111 | _hurd_port_get (struct hurd_port *port, | |
112 | struct hurd_userlink *link); | |
113 | ||
114 | #if defined __USE_EXTERN_INLINES && defined _LIBC | |
2f8902cc | 115 | # if IS_IN (libc) |
6f9dc08b | 116 | _HURD_PORT_H_EXTERN_INLINE mach_port_t |
28f540f4 RM |
117 | _hurd_port_get (struct hurd_port *port, |
118 | struct hurd_userlink *link) | |
119 | { | |
120 | mach_port_t result; | |
121 | HURD_CRITICAL_BEGIN; | |
122 | __spin_lock (&port->lock); | |
123 | result = _hurd_port_locked_get (port, link); | |
124 | HURD_CRITICAL_END; | |
125 | return result; | |
126 | } | |
2f8902cc | 127 | # endif |
28f6186f | 128 | #endif |
28f540f4 RM |
129 | |
130 | ||
7fa495cd ST |
131 | /* Relocate LINK to NEW_LINK. |
132 | To be used when e.g. reallocating a link array. */ | |
133 | ||
134 | extern void | |
135 | _hurd_port_move (struct hurd_port *port, | |
136 | struct hurd_userlink *new_link, | |
137 | struct hurd_userlink *link); | |
138 | ||
139 | #if defined __USE_EXTERN_INLINES && defined _LIBC | |
140 | # if IS_IN (libc) | |
141 | _HURD_PORT_H_EXTERN_INLINE void | |
142 | _hurd_port_move (struct hurd_port *port, | |
143 | struct hurd_userlink *new_link, | |
144 | struct hurd_userlink *link) | |
145 | { | |
146 | HURD_CRITICAL_BEGIN; | |
147 | __spin_lock (&port->lock); | |
148 | _hurd_userlink_move (new_link, link); | |
149 | __spin_unlock (&port->lock); | |
150 | HURD_CRITICAL_END; | |
151 | } | |
152 | # endif | |
153 | #endif | |
154 | ||
155 | ||
28f540f4 RM |
156 | /* Free a reference gotten with `USED_PORT = _hurd_port_get (PORT, LINK);' */ |
157 | ||
28f6186f ST |
158 | extern void |
159 | _hurd_port_free (struct hurd_port *port, | |
160 | struct hurd_userlink *link, | |
161 | mach_port_t used_port); | |
162 | ||
163 | #if defined __USE_EXTERN_INLINES && defined _LIBC | |
2f8902cc | 164 | # if IS_IN (libc) |
6f9dc08b | 165 | _HURD_PORT_H_EXTERN_INLINE void |
28f540f4 RM |
166 | _hurd_port_free (struct hurd_port *port, |
167 | struct hurd_userlink *link, | |
168 | mach_port_t used_port) | |
169 | { | |
170 | int dealloc; | |
171 | if (used_port == MACH_PORT_NULL) | |
172 | /* When we fetch an empty port cell with _hurd_port_get, | |
173 | it does not link us on the users chain, since there is | |
174 | no shared resource. */ | |
175 | return; | |
176 | HURD_CRITICAL_BEGIN; | |
177 | __spin_lock (&port->lock); | |
178 | dealloc = _hurd_userlink_unlink (link); | |
179 | __spin_unlock (&port->lock); | |
180 | HURD_CRITICAL_END; | |
181 | if (dealloc) | |
182 | __mach_port_deallocate (__mach_task_self (), used_port); | |
183 | } | |
2f8902cc | 184 | # endif |
28f6186f | 185 | #endif |
28f540f4 RM |
186 | |
187 | ||
188 | /* Set *PORT's port to NEWPORT. NEWPORT's reference is consumed by PORT->port. | |
189 | PORT->lock is locked. */ | |
190 | ||
28f6186f ST |
191 | extern void _hurd_port_locked_set (struct hurd_port *port, mach_port_t newport); |
192 | ||
193 | #if defined __USE_EXTERN_INLINES && defined _LIBC | |
2f8902cc | 194 | # if IS_IN (libc) |
6f9dc08b | 195 | _HURD_PORT_H_EXTERN_INLINE void |
28f540f4 RM |
196 | _hurd_port_locked_set (struct hurd_port *port, mach_port_t newport) |
197 | { | |
198 | mach_port_t old; | |
199 | old = _hurd_userlink_clear (&port->users) ? port->port : MACH_PORT_NULL; | |
200 | port->port = newport; | |
201 | __spin_unlock (&port->lock); | |
202 | if (old != MACH_PORT_NULL) | |
203 | __mach_port_deallocate (__mach_task_self (), old); | |
204 | } | |
2f8902cc | 205 | # endif |
28f6186f | 206 | #endif |
28f540f4 RM |
207 | |
208 | /* Same, but locks PORT first. */ | |
209 | ||
28f6186f ST |
210 | extern void _hurd_port_set (struct hurd_port *port, mach_port_t newport); |
211 | ||
212 | #if defined __USE_EXTERN_INLINES && defined _LIBC | |
2f8902cc | 213 | # if IS_IN (libc) |
6f9dc08b | 214 | _HURD_PORT_H_EXTERN_INLINE void |
28f540f4 RM |
215 | _hurd_port_set (struct hurd_port *port, mach_port_t newport) |
216 | { | |
217 | HURD_CRITICAL_BEGIN; | |
218 | __spin_lock (&port->lock); | |
219 | _hurd_port_locked_set (port, newport); | |
220 | HURD_CRITICAL_END; | |
221 | } | |
2f8902cc | 222 | # endif |
28f6186f | 223 | #endif |
28f540f4 RM |
224 | |
225 | ||
226 | #endif /* hurd/port.h */ |