• 沒有找到結果。

Synchronization Operation

在文檔中 多執行緒Java處理器設計 (頁 30-36)

第三章 Multicore Multithreading Java 處理器架構

3.2. Synchronization Operation

為了在 multithreading 環境下支援同步機制,本章節前面有舉例提到 Java 語言提供 Synchronized 保留字,相關實作方式包含 synchronized statement (圖 9(a))與 synchronized method (圖 9(b)),其中 synchronized method 的細節留給個別 Java 平台實做[6]。圖 9的 class B 用 Java compiler 所產生的 method B2、B3 的 bytecode 會包含 monitorenter 與 monitorexit 指令,因此當 TestTH class (圖 10)產生兩個 threads t1, t2 之後每次執行 method B2 或 B3 時,必然會執行到 monitor 相關指令;然而 Class A 編譯過後所產生的 method A2、A3 的 bytecode 並不包含這兩個指令,因此我們在 JAIP 處理器做少部分的修改以 實現 synchonized method 功能。

21

Complex_flag

以下先說明 JAIP 處理器的 Bytecode Execution Engine 如何解析 monitorenter 與 monitorexit 並啟動 ICCU,再說明 synchronized method 電路實作方式。圖 15說明 JAIP 的 Fetch stage 讀取 bytecode 複雜指令時,把原本 bytecode 指令轉換成一系列 j_code 指 令再依序傳到 Decode Stage 解析,某些指令如果無法在 1 clock 內於 Fetch、Decode、

Execute stage 完成工作的都被視為複雜指令。根據 Java instruction set 定義,執行 monitorente 與 monitorexit 這 2 個指令之前 Java Stack 的頂端元素必定存放 lock object 的 參考位置,當 current thread 執行這 2 個指令時,便會觸發 Java VM 內部機制,讀取這個 lock object 且檢查是否已經被其他 thread 占用,再回傳訊息給 current thread 判斷 thread state 是否會改變,最後 Java VM 內部執行 pop 的動作將 lock object 參考位置從 Java stack

22

頂端移除。而 JAIP 與 Data Coherence Controller 無法在 1 clock 內完成以上動作,因此 monitorenter 與 monitorexit 指令在 JAIP 內部被歸類為複雜指令。

當 monitorenter 與 monitorexit 進入 Translate Stage 時,Two-level Java Stack memory 的頂端元素為 lock object 的參考位置,Translate Stage 的輸出訊號 complex_flag 等於 1,

此時 jcode_info_AB 的內容代表 j_code ROM 的參考位置,指向 monitorenter 與 monitorexit 的 j_code 序列中第一個 j_code 位置。j_code ROM 為一個 on-chip block RAM 用來儲存 每個 bytecode 複雜指令所對應到的 j_code 序列,j_code 指令 0xF8 被用來觸發 Decode Stage 的 monitor_enter_req(圖 3-3),j_code 指令 0xF9 被用來觸發 Decode Stage 的 monitor_exit_req,而 j_code 指令 0x78 代表從 Two-level Java Stack memory 移除一個頂端 元素。0xF8 與 0x78 這 2 個 j_code 在此被用來實做 monitorenter 複雜指令,0xF9 與 0x78 這 2 個 j_code 在此被用來實做 monitorexit 複雜指令,以圖 15 為例,monitorenter 與 monitorexit 對應的 j_code 序列儲存在 j_code ROM 的起始位置分別為 36 與 50。

JAIP Fetch Stage 處理指令 monitorenter 與 monitorexit 的流程皆類似,在此一併描述 其流程。假設目前 Fetch Stage 正在處理 monitorenter 指令,則 mode_reg 的值變成 1,

jcode_info_AB=36 傳入 j_code address translation controller (圖 15),透過其內部電路決定 把 jcode_info_AB 的值傳給 jcode_addr,同時 mode_reg=1 表示 Fetch Stage 目前執行的 是複雜指令。因此從 j_code ROM 讀取的 j_code 會藉由 multiplexer 傳給 j_code_pair,下 個 clock j_code ROM 的訊號輸出為 0xF8 與 0xFF,當 Decode Stage 解析這組 j_code 時會 拉起 monitor_enter_flag,如 section 3-1 描述也會進一步啟動 ICCU,同時 stall_fetch=1 使 j_code ROM 暫停往下讀取下一個 j_code。等到 ICCU 整個執行完畢後,便會恢復整 個 Bytecode Execution Engine 正常運作,意即 stall_fetch=0。Fetch stage 累加 jcode_addr 其值為 37,並且到 j_code ROM 往下讀取一對 j_code 0x78 與 0xFF,移除 Two-level Java Stack memory 頂端元素。之後 complex_flag 與 mode_reg 等於 0,Fetch Stage 開始處理下 一個 bytecode 指令。

為了實做 synchronized method 電路,我們將在 method info 之中加入 synchronized flag

(如圖 14的 sync_flag),呼叫 method 過程中 DSRU 可以藉由 sync_flag 數值判斷是否為

23

synchronized method,修改 Fetch Stage 的 j_code address translation controller,使 DSRU 與 Method Area Controller 可以傳送信號控制 jcode_addr,我們在 j_code ROM 之中定義 2 組 j_code 序列並命名為 invoke_sync_mthd 與 rtn_sync_mthd,如圖 15所敘述,這 2 個 j_code 序列的起始位置分別為 35 與 49,結束位置分別為 37 與 51,以此方式重複使用 monitorenter 與 monitoerexit 的 j_code 序列;最後在 return frame 中加入 synchronized flag (圖 17),當執行 return 相關指令時 Method Area Controller 可判斷 synchronized flag 決定 是否需要執行釋放 lock object。

XRT: Cross-reference table MT: method

IF: interface

DRC: Dynamic Res. Ctrlr FLD: field

ID matches head of list

ID does not match head of list matched

still searching?

class not loaded

Execution of a

static/native/clinit method, new object,

or field access

Stack Init flag is activated

DCCCU gets the task done

圖 16 在 DSRU 中呼叫 synchronized method 的流程

當 Class Parser 解析一個 class 過程中如果遇到 synchonized method,則該 method info

24

的 sync_flag=1,Class parser 最後把所有 method_info 資訊依序寫到 cross reference table。

當 current thread 呼叫 method 時會執行相關複雜指令例如 invokevirtual、invokeinterface、

invokestatic 等,Fetch Stage 的 mode_reg=1,啟動 DSRU,其流程如圖 16所示,此時 DSRU 狀態從 Idle 到 Get_XRT_idx_from_CSCB,此時將 return frame 放到 Two-level Java stack memory 的頂端元素 (TOS_A、TOS_B,圖 19),同時將 operand bytes 及 control flags 從 Decode stage 傳給 DSRU,DSRU 之後根據 decode stage 給的 control flags 來決定工作內 容,如果發現是要呼叫 method 的動作,並且 DSRU 搜尋到正確的 class ID 與 method ID 時,其狀態進入到 Check_FLD_or_MT_info,檢查目前這個 method 相關資料是否已被載 入到 Method Area Circular Buffer 與 Class Symbol Table Circular Buffer,如果沒有則先進 入 DynamicClass_Loading_Parsing 狀態,啟動 Class parser 把 class data 與 method bytecode 分別載入 JAIP 之後,再進入下個狀態 MACB_CSCB_Loading。如果 method bytecode 已 被載入到 Method Area Circular Buffer,則直接進入 MACB_CSCB_Loading。

Cls_id Lv_cnt (1) (2) vp

Mthd_id jpc

(1) Reserved bit (2) Synchronized bit 1st. Entry

2nd. Entry

圖 17 return frame 格式

Method Area Controller 把呼叫的 method 完全載入到 Method Area Circular Buffer 之 後,DSRU 狀態進入到 Stack_init,此時 stall_fetch=0,所以 j_code ROM 輸出的 j_code 被傳到 jcode_pair 進入 Decode Stage。調整完 local variable pointer (vp)與 stack pointer (sp) 之後,此時 DSRU 內部 register 保存 method info 的訊息,並且呼叫 method 的工作已完 成,vp 指向 current method 的第 1 個 local variable(object 參考位置)。接著檢查 method info 的 sync_flag 訊號,如果是呼叫 synchronized method 則 sync_flag=1,DSRU 狀態從 Stack_init 轉成 Request_Lock_object。此時 2-level Java stack memory 的頂端元素為 return frame 的第一個 entry (圖 17),故直接把 stack 頂端元素的 synchronized bit 設成 1,DSRU

25

的 invoke_sync_flag=1,啟動 fetch stage 的 J_code address translation controller(如圖 15),

此時 jcode_addr=35 指向 invoke_sync_mthd 的 j_code 序列中第一個位置。並且下個 clock 讀取 j_code 0x18 與 0xFF,j_code 0x18 會把 vp 指向的 stack entry(第一個 local variable,

lock object 參考位置)加到 stack 頂端,接著 J_code address translation controller 再累加 jcode_addr 的值為 36 使下一組 j_code 0xF8 與 0xFF 被讀取。後續步驟跟上一段執行 monitorenter 的 j_code 序列流程一樣。等到 monitorenter 的 j_code 序列整個執行完畢後,

不管在 Data Coherence Controller 是否成功取得 lock object 權限,此時 mode_reg=0,DSRU 狀態回到 Idle。

當 current thread 在 synchronized method 底下執行 return 相關指令時,2-level Java Stack memory 的頂端 2 個元素(TOS_A、TOS_B,圖 19)分別存放 synchronized method 的 2 個 return frames(圖 17),Decode Stage 發送訊號讀取 TOS_A 的 synchronized bit 判斷 是否要執行 monitorexit 指令,結束之後再從 Class Symbol Table Circular Buffer 與 Method Area Circular Buffer 載入前一個 method image 與 symbol information(圖 18),Class Symbol Table Controller 的執行流程與 Method Area Controller 類似,在此一併說明。當 Method Area Controller 狀態為 Get_Offset,如果 return frames 的 synchronized bit = 1 則下個狀態 為 Release_lock_object;否則下個狀態為 Check_Offset。當 Method Area Controller 狀態 為 Release_lock_object,rtn_sync_flag=1 並且啟動 fetch stage 的 J_code address translation controller,此時 jcode_addr=49 指向 rtn_sync_mthd 的 j_code 序列中第一個位置。並且在 下個 clock 讀取 j_code 0x18 與 0xFF,此時 vp、sp 與 synchronized method 的 local variables 存放的位置未被清除,因此透過 vp 載入第一個 local variable(lock object 參考位置)加到 stack 頂端,接著 J_code address translation controller 再累加 jcode_addr 的值為 50 使下一 組 j_code 0xF9 與 0xFF 被讀取。後續步驟跟上一段執行 monitorexit 的 j_code 序列流程 一樣。等到 monitorexit 的 j_code 序列整個執行完畢後,此時 mode_reg=0,Method Area Controller 狀態進入 Check_Offset,開始載入 parent method 的 bytecode。

26

Wait the job done

Offset Ready

The method byteocdes are

cached

Mthd Loading

The related

constant pool data are not cached

Wait_Ack

#bytes needed < #bytes loaded

Command ack from bus

Complete writing data with burst length

Complete signal From bus

圖 18 The state diagram of Method Area Controller

在文檔中 多執行緒Java處理器設計 (頁 30-36)