Back to index

glibc  2.9
userlink.h
Go to the documentation of this file.
00001 /* Support for chains recording users of a resource; `struct hurd_userlink'.
00002    Copyright (C) 1994, 1995, 1997, 1999, 2007 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #ifndef       _HURD_USERLINK_H
00021 
00022 #define       _HURD_USERLINK_H     1
00023 #include <features.h>
00024 
00025 #define __need_NULL
00026 #include <stddef.h>
00027 
00028 #include <hurd/signal.h>
00029 #include <setjmp.h>
00030 
00031 
00032 /* This structure records a link in two doubly-linked lists.
00033    We call these the per-resource user list and the per-thread
00034    active-resource list.
00035 
00036    Users of a given resource are recorded by their presence in a list
00037    associated with that resource.  A user attaches his own link (in local
00038    storage on his stack) to a shared chain at the time he begins using some
00039    resource.  When finished with that resource, the user removes his link
00040    from the chain.  If his link is the last (there are no other users of
00041    the resource), and his chain has been detached from the shared cell (the
00042    resource in the cell has been replaced), then the user deallocates the
00043    resource that he used.
00044 
00045    All uses of shared resources by a single thread are linked together by
00046    its `active-resource' list; the head of this list is stored in the
00047    per-thread sigstate structure.  When the thread makes a non-local exit
00048    (i.e. longjmp), it will examine its active-resource list, and each link
00049    residing in a stack frame being jumped out of will be unlinked from both
00050    the resource's user list and the thread's active-resource list, and
00051    deallocate the resource if that was the last user link for that resource.
00052 
00053    NOTE: Access to a thread's active-resource list must always be done
00054    inside a signal-proof critical section; the functions in this file
00055    assume they are called inside a critical section, and do no locking of
00056    their own.  Also important: the longjmp cleanup relies on all userlink
00057    structures residing on the stack of the using thread.  */
00058 
00059 struct hurd_userlink
00060   {
00061     struct
00062       {
00063        struct hurd_userlink *next, **prevp;
00064       } resource, thread;
00065 
00066     /* This function is called when a non-local exit
00067        unwinds the frame containing this link.  */
00068     void (*cleanup) (void *cleanup_data, jmp_buf env, int val);
00069     void *cleanup_data;
00070   };
00071 
00072 
00073 #ifndef _HURD_USERLINK_H_EXTERN_INLINE
00074 #define _HURD_USERLINK_H_EXTERN_INLINE __extern_inline
00075 #endif
00076 
00077 
00078 /* Attach LINK to the chain of users at *CHAINP.  */
00079 
00080 _HURD_USERLINK_H_EXTERN_INLINE void
00081 _hurd_userlink_link (struct hurd_userlink **chainp,
00082                    struct hurd_userlink *link)
00083 {
00084   struct hurd_userlink **thread_chainp;
00085 
00086   link->resource.next = *chainp;
00087   if (link->resource.next)
00088     link->resource.next->resource.prevp = &link->resource.next;
00089   link->resource.prevp = chainp;
00090   *chainp = link;
00091 
00092   /* Also chain it on the current thread's list of active resources.  */
00093   thread_chainp = &_hurd_self_sigstate ()->active_resources;
00094   link->thread.next = *thread_chainp;
00095   if (link->thread.next)
00096     link->thread.next->thread.prevp = &link->thread.next;
00097   link->thread.prevp = thread_chainp;
00098   *thread_chainp = link;
00099 }
00100 
00101 
00102 /* Detach LINK from its chain.  Returns nonzero iff this was the
00103    last user of the resource and it should be deallocated.  */
00104 
00105 _HURD_USERLINK_H_EXTERN_INLINE int
00106 _hurd_userlink_unlink (struct hurd_userlink *link)
00107 {
00108   /* We should deallocate the resource used if this chain has been detached
00109      from the cell (and thus has a nil `prevp'), and there is no next link
00110      representing another user reference to the same resource. */
00111   int dealloc = ! link->resource.next && ! link->resource.prevp;
00112 
00113   /* Remove our link from the chain of current users.  */
00114   if (link->resource.prevp)
00115     *link->resource.prevp = link->resource.next;
00116   if (link->resource.next)
00117     link->resource.next->resource.prevp = link->resource.prevp;
00118 
00119   /* Remove our link from the chain of currently active resources
00120      for this thread.  */
00121   *link->thread.prevp = link->thread.next;
00122   if (link->thread.next)
00123     link->thread.next->thread.prevp = link->thread.prevp;
00124 
00125   return dealloc;
00126 }
00127 
00128 
00129 /* Clear all users from *CHAINP.  Call this when the resource *CHAINP
00130    protects is changing.  If the return value is nonzero, no users are on
00131    the chain and the caller should deallocate the resource.  If the return
00132    value is zero, someone is still using the resource and they will
00133    deallocate it when they are finished.  */
00134 
00135 _HURD_USERLINK_H_EXTERN_INLINE int
00136 _hurd_userlink_clear (struct hurd_userlink **chainp)
00137 {
00138   if (*chainp == NULL)
00139     return 1;
00140 
00141   /* Detach the chain of current users from the cell.  The last user to
00142      remove his link from that chain will deallocate the old resource.  */
00143   (*chainp)->resource.prevp = NULL;
00144   *chainp = NULL;
00145   return 0;
00146 }
00147 
00148 #endif /* hurd/userlink.h */