]> git.ipfire.org Git - thirdparty/glibc.git/blame - hurd/hurd/userlink.h
hurd: Fix spawni's user_link reallocation
[thirdparty/glibc.git] / hurd / hurd / userlink.h
CommitLineData
28f540f4 1/* Support for chains recording users of a resource; `struct hurd_userlink'.
688903eb 2 Copyright (C) 1994-2018 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
PE
16 License along with the GNU C Library; if not, see
17 <http://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
RM
100
101 /* Also chain it on the current thread's list of active resources. */
102 thread_chainp = &_hurd_self_sigstate ()->active_resources;
103 link->thread.next = *thread_chainp;
104 if (link->thread.next)
105 link->thread.next->thread.prevp = &link->thread.next;
106 link->thread.prevp = thread_chainp;
107 *thread_chainp = link;
28f540f4 108}
2f8902cc 109# endif
28f6186f 110#endif
28f540f4
RM
111
112
1474b80f
RM
113/* Detach LINK from its chain. Returns nonzero iff this was the
114 last user of the resource and it should be deallocated. */
28f540f4 115
28f6186f
ST
116extern int _hurd_userlink_unlink (struct hurd_userlink *link);
117
118#if defined __USE_EXTERN_INLINES && defined _LIBC
2f8902cc 119# if IS_IN (libc)
6f9dc08b 120_HURD_USERLINK_H_EXTERN_INLINE int
28f540f4
RM
121_hurd_userlink_unlink (struct hurd_userlink *link)
122{
1474b80f
RM
123 /* We should deallocate the resource used if this chain has been detached
124 from the cell (and thus has a nil `prevp'), and there is no next link
125 representing another user reference to the same resource. */
126 int dealloc = ! link->resource.next && ! link->resource.prevp;
28f540f4
RM
127
128 /* Remove our link from the chain of current users. */
1474b80f
RM
129 if (link->resource.prevp)
130 *link->resource.prevp = link->resource.next;
131 if (link->resource.next)
132 link->resource.next->resource.prevp = link->resource.prevp;
133
134 /* Remove our link from the chain of currently active resources
135 for this thread. */
136 *link->thread.prevp = link->thread.next;
137 if (link->thread.next)
138 link->thread.next->thread.prevp = link->thread.prevp;
28f540f4
RM
139
140 return dealloc;
141}
2f8902cc 142# endif
28f6186f 143#endif
28f540f4 144
7fa495cd
ST
145/* Relocate LINK to NEW_LINK.
146 To be used when e.g. reallocating a link array. */
147
148extern void _hurd_userlink_move (struct hurd_userlink *new_link,
149 struct hurd_userlink *link);
150
151#if defined __USE_EXTERN_INLINES && defined _LIBC
152# if IS_IN (libc)
153_HURD_USERLINK_H_EXTERN_INLINE void
154_hurd_userlink_move (struct hurd_userlink *new_link,
155 struct hurd_userlink *link)
156{
157 *new_link = *link;
158
159 if (new_link->resource.next != NULL)
160 new_link->resource.next->resource.prevp = &new_link->resource.next;
278fdabd 161 *new_link->resource.prevp = new_link;
7fa495cd
ST
162
163 if (new_link->thread.next != NULL)
164 new_link->thread.next->thread.prevp = &new_link->thread.next;
278fdabd 165 *new_link->thread.prevp = new_link;
7fa495cd
ST
166}
167# endif
168#endif
28f540f4
RM
169
170/* Clear all users from *CHAINP. Call this when the resource *CHAINP
171 protects is changing. If the return value is nonzero, no users are on
172 the chain and the caller should deallocate the resource. If the return
173 value is zero, someone is still using the resource and they will
174 deallocate it when they are finished. */
175
28f6186f
ST
176extern int _hurd_userlink_clear (struct hurd_userlink **chainp);
177
178#if defined __USE_EXTERN_INLINES && defined _LIBC
2f8902cc 179# if IS_IN (libc)
6f9dc08b 180_HURD_USERLINK_H_EXTERN_INLINE int
28f540f4
RM
181_hurd_userlink_clear (struct hurd_userlink **chainp)
182{
183 if (*chainp == NULL)
184 return 1;
185
186 /* Detach the chain of current users from the cell. The last user to
187 remove his link from that chain will deallocate the old resource. */
1474b80f 188 (*chainp)->resource.prevp = NULL;
28f540f4
RM
189 *chainp = NULL;
190 return 0;
191}
2f8902cc 192# endif
28f6186f 193#endif
28f540f4
RM
194
195#endif /* hurd/userlink.h */