
ãã®èšäºã§ã¯ã
libcdsã©ã€ãã©ãªãŒãåºåããïŒã§ããã°éªéã«ãªããªãããã«ïŒããšã§ãããã¯ããªãŒã®ã³ã³ãããŒãäœæããææ³ã玹ä»ããŸãã
ããã¯ããªãŒã³ã³ããã®å®å
šãªã¡ã¢ãªè§£æŸã®ããã®å¥ã®ææ³ãRCUã«ã€ããŠèª¬æããŸãã ãã®ææ³ã¯ãåè¿°ã®ã¢ã©ãã¶ãŒããã€ã³ã¿ãŒã¢ã«ãŽãªãºã ãšã¯å€§ããç°ãªããŸãã
èªã¿åã-ã³ããŒæŽæ°ïŒRCUïŒã¯ããã»ãŒèªã¿åãå°çšããã€ãŸããã£ãã«å€æŽãããªãããŒã¿æ§é çšã«èšèšãããåæææ³ã§ãã ãã®ãããªæ§é ã®å
žåçãªäŸã¯ãããããšã»ããã§ãããããã®ã»ãšãã©ã®æäœã¯æ€çŽ¢ãã€ãŸãããŒã¿ã®èªã¿åãã§ãã éåžžã®ãããã§ã¯ãåŒã³åºãããæäœã®90ïŒ
以äžãããŒæ€çŽ¢ã§ãããšèããããŠãããããæ€çŽ¢æäœãæéã§ããããšãéèŠã§ãã æ€çŽ¢ã®åæã¯åºæ¬çã«äžèŠã§ã-ã©ã€ã¿ãŒã®ãªããªãŒããŒã¯äžŠè¡ããŠäœæ¥ã§ããŸãã RCUã¯ãèªã¿åãæäœã«å¯ŸããŠã®ã¿ãªãŒããŒããããæå°éã«æããŸãã
Read-Copy Updateãšããååã¯ã©ãããæ¥ãã®ã§ããïŒ åœåããã®ã¢ã€ãã¢ã¯éåžžã«ã·ã³ãã«ã§ãããããŒã¿æ§é ã¯ãã£ãã«å€æŽãããŸããã
å€æŽããå¿
èŠ
ãããå Žåã¯ã
ã³ããŒãäœæãã
ã³ããŒã§å€æŽïŒããŒã¿ã®è¿œå ãŸãã¯åé€ïŒãè¡ããŸãã åæã«ããã©ã¬ã«ãªãŒããŒã¯å
ã®å€æŽãããŠããªãæ§é ã§åäœããŸãã ããå®å
šãªæç¹ã§ãèªè
ãããªãå ŽåãããŒã¿æ§é ãå€æŽãããã³ããŒã§çœ®ãæããããšãã§ããŸãã ãã®çµæã以éã®ãã¹ãŠã®ãªãŒããŒã«ã¯ãã©ã€ã¿ãŒã«ãã£ãŠè¡ãããå€æŽã衚瀺ãããŸãã
RCUãã¯ãããžãŒã®äœæè
ã§ããç©æ¥µçãªããã¢ãŒã¿ãŒã¯Paul McKenneyã§ãã 圌ã¯ãRCUæ奜家ãã®åŠæ ¡å
šäœãçããŠãããããããããã¯ããªãŒããã³éäŒçµ±çãªåæã¹ããŒã ã®åéã§å€ãã®æåãªç§åŠè
ãåºãŠããŸããããŸãã圌ã¯Linuxã«ãŒãã«ïŒLinuxã«ãŒãã«ã

RCUã¯2002幎ã«Linuxã«ãŒãã«ã«å°å
¥ãããŠä»¥æ¥ãã«ãŒãã«ã³ãŒãã«ãŸããŸãæé·ããŠããŸããå³ã®å³ãåç
§ããŠãã ããã é·ãéãããã¯ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®ã«ãŒãã«å°çšã®åææè¡ãšããŠäœçœ®ã¥ããããŠããŸããã ã«ãŒãã«ã¯ãŠãŒã¶ãŒãšã·ã¹ãã ã®äž¡æ¹ã®ãã¹ãŠã®ã¹ã¬ãããå®å
šã«å¶åŸ¡ãããããã«ãŒãã«å
ã§ããŒã¿ãå€æŽãããã³ããŒã§çœ®ãæããããå®å
šãªç¬éãå€æããã®ã¯éåžžã«ç°¡åã§ãã ããããç§ãã¡ã¯RCUã®å¿çšã«èå³ããããŸããããã¯å¯èœã§ããïŒ ãã®è³ªåã«çããåã«ãRCUã®çè«ãšããã«äœ¿çšãããçšèªããã詳现ã«æ€èšããŸãã
RCUã®äžè¬çãªèª¬æ
RCUã®æŠå¿µã«é¢ããäžèšã®èª¬æã¯éåžžã«åçŽã§ãã ãåç¥ã®ããã«ãã¢ãããã¯æäœããããããããŒã¿ã®ã³ããŒãäœæããããšã¯ã§ããŸããããèªã¿åããšäžŠè¡ããŠããŒã¿æ§é ãããªã³ã¶ãã©ã€ãã§å€æŽããŸãã 次ã«ãããªãŒããŒãã¯ãããŒã¿æ§é ããèŠçŽ ãåé€ãã以å€ã®æäœãå®è¡ããã¹ã¬ããã«ãªããŸãã ã©ã€ã¿ãŒã¯ãæ§é ããäœããåé€ããã¹ããªãŒã ã§ãã åé€ãããããŒã¿ã誰ããèžãŸãªãããšãã«åé€ãè¡ãå¿
èŠããããŸããããããªããšãABAã®åé¡ããã¡ã¢ãªã®ç ŽæãŸã§ãæ€åºãå°é£ãªåé¡ãå€æ°çºçããŸãã RCUã¯ãåè¿°ã®ãã¶ãŒããã€ã³ã¿ãŒã¹ããŒã ãšã¯ç°ãªãæ¹æ³ã䜿çšããŠãããããã¹ãŠã®åé¡ã解決ããŸãã
RCUãã¯ããã¯ã®èªè
ã¯ãèªã¿åãåŽã®ã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ã§å®è¡ããŸãã ãã®ãããªã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ã«å
¥ããšããªãŒããŒã¯
rcu_read_lock()
é¢æ°ãåŒã³åºãã
rcu_read_lock()
ãããš
rcu_read_lock()
åŒã³åºããŸãã ãããã¯éåžžã«è»œéãªæ©èœã§ãããããã©ãŒãã³ã¹ã«ã¯ã»ãšãã©åœ±é¿ããŸããã Linuxã«ãŒãã«ã§ã¯ããŸã£ããééãéããŸããïŒãŒããªãŒããŒãããïŒã
ã¹ããªãŒã ãã¯ãªãã£ã«ã«èªã¿åãã»ã¯ã·ã§ã³ã«ãªãå Žåãã¹ããªãŒã ã¯
éæ¢ç¶æ
ïŒéæ¢ç¶æ
ãéæ¢ç¶æ
ïŒã«ãããšèšãããŸãã åã¹ã¬ãããå°ãªããšã1åã¯éæ¢ç¶æ
ã«ãã
æéã¯ã
ç¶äºæéãšåŒã°ããŸãã ç¶äºæéãçµäºããåã«éå§ããåéèŠãªèªã¿åãã»ã¯ã·ã§ã³ã¯ãç¶äºæéãçµäºããåã«çµäºããå¿
èŠããããŸãã éèŠãªèªã¿åãã»ã¯ã·ã§ã³ã¯æéã§ãããããåç¶äºæéã¯æéã§ããããšãä¿èšŒãããŠããŸãïŒã¹ã¬ããã®æ°ã¯æéã§ãããåªããããã°ã©ããŒã§ãããç¡éã«ãŒããã¹ã¬ããã¯ã©ãã·ã¥ãåé¿ã§ããããšãç解ãããŠããŸãïŒã

ããŒã¿æ§é ããèŠçŽ ãåé€ããã©ã€ã¿ãŒã¹ã¬ããã¯ãæ§é ããèŠçŽ ãé€å€ããç¶äºæéã®çµäºãåŸ
ã¡ãŸãã ç¶äºæéã®çµäºãšã¯ãåé€ããèŠçŽ ã«ã¢ã¯ã»ã¹ã§ãããªãŒããŒãããªãããšãæå³ããŸãïŒå³ãåç
§ããã®ãèªã¿åããé·æ¹åœ¢ã¯éèŠãªèªã¿åãã»ã¯ã·ã§ã³ã§ãïŒã ãããã£ãŠãã©ã€ã¿ãŒã¹ã¬ããã¯ã¢ã€ãã ãå®å
šã«ç©ççã«åé€ã§ããŸãã
åé€ã¯2段éã§å®è¡ãããŸããæåã®æ®µéã§ãããåé€ãã¯ãããŒã¿æ§é ããèŠçŽ ãã¢ãããã¯ã«åé€ããŸãããã¡ã¢ãªãç©ççã«è§£æŸããŸããã 代ããã«ãã©ã€ã¿ãŒã¯ç¹å¥ãª
synchronize_rcu()
ããªããã£ããåŒã³åºããŠç¶äºæéã®éå§ãéç¥ããçµäºããã®ãåŸ
ã¡ãŸãã åé€ãããã¢ã€ãã ã«ã¯ãã©ã€ã¿ãŒãšäžŠè¡ããŠéèŠãªèªæžã»ã¯ã·ã§ã³ã宣èšãããªãŒããŒã®ã¿ãã¢ã¯ã»ã¹ã§ããŸãïŒå³ã§ã¯ããã®ãããªã»ã¯ã·ã§ã³ã¯ç°è²ã§åŒ·èª¿è¡šç€ºãããŠããŸãïŒã å®çŸ©ã«ããããã®ãããªèªè
ã¯ãã¹ãŠãç¶äºæéãçµäºããåã«äœæ¥ãçµäºããŸãã ç¶äºæéã®çµäºæãã€ãŸããç¶äºæéäžã«éå§ãŸãã¯ã¢ã¯ãã£ãã«ãªã£ããã¹ãŠã®éèŠãªèªã¿åãã»ã¯ã·ã§ã³ãå®äºãããšãåé€ã®2çªç®ã®æ®µéã§ãããã¬ã¯ã©ã¡ãŒã·ã§ã³ããã€ãŸãèŠçŽ ã®äžã®ã¡ã¢ãªã®ç©ççãªåé€ãéå§ãããŸãã
ã芧ã®ãšãããRCUã®åæææ³ã¯éåžžã«ç°¡åã§ãã åé¡ã¯æ®ã£ãŠããŸã-ãŠãŒã¶ãŒã³ãŒãã§ç¶äºæéã®çµäºãå€æããæ¹æ³ã¯ïŒ å
ã®RCUã¯ããã¹ãŠã®ã¹ã¬ãããå®å
šã«å¶åŸ¡ã§ãããããLinuxã«ãŒãã«ã«åãããŠå€§å¹
ã«èª¿æŽãããŠããŸãã ãŠãŒã¶ãŒç©ºéã³ãŒãã®å Žåãå
ã®RCUã®ã¢ãããŒãã¯é©çšã§ããŸããã
ãŠãŒã¶ãŒã¹ããŒã¹RCU
ãã®æ±ºå®ã¯ã2009幎ã«P. McKenneyã®ä»£è¡šã§ããM.Desnoyersã®
è«æ ïŒç¬¬6ç« ïŒRCUã®User-Level ImplementationsïŒã§äžããããŸããã
M.Desnoyersã¯ããŠãŒã¶ãŒã¹ããŒã¹RCUïŒURCUïŒã®3ã€ã®ãœãªã¥ãŒã·ã§ã³ãæäŸããŠããŸãã
- éæ¢ç¶æ
ããŒã¹ã®ã¬ã¯ã©ã¡ãŒã·ã§ã³RCUã¯ãèªè
ã«ãšã£ãŠéåžžã«è»œéãªã¹ããŒã ã§ãããã¯ãªãã£ã«ã«ãªèªã¿åãã»ã¯ã·ã§ã³å€ã®ã¹ã¬ãããå®æçã« ãéæ¢ç¶æ
ã«ãªã£ãŠããããšå®£èšããå¿
èŠããããŸãã ãã®ãœãªã¥ãŒã·ã§ã³ã¯ãæ±çšã©ã€ãã©ãªãŒã§ããlibcdsã«ã¯é©ããŠããªããããæ€èšããŸããã
- æ±çšURCUãŠãŒã¶ãŒç©ºéRCUã¯ãäžè¬çãªå®è£
ã«é©ããã¢ã«ãŽãªãºã ã§ããããã«ã€ããŠã¯ä»¥äžã§èª¬æããŸãã
- ä¿¡å·åŠçãä»ãããŠãŒã¶ãŒç©ºéRCUãèå³æ·±ãä¿¡å·ããŒã¹ã®ã¢ã«ãŽãªãºã ã§ãïŒ* nixã·ã¹ãã ã«é©ããŠããŸãããWindowsã«ã¯é©çšãããŸããïŒã libcdsã©ã€ãã©ãªã«å®è£
ãããŠãããããæ±çšRCUããããããã«ããã©ãŒãã³ã¹ãå£ã£ãŠããŸãã ãã®èšäºã§ã¯ãããèæ
®ããŸãã;èå³ã®ãã人ã¯M.Desnoyers'aã®è«æãšlibcdsã®ãœãŒã¹ã³ãŒããåç
§ããŸãã
æ±çšURCU
M.Desnoyersã¯ãURCUã¢ã«ãŽãªãºã ãéåžžã«è©³çŽ°ãã€åŸ¹åºçã«è§£æãããããããã€ãã®å€æ°ãšé¢æ°ã®ååã®ã¿ãå€æŽããŠlibcdsã§æ¡çšãããŠãããã®ã«å¯Ÿå¿ããããã«ããŸãã
URCUã¹ããŒãã¯2ã€ã®å€æ°ãå®çŸ©ããŸãã
std::atomic<uint32_t> g_nGlobalCtl(1) ; struct thread_record { std::atomic<uint32_t> nThreadCtl; thread_record * pNext; thread_record(): nThreadCtl(0), pNext(nullptr) {} };
thread_record
æ§é äœã«ã¯ãã¹ã¬ããã«ããŒã«ã«ãªããŒã¿ãå«ãŸãããã®ãããªãã¹ãŠã®ãªããžã§ã¯ããRCUã¹ã¬ããã®ãªã¹ãã«ãªã³ã¯ããŸãã
nThreadCtl
ã®äžäœ31ãããã«ã¯ãURCUåŒã³åºãã®ãã¹ãã®æ·±ãã®ã«ãŠã³ã¿ãŒãå«ãŸããŸãïŒã¯ããURCUã¯ã¯ãªãã£ã«ã«ãªèªã¿åãã»ã¯ã·ã§ã³ã®ã»ãŒç¡å¶éã®ãã¹ããèš±å¯ããŸãïŒãé«ãããã¯ãã¹ã¬ãããã¯ãªãã£ã«ã«ãªèªã¿åãã»ã¯ã·ã§ã³ã«å
¥ãæç¹ã®ç¶äºæéã®èå¥åã決å®ããŸãã 説æããã¹ããŒã ã§ã¯ãç¶äºæéã®èå¥åã¯2ã€ã ãã§ååã§ãã
ã°ããŒãã«å€æ°
g_nGlobalCtl
ã®äžäœãããã«ã¯çŸåšã®ç¶äºæéã®èå¥åãå«ãŸããäžäœãããã¯
nThreadCtl
ã¹ã¬ããããšã®å€æ°ãåæåãã圹å²ã
nThreadCtl
ãå€æŽãããŸããã
éèŠãªèªã¿åãã»ã¯ã·ã§ã³ãã/ã«åºå
¥ãããã«ã¯
access_unlock
ããããé¢æ°
access_lock
ããã³
access_unlock
䜿çšã
access_lock
ã
static uint32_t const c_nControlBit = 0x80000000; static uint32_t const c_nNestMask = c_nControlBit â 1; void access_lock() { thread_record * pRec = get_thread_record(); assert( pRec != nullptr ); uint32_t tmp = pRec->nThreadCtl.load( std::memory_order_relaxed ); if ( (tmp & c_nNestMask) == 0 ) { pRec->nThreadCtl.store(g_nGlobalCtl.load( std::memory_order_relaxed ), std::memory_order_relaxed ); std::thread_fence( std::memory_order_acquire ); } else pRec->nThreadCtl.fetch_add( 1, std::memory_order_relaxed ); } void access_unlock() { thread_record * pRec = get_thread_record(); assert( pRec != nullptr ); pRec->nThreadCtl.fetch_sub( 1, std::memory_order_release ); }
URCUã®ã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ã«å
¥ããšãåŒã³åºãããã¹ããããŠãããã©ããããã§ãã¯ãããŸãã åŒã³åºãããã¹ããããŠããå ŽåïŒã€ãŸããäžäœ31ãããã®ã«ãŠã³ã¿ãŒããŒãã§ã¯ãªãå ŽåïŒããã¹ãã«ãŠã³ã¿ãŒã¯åçŽã«ã€ã³ã¯ãªã¡ã³ããããŸãã åŒã³åºãããã¹ããããŠããªãå ŽåãçŸåšã®ã¹ã¬ããã®
nThreadCtl
å€æ°ã«ã°ããŒãã«å€æ°
g_nGlobalCtl
å€ãå²ãåœãŠãããŸãã ããã¯ãã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ãç¹å®ã®ç¶äºæéïŒé«ããã
g_nGlobalCtl
ïŒã«å
¥åãããããšã瀺ããäœããã
g_nGlobalCtl
ãŠãããã¯çŸåšã®ã¹ããªãŒã ã®ãã¹ãã«ãŠã³ã¿ãŒãåæåããŸãã ã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ãžã®æåã®æãå€éšããã®å
¥ãå£ã§ã¯ãã¡ã¢ãªã®ç²åŸããªã¢ãé©çšãããŸãã ããã«ãããåŸç¶ã®ã³ãŒããããã»ããµãŸãã¯ã³ã³ãã€ã©ã«ãã£ãŠããªã¢ã®äžæµã«ç§»åïŒãæé©åãïŒãããªãããšãä¿èšŒãããŸãã ããã«ããããã¹ãŠã®ããã»ããµã«å¯Ÿããã¹ããªãŒã ã®çŸåšã®ç¶äºæéã®å¯èŠæ§ãä¿èšŒãããŸã-ãã®é åºã«éåãããšãURCUã¢ã«ãŽãªãºã ã厩ããŸãã
ãã¹ããããã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ã«å
¥ãå ŽåãçŸåšã®ç¶äºæéïŒé«ãããïŒã¯å€ãããªããããããªã¢ã¯å¿
èŠãããŸããã
ã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ïŒ
access_unlock
ïŒãçµäºãã
nThreadCtl
çŸåšã®ã¹ã¬ããã®
nThreadCtl
ãã¹ãã«ãŠã³ã¿ãŒãåçŽã«æžåãããŸãã ã¢ãããã¯æäœã®ãªãªãŒã¹ã»ãã³ãã£ã¯ã¹ãé©çšãããŸãã å®éãããã§ãªãªãŒã¹ããªã¢ãå¿
èŠã«ãªãã®ã¯ãæäžäœã®ã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ãé¢ãããšãïŒãã¹ãã«ãŠã³ã¿ãŒã1ãã0ã«ç§»åãããšãïŒããã¹ããããã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ãé¢ãããšãããªã©ãã¯ã¹ããã»ãã³ãã£ã¯ã¹ã§ååã§ãã ãã¹ãã«ãŠã³ã¿ãŒã1ãã0ã«ç§»è¡ãããšããã¹ããªãŒã ãRCUã䜿çšããªããªã£ãããšããã¢ããŠã³ã¹ã¡ã³ããå®éã«çºçãããããã«ãŠã³ã¿ãŒããªã»ãããããšãã®ãªãªãŒã¹ããªã¢ãå¿
èŠã§ããã€ãŸããç¶äºæéããã®çµäºã¯URCUã¢ã«ãŽãªãºã ã«ãšã£ãŠéèŠã§ãã³ã³ãã€ã©ãŒãŸãã¯ããã»ããµãŒã«ããé åºéåã¢ã«ãŽãªãºã ã®åäœäžèœã«ã€ãªãããŸãã ã³ãŒãå
ã®ç¶æ³ã0-not 0ããèªèããã«ã¯ãæ¡ä»¶ä»ãé·ç§»ãå¿
èŠã«ãªããŸããããã¯ã
access_unlock
é¢æ°ã«ããã©ãŒãã³ã¹ãè¿œå ããå¯èœæ§ãäœãã
access_unlock
ã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ã䜿çšããäž»ãªãã¿ãŒã³ã¯ãã¹ããªãã§ãã
ã芧ã®ãšãããèªè
åŽã®ã³ãŒãã¯éåžžã«è»œéã§ãã ã¢ãããã¯ãªèªã¿åããšæžã蟌ã¿ããã³ã¹ã¬ããããŒã«ã«ããŒã¿ã䜿çšãããŸãã ãã¡ãããããã¯ãŒããªãŒããŒãããã§ã¯ãããŸããããããã§ããã¥ãŒããã¯ã¹ãCASãããã¯ããã«åªããŠããŸãã
ã©ã€ã¿ãŒã¹ã¬ããã¯ãã¢ã€ãã ãç©ççã«åé€ããåã«ããŸãç¶äºæéãå®äºããŠããããšã確èªããå¿
èŠããããŸãã ç¶äºæéãçµäºããæ¡ä»¶ã¯ã次ã®2ã€ã®ããããã§ãã
- åã¹ã¬ããã®
nThreadCtl
ãããïŒãã¹ãã«ãŠã³ã¿ãŒïŒ nThreadCtl
ãŒãã«çãããããã¯ãã¹ã¬ãããURCUã®ã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ã«ãªãããšãæå³ãã nThreadCtl
ã®äžäœãããã¯nThreadCtl
ã®äžäœããããšnThreadCtl
ããŸãããããã¯ãç¶äºæéã®éå§åŸã«ãªãŒããŒãã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ã«å
¥ã£ãããšãæå³ããŸãã
ãããã®æ¡ä»¶ã¯ã次ã®æ©èœã«ãã£ãŠãã§ãã¯ãããŸãã
bool check_grace_period( thread_record * pRec ) { uint32_t const v = pRec->nThreadCtl.load( std::memory_order_relaxed ); return (v & general_purpose_rcu::c_nNestMask) && ((( v ^ g_nGlobalCtl.load( std::memory_order_relaxed )) & ~c_nNestedMask )); }
ç©ççãªåé€ã®åã«ãã©ã€ã¿ãŒã¯çŸåšã®ç¶äºæéã®çµäºãäºæãã
synchronize
é¢æ°ãåŒã³åºããŸãã
std::mutex g_Mutex ; void synchronize() { std::atomic_thread_fence( std::memory_order_acquire ); { cds::lock::scoped_lock<std::mutex> sl( g_Mutex ); flip_and_wait(); flip_and_wait(); } std::atomic_thread_fence( std::memory_order_release ); }
ããã§ã
g_Mutex
ã¯URCUã¢ã«ãŽãªãºã ã®ã°ããŒãã«ãã¥ãŒããã¯ã¹ã§ãïŒã¯ããã¯ãïŒURCUã¯äŸç¶ãšããŠ
åææè¡ã§ããããããã¥ãŒããã¯ã¹ããªããããã©ãã«ããããŸããïŒã ãããã£ãŠã1ã€ã®ã©ã€ã¿ãŒã¹ã¬ããã®ã¿ã
synchronize
å
¥ãããšãã§ããŸãã RCUã¯ãã»ãŒèªã¿åãå°çšãã®ããŒã¿çšã«é
眮ãããããšãå¿ããªãã§ãã ããããããã£ãŠããã®ãã¥ãŒããã¯ã¹ã§ã¯ç¹å¥ãªã¯ã©ãã·ã¥ã¯æ³å®ãããŠããŸããã
ã©ã€ã¿ãŒã¯ã
flip_and_wait
é¢æ°ãåŒã³åºãããšã«ãããç¶äºæéã®çµäºãäºæããŸãã
void flip_and_wait() { g_nGlobalCtl.fetch_xor( c_nControlBit, std::memory_order_seq_cst ); for (thread_record* pRec = g_ThreadList.head(std::memory_order_acquire); pRec!= nullptr; pRec = pRec->m_pNext ) { while ( check_grace_period( pRec )) { sleep( 10 );
ãã®é¢æ°ã¯ãç¶äºæéã®èå¥åãå€æŽããŸããããã¯ãã¢ãããã¯ãª
fetch_xor
ã䜿çšããŠæ°ããç¶äºæéã®éå§ãæå³ãããã¹ãŠã®
check_grace_period
ã¹ã¬ããããã®æ°ããç¶äºæéãå®äºãããŸã§åŸ
æ©ããŸãïŒ
fetch_xor
ãåŒã³åºã
check_grace_period
ïŒã æ¬äŒŒã³ãŒãã§ã¯ãåŸ
æ©ã¯10ããªç§ã®åçŽãªã¹ãªãŒãã§ããå®éã®libcdsã³ãŒãã§ã¯ãããã¯ãªãæŠç¥ãèšå®ãããã³ãã¬ãŒããã©ã¡ãŒã¿ãŒã䜿çšãããŸãã
ã©ã€ã¿ãŒã
flip_and_wait
2ååŒã³åºãã®
flip_and_wait
ãªãã§ããïŒ æ確ã«ããããã«ã2ã€ã®ã¹ããªãŒã AãšBã䜿çšãããã®äžé£ã®ã¢ã¯ã·ã§ã³ãæ€èšããŠ
flip_and_wait
ã
access_lock
Aã¯access_lock
åŒã³åºãaccess_lock
ã ãã®é¢æ°ã®æ¬äœã§ã¯ãåŒã³åºãããã¹ããããŠããªããšå€æãããã°ããŒãã«g_nGlobalCtl
ãèªã¿åãããŸããããããŸã§nThreadCtl
å€æ°nThreadCtl
å²ãåœãŠãããŠããŸããïŒãã¹ãŠã䞊è¡ããŠè¡ãããããããã®ç¶æ³ã¯ãŸã£ããåãå
¥ããããŸãïŒ- ã¹ã¬ããBã¯
synchronize
åŒã³åºããŸãã æåã®flip_and_wait
ã flip_and_wait
ã®ç¶äºæéèå¥åããããå€æŽããg_nGlobalCtl
ã çŸåšã®ç¶äºæéèå¥åã¯1ã«ãªããŸã - URCUã®ã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ã«ã¯èª°ãããªãããïŒã¹ã¬ããAãå€æ°
nThreadCtl
å€ããŸã èšå®ããŠããªãããšãæãåºããŠnThreadCtl
ïŒãã¹ã¬ããBã¯synchronize
å®äºããŸã nThreadCtl
Aã¯ãã®å€æ°nThreadCtl
å²ãåœãŠãŸãã ã¹ããªãŒã ããç¶äºæéã®å€ãå€ïŒ0ã«çããïŒãèªã¿åã£ãããšãæãåºããŠãã ãããaccess_lock
Aã¯access_lock
ãçµäºããã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ã§å®è¡ãç¶ç¶ãaccess_lock
- ã¹ã¬ããBã®åŒã³åºãã¯å床
synchronize
ããŸãïŒæããã«ãäœããããäžåºŠåé€ãããïŒã ç¹°ãè¿ããŸãããçŸåšã®ç¶äºæéã¯g_nGlobalCtl
ã«g_nGlobalCtl
ããããããã®èå¥åã¯0ã«ãªããŸãã
ãã ããã¹ã¬ããAã¯ãBãç¶äºæéãå€æŽãã
åã«éå§ããã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ã«ãããŸãã URCUã®ã»ãã³ãã£ã¯ã¹ãžã®éåãæçµçã«ã¯ABAããã¡ã¢ãªç Žæã«è³ããŸã§ãå
šäœçãªåé¡ã«ã€ãªãããŸãã ãªã³ãŒã«ïŒ
synchronize
ã¯ãèŠçŽ ã®ã¡ã¢ãªãç©ççã«åé€ããåã«ã©ã€ã¿ãŒã«ãã£ãŠåŒã³åºãããŸã
flip_and_wait
2åãã€ãŸãç¶äºæéã®çµäºã2ååŸ
æ©ããããšã§ãã¹ã¬ããã®ç«¶åçãªå®è¡ãåå ã§ããäžèšã®åé¡ã解決ããŸãã
å¥ã®è§£æ±ºçãã¡ãããç¶äºæéèå¥åãããã®ä»£ããã«ã«ãŠã³ã¿ã䜿çšããå Žåãå¥ã®æ¹æ³ã§ãã®åé¡ã解決ã§ããŸãã ããããã¿ã°ä»ããã€ã³ã¿ãŒã¢ã«ãŽãªãºã ã«é¢ããèšäºã§æ¢ã«èŠãåé¡ãçºçããŸãããã«ãŠã³ã¿ãŒããªãŒããŒãããŒããŠããŸãã ä¿¡é Œæ§ã®ããã«ãã«ãŠã³ã¿ã¯32ãããã§ããå¿
èŠããããããããã°ãªãŒããŒãããŒã¯æããããŸããã ãã ãããã®ãããªã«ãŠã³ã¿ã䜿çšãããšã32ããããã©ãããã©ãŒã ã§64ãããã®ã¢ãããã¯ã¿ã€ããå¿
èŠã«ãªããŸãã ãã®ã¿ã€ãã¯ããã§ãªããããããéå¹ççã§ãã ãŸãã¯ãURCUã®éèŠãªã»ã¯ã·ã§ã³ã®ãã¹ããæŸæ£ããå¿
èŠããããŸããããããããŸã䟿å©ã§ã¯ãããŸããã
ãããã£ãŠãç¶äºæéã®èå¥åãšããŠãããã䜿çšãã2ã€ã®flip_and_wait
ãåŒã³åºãäžè¬çãªãœãªã¥ãŒã·ã§ã³ã«ã€ããŠèª¬æããŸãã
libcdsã§ã®URCUå®è£

äžèšã®URCUã¢ã«ãŽãªãºã ã¯ãã¹ãŠã®ãŠãŒã¶ãŒã«é©ããŠããŸããã
ååé€ã®
åã«ããªãéã
synchronize
ãåŒã³åºãå¿
èŠããããŸãã ãããæ¹åããæ¹æ³ã¯ãããŸããïŒ
ã¯ãããã¶ãŒããã€ã³ã¿ãŒã¢ã«ãŽãªãºã ãšåãæ¹æ³ã䜿çšããŠãé
延åé€ãé©çšã§ããŸãã åé€ãã代ããã«ãèŠçŽ ããããã¡ã«å
¥ããŸãã ãããã¡ãŒããã£ã±ãã«ãªã£ãå Žåã«ã®ã¿ã
synchronize
é¢æ°ãåŒã³åºããŸãã ãã¶ãŒããã€ã³ã¿ãŒãšã¯ç°ãªããURCUã§ã¯ããããã¡ãŒã¯ãã¹ãŠã®ã¹ã¬ããã«å
±éã§ãïŒäžè¬ã«ãã¹ã¬ããããšã®ãããã¡ãŒãäœæã§ããŸãããããã劚ãããã®ã¯äœããããŸããïŒã
ããã«ããããã¡ãäžæ¯ã«ãªã£ããšãã«ãããã¡ãã¯ãªãŒã³ã¢ããããããã«å
±æããã©ã€ã¿ã®é床ãäœäžãããªãããã«ããããã¡ã¯ãªãŒãã³ã°æ©èœãã€ãŸãå®éã®åé€ãå¥ã®ã¹ã¬ããã«å²ãåœãŠãããšãã§ããŸãã
libcdsã©ã€ãã©ãªã«ã¯
5ã€ã® URCUå®è£
ãããããããã¯ãã¹ãŠ
cds::urcu
ã
general_instant
ã¯ã説æãããŠããURCUã¢ã«ãŽãªãºã ã«å®å
šã«æºæ ããå®è£
ã§ããååé€ã«ããã synchronize
ããããã¡ãªã³ã°ãªããçºçããŸãã åé€ãéåžžã«é »ç¹ãªæäœã§ããå Žåãã€ãŸããæ§é ããã»ãšãã©èªã¿åãå°çšãã§ã¯ãªãå Žåããã®å®è£
ã¯ããªãé
ãgeneral_buffered
ã¯ãäºåã«æ±ºãããããµã€ãºã®äžè¬çãªããã¯ããªãŒãããã¡ãåããå®è£
ã§ãã Dmitry Vyukovã®ãã¥ãŒã¯ããã¯ããªãŒãããã¡ãŒãšããŠäœ¿çšãããŸã-cds cds::container::VyukovMPMCCycleQueue
ã ãã®å®è£
ã®ããã©ãŒãã³ã¹ã¯ããã¶ãŒããã€ã³ã¿ãŒã«å¹æµããŸããgeneral_threaded
- general_threaded
ãšäŒŒãŠãgeneral_buffered
ãããããã¡ãªã³ã°ã¯å°çšã¹ã¬ããã«ãã£ãŠè¡ãããŸãã ãã®å®è£
ã¯ãå°çšã¹ããªãŒã ãšã®è¿œå ã®åæã®ããã general_buffered
ãããããã«å£ããŸãããã©ã€ã¿ãŒã®é床ã¯äœäžããŸãããsignal_buffered
ã¯general_buffered
ã«é¡äŒŒããŠããŸãããä¿¡å·åŠçURCUã«åºã¥ããŠããŸãã Windowsã·ã¹ãã çšã§ã¯ãããŸããsignal_threaded
ã·ã°ãã«åŠçURCUã®general_threadedã«é¡äŒŒã ãŸããWindowsçšã§ã¯ãããŸãã
ãã®ãããªè±å¯ãªURCUå®è£
ã¯ãURCUã®äžã§ã³ã³ããã®ç¹æ®åãèšè¿°ããåé¡ãåŒãèµ·ãããŸãã å®éãURCUã¹ããŒã ã®ã³ã³ããã®å®è£
ã¯ããã¶ãŒããã€ã³ã¿ãŒã®å®è£
ãšã¯å€§ããç°ãªããŸãã ãããã£ãŠãURCUã«ã¯åå¥ã®å°éåãå¿
èŠã§ãã 5ã€ã§ã¯ãªãã1ã€ã®å°éåéãå¿
èŠã§ãã
URCUã§ã®å°éåéã®èšè¿°ã容æã«ããããã«ãã©ãããŒã¯ã©ã¹
cds::urcu::gc
ãå°å
¥ãããŸããã
template <typename RCUimpl> class gc;
ããã§ã
RCUimpl
ã¯
RCUimpl
ã®å®è£
ã®1ã€ã§ã
general_instant
ã
general_buffered
ãªã©ããã®ãããªã©ãããŒããããšãURCUã®ç¹æ®åãç°¡åã«èšè¿°ã§ããŸãã
template < class RCU, typename Key, typename Value, class Traits > class SplitListMap< cds::urcu::gc< RCU >, Key, Value, Traits > ...
libcdsã§ã¯ãåé€æã®URCUã¢ã«ãŽãªãºã ã®äž»ãªæ©èœã¯
synchronize
ã§ã¯ãªãã
retire_ptr
ã ãã®é¢æ°ã¯ãåé€ãããã¢ã€ãã ãURCUãããã¡ãŒã«é
眮ããé©åãªã¿ã€ãã³ã°ïŒãããã¡ãŒããã£ã±ãã«ãªã£ããšããªã©ïŒã«
synchronize
åŒã³åºããŸãã ãããã£ãŠã
synchronize
ããããã®æ瀺çãªåŒã³åºãã¯å¿
èŠã§
synchronize
ãŸããããæå¹ã§ãã ããã«ããã®ãœãªã¥ãŒã·ã§ã³ã¯URCUãšãã¶ãŒããã€ã³ã¿ãŒã®ã€ã³ã¿ãŒãã§ãŒã¹ãçµ±åããŸãã
ãªã¹ããããŠãããã¹ãŠã®URCUã¢ã«ãŽãªãºã ã¯ãlibcdsã®å
žåçãªæ¹æ³ã§å®è£
ãããŸããããããã«ã€ããŠãã©ãããŒãªããžã§ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒ
cds::urcu::gc<cds::urcu::general_buffered<> >
ã
main()
ã®å
é ã§åŒã³åºãããšã§åæåãããã°ããŒãã«ã·ã³ã°ã«ãã³ãªããžã§ã¯ãããããŸãã
cds::Initialize()
ãåŒã³åºããåŸ
cds::Initialize()
ïŒ
#include <cds/init.h> //cds::Initialize cds::Terminate #include <cds/gc/general_buffered.h> // general_buffered URCU int main(int argc, char** argv) { // libcds cds::Initialize() ; { // general_buffered URCU cds::urcu::gc<cds::urcu::general_buffered<> > gbRCU ; // main thread lock-free // main thread // libcds cds::threading::Manager::attachThread() ; // , libcds // ... } // libcds cds::Terminate() ; }
ãã¶ãŒããã€ã³ã¿ãŒã¹ããŒã ãšåæ§ã«ãURCUã³ã³ãããŒã䜿çšããåã¹ã¬ããã¯ãç¹å¥ãªæ¹æ³ã§åæåããå¿
èŠããããŸãã
libcdsã©ã€ãã©ãªã®URCUã³ã³ããã®äœ¿çšã¯å®å
šã«ééçã§ããURCUgcã§ã³ã³ãããªããžã§ã¯ãã宣èšããã ãã§ãã URCUã䜿çšããäœæ¥ã®è©³çŽ°ã¯ãã¹ãŠãã³ã³ãããŒã®URCUç¹æ®åã®äžã«é ãããŠããŸãã ãã®ãããªã³ã³ããã«ã¢ã¯ã»ã¹ããå Žåãå€éšåæã¯å¿
èŠãããŸããã
UPDïŒãã£ãšïŒãå€éšåæã¯å¿
èŠãããŸããã -ç§ã¯å°ãè奮ããŸããã
å®éãããã€ãã®URCUã³ã³ããã®äžéšã®ã¡ãœããã§ã¯ãæåã«ã¯ãªãã£ã«ã«èªã¿åãã»ã¯ã·ã§ã³ã«å
¥ãå¿
èŠããããŸãã éåžžããããã¯ã³ã³ããã¢ã€ãã ãåé€ïŒååŸïŒããããã®ã¡ãœããã§ãã URCUã¯ãããŒã§èŠã€ãã£ãèŠçŽ ãžã®ãã€ã³ã¿ãŒãè¿ãæ©èœãæäŸã§ããŸãã ãã®ãããªæ©äŒã¯ã競åããªãã¹ã¬ããã«ãã£ãŠãã€ã§ãèŠçŽ ãåé€ã§ããããããã¹ãã€ã³ã¿ã®æ»ãå€ãé垞䌌ãŠããããã¯ããªãŒã®äžçã§ã¯ãŸããªäŸå€ã§ãã ãã ããè¿ãããèŠçŽ ãã€ã³ã¿ãå®å
šã«äœ¿çšããã«ã¯ãéèŠãªèªã¿åãã»ã¯ã·ã§ã³ã«ããå¿
èŠããããŸãã ãã®ããããã®å Žåãã³ã³ããã¡ãœãããåŒã³åºãåã«access_lock
ãæ瀺çã«åŒã³åºãå¿
èŠãããããã€ã³ã¿ãŒaccess_unlock
ãaccess_unlock
æè¯ã®ïŒäŸå€ã«å¯ŸããŠå®å
šãªïŒã¡ãœããã¯ãå¥ã®ã³ãŒããããã¯ã§access_unlock
-lockã䜿çšããããšã§ãã
libcdsã©ã€ãã©ãªã®URCUã³ã³ããã®åã¡ãœããã®èª¬æã«ã¯ããã®ã¡ãœãããåŒã³åºãæ¹æ³ã瀺ãããŠããŸã-ã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ãã©ããã
libcdsããã®URCUã®å®è£
ã«åºã¥ããŠç¬èªã®ã³ã³ããã¯ã©ã¹ãäœæããå Žåã¯ãã©ã€ãã©ãªã®URCUã³ã³ããã®å
éšããã€ã¹ã詳现ã«ç解ããå¿
èŠããããŸãã ååãšããŠã
gc::access_unlock()
ãªããšã¯ãããŸããïŒã¡ãœããã«å
¥ããšãã«
gc::access_lock()
ã
gc::access_unlock()
ãçµäºãããšãã«
gc::access_unlock()
ã
gc::access_unlock()
ïŒããã§
gc
ã¯URCUå®è£
ã®1ã€ã§ããäŸå€ã®å®å
šæ§ã®ããã«ãé¢æ°ãåŒã³åºã代ããã«ã¹ã³ãŒãããã¯ãã¯ããã¯ã䜿çšããããšããå§ãããŸãïŒ ã å¯äžã®åŸ®åŠãªç¹ã¯ãèŠçŽ ã®åé€ã§ãïŒdeleteã¡ãœãããã¯ãªãã£ã«ã«èªã¿åãã»ã¯ã·ã§ã³ã«ããå¿
èŠããããŸããã
gc::retire_ptr
åŒã³åºãããšã«ããèŠçŽ ã®ç©ççãªåé€ã¯ã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ã®
å€åŽã§è¡ãå¿
èŠããããŸããããããªããšãããããã¯ãçºçããŸãïŒ
gc::retire_ptr
ã¯
synchronize
ãåŒã³åºãããšãã§ããŸã
Libcdsã¯ããã¹ãŠã®ã»ããããã³ãããã¯ã©ã¹ã®URCUç¹æ®åãå®çŸ©ããŸãã ãã¥ãŒã³ã³ãããšã¹ã¿ãã¯ã³ã³ããã®URCUã®ç¹æ®åã¯æªå®çŸ©ã§ãããã»ãŒèªã¿åãå°çšãã®ã³ã³ããã§ã¯ãªããããURCUã¯ãããã«å¯Ÿå¿ããŠããŸããã
ããã¯ããªãŒã®ããŒã¿æ§é éå§ããåºæ¬ïŒ
äžïŒ
å€ããïŒ