精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一篇關于Semaphore 的原理與實現

開發 后端
在這個 treap 結構里,從 elem 的視角(其實就是 lock 的 addr)來看,這個結構是個二叉搜索樹。從 ticket 的角度來看,整個結構就是一個小頂堆。所以才叫樹堆(treap)。

[[399540]]

本文轉載自微信公眾號「碼農桃花源」,作者曹春暉。轉載本文請聯系碼農桃花源公眾號。

Semaphore

數據結構

  1. // Go 語言中暴露的 semaphore 實現 
  2. // 具體的用法是提供 sleep 和 wakeup 原語 
  3. // 以使其能夠在其它同步原語中的競爭情況下使用 
  4. // 因此這里的 semaphore 和 Linux 中的 futex 目標是一致的 
  5. // 只不過語義上更簡單一些 
  6. // 
  7. // 也就是說,不要認為這些是信號量 
  8. // 把這里的東西看作 sleep 和 wakeup 實現的一種方式 
  9. // 每一個 sleep 都會和一個 wakeup 配對 
  10. // 即使在發生 race 時,wakeup 在 sleep 之前時也是如此 
  11. // 
  12. // See Mullender and Cox, ``Semaphores in Plan 9,'' 
  13. // http://swtch.com/semaphore.pdf 
  14.  
  15. // 為 sync.Mutex 準備的異步信號量 
  16.  
  17. // semaRoot 持有一棵 地址各不相同的 sudog(s.elem) 的平衡樹 
  18. // 每一個 sudog 都反過來指向(通過 s.waitlink)一個在同一個地址上等待的其它 sudog 們 
  19. // 同一地址的 sudog 的內部列表上的操作時間復雜度都是 O(1)。頂層 semaRoot 列表的掃描 
  20. // 的時間復雜度是 O(log n),n 是被哈希到同一個 semaRoot 的不同地址的總數,每一個地址上都會有一些 goroutine 被阻塞。 
  21. // 訪問 golang.org/issue/17953 來查看一個在引入二級列表之前性能較差的程序樣例,test/locklinear.go 
  22. // 中有一個復現這個樣例的測試 
  23. type semaRoot struct { 
  24.     lock  mutex 
  25.     treap *sudog // root of balanced tree of unique waiters. 
  26.     nwait uint32 // Number of waiters. Read w/o the lock. 
  27.  
  28. // Prime to not correlate with any user patterns. 
  29. const semTabSize = 251 
  30.  
  31. var semtable [semTabSize]struct { 
  32.     root semaRoot 
  33.     pad  [sys.CacheLineSize - unsafe.Sizeof(semaRoot{})]byte 
  34.  
  35. func semroot(addr *uint32) *semaRoot { 
  36.     return &semtable[(uintptr(unsafe.Pointer(addr))>>3)%semTabSize].root 
  1. ┌─────┬─────┬─────┬─────┬─────┬────────────────────────┬─────┐                  
  2. │  0  │  1  │  2  │  3  │  4  │         .....          │ 250 │                  
  3. └─────┴─────┴─────┴─────┴─────┴────────────────────────┴─────┘                  
  4.    │                                                      │                     
  5.    │                                                      │                     
  6.    └──┐                                                   └─┐                   
  7.       │                                                     │                   
  8.       │                                                     │                   
  9.       ▼                                                     ▼                   
  10.  ┌─────────┐                                           ┌─────────┐              
  11.  │ struct  │                                           │ struct  │              
  12.  ├─────────┴─────────┐                                 ├─────────┴─────────┐    
  13.  │   root semaRoot   │──┐                              │   root semaRoot   │──┐ 
  14.  ├───────────────────┤  │                              ├───────────────────┤  │ 
  15.  │        pad        │  │                              │        pad        │  │ 
  16.  └───────────────────┘  │                              └───────────────────┘  │ 
  17.                         │                                                     │ 
  18.        ┌────────────────┘                                    ┌────────────────┘ 
  19.        │                                                     │                  
  20.        │                                                     │                  
  21.        ▼                                                     ▼                  
  22.  ┌──────────┐                                          ┌──────────┐             
  23.  │ semaRoot │                                          │ semaRoot │             
  24.  ├──────────┴────────┐                                 ├──────────┴────────┐    
  25.  │    lock mutex     │                                 │    lock mutex     │    
  26.  ├───────────────────┤                                 ├───────────────────┤    
  27.  │   treap *sudog    │                                 │   treap *sudog    │    
  28.  ├───────────────────┤                                 ├───────────────────┤    
  29.  │   nwait uint32    │                                 │   nwait uint32    │    
  30.  └───────────────────┘                                 └───────────────────┘ 

treap 結構:

  1.                                  ┌──────────┐                                     
  2.                             ┌─┬─▶│  sudog   │                                     
  3.                             │ │  ├──────────┴────────────┐                        
  4.       ┌─────────────────────┼─┼──│      prev *sudog      │                        
  5.       │                     │ │  ├───────────────────────┤                        
  6.       │                     │ │  │      next *sudog      │────┐                   
  7.       │                     │ │  ├───────────────────────┤    │                   
  8.       │                     │ │  │     parent *sudog     │    │                   
  9.       │                     │ │  ├───────────────────────┤    │                   
  10.       │                     │ │  │  elem unsafe.Pointer  │    │                   
  11.       │                     │ │  ├───────────────────────┤    │                   
  12.       │                     │ │  │     ticket uint32     │    │                   
  13.       │                     │ │  └───────────────────────┘    │                   
  14.       │                     │ │                               │                   
  15.       │                     │ │                               │                   
  16.       │                     │ │                               │                   
  17.       │                     │ │                               │                   
  18.       │                     │ │                               │                   
  19.       │                     │ │                               │                   
  20.       ▼                     │ │                               ▼                   
  21. ┌──────────┐                │ │                         ┌──────────┐              
  22. │  sudog   │                │ │                         │  sudog   │              
  23. ├──────────┴────────────┐   │ │                         ├──────────┴────────────┐ 
  24. │      prev *sudog      │   │ │                         │      prev *sudog      │ 
  25. ├───────────────────────┤   │ │                         ├───────────────────────┤ 
  26. │      next *sudog      │   │ │                         │      next *sudog      │ 
  27. ├───────────────────────┤   │ │                         ├───────────────────────┤ 
  28. │     parent *sudog     │───┘ └─────────────────────────│     parent *sudog     │ 
  29. ├───────────────────────┤                               ├───────────────────────┤ 
  30. │  elem unsafe.Pointer  │                               │  elem unsafe.Pointer  │ 
  31. ├───────────────────────┤                               ├───────────────────────┤ 
  32. │     ticket uint32     │                               │     ticket uint32     │ 
  33. └───────────────────────┘                               └───────────────────────┘ 

在這個 treap 結構里,從 elem 的視角(其實就是 lock 的 addr)來看,這個結構是個二叉搜索樹。從 ticket 的角度來看,整個結構就是一個小頂堆。

所以才叫樹堆(treap)。

相同 addr,即對同一個 mutex 上鎖的 g,會阻塞在同一個地址上。這些阻塞在同一個地址上的 goroutine 會被打包成 sudog,組成一個鏈表。用 sudog 的 waitlink 相連:

  1. ┌──────────┐                         ┌──────────┐                          ┌──────────┐              
  2. │  sudog   │                  ┌─────▶│  sudog   │                   ┌─────▶│  sudog   │              
  3. ├──────────┴────────────┐     │      ├──────────┴────────────┐      │      ├──────────┴────────────┐ 
  4. │    waitlink *sudog    │─────┘      │    waitlink *sudog    │──────┘      │    waitlink *sudog    │ 
  5. ├───────────────────────┤            ├───────────────────────┤             ├───────────────────────┤ 
  6. │    waittail *sudog    │            │    waittail *sudog    │             │    waittail *sudog    │ 
  7. └───────────────────────┘            └───────────────────────┘             └───────────────────────┘ 

中間的元素的 waittail 都會指向最后一個元素:

  1. ┌──────────┐                                                                                            
  2. │  sudog   │                                                                                            
  3. ├──────────┴────────────┐                                                                               
  4. │    waitlink *sudog    │                                                                               
  5. ├───────────────────────┤                                                                               
  6. │    waittail *sudog    │───────────────────────────────────────────────────────────┐                   
  7. └───────────────────────┘                                                           │                   
  8.                                   ┌──────────┐                                      │                   
  9.                                   │  sudog   │                                      │                   
  10.                                   ├──────────┴────────────┐                         │                   
  11.                                   │    waitlink *sudog    │                         │                   
  12.                                   ├───────────────────────┤                         │                   
  13.                                   │    waittail *sudog    │─────────────────────────┤                   
  14.                                   └───────────────────────┘                         ▼                   
  15.                                                                               ┌──────────┐              
  16.                                                                               │  sudog   │              
  17.                                                                               ├──────────┴────────────┐ 
  18.                                                                               │    waitlink *sudog    │ 
  19.                                                                               ├───────────────────────┤ 
  20.                                                                               │    waittail *sudog    │ 
  21.                                                                               └───────────────────────┘ 

對外封裝

在 sema.go 里實現的內容,用 go:linkname 導出給 sync、poll 庫來使用,也是在鏈接期做了些手腳:

  1. //go:linkname sync_runtime_Semacquire sync.runtime_Semacquire 
  2. func sync_runtime_Semacquire(addr *uint32) { 
  3.     semacquire1(addr, false, semaBlockProfile) 
  4.  
  5. //go:linkname poll_runtime_Semacquire internal/poll.runtime_Semacquire 
  6. func poll_runtime_Semacquire(addr *uint32) { 
  7.     semacquire1(addr, false, semaBlockProfile) 
  8.  
  9. //go:linkname sync_runtime_Semrelease sync.runtime_Semrelease 
  10. func sync_runtime_Semrelease(addr *uint32, handoff bool) { 
  11.     semrelease1(addr, handoff) 
  12.  
  13. //go:linkname sync_runtime_SemacquireMutex sync.runtime_SemacquireMutex 
  14. func sync_runtime_SemacquireMutex(addr *uint32, lifo bool) { 
  15.     semacquire1(addr, lifo, semaBlockProfile|semaMutexProfile) 
  16.  
  17. //go:linkname poll_runtime_Semrelease internal/poll.runtime_Semrelease 
  18. func poll_runtime_Semrelease(addr *uint32) { 
  19.     semrelease(addr) 

實現

sem 本身支持 acquire 和 release,其實就是 OS 里常說的 P 操作和 V 操作。

公共部分

  1. func cansemacquire(addr *uint32) bool { 
  2.     for { 
  3.         v := atomic.Load(addr) 
  4.         if v == 0 { 
  5.             return false 
  6.         } 
  7.         if atomic.Cas(addr, v, v-1) { 
  8.             return true 
  9.         } 
  10.     } 

acquire 過程

  1. type semaProfileFlags int 
  2.  
  3. const ( 
  4.     semaBlockProfile semaProfileFlags = 1 << iota 
  5.     semaMutexProfile 
  6.  
  7. // Called from runtime. 
  8. func semacquire(addr *uint32) { 
  9.     semacquire1(addr, false, 0) 
  10.  
  11. func semacquire1(addr *uint32, lifo bool, profile semaProfileFlags) { 
  12.     gp := getg() 
  13.     if gp != gp.m.curg { 
  14.         throw("semacquire not on the G stack"
  15.     } 
  16.  
  17.     // 低成本的情況 
  18.     if cansemacquire(addr) { 
  19.         return 
  20.     } 
  21.  
  22.     // 高成本的情況: 
  23.     //    增加 waiter count 的值 
  24.     //    再嘗試調用一次 cansemacquire,成本了就直接返回 
  25.     //    沒成功就把自己作為一個 waiter 入隊 
  26.     //    sleep 
  27.     //    (之后 waiter 的 descriptor 被 signaler 用 dequeue 踢出) 
  28.     s := acquireSudog() 
  29.     root := semroot(addr) 
  30.     t0 := int64(0) 
  31.     s.releasetime = 0 
  32.     s.acquiretime = 0 
  33.     s.ticket = 0 
  34.  
  35.     for { 
  36.         lock(&root.lock) 
  37.         // 給 nwait 加一,這樣后來的就不會在 semrelease 中進低成本的路徑了 
  38.         atomic.Xadd(&root.nwait, 1) 
  39.         // 檢查 cansemacquire 避免錯過了喚醒 
  40.         if cansemacquire(addr) { 
  41.             atomic.Xadd(&root.nwait, -1) 
  42.             unlock(&root.lock) 
  43.             break 
  44.         } 
  45.         // 在 cansemacquire 之后的 semrelease 都可以知道我們正在等待 
  46.         // (上面設置了 nwait),所以會直接進入 sleep 
  47.         // 注: 這里說的 sleep 其實就是 goparkunlock 
  48.         root.queue(addr, s, lifo) 
  49.         goparkunlock(&root.lock, "semacquire", traceEvGoBlockSync, 4) 
  50.         if s.ticket != 0 || cansemacquire(addr) { 
  51.             break 
  52.         } 
  53.     } 
  54.     if s.releasetime > 0 { 
  55.         blockevent(s.releasetime-t0, 3) 
  56.     } 
  57.     releaseSudog(s) 

release 過程

  1. func semrelease(addr *uint32) { 
  2.     semrelease1(addr, false
  3.  
  4. func semrelease1(addr *uint32, handoff bool) { 
  5.     root := semroot(addr) 
  6.     atomic.Xadd(addr, 1) 
  7.  
  8.     // 低成本情況: 沒有 waiter? 
  9.     // 這個 atomic 的檢查必須發生在 xadd 之前,以避免錯誤喚醒 
  10.     // (具體參見 semacquire 中的循環) 
  11.     if atomic.Load(&root.nwait) == 0 { 
  12.         return 
  13.     } 
  14.  
  15.     // 高成本情況: 搜索 waiter 并喚醒它 
  16.     lock(&root.lock) 
  17.     if atomic.Load(&root.nwait) == 0 { 
  18.         // count 值已經被另一個 goroutine 消費了 
  19.         // 所以我們不需要喚醒其它 goroutine 了 
  20.         unlock(&root.lock) 
  21.         return 
  22.     } 
  23.     s, t0 := root.dequeue(addr) 
  24.     if s != nil { 
  25.         atomic.Xadd(&root.nwait, -1) 
  26.     } 
  27.     unlock(&root.lock) 
  28.     if s != nil { // 可能會很慢,所以先解鎖 
  29.         acquiretime := s.acquiretime 
  30.         if acquiretime != 0 { 
  31.             mutexevent(t0-acquiretime, 3) 
  32.         } 
  33.         if s.ticket != 0 { 
  34.             throw("corrupted semaphore ticket"
  35.         } 
  36.         if handoff && cansemacquire(addr) { 
  37.             s.ticket = 1 
  38.         } 
  39.         readyWithTime(s, 5) 
  40.     } 
  41.  
  42. func readyWithTime(s *sudog, traceskip int) { 
  43.     if s.releasetime != 0 { 
  44.         s.releasetime = cputicks() 
  45.     } 
  46.     goready(s.g, traceskip) 

treap 結構

sudog 按照地址 hash 到 251 個 bucket 中的其中一個,每一個 bucket 都是一棵 treap。而相同 addr 上的 sudog 會形成一個鏈表。

為啥同一個地址的 sudog 不需要展開放在 treap 中呢?顯然,sudog 喚醒的時候,block 在同一個 addr 上的 goroutine,說明都是加的同一把鎖,這些 goroutine 被喚醒肯定是一起被喚醒的,相同地址的 g 并不需要查找才能找到,只要決定是先進隊列的被喚醒(fifo)還是后進隊列的被喚醒(lifo)就可以了。

  1. // queue 函數會把 s 添加到 semaRoot 上阻塞的 goroutine 們中 
  2. // 實際上就是把 s 添加到其地址對應的 treap 上 
  3. func (root *semaRoot) queue(addr *uint32, s *sudog, lifo bool) { 
  4.     s.g = getg() 
  5.     s.elem = unsafe.Pointer(addr) 
  6.     s.next = nil 
  7.     s.prev = nil 
  8.  
  9.     var last *sudog 
  10.     pt := &root.treap 
  11.     for t := *pt; t != nil; t = *pt { 
  12.         if t.elem == unsafe.Pointer(addr) { 
  13.             // Already have addr in list. 
  14.             if lifo { 
  15.                 // treap 中在 t 的位置用 s 覆蓋掉 t 
  16.                 *pt = s 
  17.                 s.ticket = t.ticket 
  18.                 s.acquiretime = t.acquiretime 
  19.                 s.parent = t.parent 
  20.                 s.prev = t.prev 
  21.                 s.next = t.next 
  22.                 if s.prev != nil { 
  23.                     s.prev.parent = s 
  24.                 } 
  25.                 if s.next != nil { 
  26.                     s.next.parent = s 
  27.                 } 
  28.                 // 把 t 放在 s 的 wait list 的第一個位置 
  29.                 s.waitlink = t 
  30.                 s.waittail = t.waittail 
  31.                 if s.waittail == nil { 
  32.                     s.waittail = t 
  33.                 } 
  34.                 t.parent = nil 
  35.                 t.prev = nil 
  36.                 t.next = nil 
  37.                 t.waittail = nil 
  38.             } else { 
  39.                 // 把 s 添加到 t 的等待列表的末尾 
  40.                 if t.waittail == nil { 
  41.                     t.waitlink = s 
  42.                 } else { 
  43.                     t.waittail.waitlink = s 
  44.                 } 
  45.                 t.waittail = s 
  46.                 s.waitlink = nil 
  47.             } 
  48.             return 
  49.         } 
  50.         last = t 
  51.         if uintptr(unsafe.Pointer(addr)) < uintptr(t.elem) { 
  52.             pt = &t.prev 
  53.         } else { 
  54.             pt = &t.next 
  55.         } 
  56.     } 
  57.  
  58.     // 把 s 作為樹的新的葉子插入進去 
  59.     // 平衡樹使用 ticket 作為堆的權重值,這個 ticket 是隨機生成的 
  60.     // 也就是說,這個結構以元素地址來看的話,是一個二叉搜索樹 
  61.     // 同時用 ticket 值使其同時又是一個小頂堆,滿足 
  62.     // s.ticket <= both s.prev.ticket and s.next.ticket. 
  63.     // https://en.wikipedia.org/wiki/Treap 
  64.     // http://faculty.washington.edu/aragon/pubs/rst89.pdf 
  65.     // 
  66.     // s.ticket 會在一些地方和 0 相比,因此只設置最低位的 bit 
  67.     // 這樣不會明顯地影響 treap 的質量? 
  68.     s.ticket = fastrand() | 1 
  69.     s.parent = last 
  70.     *pt = s 
  71.  
  72.     // 按照 ticket 來進行旋轉,以滿足 treap 的性質 
  73.     for s.parent != nil && s.parent.ticket > s.ticket { 
  74.         if s.parent.prev == s { 
  75.             root.rotateRight(s.parent) 
  76.         } else { 
  77.             if s.parent.next != s { 
  78.                 panic("semaRoot queue"
  79.             } 
  80.             root.rotateLeft(s.parent) 
  81.         } 
  82.     } 
  83.  
  84. // dequeue 會搜索到阻塞在 addr 地址的 semaRoot 中的第一個 goroutine 
  85. // 如果這個 sudog 需要進行 profile,dequeue 會返回它被喚醒的時間(now),否則的話 now 為 0 
  86. func (root *semaRoot) dequeue(addr *uint32) (found *sudog, now int64) { 
  87.     ps := &root.treap 
  88.     s := *ps 
  89.     for ; s != nil; s = *ps { 
  90.         if s.elem == unsafe.Pointer(addr) { 
  91.             goto Found 
  92.         } 
  93.         if uintptr(unsafe.Pointer(addr)) < uintptr(s.elem) { 
  94.             ps = &s.prev 
  95.         } else { 
  96.             ps = &s.next 
  97.         } 
  98.     } 
  99.     return nil, 0 
  100.  
  101. Found: 
  102.     now = int64(0) 
  103.     if s.acquiretime != 0 { 
  104.         now = cputicks() 
  105.     } 
  106.     if t := s.waitlink; t != nil { 
  107.         // 替換掉同樣在 addr 上等待的 t。 
  108.         *ps = t 
  109.         t.ticket = s.ticket 
  110.         t.parent = s.parent 
  111.         t.prev = s.prev 
  112.         if t.prev != nil { 
  113.             t.prev.parent = t 
  114.         } 
  115.         t.next = s.next 
  116.         if t.next != nil { 
  117.             t.next.parent = t 
  118.         } 
  119.         if t.waitlink != nil { 
  120.             t.waittail = s.waittail 
  121.         } else { 
  122.             t.waittail = nil 
  123.         } 
  124.         t.acquiretime = now 
  125.         s.waitlink = nil 
  126.         s.waittail = nil 
  127.     } else { 
  128.         // 向下旋轉 s 到葉節點,以進行刪除,同時要考慮優先級 
  129.         for s.next != nil || s.prev != nil { 
  130.             if s.next == nil || s.prev != nil && s.prev.ticket < s.next.ticket { 
  131.                 root.rotateRight(s) 
  132.             } else { 
  133.                 root.rotateLeft(s) 
  134.             } 
  135.         } 
  136.         // Remove s, now a leaf. 
  137.         // 刪除 s,現在是葉子節點了 
  138.         if s.parent != nil { 
  139.             if s.parent.prev == s { 
  140.                 s.parent.prev = nil 
  141.             } else { 
  142.                 s.parent.next = nil 
  143.             } 
  144.         } else { 
  145.             root.treap = nil 
  146.         } 
  147.     } 
  148.     s.parent = nil 
  149.     s.elem = nil 
  150.     s.next = nil 
  151.     s.prev = nil 
  152.     s.ticket = 0 
  153.     return s, now 

 

責任編輯:武曉燕 來源: 碼農桃花源
相關推薦

2021-09-05 07:55:36

Lsm核心實現

2022-04-08 08:32:40

mobx狀態管理庫redux

2021-04-08 11:00:56

CountDownLaJava進階開發

2021-09-15 19:05:16

數據開源項目

2022-05-25 08:31:31

ArthasInstrument

2021-10-11 11:08:33

HDFS快照系統

2021-08-11 07:02:21

npm包管理器工具

2019-07-02 05:02:56

NVMe接口存儲

2022-07-14 14:18:59

Kubernetes架構

2019-04-01 08:15:21

Java線程池多核處理器

2022-05-08 19:58:10

JSONPJavaScript

2021-08-27 07:47:06

SQL靜態程序

2022-02-18 08:54:21

docker操作系統Linux

2022-11-08 10:52:25

Flowable節點表單

2021-07-12 10:36:36

Blazor組件入門

2022-04-02 09:38:00

CSS3flex布局方式

2021-04-18 18:03:06

工作樹遠程版本

2021-09-08 09:22:34

SentryCLIOS

2021-12-04 22:05:02

Linux

2022-05-17 08:02:55

GoTryLock模式
點贊
收藏

51CTO技術棧公眾號

色香蕉久久蜜桃| 97国产一区二区| www.99久久热国产日韩欧美.com| 一道本在线免费视频| 国内精品不卡| 不卡在线观看av| 国产精品高清免费在线观看| 在线观看亚洲网站| 国产一区在线电影| 在线观看www91| 麻豆一区二区三区在线观看| 天堂中文在线资源| 蜜桃免费网站一区二区三区| 欧美日韩成人免费| 91精品久久久久久久久久久久| 中文字幕一区日韩精品| 在线一区二区三区做爰视频网站| 国产一二三四五| 黄色av网站在线免费观看| 国产精品99久久久久久有的能看 | 高清日韩av电影| 国产成人超碰人人澡人人澡| 国产精品中文久久久久久久| 国产一级做a爱片久久毛片a| 久久久久久久久久久妇女| 亚洲男人天堂久| 涩视频在线观看| 亚洲青青一区| 在线观看视频一区二区| 少妇人妻大乳在线视频| 黄色一级大片在线免费看产| 国产欧美日韩三区| 久久精品午夜一区二区福利| 国产ts人妖调教重口男| 麻豆一区二区在线| 国产精品99久久久久久白浆小说 | 99国产在线视频| 中文字幕一区二区三区波野结| 国产精品日韩久久久| 欧美日韩国产成人高清视频| 182在线观看视频| 欧美肉体xxxx裸体137大胆| 日韩成人在线观看| 超碰caoprom| 大香伊人久久精品一区二区| 日韩欧美国产三级| 波多野结衣中文字幕在线播放| 黄页免费欧美| 欧美日韩一区三区| 性刺激的欧美三级视频| 日韩不卡在线| 欧美三电影在线| 91小视频网站| 日韩欧乱色一区二区三区在线| 欧美日韩国产天堂| 国产成人美女视频| www 久久久| 日韩欧美国产午夜精品| zjzjzjzjzj亚洲女人| 成人爽a毛片| 亚洲大胆人体在线| 日本japanese极品少妇| 婷婷亚洲成人| 亚洲网站在线播放| 开心激情五月网| 中文字幕av亚洲精品一部二部| 欧美成人h版在线观看| 欧美日韩偷拍视频| 91久久视频| 日本精品视频在线观看| 波多野结衣网站| 久久狠狠亚洲综合| 亚洲资源在线看| 日本精品久久久久久| 26uuuu精品一区二区| 色吧亚洲视频| 成人在线免费看黄| 亚洲成a人片在线观看中文| 日韩欧美精品在线观看视频| 成人亚洲免费| 欧美成人aa大片| 中文字幕在线免费看线人| 欧美亚洲国产激情| 麻豆乱码国产一区二区三区| 日本五十路女优| 日日摸夜夜添夜夜添精品视频| 国产有码在线一区二区视频| 狠狠综合久久av一区二区| 久久久九九九九| 国产奶头好大揉着好爽视频| 91桃色在线| 欧美日韩在线播放一区| 亚洲AV成人精品| 久久av中文| 欧美激情第99页| 国产日韩在线免费观看| 国产精品1024| 日韩av电影免费在线观看| 性爱视频在线播放| 在线免费观看不卡av| 佐山爱在线视频| 国产一区毛片| 97在线看免费观看视频在线观看| 中文字幕av网站| 成人黄页在线观看| 亚洲乱码国产乱码精品天美传媒| 免费在线播放电影| 欧美日韩中文字幕一区二区| 国产av一区二区三区传媒| 日本大胆欧美| 26uuu久久噜噜噜噜| 99er热精品视频| 国产日韩在线不卡| www.日本在线播放| 视频精品一区| 综合网中文字幕| 亚洲婷婷综合网| 国产成人精品免费| 亚洲国产精品影视| 亚洲a∨精品一区二区三区导航| 精品国产髙清在线看国产毛片| 国产又粗又猛又爽又黄的视频小说| 亚洲东热激情| 91九色在线免费视频| av网站大全在线观看| 欧美性生活大片免费观看网址| 黄色片子免费看| 久久综合电影| 国产精品视频网| 国产午夜在线视频| 一本久久a久久精品亚洲| 色哟哟视频在线| 韩日精品视频| 99在线免费观看视频| 日本中文字幕在线观看| 在线免费观看日本欧美| 黄色aaa视频| 香蕉久久久久久久av网站| 国产久一道中文一区| 欧美xxxx黑人又粗又长| 日韩欧美中文字幕制服| 久久免费看少妇高潮v片特黄| 久久成人av少妇免费| 亚洲国产激情一区二区三区| 欧美色片在线观看| 亚洲网站视频福利| 羞羞色院91蜜桃| 中文字幕的久久| 成年网站在线播放| 成人久久电影| 91精品国产自产在线老师啪| 欧美午夜电影一区二区三区| 51精品秘密在线观看| 91 在线视频| 国产成人在线色| 国产真实老熟女无套内射| 国产成人aa在线观看网站站| 国内揄拍国内精品少妇国语| 深夜福利视频网站| 欧美丝袜一区二区| 一色道久久88加勒比一| 麻豆一区二区三区| 超级碰在线观看| 国内精品麻豆美女在线播放视频| 高清欧美性猛交| 天堂a√在线| 无码av免费一区二区三区试看 | 天堂在线中文字幕| 日本精品视频一区二区三区| 欧美巨胸大乳hitomi| 国产在线精品一区二区夜色 | 中文字幕一区久| 国产一区二区激情| 国产麻豆免费视频| 午夜精品久久久久久久久久久 | 欧美在线视频观看免费网站| 激情在线视频| 欧美一区二区三区的| 国产成人无码精品久在线观看| 91毛片在线观看| www.久久久久久久久久久| 欧美午夜国产| 欧美一区二区三区精美影视 | 亚洲电影中文字幕| 日本免费精品视频| 亚洲免费视频成人| 深爱五月激情网| 国产精品中文欧美| 国产a级一级片| 99视频精品视频高清免费| 国产精品日韩一区二区免费视频| 欧美舌奴丨vk视频| 欧美成人手机在线| 国产免费视频在线| 欧美精品一区二区久久婷婷 | 欧美精品一区二区久久久| 不卡av电影在线| 一区av在线播放| avhd101老司机| 粉嫩av一区二区三区粉嫩| 天天操天天摸天天爽| 亚洲午夜精品久久久久久app| 日韩欧美一区二区视频在线播放| 9l视频自拍蝌蚪9l视频成人| 国产精品欧美日韩久久| 草草视频在线| 超碰97人人做人人爱少妇| 精品亚洲综合| 亚洲国产精品999| 国产精品视频无码| 色婷婷亚洲精品| 亚欧视频在线观看| 亚洲激情综合网| 精品人体无码一区二区三区| 91丝袜呻吟高潮美腿白嫩在线观看| 99久久99精品| 免费人成精品欧美精品| 免费在线观看日韩视频| 亚洲第一伊人| 久久亚洲a v| 91精品国产91久久久久久黑人| 欧美日韩在线观看一区| 欧美wwwsss9999| 国产乱码一区| av不卡一区二区| 999视频在线免费观看| 日韩久久一区| 成人黄色免费在线观看| 日韩精品第一| 日本高清视频精品| 美女av在线免费看| 98精品在线视频| 国产在线天堂www网在线观看| 欧美大片在线看| 午夜伦理大片视频在线观看| 久久九九亚洲综合| 麻豆网站在线看| 日韩三级成人av网| 日本亚洲精品| 精品国产美女在线| www免费视频观看在线| 按摩亚洲人久久| 精品视频在线一区二区| 久久精品99久久久久久久久 | 97超碰国产精品女人人人爽 | 亚洲精品tv久久久久久久久久| 色阁综合av| 国产精品国产一区| 久久久国产精华液999999| 午夜av一区| avove在线观看| 亚洲一级二级| www一区二区www免费| 国产亚洲成人一区| 日韩av在线综合| 奇米在线7777在线精品| 中文字幕亚洲欧洲| 国内精品久久久久影院色| 国产九九九视频| 国产成a人亚洲精| 99久久人妻精品免费二区| 久久久无码精品亚洲日韩按摩| 小早川怜子久久精品中文字幕| 国产精品国产三级国产普通话蜜臀 | 伦伦影院午夜理论片| 国产成人在线免费观看| 给我免费观看片在线电影的| 久久精品亚洲乱码伦伦中文| 99久久99久久精品免费看小说.| 亚洲欧洲韩国日本视频| 欧美黄色免费看| 欧美视频专区一二在线观看| 中文字幕在线观看欧美| 欧美成人一区二区三区片免费 | 亚洲一区在线观| 日韩三级免费观看| 欧洲一区av| 久久天堂电影网| 久草免费在线视频| 国产精品久久久久一区二区| 日韩欧美久久| 免费看成人片| 自拍日韩欧美| 91免费视频网站在线观看| 久久精品国产精品亚洲综合| 稀缺小u女呦精品呦| 中文字幕欧美国产| 久久久久香蕉视频| 欧美午夜不卡视频| 狠狠躁夜夜躁av无码中文幕| 在线日韩中文字幕| 人交獸av完整版在线观看| 国产99久久精品一区二区| 国产精品欧美一区二区三区不卡| 久久精品日产第一区二区三区精品版| 999国产精品999久久久久久| 免费国产a级片| 精品一区二区日韩| 自拍偷拍亚洲天堂| 亚洲成人精品影院| 国产又粗又大又爽| 亚洲欧美国产视频| 男女在线观看视频| 国产精品一区二区3区| 亚洲国产网址| 成年人视频网站免费| 麻豆国产91在线播放| 人人妻人人澡人人爽人人精品 | 日韩有码视频在线| 亚洲天堂av影院| 99re在线国产| 99精品美女| 一区二区在线播放视频| 成人18视频在线播放| 99视频只有精品| 欧美日韩一区二区三区四区| 欧洲成人av| 91精品国产高清久久久久久| 一区二区视频| 自拍偷拍视频在线| 毛片av一区二区| 日本二区在线观看| 欧美性极品xxxx娇小| 亚洲av无码乱码国产精品久久| 日韩视频在线免费| 国产69精品久久| 涩涩日韩在线| 久久久一二三| 国产特级黄色录像| 黑丝美女久久久| 亚洲欧洲成人在线| 久久久噜噜噜久久中文字免| 最新国产一区二区| 国内自拍中文字幕| 国产精品一区二区在线观看不卡| 看黄色录像一级片| 91精品欧美一区二区三区综合在 | 亚洲最大av| 天天做天天干天天操| 亚洲欧洲成人精品av97| 国产永久免费视频| 久久色精品视频| 电影一区二区三区久久免费观看| 一区二区不卡在线视频 午夜欧美不卡' | 天天看天天摸天天操| 亚洲情趣在线观看| 国产精品国产三级国产普通话对白 | 国产在线一区二区三区| 91综合视频| 黄色a级三级三级三级| 亚洲精品成人天堂一二三| 国产黄色av网站| 久久久久久有精品国产| 免费日韩一区二区三区| 日本在线观看a| 国产欧美一区二区三区在线看蜜臀 | 丝袜美腿诱惑一区二区三区| 日本精品视频一区| 久久福利视频一区二区| 日韩三级在线观看视频| 欧美zozozo| 水蜜桃在线视频| 日韩福利影院| 久久91精品久久久久久秒播| 永久久久久久久| 亚洲白拍色综合图区| 伊人色综合一区二区三区影院视频| 日本三级中国三级99人妇网站| 老司机免费视频一区二区三区| 极品久久久久久| 亚洲黄色有码视频| 日韩高清在线| 路边理发店露脸熟妇泻火| 99精品视频中文字幕| 波多野结衣视频在线观看| 欧美乱大交做爰xxxⅹ性3| 日本午夜精品| 国产aaaaa毛片| 亚洲一区免费视频| 国产精品视频一区二区久久| 亚洲自拍偷拍在线| 国产精品久久久久毛片大屁完整版| 国产成人福利在线| 日韩无一区二区| 欧美羞羞视频| 日韩视频 中文字幕| 久久久美女艺术照精彩视频福利播放| 一区二区视频网站| 欧美激情一级精品国产| av影片在线一区| 国产精品一区二区人妻喷水| 欧美色视频在线| 国产高清中文字幕在线| 中文网丁香综合网| 久久久一区二区三区| 精品国产99久久久久久宅男i| 欧美一级大片在线免费观看| 中文在线日韩| 后入内射无码人妻一区| 亚洲精品一区二区久|