Main Page   File List  

lock_wq.h

Go to the documentation of this file.
00001 /* $Id: lock_wq.h 28276 2007-04-10 12:44:30Z adam $ */
00002 /*****************************************************************************/
00012 /* (c) 2003 Technische Universitaet Dresden
00013  * This file is part of DROPS, which is distributed under the terms of the
00014  * GNU General Public License 2. Please see the COPYING file for details. */
00015 
00016 #ifndef __L4UTIL_LOCK_WQ_H__
00017 #define __L4UTIL_LOCK_WQ_H__
00018 
00019 #include <l4/sys/types.h>
00020 #include <l4/sys/syscalls.h>
00021 #include <l4/sys/ipc.h>
00022 #include <l4/util/atomic.h>
00023 
00024 EXTERN_C_BEGIN
00025 
00026 typedef struct l4util_wq_lock_queue_elem_t
00027 {
00028   volatile struct l4util_wq_lock_queue_elem_t *next, *prev;
00029   l4_threadid_t   id;
00030 } l4util_wq_lock_queue_elem_t;
00031 
00032 typedef struct
00033 {
00034   l4util_wq_lock_queue_elem_t *last;
00035 } l4util_wq_lock_queue_base_t;
00036 
00037 static inline int
00038 l4util_wq_lock_lock(l4util_wq_lock_queue_base_t *queue,
00039                     l4util_wq_lock_queue_elem_t *q);
00040 static inline int
00041 l4util_wq_lock_unlock(l4util_wq_lock_queue_base_t *queue, 
00042                       l4util_wq_lock_queue_elem_t *q);
00043 static inline int
00044 l4util_wq_lock_locked(l4util_wq_lock_queue_base_t *queue);
00045 
00046 /* Implementation */
00047 inline int
00048 l4util_wq_lock_lock(l4util_wq_lock_queue_base_t *queue,
00049                     l4util_wq_lock_queue_elem_t *q)
00050 {
00051   l4util_wq_lock_queue_elem_t *old;
00052   l4_msgdope_t result;
00053   int err;
00054   l4_umword_t dummy;
00055 
00056   q->next = 0;
00057   q->id   = l4_myself();
00058   old     = (l4util_wq_lock_queue_elem_t*)
00059                     l4util_xchg((l4_umword_t*)(&queue->last), (l4_umword_t)q);
00060   if (old != 0)
00061     {
00062       /* already locked */
00063       old->next = q;
00064       q->prev   = old;
00065       if ((err = l4_ipc_receive(old->id, L4_IPC_SHORT_MSG, &dummy, &dummy,
00066                                 L4_IPC_NEVER, &result))!=0)
00067         return err;
00068       if ((err = l4_ipc_send   (old->id, L4_IPC_SHORT_MSG, 0, 0,
00069                                 L4_IPC_NEVER, &result))!=0)
00070         return err;
00071     }
00072   return 0;
00073 }
00074 
00075 inline int
00076 l4util_wq_lock_unlock(l4util_wq_lock_queue_base_t *queue, 
00077                       l4util_wq_lock_queue_elem_t *q)
00078 {
00079   volatile l4util_wq_lock_queue_elem_t *other;
00080   l4_msgdope_t result;
00081   int err;
00082   l4_umword_t dummy;
00083 
00084   other = (l4util_wq_lock_queue_elem_t*)
00085                   l4util_cmpxchg_res((l4_umword_t*)(&queue->last), 
00086                                                    (l4_umword_t)q,
00087                                                    (l4_umword_t)NULL);
00088   if (other == q)
00089     {
00090       /* nobody wants the lock */
00091     }
00092   else
00093     {
00094       /* someone wants the lock */
00095       while(q->next != other)
00096         {
00097           /* 2 possibilities:
00098              - other is next, but didnt sign, give it the time
00099              - other is not next, find the next by backward iteration */
00100           if (other->prev == NULL)
00101             {
00102               /* - other didnt sign its prev, give it the time to do this */
00103               l4_thread_switch(other->id);
00104             }
00105           else if (other->prev!=q)
00106             {
00107               /* 2 poss:
00108                  - if other is next it might be signed up to now 
00109                    (other->prev == q)
00110                    - other is not something else then next (its not NULL,
00111                      we know this), go backward */
00112               other = other->prev;
00113             }
00114         }
00115       /* now we have the next in other */
00116       /* send an ipc, timeout never */
00117       if((err = l4_ipc_call(q->next->id, 
00118                             L4_IPC_SHORT_MSG, 0,0,
00119                             L4_IPC_SHORT_MSG, &dummy, &dummy,
00120                             L4_IPC_NEVER,
00121                             &result))!=0)
00122         return err;
00123     }
00124   return 0;
00125 }
00126 
00127 inline int
00128 l4util_wq_lock_locked(l4util_wq_lock_queue_base_t *queue)
00129 {
00130   return queue->last!=NULL;
00131 }
00132 
00133 EXTERN_C_END
00134 
00135 #endif

L4 Utilities, part of DROPS  © 2000-2003