00001
00002
00012
00013
00014
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
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
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
00091 }
00092 else
00093 {
00094
00095 while(q->next != other)
00096 {
00097
00098
00099
00100 if (other->prev == NULL)
00101 {
00102
00103 l4_thread_switch(other->id);
00104 }
00105 else if (other->prev!=q)
00106 {
00107
00108
00109
00110
00111
00112 other = other->prev;
00113 }
00114 }
00115
00116
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