📄 multi_consumer.uc
字号:
;------------------------------------------------------------------------------------
;
; I N T E L P R O P R I E T A R Y
;
; COPYRIGHT (c) 2001 BY INTEL CORPORATION. ALL RIGHTS
; RESERVED. NO PART OF THIS PROGRAM OR PUBLICATION MAY
; BE REPRODUCED, TRANSMITTED, TRANSCRIBED, STORED IN A
; RETRIEVAL SYSTEM, OR TRANSLATED INTO ANY LANGUAGE OR COMPUTER
; LANGUAGE IN ANY FORM OR BY ANY MEANS, ELECTRONIC, MECHANICAL,
; MAGNETIC, OPTICAL, CHEMICAL, MANUAL, OR OTHERWISE, WITHOUT
; THE PRIOR WRITTEN PERMISSION OF :
;
; INTEL CORPORATION
;
; 2200 MISSION COLLEGE BLVD
;
; SANTA CLARA, CALIFORNIA 95052-8119
;
;------------------------------------------------------------------------------------
// File : multi_consumer.uc
//
// Description : (First see multi_producer.uc for an overall description.)
//
// This file contains the code for multi consumer, illustrating use of scratch rings.
//
// Psuedo Code
// 1. Wait (for signal) until Initialisation is done by producer.
// 2. Check if the ring is empty.
// 3. If not empty get an item from the ring.
// 4. Keep doing it again and again. (goto step 2)
#include "scratchring.h"
#include "sig_macros.uc"
.reg $rdata, ring
.sig scr_get ; signal for scratch get
.sig volatile wake_cons, wake_thrd ; signal for waking consumers, waking threads
// We use manual allocation for these signals because we have problems
// using "visible" (.sig visible wake_cons in multi_producer) and "remote" in this file
// Until it is solved, we'll have to use this manual allocation.
.addr wake_cons SIG_WAKE_CONS
.addr wake_thrd SIG_WAKE_THRD
// thread 0 starts here.
.if (ctx() == 0)
alu_shf[ring, --, b, RING_NUMBER, <<2] ; ring number in a register
// For thread 0, Wait until the prodcuer has initialised the ring and is ready.
ctx_arb[wake_cons] ; Wait for signal from producer
br[poll#] ; start consuming from the ring
.endif
// All other threads start here.
alu_shf[ring, --, b, RING_NUMBER, <<2] ; ring number in a register
// wait for signal from prev. thread.
ctx_arb[wake_thrd] ; Wait for signal from prev thread
// Get data from ring, only after checking if the ring is not empty.
// Ring is empty if the "get" data returns zero. This has the implication
// that we should not put a zero on the ring.
// Unlike producer, we should not stall (loop) on empty ring. We should
// asssume that we received a null packet, signal the next thread
// and proceed thro' the pipeline with an empty packet.
// However, for simplicity, we loop in this example.
poll#:
scratch[get, $rdata, 0, ring, 1], ctx_swap[scr_get] ; Get 1 word from ring.
alu[--, $rdata, -, 0] ; Check for 0. i.e check if ring empty
beq[poll#] ; if empty, go back.
// Do something with the data here.
nop ; set break point and see.
// Signal Next Thread to consume.
//.if (ctx() != 7)
br=ctx[7, thread7#]
signal_next_ctx[wake_thrd] ; signal next thread in the same ME.
br[wait#] ; wait for next iteration.
//.else
thread7#:
signal_first_ctx[wake_thrd] ; Thread 7, so signal first thread
//.endif
wait#:
ctx_arb[wake_thrd] ; wait for signal from prev thread
br[poll#] ; Keep consuming on the ring.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -