精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

国产精品自拍视频在线| 欧美日韩亚洲一区二区三区在线观看| 香蕉久久久久久久| 国产精品免费精品自在线观看| 亚洲免费资源在线播放| 精品国产乱码久久久久久久软件| 福利网址在线观看| 香蕉久久网站| 国产视频久久久久| 激情图片中文字幕| 成人教育av| 亚洲免费看黄网站| 欧美日韩高清免费| 国产99对白在线播放| 亚洲一区二区三区四区五区午夜 | 亚洲精品第1页| 国产呦系列欧美呦日韩呦| 中文字幕免费播放| 亚洲经典在线| 久久久精品国产亚洲| 国产 中文 字幕 日韩 在线| 日韩在线你懂得| 欧美性猛交xxxxx水多| 久久久国产精华液999999| 无码精品人妻一区二区| 国产精品综合二区| 国产日本欧美视频| 女人十八岁毛片| 黄色工厂这里只有精品| 日韩中文字幕网址| 久久精品一区二区免费播放| 6080亚洲理论片在线观看| 欧美亚日韩国产aⅴ精品中极品| 国产精品第157页| 午夜视频在线观看免费视频| 97久久超碰精品国产| 亚洲综合国产精品| 国产又粗又猛又黄又爽无遮挡| 亚洲经典在线| 久久久久久久久国产精品| 天天鲁一鲁摸一摸爽一爽| 国产精品一区高清| 亚洲精品有码在线| 欧美 日本 国产| 欧美在线导航| 日韩精品在线视频| 亚洲黄色免费在线观看| 乱中年女人伦av一区二区| 日韩欧美色电影| 国产精品igao网网址不卡| 韩日精品一区| 欧美日韩久久久一区| 男女爽爽爽视频| 全球最大av网站久久| 欧美自拍偷拍一区| 免费看涩涩视频| 日韩av黄色| 日韩一区二区在线观看视频播放| 欧美成人黄色网址| 激情久久99| 欧美色男人天堂| 九九热免费在线观看| 日本a人精品| 7777精品伊人久久久大香线蕉超级流畅 | 特级西西人体高清大胆| gogogo高清在线观看一区二区| 亚洲欧美日韩国产成人| 亚洲成人黄色av| 天天影视欧美综合在线观看| 久久久国产精品亚洲一区| www.99re7| 亚洲高清在线| 国产成人avxxxxx在线看 | 国产精品久久久一区二区| 97超碰国产精品女人人人爽| 无码人妻精品一区二区| 日本aⅴ精品一区二区三区| 国产欧美日韩免费| www.av导航| 91在线免费视频观看| 色噜噜一区二区| 成年人黄视频在线观看| 亚洲高清在线视频| 国产日产欧美视频| 欧美成人xxxx| 精品国产乱码久久久久久闺蜜| 182在线视频| 欧美日韩中文字幕一区二区三区| 按摩亚洲人久久| 免费毛片一区二区三区| 久久精品男女| 成人欧美一区二区三区在线| 欧美特级特黄aaaaaa在线看| 国产日产欧美精品一区二区三区| 中文字幕乱码免费| 日本在线播放一二三区| 欧美日韩国产在线观看| 亚洲麻豆一区二区三区| 不卡视频在线| 久久久久女教师免费一区| 亚洲大片免费观看| 国产成人在线视频免费播放| 欧美日韩精品一区| 羞羞的视频在线观看| 色婷婷精品久久二区二区蜜臀av | 国产亚洲欧美色| 穿情趣内衣被c到高潮视频| 9999精品成人免费毛片在线看| 欧美在线短视频| 男人的天堂影院| 欧美成人激情| 日本三级韩国三级久久| www三级免费| 国产精品免费看片| 国产亚洲天堂网| 日本免费一区二区三区视频| 亚洲精品一区久久久久久| 免费在线看黄网址| 久久黄色级2电影| 欧美日韩在线观看一区| av电影一区二区三区| 国产精品自拍第一页| 国产高清不卡一区二区| 一区二区成人国产精品 | 亚洲少妇30p| 男女视频一区二区三区| 精品视频高潮| 欧美日本啪啪无遮挡网站| 在线观看不卡的av| 久久午夜免费电影| 激情深爱综合网| 中文一区二区三区四区| 久久精品国产2020观看福利| 波多野结衣一区二区三区在线| eeuss鲁片一区二区三区在线观看| 中文字幕av日韩精品| 一区二区视频免费完整版观看| 亚洲精品国产福利| 免费一级全黄少妇性色生活片| 麻豆传媒一区二区三区| 水蜜桃一区二区| 成人看片网站| 在线国产精品播放| 91麻豆精品在线| 日本一区二区三区在线不卡| 色综合av综合无码综合网站| 欧美aaaaa级| 4p变态网欧美系列| 涩爱av在线播放一区二区| 亚洲国产欧美在线| 成人区人妻精品一区二| 好看的av在线不卡观看| 99视频网站| 精品自拍一区| 欧美私人免费视频| 刘亦菲国产毛片bd| 久久99精品久久久| 一区二区三区三区在线| 伊人久久综合网另类网站| 深夜福利一区二区| 国产精品久久久久毛片| 亚洲精选免费视频| xxxx国产视频| 一区二区日韩免费看| 久久久精彩视频| 人人鲁人人莫人人爱精品| 一个色综合导航| 在线观看国产小视频| 国产精品国产三级国产aⅴ入口 | 久久免费福利视频| 婷婷亚洲一区二区三区| 黄色一区二区三区| 人妻av无码一区二区三区| 男女性色大片免费观看一区二区| 在线看视频不卡| 97久久超碰| 欧洲永久精品大片ww免费漫画| 国产资源在线观看| 欧美日本视频在线| 久久这里只有精品国产| 91天堂素人约啪| 亚洲久久中文字幕| 欧美日韩一卡| 欧美自拍资源在线| 日韩有码欧美| 91高清免费视频| 91欧美在线视频| 精品国产亚洲一区二区三区在线观看| 六月丁香在线视频| 国产欧美精品一区二区三区四区| 一级黄色在线播放| 国产日韩欧美一区| 永久免费精品视频网站| 永久免费精品视频| 国产精品第七十二页| 菠萝菠萝蜜在线观看| 亚洲第一福利在线观看| 高潮无码精品色欲av午夜福利| 亚洲伦理在线精品| 老鸭窝一区二区| 国产乱码精品一区二区三区av| 欧美日韩亚洲一| 99成人在线视频| 美媛馆国产精品一区二区| 国产高清视频一区二区| 啪一啪鲁一鲁2019在线视频| www久久日com| 在线视频亚洲欧美| 天天干天天摸天天操| 9191精品国产综合久久久久久| 激情五月色婷婷| 亚洲欧美色图小说| 久久久久久久毛片| 不卡电影免费在线播放一区| 日本中文字幕影院| 久久不射2019中文字幕| 欧妇女乱妇女乱视频| 久久精品高清| 欧美激情导航| 牛牛影视久久网| 成人自拍爱视频| 中文字幕日本一区| 国产精品成人av性教育| 嗯~啊~轻一点视频日本在线观看| 久久激情视频久久| h视频网站在线观看| 日韩精品免费在线视频| 亚洲欧美另类日韩| 日韩一区二区三区av| 在线视频免费观看一区| 色综合夜色一区| 日韩少妇高潮抽搐| 亚洲一区二区视频| 2018天天弄| 中文字幕一区二区三区四区不卡 | 国产精品不卡在线| 成人无码www在线看免费| 国产91精品一区二区麻豆亚洲| 久久久精品高清| 久久精品二区亚洲w码| 性生活免费在线观看| 日本午夜精品视频在线观看| 美女福利视频在线| 免费欧美日韩| 日本三级免费观看| 美女国产一区| 欧美成人免费高清视频| 亚洲在线观看| 色综合av综合无码综合网站| 久久久久91| 国产a级片免费观看| 久久久久久穴| 午夜欧美福利视频| 奇米色一区二区三区四区| 婷婷丁香激情网| 久久精品国产免费| 极品粉嫩美女露脸啪啪| 国精产品一区一区三区mba视频| 亚洲精品免费一区亚洲精品免费精品一区| 麻豆成人久久精品二区三区小说| 国产又黄又猛的视频| 国内不卡的二区三区中文字幕 | xf在线a精品一区二区视频网站| 亚洲熟女乱综合一区二区三区| 97国产一区二区| 成年人免费观看视频网站| 国产视频一区二区在线观看| 国产18无套直看片| 亚洲免费成人av| 国产精品 欧美 日韩| 欧美日韩免费区域视频在线观看| 亚洲国产成人精品女人久久| 欧美日韩国产系列| 精品人妻一区二区三区日产乱码| 亚洲激情 国产| 成在在线免费视频| 久久久999成人| caoprom在线| 日韩美女视频免费看| 99精品国自产在线| 97se视频在线观看| 亚洲裸色大胆大尺寸艺术写真| 手机成人在线| 欧美网站在线| 日本va中文字幕| 国产精品一区二区不卡| 国产精品一级黄片| 国产精品国产三级国产普通话99| 欧美一级高潮片| 欧美性xxxxxx少妇| 亚洲h视频在线观看| 亚洲视频在线播放| caopen在线视频| 日本中文字幕成人| 精品国产第一国产综合精品| 久久久水蜜桃| 欧美成熟视频| 亚洲少妇第一页| 成人美女在线视频| 免费成人深夜天涯网站| 亚洲福利视频导航| 在线免费观看高清视频| 亚洲第一二三四五区| 黄色网址在线免费播放| 欧美专区第一页| 日韩精品免费视频一区二区三区 | 成人av免费看| 日韩av在线中文字幕| 久久精品视频16| 国产成人综合亚洲网站| 亚洲一级片在线播放| 婷婷丁香久久五月婷婷| 国产婷婷在线视频| 在线观看日韩av| 亚洲天堂资源| 国产精品日韩欧美一区二区三区 | 中文字幕亚洲在线观看| 亚洲一卡二卡区| 水野朝阳av一区二区三区| 欧美激情一区二区三区p站| 一区在线中文字幕| av毛片在线免费观看| 亚洲国产成人精品一区二区| 免费黄色电影在线观看| 国产精品激情av电影在线观看| 欧美电影在线观看免费| 日韩国产小视频| 国产在线一区观看| 999福利视频| 欧美在线一二三四区| 你懂的在线观看| 国产91精品久久久久| 国产精品视屏| 18禁裸男晨勃露j毛免费观看 | 无码精品一区二区三区在线播放 | 秋霞精品一区二区三区| 亚洲大胆人体视频| av资源在线播放| 国产精品视频入口| 国产精品videossex久久发布| www.污网站| 亚洲免费在线观看| 国产成人久久精品77777综合 | 国产精品正在播放| 91久久久久久久久久久久久久 | 亚洲五码中文字幕| 亚洲成熟女性毛茸茸| 欧美多人乱p欧美4p久久| 精品成人18| 妞干网在线观看视频| 成人免费观看男女羞羞视频| 亚洲精品www久久久久久| 亚洲国产精品福利| www.九色在线| 久久伦理网站| 日韩国产欧美在线播放| 一级特黄曰皮片视频| 欧美日本在线观看| 超碰个人在线| 黑人中文字幕一区二区三区| 99精品国产在热久久下载| 精品夜夜澡人妻无码av| 一本色道久久综合狠狠躁的推荐| 国产女人在线视频| 国产精品自在线| 欧美精品二区| 日韩综合第一页| 在线观看日韩电影| 免费看美女视频在线网站| 97碰碰视频| 亚洲欧美视频一区二区三区| 国产激情av在线| 欧美一级欧美三级| 免费污视频在线| 农村寡妇一区二区三区| 久久99久久精品| 久久久久久久久97| 亚洲欧美国产一区二区三区| 成人mm视频在线观看| 日本一级黄视频| 国产无人区一区二区三区| 国产精品丝袜黑色高跟鞋| 性金发美女69hd大尺寸| 欧美日韩伦理| 少妇搡bbbb搡bbb搡打电话| 一本大道综合伊人精品热热 | 久久久亚洲影院| 精品国产不卡| 精品无码av一区二区三区不卡| 岛国视频午夜一区免费在线观看| 日韩三级影院| 国产精品三区四区| 精品中文字幕一区二区小辣椒| 国产福利久久久| 日韩在线欧美在线国产在线| 国产色噜噜噜91在线精品| 亚洲人成色77777| 一区二区视频免费在线观看| 欧美成人综合在线| 99精品国产一区二区|