在对当前的运行的进程进行阻塞时经常会用到wait_event()这个函数,来看看linux内核中时如何实现wait_event()这个函数的。


   先介绍几个宏定义函数:


   1. #define DEFINE_WAIT_FUNC(name, function) \

          wait_queue_t name = {  \

              .private = current, \

              .func    = function, \

              .task_list = LIST_HEAD_INIT((name).task_list),\

              }

   2. #define DEFINE_WAIT(name) \

        DEFINE_WAIT_FUNC(name, autoremove_wake_function)


   3. #define init_wait(name) \

       do{  \

           (name)->private = current;\

           (name)->func    = autoremove_wake_function; \

           INIT_LIST_HEAD(&name->task_list);

         }while(0)


     因此 DEFINE_WAIT(name)定义了一个wait_queue_t结构体,并且将其与当前正在运行的进程进行挂钩,同时定义了当前这个进程在被唤醒以后所做的处理函数 autoremove_wake_function()。


   wait_event()函数的实现:

  

    #define __wait_event(wq, condition) \

      do{           \

          DEFINE_WAIT(__wait);  \  定义并初始化了一个wait_queue_t

          for(;;)            \

            {     \

              prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);\

              if(condition)  \

                 break;   \  

              schedule(); \

             }

           finish_wait(&wq, &__wait); \

         }while(0)


     #define wait_event(wq, condition)     \

       do{    \

             if(condition)       \

                break;            \

             __wait_event(wq, condition);   \

         }while(0)



   wait_event_timeout()函数的实现:

 

   #define __wait_event_timeout(wq,condition,ret) \

     do{              \

         DEFINE_WAIT(__wait);  \

         for(;;) \

         {   \

            prepare_to_wait(&wq,&__wait, TASK_UNINTERRUPTIBLE); \

            if(conditon) \

              break; \

            ret = schedule_timeout(ret); \

            if(!ret)        \

              break;            \

         }

         finish_wait(&wq, &__wait); \

       }while(0)


     #define wait_event_timeout(wq, conditon, timeout)  \

       ( long __ret = timeout;\

         if(!condition) \

            __wait_event_timeout(wq, conditon, __ret); \

         __ret;)