diff options
Diffstat (limited to 'REORG.TODO/hurd/hurd/userlink.h')
-rw-r--r-- | REORG.TODO/hurd/hurd/userlink.h | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/REORG.TODO/hurd/hurd/userlink.h b/REORG.TODO/hurd/hurd/userlink.h new file mode 100644 index 0000000000..4946402df5 --- /dev/null +++ b/REORG.TODO/hurd/hurd/userlink.h @@ -0,0 +1,147 @@ +/* Support for chains recording users of a resource; `struct hurd_userlink'. + Copyright (C) 1994-2017 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 + <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_USERLINK_H + +#define _HURD_USERLINK_H 1 +#include <features.h> + +#define __need_NULL +#include <stddef.h> + +#include <hurd/signal.h> +#include <setjmp.h> + + +/* This structure records a link in two doubly-linked lists. + We call these the per-resource user list and the per-thread + active-resource list. + + Users of a given resource are recorded by their presence in a list + associated with that resource. A user attaches his own link (in local + storage on his stack) to a shared chain at the time he begins using some + resource. When finished with that resource, the user removes his link + from the chain. If his link is the last (there are no other users of + the resource), and his chain has been detached from the shared cell (the + resource in the cell has been replaced), then the user deallocates the + resource that he used. + + All uses of shared resources by a single thread are linked together by + its `active-resource' list; the head of this list is stored in the + per-thread sigstate structure. When the thread makes a non-local exit + (i.e. longjmp), it will examine its active-resource list, and each link + residing in a stack frame being jumped out of will be unlinked from both + the resource's user list and the thread's active-resource list, and + deallocate the resource if that was the last user link for that resource. + + NOTE: Access to a thread's active-resource list must always be done + inside a signal-proof critical section; the functions in this file + assume they are called inside a critical section, and do no locking of + their own. Also important: the longjmp cleanup relies on all userlink + structures residing on the stack of the using thread. */ + +struct hurd_userlink + { + struct + { + struct hurd_userlink *next, **prevp; + } resource, thread; + + /* This function is called when a non-local exit + unwinds the frame containing this link. */ + void (*cleanup) (void *cleanup_data, jmp_buf env, int val); + void *cleanup_data; + }; + + +#ifndef _HURD_USERLINK_H_EXTERN_INLINE +#define _HURD_USERLINK_H_EXTERN_INLINE __extern_inline +#endif + + +/* Attach LINK to the chain of users at *CHAINP. */ + +_HURD_USERLINK_H_EXTERN_INLINE void +_hurd_userlink_link (struct hurd_userlink **chainp, + struct hurd_userlink *link) +{ + struct hurd_userlink **thread_chainp; + + link->resource.next = *chainp; + if (link->resource.next) + link->resource.next->resource.prevp = &link->resource.next; + link->resource.prevp = chainp; + *chainp = link; + + /* Also chain it on the current thread's list of active resources. */ + thread_chainp = &_hurd_self_sigstate ()->active_resources; + link->thread.next = *thread_chainp; + if (link->thread.next) + link->thread.next->thread.prevp = &link->thread.next; + link->thread.prevp = thread_chainp; + *thread_chainp = link; +} + + +/* Detach LINK from its chain. Returns nonzero iff this was the + last user of the resource and it should be deallocated. */ + +_HURD_USERLINK_H_EXTERN_INLINE int +_hurd_userlink_unlink (struct hurd_userlink *link) +{ + /* We should deallocate the resource used if this chain has been detached + from the cell (and thus has a nil `prevp'), and there is no next link + representing another user reference to the same resource. */ + int dealloc = ! link->resource.next && ! link->resource.prevp; + + /* Remove our link from the chain of current users. */ + if (link->resource.prevp) + *link->resource.prevp = link->resource.next; + if (link->resource.next) + link->resource.next->resource.prevp = link->resource.prevp; + + /* Remove our link from the chain of currently active resources + for this thread. */ + *link->thread.prevp = link->thread.next; + if (link->thread.next) + link->thread.next->thread.prevp = link->thread.prevp; + + return dealloc; +} + + +/* Clear all users from *CHAINP. Call this when the resource *CHAINP + protects is changing. If the return value is nonzero, no users are on + the chain and the caller should deallocate the resource. If the return + value is zero, someone is still using the resource and they will + deallocate it when they are finished. */ + +_HURD_USERLINK_H_EXTERN_INLINE int +_hurd_userlink_clear (struct hurd_userlink **chainp) +{ + if (*chainp == NULL) + return 1; + + /* Detach the chain of current users from the cell. The last user to + remove his link from that chain will deallocate the old resource. */ + (*chainp)->resource.prevp = NULL; + *chainp = NULL; + return 0; +} + +#endif /* hurd/userlink.h */ |