• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            string

            string
            posts - 27, comments - 177, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            用戶級線程切換

            Posted on 2012-01-15 07:01 djx_zh 閱讀(5546) 評論(0)  編輯 收藏 引用
            實現線程庫的一個核心問題是實現線程的切換。線程切換主要做了兩件事:一是舊線程執行環境的保存,二是新線程執行環境的恢復。執行環境主要指寄存器,棧的切換也是通過寄存器的切換來完成的。
            非搶占式用戶級線程可以使用兩類接口來實現: longjmp和setjmp; swapcontext,makecontext,setcontext. 在此不再贅述。
            搶占式用戶級線程切換
            線程切換的時機。 切換分兩種,一種是主動切換,一種是被動切換。主動切換是非搶占式的;被動切換發生在時間片用完之后,一個線程的時間片用完后就要強行切換到另外的線程。那么被動切換很自然的要發生在時鐘中斷里。在linux里面我們使用alarm信號。既然如此,趕快動手吧。
            void timeHandler (int signo)
            {  
                thread_list 
            *  old;    if(signo != SIGALRM) return ;   
                signal(SIGALRM,timeHandler);   
                //! 如果有結束了的線程,釋放該線程。
                ...   

                old  
            =  sys.current;
                
            if(old == 0){
                    
            if(sys.threads){
                        sys.current  
            =  sys.threads;
                        longjmp(sys.current 
            -> thread.buf,  1 );
                    }
                }
            else{
                    sys.current  
            =  GetNext(sys.current)
                    
            if(sys.current){
                        
            if  (!setjmp(old -> thread.buf,1)){
                            longjmp(sys.current 
            -> thread.buf,  1 );
                        }
                    }
                }
            }
            我們會很悲觀的發現,alarm信號只發生了一此。問題出在哪兒呢?原來linux的信號是不可重入的。進入信號處理函數之前,該信號被屏蔽,退出該信號處理函數之后該信號重新開放。而在信號處理函數中發生longjmp后,程序就跳轉到其他線程,該信號處理函數不能退出。為了能再次進入信號處理函數,我們在切換之前就要重新開放該信號。我們可以使用siglongjmp/sigsetjmp代替longjmp/setjmp.
            雖然該方法能夠實現搶占功能,但總讓人覺得不舒服。沒有退出的信號處理函數讓人如骨鯁在喉。有沒有更優美的方法呢?
            先來看一下信號處理的流程:以alarm信號為例。
            1。 alarm信號到達,執行權由用戶空間進入內核空間,棧自動切換到內核棧(內核棧指針存放在TSS結構的ESP0中)。同時用戶空間的執行環境存放到內核棧中。
            2。 內核進行一些信號相關工作。 最后發現我們注冊了alarm信號的處理函數,然后建立執行信號handler的棧環境(通常在用戶棧棧頂),將已經保存在內核棧中的用戶執行環境復制到信號處理函數棧。 然后通過reti從內核返回到用戶空間,恢復用戶空間執行環境,執行信號處理函數。
            3。 執行完信號處理函數后,再次進入內核,注意此次進入內核后,內核棧會再次自動保存用戶空間執行環境,但這不是我們需要的。所以內核會將信號處理函數棧中的用戶執行環境復制回內核棧。
            4。  再次從內核空間切換到用戶空間,用戶執行環境自動恢復到alarm信號到達時的執行狀態。
            分析后我們會發現,當我們執行信號處理函數時,棧頂是保存了用戶執行環境的,通過更換這個執行環境,就可以達到用戶態線程切換的目的。
            #include <sys/ucontext.h>
            # if __WORDSIZE == 64
            #define OFFSET_TO_SIGCONTEXT 7 
            # else
            #define OFFSET_TO_SIGCONTEXT 3 
            # endif
            void
             timeHandler (int signo)
            {
                unsigned 
            int i, j;
                sigcontext
            * psig_context;        
                if(signo != SIGALRM) return ;
                signal(SIGALRM,timeHandler);
                __asm( 
            "lea (%%" bp_register ", %1), %0":"=r"(psig_context): "r"(OFFSET_TO_SIGCONTEXT* sizeof(ptr_size*)));
                schedule(psig_context);

            }
            用戶執行環境用sigcontext結構體來描述, 在64位系統中,該結構體位于 RBP + 7*8 位置處; 在32位系統中位于EBP+3*4位置處。 __asm( "lea (%%" bp_register ", %1), %0":"=r"(psig_context): "r"(OFFSET_TO_SIGCONTEXT* sizeof(ptr_size*))); 用于獲得該結構體指針,然后就可以傳到 調度函數用戶線程切換了。
            欧美午夜精品久久久久久浪潮| 国产69精品久久久久久人妻精品| 合区精品久久久中文字幕一区| 成人精品一区二区久久| 久久99精品九九九久久婷婷| 一本色道久久88综合日韩精品 | 久久99国产精品一区二区| 欧美精品一本久久男人的天堂| 精品无码久久久久久久动漫| 久久久久无码国产精品不卡| 蜜臀av性久久久久蜜臀aⅴ麻豆 | 亚洲国产精品综合久久网络 | 99久久国产亚洲综合精品| 99久久免费国产精精品| 久久久精品国产免大香伊 | 久久天天日天天操综合伊人av| 久久久久高潮毛片免费全部播放 | 久久91精品综合国产首页| 国产成人无码精品久久久性色| 日本免费一区二区久久人人澡| 99久久99久久精品国产片果冻| 国内精品久久久久久久久电影网| 久久久久亚洲Av无码专| 九九精品久久久久久噜噜| 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区 | 手机看片久久高清国产日韩| 久久久久久免费一区二区三区| 国产精品99久久久精品无码| 精品免费久久久久国产一区| 精品免费久久久久久久| 亚洲AV无码久久精品色欲| 中文国产成人精品久久不卡| 久久99精品国产麻豆婷婷| 日本精品久久久久中文字幕| jizzjizz国产精品久久| 亚洲欧美日韩中文久久| 狠狠色丁香婷婷久久综合五月| 久久久久亚洲AV无码去区首| 精品久久人人妻人人做精品| a高清免费毛片久久| 国产精品国色综合久久|