星期二, 2月 23, 2016

手機螢幕擷取

Zenfone 2 螢幕擷取方式
  1. 同時按電源及音量小聲鍵
  2. 快速設定小工具可以選四種,其中一個可設為螢幕截圖
  3. ASUS 個人化設定可將長按最近使用的應用程式鍵設為螢幕截圖
參考來源:http://www.androidcentral.com/how-take-screenshot-asus-zenfone-2

星期日, 2月 14, 2016

GCC 使用 MIPS DSP ASE

MIPS DSP ASE

gcc 編譯選項
  • 加「-mdsp」(24KE, 34K) 或「-mdsp2」(74K, M14KE),不然會有「undefined reference to `__ssaddhq3'」之類的錯誤
  • 加「-mips32r2」可使用 INS 指令,存取 SIMD 變數的單元有較好的效能
  • M14KE 的 DSP instructions 可組譯成 microMIPS opcode (加「-mmicromips」)
C 定義
  • __mips_dsp 或 __mips_dsp_rev=1
  • __mips_dspr2 或 __mips_dsp_rev=2
  • __MIPSEL__
Data types 及變數初始化
  • typedef short q15;
    q15 a = 0.1234 * 32768.0;
  • typedef int q31;
    q31 b = 0.2468 * 2147483648.0;
  • typedef long long a64;
  • typedef signed char v4i8 __attribute__ ((vector_size(4)));
    v4i8 a = {1, 2, 3, 4};
    v4i8 b;
    b = (v4i8) {5, 6, 7, 8};
  • typedef short v2q15 __attribute__ ((vector_size(4)));
    v2q15 a = {0x0fcb, 0x3a75};
    v2q15 b;
    b = (v2q15) {0.1234 * 32768.0, 0.4567 * 32768.0};
  • endian 問題,詳見 MD00485 2.4 2.5
C 運算子
  • fractional data 的 +, - 跟 integer data 一樣 (addu, subu),但 * (乘法) 後需要位移來對齊小數點
  • SIMD 變數可以使用 +, -, *, /, unary minus, ^, |, &, ~ 作運算,但只有 +, - 有指令 (addu.qb, subu.qb, addq.ph, subq.ph),其它 GCC 則 synthesizes 一系列指令。
暫存器多三組 HI-LO (共四組) 及 DSPControl
DSP Control Register
  • 有 6 欄位:
    namebitsmask說明
    CCOND 27:2416condition code
    OUFLAG 23:168overflow/underflow。只能用 wrdsp 清掉
    16:HI-LO 0
    17:HI-LO 1
    18:HI-LO 2
    19:HI-LO 3
    20:
    21:
    22:
    23:
    EFI 1432extract fail indicator
    C134carry bit,用在 addsc, addwc
    SCOUNT 12:72size count
    POS5:01position bits
  • 專用來存取的指令:rddsp/wrdsp
  • SCOUNT 及 POS 視為全域變數,會改變它們的指令或函數不會優化掉,包括 wrdsp, extpdp, extpdpv、及 mthlip。
  • For correctness, programmers must assume that a function call clobbers all fields of the DSP control register. That is, programmers cannot depend on the values in CCOND, OUFLAG, EFI or C across a function-call boundary. They must re-initialize the values of CCOND, OUFLAG, EFI or C before using them.
比較:使用內建函數 (Intrinsic) 及組合語言巨集 (macro)
內建函數已對 pipeline 延遲做最佳化,而 macro 沒有,而造成 code scheduling 較差、及增加 stall。

C 內建函數 (Intrinsics)
  • Q31
    • q31 __builtin_mips_addq_s_w (q31, q31);
      q31 __builtin_mips_subq_s_w (q31, q31);
    • q31 __builtin_mips_absq_s_w (q31);
    • q31 __builtin_mips_shll_s_w (q31, imm0_31);
      q31 __builtin_mips_shll_s_w (q31, i32);
    • q31 __builtin_mips_shra_r_w (q31, imm0_31);
      q31 __builtin_mips_shra_r_w (q31, i32);
    • a64 __builtin_mips_dpaq_sa_l_w (a64, q31, q31); // Q63 + Q31 * Q31 => Q63
      a64 __builtin_mips_dpsq_sa_l_w (a64, q31, q31); // Q63 - Q31 * Q31
    • q31 __builtin_mips_mulq_rs_w (q31, q31); // DSPR2
    • q31 __builtin_mips_mulq_s_w (q31, q31); // DSPR2
    • q31 __builtin_mips_addqh_w (q31, q31); // DSPR2
      q31 __builtin_mips_addqh_r_w (q31, q31); // DSPR2
    • q31 __builtin_mips_subqh_w (q31, q31); // DSPR2
      q31 __builtin_mips_subqh_r_w (q31, q31); // DSPR2
  • Q15
    • v2q15 __builtin_mips_addq_ph (v2q15, v2q15);
      v2q15 __builtin_mips_addq_s_ph (v2q15, v2q15);
      v2q15 __builtin_mips_subq_ph (v2q15, v2q15);
      v2q15 __builtin_mips_subq_s_ph (v2q15, v2q15);
    • v2q15 __builtin_mips_absq_s_ph (v2q15);
    • v2q15 __builtin_mips_shll_ph (v2q15, imm0_15);
      v2q15 __builtin_mips_shll_ph (v2q15, i32);
      v2q15 __builtin_mips_shll_s_ph (v2q15, imm0_15);
      v2q15 __builtin_mips_shll_s_ph (v2q15, i32);
    • v2q15 __builtin_mips_shra_ph (v2q15, imm0_15);
      v2q15 __builtin_mips_shra_ph (v2q15, i32);
      v2q15 __builtin_mips_shra_r_ph (v2q15, imm0_15);
      v2q15 __builtin_mips_shra_r_ph (v2q15, i32);
    • v2q15 __builtin_mips_mulq_rs_ph (v2q15, v2q15); // Q15 * Q15 => Q15
    • a64 __builtin_mips_dpaq_s_w_ph (a64, v2q15, v2q15); // 累加兩個乘積
      a64 __builtin_mips_dpsq_s_w_ph (a64, v2q15, v2q15); // 累減兩個乘積
    • a64 __builtin_mips_mulsaq_s_w_ph (a64, v2q15, v2q15); // 累加第一個乘積,減第二個乘積,跟 endian 有關
    • a64 __builtin_mips_maq_s_w_phl (a64, v2q15, v2q15); // 只累加其中一個乘積
      a64 __builtin_mips_maq_s_w_phr (a64, v2q15, v2q15);
      a64 __builtin_mips_maq_sa_w_phl (a64, v2q15, v2q15);
      a64 __builtin_mips_maq_sa_w_phr (a64, v2q15, v2q15);
    • q31 __builtin_mips_muleq_s_w_phl (v2q15, v2q15); // Q15 * Q15 => Q31,只相乘一組
      q31 __builtin_mips_muleq_s_w_phr (v2q15, v2q15);
    • Replicate a Fixed Half-word into Elements
      v2q15 __builtin_mips_repl_ph (imm_n512_511);
      v2q15 __builtin_mips_repl_ph (i32);
    • void __builtin_mips_cmp_eq_ph (v2q15, v2q15);
      void __builtin_mips_cmp_lt_ph (v2q15, v2q15);
      void __builtin_mips_cmp_le_ph (v2q15, v2q15);
    • v2q15 __builtin_mips_pick_ph (v2q15, v2q15);
    • v2q15 __builtin_mips_packrl_ph (v2q15, v2q15);
    • v2q15 __builtin_mips_mulq_s_ph (v2q15, v2q15); // DSPR2
    • v2q15 __builtin_mips_addqh_ph (v2q15, v2q15); // DSPR2
      v2q15 __builtin_mips_addqh_r_ph (v2q15, v2q15); // DSPR2
    • v2q15 __builtin_mips_subqh_ph (v2q15, v2q15); // DSPR2
      v2q15 __builtin_mips_subqh_r_ph (v2q15, v2q15); // DSPR2
    • a64 __builtin_mips_dpaqx_s_w_ph (a64, v2q15, v2q15); // DSPR2
      a64 __builtin_mips_dpaqx_sa_w_ph (a64, v2q15, v2q15); // DSPR2
      a64 __builtin_mips_dpsqx_s_w_ph (a64, v2q15, v2q15); // DSPR2
      a64 __builtin_mips_dpsqx_sa_w_ph (a64, v2q15, v2q15); // DSPR2
  • 8-bit
    • v4i8 __builtin_mips_addu_qb (v4i8, v4i8);
      v4i8 __builtin_mips_addu_s_qb (v4i8, v4i8);
      v4i8 __builtin_mips_subu_qb (v4i8, v4i8);
      v4i8 __builtin_mips_subu_s_qb (v4i8, v4i8);
    • i32 __builtin_mips_raddu_w_qb (v4i8);
    • v4i8 __builtin_mips_shll_qb (v4i8, imm0_7);
      v4i8 __builtin_mips_shll_qb (v4i8, i32);
      v4i8 __builtin_mips_shrl_qb (v4i8, imm0_7);
      v4i8 __builtin_mips_shrl_qb (v4i8, i32);
    • a64 __builtin_mips_dpau_h_qbl (a64, v4i8, v4i8);
      a64 __builtin_mips_dpau_h_qbr (a64, v4i8, v4i8);
      a64 __builtin_mips_dpsu_h_qbl (a64, v4i8, v4i8);
      a64 __builtin_mips_dpsu_h_qbr (a64, v4i8, v4i8);
    • v4i8 __builtin_mips_repl_qb (imm0_255);
      v4i8 __builtin_mips_repl_qb (i32);
    • void __builtin_mips_cmpu_eq_qb (v4i8, v4i8);
      void __builtin_mips_cmpu_lt_qb (v4i8, v4i8);
      void __builtin_mips_cmpu_le_qb (v4i8, v4i8);
      i32 __builtin_mips_cmpgu_eq_qb (v4i8, v4i8);
      i32 __builtin_mips_cmpgu_lt_qb (v4i8, v4i8);
      i32 __builtin_mips_cmpgu_le_qb (v4i8, v4i8);
      i32 __builtin_mips_cmpgdu_eq_qb (v4i8, v4i8); // DSPR2
      i32 __builtin_mips_cmpgdu_lt_qb (v4i8, v4i8); // DSPR2
      i32 __builtin_mips_cmpgdu_le_qb (v4i8, v4i8); // DSPR2
    • v4i8 __builtin_mips_pick_qb (v4i8, v4i8);
    • v4i8 __builtin_mips_absq_s_qb (v4i8); // DSPR2
    • v4i8 __builtin_mips_adduh_qb (v4i8, v4i8); // DSPR2
      v4i8 __builtin_mips_adduh_r_qb (v4i8, v4i8); // DSPR2
    • v4i8 __builtin_mips_shra_qb (v4i8, imm0_7); // DSPR2
      v4i8 __builtin_mips_shra_r_qb (v4i8, imm0_7); // DSPR2
      v4i8 __builtin_mips_shra_qb (v4i8, i32); // DSPR2
      v4i8 __builtin_mips_shra_r_qb (v4i8, i32); // DSPR2
    • v4i8 __builtin_mips_subuh_qb (v4i8, v4i8); // DSPR2
      v4i8 __builtin_mips_subuh_r_qb (v4i8, v4i8); // DSPR2
  • a64
    • i32 __builtin_mips_extr_w (a64, imm0_31);
      i32 __builtin_mips_extr_w (a64, i32);
      i32 __builtin_mips_extr_r_w (a64, imm0_31);
      i32 __builtin_mips_extr_r_w (a64, i32);
      i32 __builtin_mips_extr_rs_w (a64, imm0_31);
      i32 __builtin_mips_extr_rs_w (a64, i32);
    • i32 __builtin_mips_extr_s_h (a64, imm0_31);
      i32 __builtin_mips_extr_s_h (a64, i32);
    • i32 __builtin_mips_extp (a64, imm0_31);
      i32 __builtin_mips_extp (a64, i32);
    • i32 __builtin_mips_extpdp (a64, imm0_31);
      i32 __builtin_mips_extpdp (a64, i32);
    • a64 __builtin_mips_shilo (a64, imm_n32_31);
      a64 __builtin_mips_shilo (a64, i32);
    • a64 __builtin_mips_mthlip (a64, i32);
  • Precision Reduce/Expand
    • v4i8 __builtin_mips_precrq_qb_ph (v2q15, v2q15);
    • v4i8 __builtin_mips_precrqu_s_qb_ph (v2q15, v2q15);
    • v2q15 __builtin_mips_precequ_ph_qbl (v4i8);
      v2q15 __builtin_mips_precequ_ph_qbr (v4i8);
      v2q15 __builtin_mips_precequ_ph_qbla (v4i8);
      v2q15 __builtin_mips_precequ_ph_qbra (v4i8);
    • v2q15 __builtin_mips_preceu_ph_qbl (v4i8);
      v2q15 __builtin_mips_preceu_ph_qbr (v4i8);
      v2q15 __builtin_mips_preceu_ph_qbla (v4i8);
      v2q15 __builtin_mips_preceu_ph_qbra (v4i8);
    • v4i8 __builtin_mips_precr_qb_ph (v2i16, v2i16); // DSPR2
    • v2q15 __builtin_mips_precrq_ph_w (q31, q31);
    • v2q15 __builtin_mips_precrq_rs_ph_w (q31, q31);
    • q31 __builtin_mips_preceq_w_phl (v2q15);
      q31 __builtin_mips_preceq_w_phr (v2q15);
  • Int8 * Q15 => Q15
    • v2q15 __builtin_mips_muleu_s_ph_qbl (v4i8, v2q15);
      v2q15 __builtin_mips_muleu_s_ph_qbr (v4i8, v2q15);
  • Add and Set Carry/Add with Carry
    i32 __builtin_mips_addsc (i32, i32);
    i32 __builtin_mips_addwc (i32, i32);
  • Modular Subtraction on an Index Value
    i32 __builtin_mips_modsub (i32, i32);
  • Bit Reverse a Half-word
    i32 __builtin_mips_bitrev (i32);
  • Insert Bit Field Variable
    i32 __builtin_mips_insv (i32, i32);
  • Load Unsigned Byte/Halfword/Word Indexed
    i32 __builtin_mips_lbux (void *, i32);
    i32 __builtin_mips_lhx (void *, i32);
    i32 __builtin_mips_lwx (void *, i32);
  • Signed Multiply and Add
    a64 __builtin_mips_madd (a64, i32, i32);
  • Unsigned Mulitply and Add
    a64 __builtin_mips_maddu (a64, ui32, ui32);
  • Signed Multiply and Subtract
    a64 __builtin_mips_msub (a64, i32, i32);
  • Unsigned Multiply and Subtract
    a64 __builtin_mips_msubu (a64, ui32, ui32);
  • Signed Multiply
    a64 __builtin_mips_mult (i32, i32);
  • Unsigned Multiply
    a64 __builtin_mips_multu (ui32, ui32);
  • Left Shift and Append Bits (DSPR2)
    i32 __builtin_mips_append (i32, i32, imm0_31); // DSPR2
  • Byte Align Contents from Two Registers (DSPR2)
    i32 __builtin_mips_balign (i32, i32, imm0_3); // DSPR2
  • Right Shift and Prepend Bits (DSPR2)
    i32 __builtin_mips_prepend (i32, i32, imm0_31); // DSPR2
  • 3.9, 3.10
其它方式:
  • 全組合語言,或夾雜在 C 裡面
  • 使用 Fixed-point data types (_Frac) 搭配 C 運算子
參考資料:
  1. MD00485 -- 主要參考來源
  2. MD00086 The MIPS32® Instruction Set
  3. MD00374 The MIPS® DSP Application-Specific Extension to the MIPS32® Architecture
  4. GCC: Using Vector Instructions through Built-in Functions
相關文章:
  1. GCC Inline Assembly

星期四, 2月 04, 2016

Linux 書

Linux Kernel
參考來源
  1. Rex 的 Linux 系統軟體開發書籍推薦與 TLPI
延伸閱讀

malloc(), calloc(), realloc() 和 alloca()

可以從兩個所在動態取得記憶體,一般 malloc() 是從 heap,另一款是從 stack。

從 stack 動態配置記憶體,函數結束自動釋出。只是調整 stack 指標,效率足好。

#include <alloca.h>

void *alloca(size_t size);
  • 可簡化 longjmp() 或 siglongjmp() 的記憶體釋放,不鼓勵用在其它地方 (為什麼???)
  • 不能直接用在函數參數內,配置的記憶體夾在函數參數間可能會有問題。
  • stack overflow 時不會傳回 NULL,SIGSEGV

從 heap 動態配置記憶體

#include <stdlib.h>

// 取得 size 大小位元組、未初始化的記憶體空間。
void *malloc(size_t size);

// 從 heap 動態配置的記憶體,都需要用 free() 歸還,或者在程式結束時自動消失。
// 重複釋出可能發生不可預期的結果ptr 可以是 NULL,不進行任何動作。
void free(void *ptr);

// 基於 malloc(),取得 nmemb * size 大小的記憶體空間,並清為 0。
void *calloc(size_t nmemb, size_t size);


// 記憶體空間重新配置為 size 大小,重複部份會相同。
// 加大配置的空間時,位置可能變或不變。位置改變時會複製重複的部份,效能會較差。
void *realloc(void *ptr, size_t size);

其它使用 malloc() 的函式:strdup() 等。

malloc() 細節

heap 一般放在 Uninitialize data (bss) 後面生向高位址,另一端是 stack 生向 heap。

典型 x86-32 Linux layout

Kernel
0xC000 0000
argv, environment

Stack
Top of stack →

(unallocated memory)

Program break →
Heap

Uninitialized data (bss)

Initialized data

Text (program code)
0x0804 8000

0x0000 0000

heap 跟 stack 中間是實際沒用到的記憶體。heap 的盡頭就是 program break,不夠用時會用 sbrk() 調整 program break 來加大 heap,但通常不會縮減 heap。sbrk(0) 傳回目前 program break 位置。

藏在每一個 malloc() 的記憶體前面,會紀錄這段記憶體的大小。當 free() 時,利用記憶體空間形成 doubly link list 歸還回到 free 列表,並嘗試合併相鄰的記憶體區塊。

配置的記憶體區塊 (前置區塊大小)
size可使用的部份

已釋出可使用的列表 (利用可使用的部份存放 link list 指標)
sizeprevnext剩下可使用的部份

每次 malloc() 會先從 free 列表取得記憶體,例如用 first-fit 或 best-fit 等演算法,如取不到則嘗試加大 heap。

當配置的記憶體區塊大於 MMAP_THRESHOLD,glibc 改用系統呼叫 mmap() 配置,在 Linux 4.7 之後會受到 RLIMIT_DATA 限制。MMAP_THRESHOLD 預設 128 kB,可透過 mallopt() 調整。

在 multithread 應用,內部使用 mutex 保護相關資料結構,glibc 並建立額外的 memory allocation arenas。每個 arena 是內部用 brk() 或 mmap() 配置的大記憶體空間。

每個 process 有自己的虛擬記憶體,虛擬記憶體中實際有使用的區塊才會對應到實體記憶體。malloc() 不保證可以取得實體記憶體,萬一沒有實體記憶體體了,有些 process 會被 OOM killer 結束掉 (見 proc 檔案系統 /proc/sys/vm/overcommit_memory 和 /proc/sys/vm/oom_adj 的說明,以及 Linux kernel 的 Documentation/vm/overcommit-accounting)。

malloc() 除錯

mtrace()、muntrace()
mcheck()、mprobe()
malloc() 除錯函式庫:Electric Fence (http://www.perens.com/FreeSoftware/)、dmalloc (http://dmalloc.com/)、Valgrind (http://valgrind.org/)、Insure++ (http://www.parasoft.com/)。
mallopt()、mallinfo()

參考

  1. TLPI §7
  2. man alloca 
  3. malloc() man-page
  • asprintf()
  • mmap()
  • memalign()、posix_memalign()
  • malloc_trim()

Linux CPU 排程

Linux 程式執行以 thread 為單位,決定誰取得 CPU 使用權稱排程。Thread 在 userspace 是 preemptible 的 (非 cooperative multitasking),任何時間點 kernel tick 都有可能會中斷程式並切換到其它 thread,一個無限迴圈並不會卡住整個系統。至於透過 syscall 進入 kernel 的階段,是否 preemptible 由 kernel 設定 CONFIG_PREEMPT 決定。在 non-preemptive kernel,無限迴圈是會卡住整個系統。

註:preempty 是一種插隊的行為,像救護車,可翻作...。

由於 thread 是 preemptive 的,同一 process 內不同 thread 共用的資料,可能修改到一半有其它 thread 存取而造成錯誤 (修改被覆蓋、資料結構破壞等),所以需要 mutex 保護。函式可能重複呼叫,要看是否可以 reentry

每個 thread 有各自的 policy 及 priority 來決定排程,都會 preemptive 執行 priority 值最大的,相同 priority 的再由 policy 安排如何執行。thread 建立時會繼承 policy 及 priority。

等級policypriority說明
一般SCHED_OTHER
(預設)
0參考 nice 值動態調整 CPU 時間的使用比例,讓每個 thread 輪流、不用等候太久都能分配到 CPU 時間,滿足互動式多工系統。
SCHED_BATCH2.6.16+。類似 SCHED_OTHER,但排程會減少喚醒次數來減少 thread 切換,一般用在非互動式的程式。
SCHED_IDLE2.6.23+。以最低優先權執行。
(soft) real timeSCHED_FIFO1~99一開始先插隊執行,之後次序照先後排隊。每次執行直到等待 IO 或讓出。
SCHED_RR同 SCHED_FIFO,但每次執行有 time slice 時間限制。
SCHED_DEADLINELinux 3.14+

nice 值 (在 POSIX 是 process 層級的屬性,但目前 Linux/NPTL 實作是 thread 層級的屬性。)

  • 範圍 -20 ~ 19,預設 0,值越大越「好心」,排程分配的份量越少。對應到 kernel 內部表示的範圍是 40 ~ 1,相當於 20 - nice 值。不同 kernel 版本排程演算法有所不同。
  • 可以提高自己的 nice 值,只有 privileged thread 才能降低或設為負值 (chap35.3.2)。自從 Linux 2.6.12,process 有適當的 RLIMIT_NICE 軟性限制 (見 getrlimit()) 可以降低 nice 值。
  • round-robin timing-sharing 的 CPU 時間分配,滿足互動式多工系統需要的 Fairness (公平) 和 Responsive (不用等太久),按順序都會分配到 (不會餓死) time slice 或 quantum 的時間,除非自願放棄 (休息或等候) 才會縮短。
  • 會繼承
  • Linux 2.6.38 新增 "autogroup" 功能代表 nice 值在許多 circumstances 不再有其傳統效果。
  • getpriority(which, who):取得 which 中 who 裡 nice 值最小的。
    • which 可以是 PRIO_PROCESS (指 thread)、PRIO_PGRP、或 PRIO_USER,決定 who 是 process ID、process group ID、或 user ID。who 為 0 表示本身所屬 process、process group、或 user。
    • 由於 -1 可能是有效的值或錯誤,需先設 errno 為 0,如果回傳值是 -1 時,需檢查 errno 判別。
  • setpriority(which, who, value):
    • 有 CAP_SYS_NICE 權限可設其它 thread nice 值
    • 沒權限只能增加符合 real 或 effective user ID 的 thread。Kernel v2.6.12+ 的 RLIMI_NICE 限定可設定的範圍。
  • nice(incr)
  • 指令 nice
  • 指令 renice
POSIX realtime scheduling API 決定排程 policy 和 priority => 更緊密控制 CPU 時間
CPU affinity mask => 在多處理器系統決定可使用哪些處理器。
註:sched_get_priority_min(policy) 及 sched_get_priority_max(policy) 取得特定 policy 的 priority 範圍。
註:sched_setscheduler() 設定 pid 或自己的 policy 及 priority,而sched_setparam() 只設定 priority。sched_getscheduler()、sched_getparam() 分別取得 policy 和 prioity。在 2.6.12 以前, CAP_SYS_NICE 的 process 才能設定 policy 和 priority。另外,SCHED_OTHER process 的 real/effective user ID 和我的effective user ID 相同的,也可以設定。2.6.12 之後新增 RLIMIT_RTPRIO...。
s
避免 realtime process locking up 整個系統
  • 用 setrlimit() 設定適合的 low soft CPU time resource limit (RLIMIT_CPU, described in Section 36.3),如果 consumes too much CPU time 會送 SIGXCPU signal,預設 kill the process。
  • 用 alarm() 設定 alarm timer,如果執行超過時間會 killed by a SIGALRM signal。
  • 建立 watchdog process 執行在較高 realtime priority,無限迴圈 sleep 一段時間檢查其它 process 狀態,可順便量測 CPU time (Section 23.5.3 的 clock_getcpuclockid()) 和檢查 policy 和 priority,可降低 priority 或送 signal 停止會結束它。
  • 2.6.25 開始提供 RLIMIT_RTTIME 限制一次持續 CPU time 用量,送 signal SIGXCPU。細節見 Documentation/ scheduler/sched-rt-group.txt。
SCHED_RESET_ON_FORK
sched_yield()
註:sched_rr_get_interval() 取得 SCHED_RR 每次執行時間。
註:2.6.25+ /proc/sys/kernel/sched_rt_period_us/proc/sys/kernel/sched_rt_runtime_u

參考來源:
  1. man sched
  2. :《The Linux Programming Interface》chap. 35
  3. http://fcamel-life.blogspot.tw/2012/02/linux-process-priorities-and-scheduling.html (整理得不錯)
  4. http://stackoverflow.com/questions/10287561/sched-fifo-thread-is-preempted-by-sched-other-thread-in-linux
  5. man setpriority 
20200713 最後更新