]> git.ipfire.org Git - thirdparty/glibc.git/blame - hurd/hurd/userlink.h
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / hurd / hurd / userlink.h
CommitLineData
28f540f4 1/* Support for chains recording users of a resource; `struct hurd_userlink'.
dff8da6b 2 Copyright (C) 1994-2024 Free Software Foundation, Inc.
c84142e8 3 This file is part of the GNU C Library.
28f540f4 4
c84142e8 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.
28f540f4 9
c84142e8
UD
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.
28f540f4 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_USERLINK_H
20
21#define _HURD_USERLINK_H 1
22#include <features.h>
23
24#define __need_NULL
25#include <stddef.h>
26
3403cb7d
ST
27#if defined __USE_EXTERN_INLINES && defined _LIBC
28# if IS_IN (libc)
29# include <hurd/signal.h>
30# endif
31#endif
1474b80f
RM
32#include <setjmp.h>
33
34
35/* This structure records a link in two doubly-linked lists.
36 We call these the per-resource user list and the per-thread
c84142e8 37 active-resource list.
1474b80f
RM
38
39 Users of a given resource are recorded by their presence in a list
40 associated with that resource. A user attaches his own link (in local
41 storage on his stack) to a shared chain at the time he begins using some
42 resource. When finished with that resource, the user removes his link
43 from the chain. If his link is the last (there are no other users of
44 the resource), and his chain has been detached from the shared cell (the
45 resource in the cell has been replaced), then the user deallocates the
46 resource that he used.
47
48 All uses of shared resources by a single thread are linked together by
49 its `active-resource' list; the head of this list is stored in the
50 per-thread sigstate structure. When the thread makes a non-local exit
51 (i.e. longjmp), it will examine its active-resource list, and each link
52 residing in a stack frame being jumped out of will be unlinked from both
53 the resource's user list and the thread's active-resource list, and
54 deallocate the resource if that was the last user link for that resource.
55
56 NOTE: Access to a thread's active-resource list must always be done
57 inside a signal-proof critical section; the functions in this file
58 assume they are called inside a critical section, and do no locking of
59 their own. Also important: the longjmp cleanup relies on all userlink
60 structures residing on the stack of the using thread. */
28f540f4
RM
61
62struct hurd_userlink
63 {
1474b80f
RM
64 struct
65 {
66 struct hurd_userlink *next, **prevp;
67 } resource, thread;
68
69 /* This function is called when a non-local exit
70 unwinds the frame containing this link. */
71 void (*cleanup) (void *cleanup_data, jmp_buf env, int val);
72 void *cleanup_data;
28f540f4
RM
73 };
74
75
6f9dc08b 76#ifndef _HURD_USERLINK_H_EXTERN_INLINE
b037a293 77#define _HURD_USERLINK_H_EXTERN_INLINE __extern_inline
28f540f4
RM
78#endif
79
80
81/* Attach LINK to the chain of users at *CHAINP. */
82
28f6186f
ST
83extern void
84_hurd_userlink_link (struct hurd_userlink **chainp,
85 struct hurd_userlink *link);
86
87#if defined __USE_EXTERN_INLINES && defined _LIBC
2f8902cc 88# if IS_IN (libc)
6f9dc08b 89_HURD_USERLINK_H_EXTERN_INLINE void
28f540f4
RM
90_hurd_userlink_link (struct hurd_userlink **chainp,
91 struct hurd_userlink *link)
92{
1474b80f
RM
93 struct hurd_userlink **thread_chainp;
94
95 link->resource.next = *chainp;
96 if (link->resource.next)
5e75b232 97 link->resource.next->resource.prevp = &link->resource.next;
1474b80f 98 link->resource.prevp = chainp;
28f540f4 99 *chainp = link;
1474b80f 100
2ce0481d
ST
101 if (!__LIBC_NO_TLS ())
102 {
103 /* Also chain it on the current thread's list of active resources. */
104 thread_chainp = &_hurd_self_sigstate ()->active_resources;
105 link->thread.next = *thread_chainp;
106 if (link->thread.next)
107 link->thread.next->thread.prevp = &link->thread.next;
108 link->thread.prevp = thread_chainp;
109 *thread_chainp = link;
110 }
28f540f4 111}
2f8902cc 112# endif
28f6186f 113#endif
28f540f4
RM
114
115
1474b80f
RM
116/* Detach LINK from its chain. Returns nonzero iff this was the
117 last user of the resource and it should be deallocated. */
28f540f4 118
28f6186f
ST
119extern int _hurd_userlink_unlink (struct hurd_userlink *link);
120
121#if defined __USE_EXTERN_INLINES && defined _LIBC
2f8902cc 122# if IS_IN (libc)
6f9dc08b 123_HURD_USERLINK_H_EXTERN_INLINE int
28f540f4
RM
124_hurd_userlink_unlink (struct hurd_userlink *link)
125{
1474b80f
RM
126 /* We should deallocate the resource used if this chain has been detached
127 from the cell (and thus has a nil `prevp'), and there is no next link
128 representing another user reference to the same resource. */
129 int dealloc = ! link->resource.next && ! link->resource.prevp;
28f540f4
RM
130
131 /* Remove our link from the chain of current users. */
1474b80f
RM
132 if (link->resource.prevp)
133 *link->resource.prevp = link->resource.next;
134 if (link->resource.next)
135 link->resource.next->resource.prevp = link->resource.prevp;
136
2ce0481d
ST
137 if (!__LIBC_NO_TLS ())
138 {
139 /* Remove our link from the chain of currently active resources
140 for this thread. */
141 *link->thread.prevp = link->thread.next;
142 if (link->thread.next)
143 link->thread.next->thread.prevp = link->thread.prevp;
144 }
28f540f4
RM
145
146 return dealloc;
147}
2f8902cc 148# endif
28f6186f 149#endif
28f540f4 150
7fa495cd
ST
151/* Relocate LINK to NEW_LINK.
152 To be used when e.g. reallocating a link array. */
153
154extern void _hurd_userlink_move (struct hurd_userlink *new_link,
155 struct hurd_userlink *link);
156
157#if defined __USE_EXTERN_INLINES && defined _LIBC
158# if IS_IN (libc)
159_HURD_USERLINK_H_EXTERN_INLINE void
160_hurd_userlink_move (struct hurd_userlink *new_link,
161 struct hurd_userlink *link)
162{
163 *new_link = *link;
164
165 if (new_link->resource.next != NULL)
166 new_link->resource.next->resource.prevp = &new_link->resource.next;
278fdabd 167 *new_link->resource.prevp = new_link;
7fa495cd 168
2ce0481d
ST
169 if (!__LIBC_NO_TLS ())
170 {
171 if (new_link->thread.next != NULL)
172 new_link->thread.next->thread.prevp = &new_link->thread.next;
173 *new_link->thread.prevp = new_link;
174 }
7fa495cd
ST
175}
176# endif
177#endif
28f540f4
RM
178
179/* Clear all users from *CHAINP. Call this when the resource *CHAINP
180 protects is changing. If the return value is nonzero, no users are on
181 the chain and the caller should deallocate the resource. If the return
182 value is zero, someone is still using the resource and they will
183 deallocate it when they are finished. */
184
28f6186f
ST
185extern int _hurd_userlink_clear (struct hurd_userlink **chainp);
186
187#if defined __USE_EXTERN_INLINES && defined _LIBC
2f8902cc 188# if IS_IN (libc)
6f9dc08b 189_HURD_USERLINK_H_EXTERN_INLINE int
28f540f4
RM
190_hurd_userlink_clear (struct hurd_userlink **chainp)
191{
192 if (*chainp == NULL)
193 return 1;
194
195 /* Detach the chain of current users from the cell. The last user to
196 remove his link from that chain will deallocate the old resource. */
1474b80f 197 (*chainp)->resource.prevp = NULL;
28f540f4
RM
198 *chainp = NULL;
199 return 0;
200}
2f8902cc 201# endif
28f6186f 202#endif
28f540f4
RM
203
204#endif /* hurd/userlink.h */