Subversion Repositories Kolibri OS

Rev

Rev 6102 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #ifndef _LINUX_WAIT_H
  2. #define _LINUX_WAIT_H
  3. /*
  4.  * Linux wait queue related types and methods
  5.  */
  6. #include <linux/list.h>
  7. #include <linux/stddef.h>
  8. #include <linux/spinlock.h>
  9. #include <asm/current.h>
  10. #include <syscall.h>
  11.  
  12. typedef struct __wait_queue wait_queue_t;
  13. typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key);
  14. int default_wake_function(wait_queue_t *wait, unsigned mode, int flags, void *key);
  15.  
  16. /* __wait_queue::flags */
  17. #define WQ_FLAG_EXCLUSIVE       0x01
  18. #define WQ_FLAG_WOKEN           0x02
  19.  
  20. struct __wait_queue {
  21.         unsigned int            flags;
  22.         void                    *private;
  23.         wait_queue_func_t       func;
  24.         struct list_head        task_list;
  25.         evhandle_t evnt;
  26. };
  27.  
  28. struct wait_bit_key {
  29.         void                    *flags;
  30.         int                     bit_nr;
  31. #define WAIT_ATOMIC_T_BIT_NR    -1
  32.         unsigned long           timeout;
  33. };
  34.  
  35. struct wait_bit_queue {
  36.         struct wait_bit_key     key;
  37.         wait_queue_t            wait;
  38. };
  39.  
  40. struct __wait_queue_head {
  41.         spinlock_t              lock;
  42.         struct list_head        task_list;
  43. };
  44. typedef struct __wait_queue_head wait_queue_head_t;
  45.  
  46. struct task_struct;
  47.  
  48. /*
  49.  * Macros for declaration and initialisaton of the datatypes
  50.  */
  51.  
  52. #define __WAITQUEUE_INITIALIZER(name, tsk) {                            \
  53.         .private        = tsk,                                          \
  54.         .func           = default_wake_function,                        \
  55.         .task_list      = { NULL, NULL } }
  56.  
  57. #define DECLARE_WAITQUEUE(name, tsk)                                    \
  58.         wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)
  59.  
  60. #define __WAIT_QUEUE_HEAD_INITIALIZER(name) {                           \
  61.         .lock           = __SPIN_LOCK_UNLOCKED(name.lock),              \
  62.         .task_list      = { &(name).task_list, &(name).task_list } }
  63.  
  64. #define DECLARE_WAIT_QUEUE_HEAD(name) \
  65.         wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
  66.  
  67. #define __WAIT_BIT_KEY_INITIALIZER(word, bit)                           \
  68.         { .flags = word, .bit_nr = bit, }
  69.  
  70. #define __WAIT_ATOMIC_T_KEY_INITIALIZER(p)                              \
  71.         { .flags = p, .bit_nr = WAIT_ATOMIC_T_BIT_NR, }
  72.  
  73. extern void __init_waitqueue_head(wait_queue_head_t *q, const char *name, struct lock_class_key *);
  74.  
  75. #ifdef CONFIG_LOCKDEP
  76. # define __WAIT_QUEUE_HEAD_INIT_ONSTACK(name) \
  77.         ({ init_waitqueue_head(&name); name; })
  78. # define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) \
  79.         wait_queue_head_t name = __WAIT_QUEUE_HEAD_INIT_ONSTACK(name)
  80. #else
  81. # define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) DECLARE_WAIT_QUEUE_HEAD(name)
  82. #endif
  83.  
  84. static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
  85. {
  86.         q->flags        = 0;
  87.         q->private      = p;
  88.         q->func         = default_wake_function;
  89. }
  90.  
  91. static inline void
  92. init_waitqueue_func_entry(wait_queue_t *q, wait_queue_func_t func)
  93. {
  94.         q->flags        = 0;
  95.         q->private      = NULL;
  96.         q->func         = func;
  97. }
  98.  
  99. static inline int waitqueue_active(wait_queue_head_t *q)
  100. {
  101.         return !list_empty(&q->task_list);
  102. }
  103.  
  104. extern void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
  105. extern void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait);
  106. extern void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
  107.  
  108. static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
  109. {
  110.         list_add(&new->task_list, &head->task_list);
  111. }
  112.  
  113. /*
  114.  * Used for wake-one threads:
  115.  */
  116. static inline void
  117. __add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait)
  118. {
  119.         wait->flags |= WQ_FLAG_EXCLUSIVE;
  120.         __add_wait_queue(q, wait);
  121. }
  122.  
  123. static inline void __add_wait_queue_tail(wait_queue_head_t *head,
  124.                                          wait_queue_t *new)
  125. {
  126.         list_add_tail(&new->task_list, &head->task_list);
  127. }
  128.  
  129. static inline void
  130. __add_wait_queue_tail_exclusive(wait_queue_head_t *q, wait_queue_t *wait)
  131. {
  132.         wait->flags |= WQ_FLAG_EXCLUSIVE;
  133.         __add_wait_queue_tail(q, wait);
  134. }
  135.  
  136. static inline void
  137. __remove_wait_queue(wait_queue_head_t *head, wait_queue_t *old)
  138. {
  139.         list_del(&old->task_list);
  140. }
  141.  
  142. typedef int wait_bit_action_f(struct wait_bit_key *, int mode);
  143. void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
  144. void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key);
  145. void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
  146. void __wake_up_locked(wait_queue_head_t *q, unsigned int mode, int nr);
  147. void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr);
  148. void __wake_up_bit(wait_queue_head_t *, void *, int);
  149. int __wait_on_bit(wait_queue_head_t *, struct wait_bit_queue *, wait_bit_action_f *, unsigned);
  150. int __wait_on_bit_lock(wait_queue_head_t *, struct wait_bit_queue *, wait_bit_action_f *, unsigned);
  151. void wake_up_bit(void *, int);
  152. void wake_up_atomic_t(atomic_t *);
  153. int out_of_line_wait_on_bit(void *, int, wait_bit_action_f *, unsigned);
  154. int out_of_line_wait_on_bit_timeout(void *, int, wait_bit_action_f *, unsigned, unsigned long);
  155. int out_of_line_wait_on_bit_lock(void *, int, wait_bit_action_f *, unsigned);
  156. int out_of_line_wait_on_atomic_t(atomic_t *, int (*)(atomic_t *), unsigned);
  157. wait_queue_head_t *bit_waitqueue(void *, int);
  158.  
  159. /*
  160.  
  161. #define __wait_event(wq, condition)                                     \
  162. do {                                                                    \
  163.         DEFINE_WAIT(__wait);                                            \
  164.                                                                         \
  165.         for (;;) {                                                      \
  166.                 prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);    \
  167.                 if (condition)                                          \
  168.                         break;                                          \
  169.                 schedule();                                             \
  170.         }                                                               \
  171.         finish_wait(&wq, &__wait);                                      \
  172. } while (0)
  173.  
  174. */
  175.  
  176. #define wait_event_timeout(wq, condition, timeout)          \
  177. ({                                                          \
  178.     long __ret = timeout;                                   \
  179. do{                                                         \
  180.     wait_queue_t __wait = {                                 \
  181.         .task_list = LIST_HEAD_INIT(__wait.task_list),      \
  182.         .evnt      = CreateEvent(NULL, MANUAL_DESTROY),     \
  183.     };                                                      \
  184.     unsigned long flags;                                    \
  185.                                                             \
  186.     spin_lock_irqsave(&wq.lock, flags);                     \
  187.     if (list_empty(&__wait.task_list))                      \
  188.         __add_wait_queue(&wq, &__wait);                     \
  189.     spin_unlock_irqrestore(&wq.lock, flags);                \
  190.                                                             \
  191.     for(;;){                                                \
  192.         if (condition)                                      \
  193.             break;                                          \
  194.         WaitEventTimeout(__wait.evnt, timeout);             \
  195.     };                                                      \
  196.     if (!list_empty(&__wait.task_list)) {                   \
  197.         spin_lock_irqsave(&wq.lock, flags);                 \
  198.         list_del_init(&__wait.task_list);                   \
  199.         spin_unlock_irqrestore(&wq.lock, flags);            \
  200.     };                                                      \
  201.     DestroyEvent(__wait.evnt);                              \
  202. } while (0);                                                \
  203.     __ret;                                                  \
  204. })
  205.  
  206. #define wait_event_interruptible_timeout(wq, condition, timeout)    \
  207.         wait_event_timeout(wq, condition, timeout)
  208.  
  209.  
  210. #define wait_event(wq, condition)                           \
  211.     do{                                                     \
  212.     wait_queue_t __wait = {                                 \
  213.         .task_list = LIST_HEAD_INIT(__wait.task_list),      \
  214.         .evnt      = CreateEvent(NULL, MANUAL_DESTROY),     \
  215.     };                                                      \
  216.     unsigned long flags;                                    \
  217.                                                             \
  218.     spin_lock_irqsave(&wq.lock, flags);                     \
  219.     if (list_empty(&__wait.task_list))                      \
  220.         __add_wait_queue(&wq, &__wait);                     \
  221.     spin_unlock_irqrestore(&wq.lock, flags);                \
  222.                                                             \
  223.     for(;;){                                                \
  224.         if (condition)                                      \
  225.             break;                                          \
  226.         WaitEvent(__wait.evnt);                             \
  227.     };                                                      \
  228.     if (!list_empty_careful(&__wait.task_list)) {           \
  229.         spin_lock_irqsave(&wq.lock, flags);                 \
  230.         list_del_init(&__wait.task_list);                   \
  231.         spin_unlock_irqrestore(&wq.lock, flags);            \
  232.     };                                                      \
  233.     DestroyEvent(__wait.evnt);                              \
  234. } while (0)
  235.  
  236. #define wait_event_interruptible(wq, condition)             \
  237. ({                                                          \
  238.     int __ret = 0;                                          \
  239.     if (!(condition))                                       \
  240.         wait_event(wq, condition);                          \
  241.     __ret;                                                  \
  242. })
  243.  
  244. static inline
  245. void wake_up(wait_queue_head_t *q)
  246. {
  247.     wait_queue_t *curr;
  248.     unsigned long flags;
  249.  
  250.     spin_lock_irqsave(&q->lock, flags);
  251.     curr = list_first_entry_or_null(&q->task_list, typeof(*curr), task_list);
  252.     if(curr != NULL)
  253.     {
  254.         if(!WARN_ON(curr->evnt.handle == 0))
  255.         {
  256.             kevent_t event = {0};
  257.             event.code = -1;
  258.             RaiseEvent(curr->evnt, 0, &event);
  259.         }
  260.     }
  261.     spin_unlock_irqrestore(&q->lock, flags);
  262. }
  263.  
  264. static inline
  265. void wake_up_interruptible(wait_queue_head_t *q)
  266. {
  267.     wait_queue_t *curr;
  268.     unsigned long flags;
  269.  
  270.     spin_lock_irqsave(&q->lock, flags);
  271.     curr = list_first_entry_or_null(&q->task_list, typeof(*curr), task_list);
  272.     if(curr != NULL)
  273.     {
  274.         if(!WARN_ON(curr->evnt.handle == 0))
  275.         {
  276.             kevent_t event = {0};
  277.             event.code = -1;
  278.             RaiseEvent(curr->evnt, 0, &event);
  279.         }
  280.     }
  281.     spin_unlock_irqrestore(&q->lock, flags);
  282. }
  283.  
  284. static inline
  285. void wake_up_all(wait_queue_head_t *q)
  286. {
  287.     wait_queue_t *curr;
  288.     unsigned long flags;
  289.     spin_lock_irqsave(&q->lock, flags);
  290.     list_for_each_entry(curr, &q->task_list, task_list)
  291.     {
  292.         if(WARN_ON(curr->evnt.handle == 0))
  293.             continue;
  294.         kevent_t event = {0};
  295.         event.code = -1;
  296.         RaiseEvent(curr->evnt, 0, &event);
  297.     }
  298.     spin_unlock_irqrestore(&q->lock, flags);
  299. }
  300.  
  301.  
  302. static inline void
  303. init_waitqueue_head(wait_queue_head_t *q)
  304. {
  305.     spin_lock_init(&q->lock);
  306.     INIT_LIST_HEAD(&q->task_list);
  307. };
  308.  
  309.  
  310. //struct completion {
  311. //    unsigned int done;
  312. //    wait_queue_head_t wait;
  313. //};
  314.  
  315. int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
  316.  
  317.  
  318. #define DEFINE_WAIT_FUNC(name, function)                                \
  319.         wait_queue_t name = {                                           \
  320.                 .func           = function,                             \
  321.                 .task_list      = LIST_HEAD_INIT((name).task_list),     \
  322.                 .evnt           = CreateEvent(NULL, MANUAL_DESTROY),    \
  323.         }
  324.  
  325. #define DEFINE_WAIT(name) DEFINE_WAIT_FUNC(name, autoremove_wake_function)
  326.  
  327.  
  328. #endif
  329.  
  330.