XArray¶
- 作者:
Matthew Wilcox
概述¶
XArray 是一種抽象資料型別,其行為類似於一個巨大的指標陣列。它滿足了散列表或常規可變大小陣列的許多相同需求。與散列表不同,它允許您以快取高效的方式合理地訪問下一個或上一個條目。與可變大小陣列相比,它無需複製資料或更改 MMU 對映即可擴充套件陣列。它比雙向連結串列更節省記憶體、更易於並行化且快取友好。它利用 RCU 實現無鎖查詢。
當使用的索引密集聚類時,XArray 的實現是高效的;對物件進行雜湊並將雜湊值用作索引將無法很好地執行。XArray 針對小索引進行了最佳化,但對於大索引仍然具有良好的效能。如果您的索引可能大於 ULONG_MAX,那麼 XArray 不適合您。XArray 最重要的使用者是頁快取。
普通指標可以直接儲存在 XArray 中。它們必須是 4 位元組對齊的,這對於 kmalloc() 和 alloc_page() 返回的任何指標都是如此。對於任意使用者空間指標或函式指標則不然。您可以儲存指向靜態分配物件的指標,只要這些物件至少有 4 位元組對齊。
您還可以在 XArray 中儲存 0 到 LONG_MAX 之間的整數。您必須首先使用 xa_mk_value() 將其轉換為一個條目。當您從 XArray 檢索一個條目時,您可以透過呼叫 xa_is_value() 來檢查它是否是值條目,並透過呼叫 xa_to_value() 將其轉換回整數。
一些使用者希望標記他們儲存在 XArray 中的指標。您可以使用 xa_tag_pointer() 建立一個帶有標記的條目,使用 xa_untag_pointer() 將標記的條目轉換回未標記的指標,並使用 xa_pointer_tag() 檢索條目的標記。標記的指標使用與區分值條目和普通指標相同的位,因此您必須決定在任何特定的 XArray 中是儲存值條目還是標記指標。
XArray 不支援儲存 IS_ERR() 指標,因為某些指標會與值條目或內部條目衝突。
XArray 的一個不尋常的特性是能夠建立佔據一系列索引的條目。一旦儲存,查詢範圍內的任何索引都將返回與查詢範圍內任何其他索引相同的條目。儲存到任何一個索引都會儲存到所有這些索引。多索引條目可以明確地分割成更小的條目。取消設定(使用 xa_erase() 或使用 NULL 呼叫 xa_store())任何條目都將導致 XArray 忘記該範圍。
普通 API¶
首先初始化一個 XArray,可以使用 DEFINE_XARRAY() 用於靜態分配的 XArray,或者使用 xa_init() 用於動態分配的 XArray。一個剛初始化的 XArray 在每個索引處都包含一個 NULL 指標。
然後您可以使用 xa_store() 設定條目,並使用 xa_load() 獲取條目。xa_store() 會用新條目覆蓋任何現有條目,並返回該索引處儲存的舊條目。您可以使用 xa_erase() 或使用 xa_store() 將條目設定為 NULL 來取消設定條目。從未儲存過的條目與已被 xa_erase() 擦除的條目之間沒有區別;最近儲存為 NULL 的條目也等效,除非 XArray 是用 XA_FLAGS_ALLOC 初始化的。
您可以透過使用 xa_cmpxchg() 有條件地替換索引處的條目。與 cmpxchg() 類似,它僅當該索引處的條目具有“舊”值時才會成功。它還會返回該索引處原有的條目;如果它返回與作為“舊”值傳遞的條目相同的條目,則 xa_cmpxchg() 成功。
如果您只想在當前索引處的條目為 NULL 時才儲存新條目,可以使用 xa_insert(),如果條目不為空,它將返回 -EBUSY。
您可以透過呼叫 xa_extract() 將條目從 XArray 複製到普通陣列中。或者,您可以透過呼叫 xa_for_each()、 xa_for_each_start() 或 xa_for_each_range() 來遍歷 XArray 中的現有條目。您可能更傾向於使用 xa_find() 或 xa_find_after() 移動到 XArray 中的下一個現有條目。
呼叫 xa_store_range() 會在一定範圍的索引中儲存相同的條目。如果您這樣做,其他一些操作的行為會略顯奇怪。例如,標記一個索引處的條目可能會導致其他一些(但不是所有)索引處的條目被標記。儲存到一個索引可能會導致其他一些(但不是所有)索引檢索到的條目發生變化。
有時您需要確保後續呼叫 xa_store() 不需要分配記憶體。xa_reserve() 函式會在指定索引處儲存一個保留條目。普通 API 的使用者會將此條目視為包含 NULL。如果您不需要使用保留條目,可以呼叫 xa_release() 來移除未使用的條目。如果同時有其他使用者儲存到該條目,xa_release() 將不執行任何操作;如果您希望該條目變為 NULL,則應使用 xa_erase()。對保留條目使用 xa_insert() 將失敗。
如果陣列中的所有條目都是 NULL,則 xa_empty() 函式將返回 true。
最後,您可以透過呼叫 xa_destroy() 從 XArray 中移除所有條目。如果 XArray 條目是指標,您可能希望首先釋放這些條目。您可以透過使用 xa_for_each() 迭代器遍歷 XArray 中所有現有條目來完成此操作。
搜尋標記¶
陣列中的每個條目都關聯著三個位,稱為標記。每個標記都可以獨立地設定或清除。您可以使用 xa_for_each_marked() 迭代器遍歷已標記的條目。
您可以使用 xa_get_mark() 查詢條目上是否設定了標記。如果條目不是 NULL,您可以使用 xa_set_mark() 設定標記,並透過呼叫 xa_clear_mark() 移除條目上的標記。您可以透過呼叫 xa_marked() 查詢 XArray 中是否有任何條目設定了特定標記。從 XArray 中擦除一個條目會導致與該條目關聯的所有標記都被清除。
設定或清除多索引條目的任何索引上的標記將影響該條目覆蓋的所有索引。查詢任何索引上的標記將返回相同的結果。
沒有辦法遍歷未標記的條目;資料結構不允許高效地實現這一點。目前沒有迭代器來搜尋位的邏輯組合(例如,遍歷所有同時設定了 XA_MARK_1 和 XA_MARK_2 的條目,或遍歷所有設定了 XA_MARK_0 或 XA_MARK_2 的條目)。如果出現使用者需求,未來可能會新增這些功能。
分配 XArray¶
如果您使用 DEFINE_XARRAY_ALLOC() 來定義 XArray,或者透過向 xa_init_flags() 傳遞 XA_FLAGS_ALLOC 來初始化它,則 XArray 會跟蹤條目是否在使用中。
您可以呼叫 xa_alloc() 將條目儲存在 XArray 的未使用索引處。如果您需要從中斷上下文修改陣列,可以使用 xa_alloc_bh() 或 xa_alloc_irq() 以便在分配 ID 時停用中斷。
使用 xa_store()、xa_cmpxchg() 或 xa_insert() 也會將條目標記為已分配。與普通 XArray 不同,儲存 NULL 會將條目標記為正在使用中,就像 xa_reserve() 一樣。要釋放條目,請使用 xa_erase()(或者如果您只想在條目為 NULL 時才釋放,則使用 xa_release())。
預設情況下,最低的空閒條目從 0 開始分配。如果您想從 1 開始分配條目,使用 DEFINE_XARRAY_ALLOC1() 或 XA_FLAGS_ALLOC1 會更高效。如果您想將 ID 分配到最大值,然後迴圈回到最低的空閒 ID,可以使用 xa_alloc_cyclic()。
您不能將 XA_MARK_0 與分配 XArray 一起使用,因為此標記用於跟蹤條目是否空閒。其他標記可供您使用。
記憶體分配¶
xa_store()、xa_cmpxchg()、xa_alloc()、xa_reserve() 和 xa_insert() 函式接受一個 gfp_t 引數,以防 XArray 需要分配記憶體來儲存此條目。如果條目正在被刪除,則無需執行記憶體分配,並且指定的 GFP 標誌將被忽略。
可能無法分配記憶體,特別是如果您傳遞了一組限制性的 GFP 標誌。在這種情況下,函式會返回一個特殊值,該值可以使用 xa_err() 轉換為錯誤號。如果您不需要確切知道發生了哪個錯誤,使用 xa_is_err() 效率略高。
鎖機制¶
使用普通 API 時,您無需擔心鎖機制。XArray 使用 RCU 和內部自旋鎖來同步訪問。
- 無需加鎖
- 獲取 RCU 讀鎖
- 內部獲取 xa_lock
- 假設進入時已持有 xa_lock
如果您想利用鎖來保護儲存在 XArray 中的資料結構,您可以在呼叫 xa_load() 之前呼叫 xa_lock(),然後在呼叫 xa_unlock() 之前對找到的物件進行引用計數。這將防止在查詢物件和增加引用計數之間,儲存操作將物件從陣列中移除。您還可以使用 RCU 來避免解引用已釋放的記憶體,但這超出了本文件的範圍。
XArray 在修改陣列時不會停用中斷或軟中斷。從中斷或軟中斷上下文讀取 XArray 是安全的,因為 RCU 鎖提供了足夠的保護。
例如,如果您想在程序上下文中將條目儲存到 XArray 中,然後在軟中斷上下文中擦除它們,您可以這樣做:
void foo_init(struct foo *foo)
{
xa_init_flags(&foo->array, XA_FLAGS_LOCK_BH);
}
int foo_store(struct foo *foo, unsigned long index, void *entry)
{
int err;
xa_lock_bh(&foo->array);
err = xa_err(__xa_store(&foo->array, index, entry, GFP_KERNEL));
if (!err)
foo->count++;
xa_unlock_bh(&foo->array);
return err;
}
/* foo_erase() is only called from softirq context */
void foo_erase(struct foo *foo, unsigned long index)
{
xa_lock(&foo->array);
__xa_erase(&foo->array, index);
foo->count--;
xa_unlock(&foo->array);
}
如果您要從中斷或軟中斷上下文修改 XArray,您需要使用 xa_init_flags() 初始化陣列,並傳入 XA_FLAGS_LOCK_IRQ 或 XA_FLAGS_LOCK_BH。
上面的示例還展示了一種常見模式,即希望擴充套件儲存側 xa_lock 的覆蓋範圍,以保護與陣列關聯的某些統計資訊。
與中斷上下文共享 XArray 也是可能的,可以使用 xa_lock_irqsave() 在中斷處理程式和程序上下文中都進行加鎖,或者在程序上下文中使用 xa_lock_irq() 並在中斷處理程式中使用 xa_lock()。一些更常見的模式有輔助函式,例如 xa_store_bh()、xa_store_irq()、xa_erase_bh()、xa_erase_irq()、xa_cmpxchg_bh() 和 xa_cmpxchg_irq()。
有時您需要使用互斥鎖保護對 XArray 的訪問,因為該鎖在鎖定層次結構中位於另一個互斥鎖之上。但這並不能授權您在不持有 xa_lock 的情況下使用 __xa_erase() 等函式;xa_lock 用於 lockdep 驗證,並且將來會用於其他目的。
__xa_set_mark() 和 __xa_clear_mark() 函式也可用於您查詢條目並希望原子地設定或清除標記的情況。在這種情況下,使用高階 API 可能更高效,因為它可以避免您兩次遍歷樹。
高階 API¶
高階 API 以犧牲更難使用和更少安全保障的介面為代價,提供了更高的靈活性和更好的效能。高階 API 不會為您執行任何鎖定,並且在修改陣列時,您需要使用 xa_lock。在對陣列進行只讀操作時,您可以選擇使用 xa_lock 或 RCU 鎖。您可以在同一個陣列上混合使用高階和普通操作;實際上,普通 API 是透過高階 API 實現的。高階 API 僅適用於具有 GPL 相容許可證的模組。
高階 API 基於 xa_state。這是一個不透明的資料結構,您可以使用 XA_STATE() 宏在棧上宣告它。此宏初始化 xa_state,準備開始遍歷 XArray。它用作遊標,以維護在 XArray 中的位置,並允許您組合各種操作而無需每次都從頭開始。xa_state 的內容受 rcu_read_lock() 或 xas_lock() 保護。如果您需要釋放保護您狀態和樹的鎖,您必須呼叫 xas_pause(),這樣將來的呼叫就不會依賴於未受保護的狀態部分。
xa_state 也用於儲存錯誤。您可以呼叫 xas_error() 來檢索錯誤。所有操作在繼續之前都會檢查 xa_state 是否處於錯誤狀態,因此您無需在每次呼叫後都檢查錯誤;您可以連續進行多次呼叫,只在方便時檢查。XArray 程式碼本身當前生成的錯誤只有 ENOMEM 和 EINVAL,但它支援任意錯誤,以防您想自己呼叫 xas_set_err()。
如果 xa_state 包含 ENOMEM 錯誤,呼叫 xas_nomem() 將嘗試使用指定的 gfp 標誌分配更多記憶體,並將其快取在 xa_state 中以供下次嘗試。其思想是,您獲取 xa_lock,嘗試操作,然後釋放鎖。操作在持有鎖時嘗試分配記憶體,但它更有可能失敗。一旦您釋放了鎖,xas_nomem() 可以更努力地嘗試分配更多記憶體。如果值得重試操作(即存在記憶體錯誤**且**分配了更多記憶體),它將返回 true。如果它之前分配了記憶體,並且該記憶體沒有被使用,並且沒有錯誤(或不是 ENOMEM 的其他錯誤),那麼它將釋放之前分配的記憶體。
內部條目¶
XArray 為其自身目的保留了一些條目。這些條目從不透過普通 API 公開,但在使用高階 API 時,可以看到它們。通常處理它們的最佳方式是將它們傳遞給 xas_retry(),如果返回 true,則重試操作。
名稱 |
測試 |
用法 |
節點 |
xa_is_node() |
一個 XArray 節點。在使用多索引 xa_state 時可能會可見。 |
兄弟節點 |
多索引條目的非規範條目。該值指示此節點中的哪個槽位具有規範條目。 |
|
重試 |
此條目當前正在被持有 xa_lock 的執行緒修改。包含此條目的節點可能會在此 RCU 週期結束時釋放。您應該從陣列的頭部重新開始查詢。 |
|
零值 |
零值條目透過普通 API 顯示為 |
將來可能會新增其他內部條目。在可能的情況下,它們將由 xas_retry() 處理。
附加功能¶
xas_create_range() 函式分配儲存範圍內所有條目所需的所有記憶體。如果無法分配記憶體,它將在 xa_state 中設定 ENOMEM。
您可以使用 xas_init_marks() 將條目上的標記重置為預設狀態。這通常是所有標記清除,除非 XArray 被標記為 XA_FLAGS_TRACK_FREE,在這種情況下標記 0 被設定,所有其他標記被清除。使用 xas_store() 將一個條目替換為另一個條目不會重置該條目上的標記;如果需要重置標記,應明確進行。
xas_load() 將盡可能地將 xa_state 遊標移動到條目附近。如果您知道 xa_state 遊標已經移動到條目,並且需要檢查條目是否未更改,您可以使用 xas_reload() 來節省一次函式呼叫。
如果您需要在 XArray 中移動到不同的索引,請呼叫 xas_set()。這會將遊標重置到樹的頂部,通常會使下一個操作將遊標移動到樹中所需的位置。如果您想移動到下一個或上一個索引,請呼叫 xas_next() 或 xas_prev()。設定索引不會遍歷陣列,因此不需要持有鎖,而移動到下一個或上一個索引則需要。
您可以使用 xas_find() 搜尋下一個現有條目。這等同於 xa_find() 和 xa_find_after();如果遊標已經移動到某個條目,那麼它將找到當前引用條目之後的下一個條目。否則,它將返回 xa_state 索引處的條目。使用 xas_next_entry() 移動到下一個現有條目而不是 xas_find(),在大多數情況下可以節省一次函式呼叫,但代價是會生成更多的內聯程式碼。
xas_find_marked() 函式類似。如果 xa_state 尚未遍歷,它將返回 xa_state 索引處的條目(如果已標記)。否則,它將返回 xa_state 引用條目之後的第一個標記條目。xas_next_marked() 函式等同於 xas_next_entry()。
當使用 xas_for_each() 或 xas_for_each_marked() 遍歷 XArray 的一個範圍時,可能需要暫時停止迭代。xas_pause() 函式為此目的而存在。完成必要工作並希望恢復後,xa_state 將處於適當狀態,以便在您上次處理的條目之後繼續迭代。如果您在迭代時停用了中斷,那麼每隔 XA_CHECK_SCHED 個條目暫停迭代並重新啟用中斷是良好的習慣。
xas_get_mark()、xas_set_mark() 和 xas_clear_mark() 函式要求 xa_state 遊標已移動到 XArray 中的適當位置;如果您之前立即呼叫了 xas_pause() 或 xas_set(),它們將不執行任何操作。
您可以呼叫 xas_set_update() 以便在 XArray 每次更新節點時呼叫回撥函式。頁快取工作集程式碼使用此功能來維護其僅包含影子條目的節點列表。
多索引條目¶
XArray 能夠將多個索引繫結在一起,從而對一個索引的操作會影響所有索引。例如,儲存到任何索引都會改變從任何索引檢索到的條目的值。設定或清除任何索引上的標記將設定或清除所有繫結在一起的索引上的標記。當前實現只允許繫結對齊的 2 的冪範圍;例如,索引 64-127 可以繫結在一起,但 2-6 不可以。這可以節省大量的記憶體;例如,繫結 512 個條目將節省超過 4KB。
您可以透過使用 XA_STATE_ORDER() 或 xas_set_order(),然後呼叫 xas_store() 來建立多索引條目。使用多索引 xa_state 呼叫 xas_load() 會將 xa_state 遊標移動到樹中的正確位置,但返回值沒有意義,即使範圍內儲存有條目,也可能是內部條目或 NULL。呼叫 xas_find_conflict() 將返回範圍內的第一個條目,如果範圍內沒有條目則返回 NULL。xas_for_each_conflict() 迭代器將遍歷與指定範圍重疊的每個條目。
如果 xas_load() 遇到多索引條目,xa_state 中的 xa_index 將不會改變。當遍歷 XArray 或呼叫 xas_find() 時,如果初始索引位於多索引條目的中間,它將不會被更改。後續呼叫或迭代會將索引移動到範圍內的第一個索引。每個條目只會返回一次,無論它佔據多少個索引。
不支援將 xas_next() 或 xas_prev() 與多索引 xa_state 一起使用。對多索引條目使用這些函式中的任何一個都將揭示兄弟條目;呼叫者應跳過這些條目。
將 NULL 儲存到多索引條目的任何索引中,都會將每個索引處的條目設定為 NULL 並解除繫結。多索引條目可以透過在不持有 xa_lock 的情況下呼叫 xas_split_alloc(),然後獲取鎖並呼叫 xas_split(),或者在持有 xa_lock 的情況下呼叫 xas_try_split() 來分割成佔用更小範圍的條目。xas_split_alloc() + xas_split() 與 xas_try_alloc() 的區別在於,xas_split_alloc() + xas_split() 一次性均勻地將條目從原始順序分割到新順序,而 xas_try_split() 則根據給定索引迭代地非均勻分割包含該索引的條目。例如,要分割一個 order-9 條目,它佔用 2^(9-6)=8 個槽位(假設 XA_CHUNK_SHIFT 為 6),xas_split_alloc() + xas_split() 需要 8 個 xa_node。xas_try_split() 將 order-9 條目分割成 2 個 order-8 條目,然後根據給定索引將一個 order-8 條目分割成 2 個 order-7 條目,依此類推,並將一個 order-1 條目分割成 2 個 order-0 條目。當分割 order-6 條目並需要一個新的 xa_node 時,xas_try_split() 如果可能將嘗試分配一個。因此,xas_try_split() 只需要 1 個 xa_node 而不是 8 個。
函式和結構體¶
-
void *xa_mk_value(unsigned long v)¶
從整數建立 XArray 條目。
引數
unsigned long v要儲存在 XArray 中的值。
上下文
任何上下文。
返回
適合儲存在 XArray 中的條目。
-
unsigned long xa_to_value(const void *entry)¶
獲取儲存在 XArray 條目中的值。
引數
const void *entryXArray 條目。
上下文
任何上下文。
返回
儲存在 XArray 條目中的值。
-
bool xa_is_value(const void *entry)¶
判斷條目是否為值。
引數
const void *entryXArray 條目。
上下文
任何上下文。
返回
如果條目是值則為 true,如果是指標則為 false。
-
void *xa_tag_pointer(void *p, unsigned long tag)¶
為帶標記的指標建立 XArray 條目。
引數
void *p普通指標。
unsigned long tag標記值(0、1 或 3)。
描述
如果 XArray 的使用者願意,他們可以標記其指標而不是儲存值條目。提供了三個標記(0、1 和 3)。這些標記與 xa_mark_t 不同,因為它們不會透過陣列向上複製,也無法進行搜尋。
上下文
任何上下文。
返回
一個 XArray 條目。
-
void *xa_untag_pointer(void *entry)¶
將 XArray 條目轉換為普通指標。
引數
void *entryXArray 條目。
描述
如果您在 XArray 中儲存了帶標記的指標,請呼叫此函式獲取該指標的未標記版本。
上下文
任何上下文。
返回
一個指標。
-
unsigned int xa_pointer_tag(void *entry)¶
獲取儲存在 XArray 條目中的標記。
引數
void *entryXArray 條目。
描述
如果您在 XArray 中儲存了帶標記的指標,請呼叫此函式獲取該指標的標記。
上下文
任何上下文。
返回
一個標記。
-
bool xa_is_zero(const void *entry)¶
該條目是否為零值條目?
引數
const void *entry從 XArray 檢索到的條目
描述
普通 API 會將包含零值條目的槽位內容返回為 NULL。您只能透過高階 API 看到零值條目。
返回
如果條目是零值條目,則為 true。
-
bool xa_is_err(const void *entry)¶
報告 XArray 操作是否返回了錯誤
引數
const void *entry呼叫 XArray 函式的結果
描述
如果 XArray 操作無法完成,它將返回一個指示錯誤的特殊值。此函式告訴您是否發生了錯誤;xa_err() 告訴您發生了哪個錯誤。
上下文
任何上下文。
返回
如果條目指示錯誤,則為 true。
-
int xa_err(void *entry)¶
將 XArray 結果轉換為錯誤號。
引數
void *entry呼叫 XArray 函式的結果。
描述
如果 XArray 操作無法完成,它將返回一個編碼了錯誤號的特殊指標值。此函式從指標值中提取錯誤號,如果指標不表示錯誤號,則返回 0。
上下文
任何上下文。
返回
一個負的錯誤號或 0。
-
struct xa_limit¶
表示 ID 範圍。
定義:
struct xa_limit {
u32 max;
u32 min;
};
成員
max要分配的最大 ID(包含)。
min要分配的最低 ID(包含)。
描述
此結構體直接或透過 XA_LIMIT() 宏用於傳達有效分配的 ID 範圍。為您預定義了三個常用範圍:* xa_limit_32b - [0 - UINT_MAX] * xa_limit_31b - [0 - INT_MAX] * xa_limit_16b - [0 - USHRT_MAX]
-
struct xarray¶
XArray 的錨點。
定義:
struct xarray {
spinlock_t xa_lock;
};
成員
xa_lock保護 XArray 內容的鎖。
描述
要使用 xarray,請將其靜態定義或嵌入到您的資料結構中。它是一個非常小的資料結構,因此通常沒有必要單獨分配它並在您的資料結構中保留一個指向它的指標。
您也可以使用 xa_lock 來保護您自己的資料結構。
-
DEFINE_XARRAY_FLAGS¶
DEFINE_XARRAY_FLAGS (name, flags)
定義具有自定義標誌的 XArray。
引數
name您的 XArray 的名稱字串。
flagsXA_FLAG 值。
描述
這旨在用於檔案範圍的 XArray 定義。它宣告並初始化一個帶有指定名稱和標誌的空 XArray。它等同於對陣列呼叫 xa_init_flags(),但在編譯時而不是執行時進行初始化。
-
DEFINE_XARRAY¶
DEFINE_XARRAY (name)
定義一個 XArray。
引數
name您的 XArray 的名稱字串。
描述
這旨在用於檔案範圍的 XArray 定義。它宣告並初始化一個帶有指定名稱的空 XArray。它等同於對陣列呼叫 xa_init(),但在編譯時而不是執行時進行初始化。
-
DEFINE_XARRAY_ALLOC¶
DEFINE_XARRAY_ALLOC (name)
定義一個從 0 開始分配 ID 的 XArray。
-
DEFINE_XARRAY_ALLOC1¶
DEFINE_XARRAY_ALLOC1 (name)
定義一個從 1 開始分配 ID 的 XArray。
引數
struct xarray *xaXArray。
gfp_t flagsXA_FLAG 值。
描述
如果您需要使用特殊標誌(例如,您需要在中斷上下文中獲取鎖)初始化 XArray,請使用此函式而不是 xa_init()。
上下文
任何上下文。
引數
struct xarray *xaXArray。
描述
一個空的 XArray 充滿了 NULL 條目。
上下文
任何上下文。
引數
const struct xarray *xaXArray。
上下文
任何上下文。
返回
如果陣列僅包含 NULL 指標,則為 true。
引數
const struct xarray *xa陣列
xa_mark_t mark標記值
上下文
任何上下文。
返回
如果任何條目設定了此標記,則為 true。
-
xa_for_each_range¶
xa_for_each_range (xa, index, entry, start, last)
遍歷 XArray 的一部分。
引數
xaXArray。
index條目的索引。
entry從陣列中檢索到的條目。
start從陣列中檢索的第一個索引。
last從陣列中檢索的最後一個索引。
描述
在迭代期間,entry 將是儲存在 xa 中 index 處的條目的值。您可以在迭代期間修改 index,如果想跳過或重新處理索引。在迭代期間修改陣列是安全的。迭代結束時,entry 將被設定為 NULL,並且 index 的值將小於或等於 max。
xa_for_each_range() 是 O(n.log(n)) 而 xas_for_each() 是 O(n)。您必須自行處理 xas_for_each() 的鎖定,如果您在每次迭代後都必須解鎖,它最終也會是 O(n.log(n))。xa_for_each_range() 在遇到重試條目時會自旋;如果您打算看到重試條目,則應改用 xas_for_each() 迭代器。xas_for_each() 迭代器將比 xa_for_each_range() 展開為更多的內聯程式碼。
上下文
任何上下文。獲取並釋放 RCU 鎖。
-
xa_for_each_start¶
xa_for_each_start (xa, index, entry, start)
遍歷 XArray 的一部分。
引數
xaXArray。
index條目的索引。
entry從陣列中檢索到的條目。
start從陣列中檢索的第一個索引。
描述
在迭代期間,entry 將是儲存在 xa 中 index 處的條目的值。您可以在迭代期間修改 index,如果想跳過或重新處理索引。在迭代期間修改陣列是安全的。迭代結束時,entry 將被設定為 NULL,並且 index 的值將小於或等於 max。
xa_for_each_start() 的時間複雜度為 O(n.log(n)),而 xas_for_each() 的時間複雜度為 O(n)。你必須自行處理 xas_for_each() 的鎖定,如果你需要在每次迭代後解鎖,那麼其時間複雜度也將變為 O(n.log(n))。xa_for_each_start() 在遇到重試條目時會自旋;如果你想檢視重試條目,則應改用 xas_for_each() 迭代器。與 xa_for_each_start() 相比,xas_for_each() 迭代器會展開成更多的內聯程式碼。
上下文
任何上下文。獲取並釋放 RCU 鎖。
-
xa_for_each¶
xa_for_each (xa, index, entry)
迭代 XArray 中存在的條目。
引數
xaXArray。
index條目的索引。
entry從陣列中檢索到的條目。
描述
在迭代期間,entry 將是儲存在 xa 中 index 處的條目的值。您可以在迭代期間修改 index,如果想跳過或重新處理索引。在迭代期間修改陣列是安全的。迭代結束時,entry 將被設定為 NULL,並且 index 的值將小於或等於 max。
xa_for_each() 的時間複雜度為 O(n.log(n)),而 xas_for_each() 的時間複雜度為 O(n)。你必須自行處理 xas_for_each() 的鎖定,如果你需要在每次迭代後解鎖,那麼其時間複雜度也將變為 O(n.log(n))。xa_for_each() 在遇到重試條目時會自旋;如果你想檢視重試條目,則應改用 xas_for_each() 迭代器。與 xa_for_each() 相比,xas_for_each() 迭代器會展開成更多的內聯程式碼。
上下文
任何上下文。獲取並釋放 RCU 鎖。
-
xa_for_each_marked¶
xa_for_each_marked (xa, index, entry, filter)
迭代 XArray 中已標記的條目。
引數
xaXArray。
index條目的索引。
entry從陣列中檢索到的條目。
filter選擇標準。
描述
在迭代期間,entry 將是儲存在 xa 的 index 處的條目的值。迭代將跳過陣列中所有與 filter 不匹配的條目。如果你想跳過或重新處理索引,可以在迭代期間修改 index。在迭代期間修改陣列是安全的。迭代結束時,entry 將被設定為 NULL,並且 index 的值將小於或等於 max。
xa_for_each_marked() 的時間複雜度為 O(n.log(n)),而 xas_for_each_marked() 的時間複雜度為 O(n)。你必須自行處理 xas_for_each() 的鎖定,如果你需要在每次迭代後解鎖,那麼其時間複雜度也將變為 O(n.log(n))。xa_for_each_marked() 在遇到重試條目時會自旋;如果你想檢視重試條目,則應改用 xas_for_each_marked() 迭代器。與 xa_for_each_marked() 相比,xas_for_each_marked() 迭代器會展開成更多的內聯程式碼。
上下文
任何上下文。獲取並釋放 RCU 鎖。
-
void *xa_store_bh(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)¶
將此條目儲存到 XArray 中。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
void *entry新條目。
gfp_t gfp記憶體分配標誌。
描述
此函式類似於呼叫 xa_store(),但它在持有陣列鎖的同時停用軟中斷(softirqs)。
上下文
任何上下文。在停用軟中斷(softirqs)的同時獲取並釋放 xa_lock。
返回
此索引處的舊條目,如果發生錯誤則為 xa_err()。
-
void *xa_store_irq(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)¶
將此條目儲存到 XArray 中。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
void *entry新條目。
gfp_t gfp記憶體分配標誌。
描述
此函式類似於呼叫 xa_store(),但它在持有陣列鎖的同時停用中斷。
上下文
程序上下文。在停用中斷的同時獲取並釋放 xa_lock。
返回
此索引處的舊條目,如果發生錯誤則為 xa_err()。
引數
struct xarray *xaXArray。
unsigned long index條目的索引。
描述
此函式返回後,從 index 載入將返回 NULL。如果此索引是多索引條目的一部分,則所有索引都將被擦除,並且沒有任何條目會是多索引條目的一部分。
上下文
任何上下文。在停用軟中斷(softirqs)的同時獲取並釋放 xa_lock。
返回
曾經在此索引處的條目。
引數
struct xarray *xaXArray。
unsigned long index條目的索引。
描述
此函式返回後,從 index 載入將返回 NULL。如果此索引是多索引條目的一部分,則所有索引都將被擦除,並且沒有任何條目會是多索引條目的一部分。
上下文
程序上下文。在停用中斷的同時獲取並釋放 xa_lock。
返回
曾經在此索引處的條目。
-
void *xa_cmpxchg(struct xarray *xa, unsigned long index, void *old, void *entry, gfp_t gfp)¶
有條件地替換 XArray 中的條目。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
void *old用於比較的舊值。
void *entry要放入陣列的新值。
gfp_t gfp記憶體分配標誌。
描述
如果 index 處的條目與 old 相同,則將其替換為 entry。如果返回值等於 old,則交換成功。
上下文
任何上下文。獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
此索引處的舊值,如果發生錯誤則為 xa_err()。
-
void *xa_cmpxchg_bh(struct xarray *xa, unsigned long index, void *old, void *entry, gfp_t gfp)¶
有條件地替換 XArray 中的條目。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
void *old用於比較的舊值。
void *entry要放入陣列的新值。
gfp_t gfp記憶體分配標誌。
描述
此函式類似於呼叫 xa_cmpxchg(),但它在持有陣列鎖的同時停用軟中斷(softirqs)。
上下文
任何上下文。在停用軟中斷(softirqs)的同時獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
此索引處的舊值,如果發生錯誤則為 xa_err()。
-
void *xa_cmpxchg_irq(struct xarray *xa, unsigned long index, void *old, void *entry, gfp_t gfp)¶
有條件地替換 XArray 中的條目。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
void *old用於比較的舊值。
void *entry要放入陣列的新值。
gfp_t gfp記憶體分配標誌。
描述
此函式類似於呼叫 xa_cmpxchg(),但它在持有陣列鎖的同時停用中斷。
上下文
程序上下文。在停用中斷的同時獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
此索引處的舊值,如果發生錯誤則為 xa_err()。
-
int xa_insert(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)¶
將此條目儲存到 XArray 中,除非已有其他條目存在。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
void *entry新條目。
gfp_t gfp記憶體分配標誌。
描述
如果不存在任何條目,插入 NULL 條目將儲存一個保留條目(例如 xa_reserve())。如果存在保留條目,插入將失敗,即使從該索引載入會返回 NULL。
上下文
任何上下文。獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
儲存成功則返回 0。如果存在其他條目則返回 -EBUSY。如果無法分配記憶體則返回 -ENOMEM。
-
int xa_insert_bh(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)¶
將此條目儲存到 XArray 中,除非已有其他條目存在。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
void *entry新條目。
gfp_t gfp記憶體分配標誌。
描述
如果不存在任何條目,插入 NULL 條目將儲存一個保留條目(例如 xa_reserve())。如果存在保留條目,插入將失敗,即使從該索引載入會返回 NULL。
上下文
任何上下文。在停用軟中斷(softirqs)的同時獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
儲存成功則返回 0。如果存在其他條目則返回 -EBUSY。如果無法分配記憶體則返回 -ENOMEM。
-
int xa_insert_irq(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)¶
將此條目儲存到 XArray 中,除非已有其他條目存在。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
void *entry新條目。
gfp_t gfp記憶體分配標誌。
描述
如果不存在任何條目,插入 NULL 條目將儲存一個保留條目(例如 xa_reserve())。如果存在保留條目,插入將失敗,即使從該索引載入會返回 NULL。
上下文
程序上下文。在停用中斷的同時獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
儲存成功則返回 0。如果存在其他條目則返回 -EBUSY。如果無法分配記憶體則返回 -ENOMEM。
-
int xa_alloc(struct xarray *xa, u32 *id, void *entry, struct xa_limit limit, gfp_t gfp)¶
在 XArray 中找到儲存此條目的位置。
引數
struct xarray *xaXArray。
u32 *idID 的指標。
void *entry新條目。
struct xa_limit limit要分配的 ID 範圍。
gfp_t gfp記憶體分配標誌。
描述
在 limit.min 和 limit.max 之間找到 xa 中的空條目,將索引儲存到 id 指標中,然後將條目儲存在該索引處。併發查詢不會看到未初始化的 id。
僅可在使用 xa_init_flags() 設定了 XA_FLAGS_ALLOC 標誌的 xarray 上操作。
上下文
任何上下文。獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
成功則返回 0,如果無法分配記憶體則返回 -ENOMEM,或者如果 limit 中沒有空閒條目則返回 -EBUSY。
-
int xa_alloc_bh(struct xarray *xa, u32 *id, void *entry, struct xa_limit limit, gfp_t gfp)¶
在 XArray 中找到儲存此條目的位置。
引數
struct xarray *xaXArray。
u32 *idID 的指標。
void *entry新條目。
struct xa_limit limit要分配的 ID 範圍。
gfp_t gfp記憶體分配標誌。
描述
在 limit.min 和 limit.max 之間找到 xa 中的空條目,將索引儲存到 id 指標中,然後將條目儲存在該索引處。併發查詢不會看到未初始化的 id。
僅可在使用 xa_init_flags() 設定了 XA_FLAGS_ALLOC 標誌的 xarray 上操作。
上下文
任何上下文。在停用軟中斷(softirqs)的同時獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
成功則返回 0,如果無法分配記憶體則返回 -ENOMEM,或者如果 limit 中沒有空閒條目則返回 -EBUSY。
-
int xa_alloc_irq(struct xarray *xa, u32 *id, void *entry, struct xa_limit limit, gfp_t gfp)¶
在 XArray 中找到儲存此條目的位置。
引數
struct xarray *xaXArray。
u32 *idID 的指標。
void *entry新條目。
struct xa_limit limit要分配的 ID 範圍。
gfp_t gfp記憶體分配標誌。
描述
在 limit.min 和 limit.max 之間找到 xa 中的空條目,將索引儲存到 id 指標中,然後將條目儲存在該索引處。併發查詢不會看到未初始化的 id。
僅可在使用 xa_init_flags() 設定了 XA_FLAGS_ALLOC 標誌的 xarray 上操作。
上下文
程序上下文。在停用中斷的同時獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
成功則返回 0,如果無法分配記憶體則返回 -ENOMEM,或者如果 limit 中沒有空閒條目則返回 -EBUSY。
-
int xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry, struct xa_limit limit, u32 *next, gfp_t gfp)¶
在 XArray 中找到儲存此條目的位置。
引數
struct xarray *xaXArray。
u32 *idID 的指標。
void *entry新條目。
struct xa_limit limit已分配 ID 的範圍。
u32 *next指向下一個要分配的 ID 的指標。
gfp_t gfp記憶體分配標誌。
描述
在 limit.min 和 limit.max 之間找到 xa 中的空條目,將索引儲存到 id 指標中,然後將條目儲存在該索引處。併發查詢不會看到未初始化的 id。空條目的搜尋將從 next 開始,如果需要,將迴圈查詢。
僅可在使用 xa_init_flags() 設定了 XA_FLAGS_ALLOC 標誌的 xarray 上操作。
請注意,關心是否發生迴圈的呼叫者應改用 __xa_alloc_cyclic()。
上下文
任何上下文。獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
分配成功則返回 0,如果無法分配記憶體則返回 -ENOMEM,或者如果 limit 中沒有空閒條目則返回 -EBUSY。
-
int xa_alloc_cyclic_bh(struct xarray *xa, u32 *id, void *entry, struct xa_limit limit, u32 *next, gfp_t gfp)¶
在 XArray 中找到儲存此條目的位置。
引數
struct xarray *xaXArray。
u32 *idID 的指標。
void *entry新條目。
struct xa_limit limit已分配 ID 的範圍。
u32 *next指向下一個要分配的 ID 的指標。
gfp_t gfp記憶體分配標誌。
描述
在 limit.min 和 limit.max 之間找到 xa 中的空條目,將索引儲存到 id 指標中,然後將條目儲存在該索引處。併發查詢不會看到未初始化的 id。空條目的搜尋將從 next 開始,如果需要,將迴圈查詢。
僅可在使用 xa_init_flags() 設定了 XA_FLAGS_ALLOC 標誌的 xarray 上操作。
請注意,關心是否發生迴圈的呼叫者應改用 __xa_alloc_cyclic()。
上下文
任何上下文。在停用軟中斷(softirqs)的同時獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
分配成功則返回 0,如果無法分配記憶體則返回 -ENOMEM,或者如果 limit 中沒有空閒條目則返回 -EBUSY。
-
int xa_alloc_cyclic_irq(struct xarray *xa, u32 *id, void *entry, struct xa_limit limit, u32 *next, gfp_t gfp)¶
在 XArray 中找到儲存此條目的位置。
引數
struct xarray *xaXArray。
u32 *idID 的指標。
void *entry新條目。
struct xa_limit limit已分配 ID 的範圍。
u32 *next指向下一個要分配的 ID 的指標。
gfp_t gfp記憶體分配標誌。
描述
在 limit.min 和 limit.max 之間找到 xa 中的空條目,將索引儲存到 id 指標中,然後將條目儲存在該索引處。併發查詢不會看到未初始化的 id。空條目的搜尋將從 next 開始,如果需要,將迴圈查詢。
僅可在使用 xa_init_flags() 設定了 XA_FLAGS_ALLOC 標誌的 xarray 上操作。
請注意,關心是否發生迴圈的呼叫者應改用 __xa_alloc_cyclic()。
上下文
程序上下文。在停用中斷的同時獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
分配成功則返回 0,如果無法分配記憶體則返回 -ENOMEM,或者如果 limit 中沒有空閒條目則返回 -EBUSY。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
gfp_t gfp記憶體分配標誌。
描述
確保陣列中 index 處有位置可以儲存條目。如果 index 處已儲存有內容,此函式不執行任何操作。如果該處沒有內容,則此條目被標記為保留。從保留條目載入會返回一個 NULL 指標。
如果你沒有使用已保留的條目,請呼叫 xa_release() 或 xa_erase() 來釋放所有不必要的記憶體。
上下文
任何上下文。獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
如果預留成功則返回 0,失敗則返回 -ENOMEM。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
gfp_t gfp記憶體分配標誌。
描述
停用軟中斷(softirq)版本的 xa_reserve()。
上下文
任何上下文。在停用軟中斷(softirqs)的同時獲取並釋放 xa_lock。
返回
如果預留成功則返回 0,失敗則返回 -ENOMEM。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
gfp_t gfp記憶體分配標誌。
描述
停用中斷版本的 xa_reserve()。
上下文
程序上下文。在停用中斷的同時獲取並釋放 xa_lock。
返回
如果預留成功則返回 0,失敗則返回 -ENOMEM。
引數
struct xarray *xaXArray。
unsigned long index條目的索引。
描述
呼叫 xa_reserve() 後,你可以呼叫此函式來釋放預留。如果 index 處的條目已儲存資料,則此函式不執行任何操作。
-
bool xa_is_sibling(const void *entry)¶
該條目是兄弟條目嗎?
引數
const void *entry從 XArray 檢索到的條目
返回
如果該條目是兄弟條目,則為 true。
-
bool xa_is_retry(const void *entry)¶
該條目是重試條目嗎?
引數
const void *entry從 XArray 檢索到的條目
返回
如果該條目是重試條目,則為 true。
-
bool xa_is_advanced(const void *entry)¶
該條目是否僅限於高階 API 使用?
引數
const void *entry要儲存到 XArray 中的條目。
返回
如果該條目無法透過普通 API 儲存,則為 true。
-
xa_update_node_t¶
型別定義(Typedef):XArray 的回撥函式。
語法
void xa_update_node_t (struct xa_node *node)
引數
struct xa_node *node正在處理的節點
描述
每當 XArray 更新節點中存在和值條目的計數時,都會呼叫此函式。它允許高階使用者維護節點中的 private_list。
上下文
xa_lock 被持有,並且中斷可能被停用。實現不應釋放 xa_lock,也不應重新啟用中斷。
-
XA_STATE¶
XA_STATE (name, array, index)
宣告一個 XArray 操作狀態。
引數
name此操作狀態的名稱(通常為 xas)。
array要操作的陣列。
index感興趣的初始索引。
描述
在棧上宣告並初始化一個 xa_state。
-
XA_STATE_ORDER¶
XA_STATE_ORDER (name, array, index, order)
宣告一個 XArray 操作狀態。
引數
name此操作狀態的名稱(通常為 xas)。
array要操作的陣列。
index感興趣的初始索引。
order條目的階(order)。
描述
在棧上宣告並初始化一個 xa_state。此 XA_STATE() 變體允許你指定要操作的元素的“階(order)”。
-
int xas_error(const struct xa_state *xas)¶
返回儲存在 xa_state 中的 errno。
引數
const struct xa_state *xasXArray 操作狀態。
返回
如果沒有記錄錯誤則返回 0。如果記錄了錯誤則返回一個負的 errno。
-
void *xas_set_err(struct xa_state *xas, long err)¶
在 xa_state 中記錄一個錯誤。
引數
struct xa_state *xasXArray 操作狀態。
long err負錯誤碼。
描述
僅使用負 err 呼叫此函式;零或正錯誤可能不會按你預期的方式執行。如果你想清除 xa_state 中的錯誤,請使用 xas_reset()。
-
bool xas_invalid(const struct xa_state *xas)¶
xas 是否處於重試或錯誤狀態?
引數
const struct xa_state *xasXArray 操作狀態。
返回
如果 xas 無法用於操作,則為 true。
-
bool xas_valid(const struct xa_state *xas)¶
xas 是否是陣列中的有效遊標?
引數
const struct xa_state *xasXArray 操作狀態。
返回
如果 xas 可用於操作,則為 true。
-
bool xas_is_node(const struct xa_state *xas)¶
xas 是否指向一個節點?
引數
const struct xa_state *xasXArray 操作狀態。
返回
如果 xas 當前引用一個節點,則為 true。
-
void *xas_reset(struct xa_state *xas)¶
重置 XArray 操作狀態。
引數
struct xa_state *xasXArray 操作狀態。
描述
重置 xas 的錯誤或遍歷狀態,以便將來對陣列的遍歷將從根節點開始。如果你已釋放 xarray 鎖並想重用 xa_state,請使用此功能。
上下文
任何上下文。
-
bool xas_retry(struct xa_state *xas, const void *entry)¶
如果合適,重試操作。
引數
struct xa_state *xasXArray 操作狀態。
const void *entry來自 xarray 的條目。
描述
高階函式有時可能會返回一個內部條目,例如重試條目或零條目。此函式將 xas 設定為在需要時從陣列頭部重新開始遍歷。
上下文
任何上下文。
返回
如果操作需要重試,則為 true。
-
void *xas_reload(struct xa_state *xas)¶
從 xarray 重新獲取一個條目。
引數
struct xa_state *xasXArray 操作狀態。
描述
使用此函式檢查先前載入的條目是否仍具有相同的值。這對於無鎖頁快取查詢非常有用,在該查詢中,我們僅使用 RCU 鎖來保護我們遍歷陣列,鎖定頁面,然後檢查頁面自我們查詢以來是否未移動。
呼叫者保證 xas 仍然有效。如果它可能處於錯誤或重新啟動狀態,請改用 xas_load()。
返回
xarray 中此位置的條目。
-
void *xas_set(struct xa_state *xas, unsigned long index)¶
為不同索引設定 XArray 操作狀態。
引數
struct xa_state *xasXArray 操作狀態。
unsigned long indexXArray 中的新索引。
描述
將操作狀態移動到引用不同的索引。這將導致從頂部開始遍歷;請參閱 xas_next() 以移動到相鄰索引。
-
void *xas_advance(struct xa_state *xas, unsigned long index)¶
跳過兄弟條目。
引數
struct xa_state *xasXArray 操作狀態。
unsigned long index最後一個兄弟條目的索引。
描述
將操作狀態移動到引用最後一個兄弟條目。這對於通常希望看到兄弟條目但有時希望跳過它們的迴圈很有用。如果你想移動到一個不屬於此條目的索引,請使用 xas_set()。
-
void *xas_set_order(struct xa_state *xas, unsigned long index, unsigned int order)¶
為多槽條目設定 XArray 操作狀態。
引數
struct xa_state *xasXArray 操作狀態。
unsigned long index操作的目標。
unsigned int order條目佔用 2^**order** 個索引。
-
void *xas_set_update(struct xa_state *xas, xa_update_node_t update)¶
為回撥設定 XArray 操作狀態。
引數
struct xa_state *xasXArray 操作狀態。
xa_update_node_t update更新節點時要呼叫的函式。
描述
XArray 可以在更新 xa_node 後通知呼叫者。這是高階功能,僅頁快取和交換快取需要。
-
void *xas_next_entry(struct xa_state *xas, unsigned long max)¶
將迭代器前進到下一個存在的條目。
引數
struct xa_state *xasXArray 操作狀態。
unsigned long max要返回的最高索引。
描述
xas_next_entry() 是一個行內函數,用於最佳化 xarray 遍歷以提高速度。它等同於呼叫 xas_find(),並將為所有複雜情況呼叫 xas_find()。
返回
xas 當前引用的條目之後的下一個存在的條目。
-
void *xas_next_marked(struct xa_state *xas, unsigned long max, xa_mark_t mark)¶
將迭代器前進到下一個已標記的條目。
引數
struct xa_state *xasXArray 操作狀態。
unsigned long max要返回的最高索引。
xa_mark_t mark要搜尋的標記。
描述
xas_next_marked() 是一個行內函數,用於最佳化 xarray 遍歷以提高速度。它等同於呼叫 xas_find_marked(),並將為所有複雜情況呼叫 xas_find_marked()。
返回
xas 當前引用的條目之後的下一個已標記的條目。
-
xas_for_each¶
xas_for_each (xas, entry, max)
迭代 XArray 的一個範圍。
引數
xasXArray 操作狀態。
entry從陣列中檢索到的條目。
max從陣列中檢索的最高索引。
描述
迴圈體將為 xarray 中當前 xas 位置和 max 之間的每個存在的條目執行。entry 將被設定為從 xarray 中檢索到的條目。在迴圈體中從陣列中刪除條目是安全的。在迭代時,你應持有 RCU 鎖或 xa_lock。如果你需要釋放鎖,請首先呼叫 xas_pause()。
-
xas_for_each_marked¶
xas_for_each_marked (xas, entry, max, mark)
迭代 XArray 的一個範圍。
引數
xasXArray 操作狀態。
entry從陣列中檢索到的條目。
max從陣列中檢索的最高索引。
mark要搜尋的標記。
描述
迴圈體將為 xarray 中當前 xas 位置和 max 之間的每個已標記條目執行。entry 將被設定為從 xarray 中檢索到的條目。在迴圈體中從陣列中刪除條目是安全的。在迭代時,你應持有 RCU 鎖或 xa_lock。如果你需要釋放鎖,請首先呼叫 xas_pause()。
-
xas_for_each_conflict¶
xas_for_each_conflict (xas, entry)
迭代 XArray 的一個範圍。
引數
xasXArray 操作狀態。
entry從陣列中檢索到的條目。
描述
迴圈體將為 xas 指定範圍內的 XArray 中的每個條目執行。如果迴圈正常終止,entry 將為 NULL。使用者可以跳出迴圈,這將使 entry 設定為衝突條目。呼叫者也可以呼叫 xa_set_err() 以在設定錯誤記錄原因的同時退出迴圈。
-
void *xas_prev(struct xa_state *xas)¶
將迭代器移動到前一個索引。
引數
struct xa_state *xasXArray 操作狀態。
描述
如果 xas 處於錯誤狀態,它將保持錯誤狀態,並且此函式將返回 NULL。如果 xas 從未被遍歷,它將產生呼叫 xas_load() 的效果。否則,索引將減一,並且狀態將被遍歷到陣列中進行下一次操作的正確位置。
如果迭代器引用索引 0,此函式將迴圈到 ULONG_MAX。
返回
新索引處的條目。這可能是 NULL 或一個內部條目。
-
void *xas_next(struct xa_state *xas)¶
將狀態移動到下一個索引。
引數
struct xa_state *xasXArray 操作狀態。
描述
如果 xas 處於錯誤狀態,它將保持錯誤狀態,並且此函式將返回 NULL。如果 xas 從未被遍歷,它將產生呼叫 xas_load() 的效果。否則,索引將加一,並且狀態將被遍歷到陣列中進行下一次操作的正確位置。
如果迭代器引用索引 ULONG_MAX,此函式將迴圈到 0。
返回
新索引處的條目。這可能是 NULL 或一個內部條目。
-
void *xas_load(struct xa_state *xas)¶
從 XArray 載入一個條目(高階)。
引數
struct xa_state *xasXArray 操作狀態。
描述
通常將 xas 遍歷到適當狀態以載入儲存在 xa_index 的條目。但是,如果 xas 處於錯誤狀態,它將不執行任何操作並返回 NULL。xas_load() 永遠不會展開樹。
如果 xa_state 設定為操作多索引條目,xas_load() 可能會返回 NULL 或內部條目,即使 xas 指定的範圍內存在條目。
上下文
任何上下文。呼叫者應持有 xa_lock 或 RCU 鎖。
返回
通常是 XArray 中的一個條目,但有關例外情況請參閱描述。
-
bool xas_nomem(struct xa_state *xas, gfp_t gfp)¶
如果需要,分配記憶體。
引數
struct xa_state *xasXArray 操作狀態。
gfp_t gfp記憶體分配標誌。
描述
如果我們需要向 XArray 新增新節點,我們會在持有鎖的同時嘗試使用 GFP_NOWAIT 分配記憶體,這通常會成功。如果失敗,則 xas 會被標記為需要記憶體才能繼續。呼叫者應釋放鎖並呼叫 xas_nomem()。如果 xas_nomem() 成功,呼叫者應重試操作。
前進進度得到保證,因為一個節點在此處分配並存儲在 xa_state 中,xas_alloc() 將在那裡找到它。更多節點可能會在 slab 分配器中找到,但我們不會在這裡佔用它們。
返回
如果需要記憶體且已成功分配,則為 true。
-
void *xas_free_nodes(struct xa_state *xas, struct xa_node *top)¶
釋放此節點及其引用的所有節點
引數
struct xa_state *xas陣列操作狀態。
struct xa_node *top要釋放的節點
描述
此節點已從樹中刪除。我們現在必須釋放它及其所有子節點。可能存在帶有對樹引用資料的 RCU 遍歷器,因此我們必須用重試標記替換所有條目。
-
void *xas_create_range(struct xa_state *xas)¶
確保對此範圍的儲存操作將成功
引數
struct xa_state *xasXArray 操作狀態。
描述
建立 xas 覆蓋範圍內所有槽位。設定 xas 建立單索引條目並將其定位在範圍的開頭。這有利於尚未轉換為使用多索引條目的使用者。
-
void *xas_store(struct xa_state *xas, void *entry)¶
將此條目儲存到 XArray 中。
引數
struct xa_state *xasXArray 操作狀態。
void *entry新條目。
描述
如果 xas 正在操作多索引條目,此函式返回的條目本質上是無意義的(它可能是內部條目,也可能是 NULL,即使該範圍覆蓋的某些索引處存在非 NULL 條目)。這對任何現有使用者都不是問題,並且如果需要可以更改。
返回
此索引處的舊條目。
-
bool xas_get_mark(const struct xa_state *xas, xa_mark_t mark)¶
返回此標記的狀態。
引數
const struct xa_state *xasXArray 操作狀態。
xa_mark_t mark標記號。
返回
如果標記已設定則返回 true,如果標記已清除或 xas 處於錯誤狀態則返回 false。
-
void *xas_set_mark(const struct xa_state *xas, xa_mark_t mark)¶
在此條目及其父節點上設定標記。
引數
const struct xa_state *xasXArray 操作狀態。
xa_mark_t mark標記號。
描述
在此條目上設定指定的標記,並沿樹向上,在其所有祖先條目上設定標記。如果 xas 尚未遍歷到某個條目,或者處於錯誤狀態,則不執行任何操作。
-
void xas_clear_mark(const struct xa_state *xas, xa_mark_t mark)¶
清除此條目及其父級上的標記。
引數
const struct xa_state *xasXArray 操作狀態。
xa_mark_t mark標記號。
描述
清除此條目上指定的標記,並回溯到頭部,嘗試清除所有祖先條目上的標記。如果 xas 尚未遍歷到某個條目,或者處於錯誤狀態,則不執行任何操作。
-
void xas_init_marks(const struct xa_state *xas)¶
初始化此條目的所有標記
引數
const struct xa_state *xas陣列操作狀態。
描述
初始化由 xas 指定的條目的所有標記。如果正在使用標記跟蹤空閒條目,則需要在所有條目上設定此標記。所有其他標記都將被清除。
此實現效率不高;我們可能會多次遍歷樹。
-
void xas_split_alloc(struct xa_state *xas, void *entry, unsigned int order, gfp_t gfp)¶
為拆分條目分配記憶體。
引數
struct xa_state *xasXArray 操作狀態。
void *entry將儲存在陣列中的新條目。
unsigned int order當前條目階。
gfp_t gfp記憶體分配標誌。
描述
此函式應在呼叫 xas_split() 之前呼叫。如有必要,它將分配新節點(並用 entry 填充它們),以準備將 order 大小的條目拆分為儲存在 xas 中的階的條目。
上下文
如果 gfp 標誌允許,可能會睡眠。
-
void xas_split(struct xa_state *xas, void *entry, unsigned int order)¶
將多索引條目拆分為更小的條目。
引數
struct xa_state *xasXArray 操作狀態。
void *entry要儲存在陣列中的新條目。
unsigned int order當前條目階。
描述
新條目的大小在 xas 中設定。**entry** 中的值將被複制到所有替換條目。
上下文
任何上下文。呼叫者應持有 xa_lock。
-
unsigned int xas_try_split_min_order(unsigned int order)¶
xas_try_split()可接受的最小拆分階
引數
unsigned int order當前條目階。
描述
如果不需要新的 xa_node,xas_try_split() 可以將多索引條目拆分到小於 order - 1 的大小。此函式提供了 xas_try_split() 支援的最小階。
返回
xas_try_split() 支援的最小階
上下文
任何上下文。
-
void *xas_try_split(struct xa_state *xas, void *entry, unsigned int order)¶
嘗試拆分多索引條目。
引數
struct xa_state *xasXArray 操作狀態。
void *entry要儲存在陣列中的新條目。
unsigned int order當前條目階。
描述
新條目的大小在 xas 中設定。**entry** 中的值將複製到所有替換條目。當且僅當需要一個新的 xa_node 時,如果 xas->xa_alloc 為 NULL,函式將使用 GFP_NOWAIT 獲取一個。如果需要更多新的 xa_node,函式將返回 EINVAL 錯誤。
注意
如果想最小化 xas_try_split() 呼叫,請使用 xas_try_split_min_order() 獲取下一個拆分階,而不是 order - 1。
上下文
任何上下文。呼叫者應持有 xa_lock。
-
void xas_pause(struct xa_state *xas)¶
暫停遍歷以釋放鎖。
引數
struct xa_state *xasXArray 操作狀態。
描述
某些使用者需要暫停遍歷並釋放其持有的鎖,以便讓步給更高優先順序的執行緒或對條目執行操作。這些使用者在釋放鎖之前應呼叫此函式。它會重置 xas,使其在使用者重新獲得鎖後適合下一次迴圈迭代。如果在遍歷過程中發現的大多數條目都需要呼叫 xas_pause(),則 xa_for_each() 迭代器可能更適合。
請注意,xas_pause() 僅適用於正向迭代。如果使用者需要暫停反向迭代,我們將需要一個 xas_pause_rev()。
-
void *xas_find(struct xa_state *xas, unsigned long max)¶
在 XArray 中查詢下一個存在的條目。
引數
struct xa_state *xasXArray 操作狀態。
unsigned long max要返回的最高索引。
描述
如果 xas 尚未遍歷到某個條目,則返回索引 >= xas.xa_index 的條目。如果已遍歷,則當前指向的條目已處理,因此我們移動到下一個條目。
如果未找到條目且陣列小於 max,則迭代器將設定為陣列中尚未存在的最小索引。這使得 xas 可以立即傳遞給 xas_store()。
返回
如果找到條目則返回該條目,否則返回 NULL。
-
void *xas_find_marked(struct xa_state *xas, unsigned long max, xa_mark_t mark)¶
在 XArray 中查詢下一個被標記的條目。
引數
struct xa_state *xasXArray 操作狀態。
unsigned long max要返回的最高索引。
xa_mark_t mark要搜尋的標記號。
描述
如果 xas 尚未遍歷到某個條目,則返回索引 >= xas.xa_index 的標記條目。如果已遍歷,則當前指向的條目已處理,因此我們返回索引 > xas.xa_index 的第一個標記條目。
如果未找到標記條目且陣列小於 max,則 xas 被設定為邊界狀態,並且 xas->xa_index 被設定為陣列中尚未存在的最小索引。這使得 xas 可以立即傳遞給 xas_store()。
如果在達到 max 之前未找到條目,則 xas 被設定為重啟狀態。
返回
如果找到條目則返回該條目,否則返回 NULL。
-
void *xas_find_conflict(struct xa_state *xas)¶
在指定範圍內查詢下一個存在的條目。
引數
struct xa_state *xasXArray 操作狀態。
描述
xas 描述了一個範圍以及該範圍內的位置。
上下文
任何上下文。要求持有 xa_lock。
返回
xas 覆蓋範圍內的下一個條目,或 NULL。
引數
struct xarray *xaXArray。
unsigned long index陣列中的索引。
上下文
任何上下文。獲取並釋放 RCU 鎖。
返回
xa 中 index 處的條目。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
描述
此函式返回後,從 index 載入將返回 NULL。如果此索引是多索引條目的一部分,則所有索引都將被擦除,並且沒有任何條目會是多索引條目的一部分。
上下文
任何上下文。進入時要求持有 xa_lock。
返回
曾經在此索引處的條目。
引數
struct xarray *xaXArray。
unsigned long index條目的索引。
描述
此函式返回後,從 index 載入將返回 NULL。如果此索引是多索引條目的一部分,則所有索引都將被擦除,並且沒有任何條目會是多索引條目的一部分。
上下文
任何上下文。獲取並釋放 xa_lock。
返回
曾經在此索引處的條目。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
void *entry新條目。
gfp_t gfp記憶體分配標誌。
描述
呼叫此函式時,您必須已持有 xa_lock。如果需要分配記憶體,它會釋放鎖,然後重新獲取。
上下文
任何上下文。進入時要求持有 xa_lock。如果 gfp 標誌允許,可能會釋放並重新獲取 xa_lock。
返回
此索引處的舊條目,如果發生錯誤則為 xa_err()。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
void *entry新條目。
gfp_t gfp記憶體分配標誌。
描述
此函式返回後,從該索引載入將返回 entry。儲存到現有的多索引條目會更新每個索引的條目。與 index 關聯的標記不受影響,除非 entry 為 NULL。
上下文
任何上下文。獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會休眠。
返回
成功時返回此索引處的舊條目;如果 entry 無法儲存在 XArray 中,則返回 xa_err(-EINVAL);如果記憶體分配失敗,則返回 xa_err(-ENOMEM)。
-
void *__xa_cmpxchg(struct xarray *xa, unsigned long index, void *old, void *entry, gfp_t gfp)¶
有條件地替換 XArray 中的條目。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
void *old用於比較的舊值。
void *entry要放入陣列的新值。
gfp_t gfp記憶體分配標誌。
描述
呼叫此函式時,您必須已持有 xa_lock。如果需要分配記憶體,它會釋放鎖,然後重新獲取。
如果 index 處的條目與 old 相同,則將其替換為 entry。如果返回值等於 old,則交換成功。
上下文
任何上下文。進入時要求持有 xa_lock。如果 gfp 標誌允許,可能會釋放並重新獲取 xa_lock。
返回
此索引處的舊值,如果發生錯誤則為 xa_err()。
-
int __xa_insert(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)¶
如果 XArray 中不存在條目,則儲存此條目。
引數
struct xarray *xaXArray。
unsigned long index陣列索引。
void *entry新條目。
gfp_t gfp記憶體分配標誌。
描述
如果不存在任何條目,插入 NULL 條目將儲存一個保留條目(例如 xa_reserve())。如果存在保留條目,插入將失敗,即使從該索引載入會返回 NULL。
上下文
任何上下文。進入時要求持有 xa_lock。如果 gfp 標誌允許,可能會釋放並重新獲取 xa_lock。
返回
儲存成功則返回 0。如果存在其他條目則返回 -EBUSY。如果無法分配記憶體則返回 -ENOMEM。
-
void *xa_store_range(struct xarray *xa, unsigned long first, unsigned long last, void *entry, gfp_t gfp)¶
將此條目儲存在 XArray 的一系列索引中。
引數
struct xarray *xaXArray。
unsigned long first要影響的起始索引。
unsigned long last要影響的結束索引。
void *entry新條目。
gfp_t gfp記憶體分配標誌。
描述
此函式返回後,從 first 和 last(包括兩者)之間的任何索引載入都將返回 entry。儲存到現有的多索引條目會更新每個索引的條目。與 index 關聯的標記不受影響,除非 entry 為 NULL。
上下文
程序上下文。獲取並釋放 xa_lock。如果 gfp 標誌允許,可能會睡眠。
返回
成功時返回 NULL;如果 entry 無法儲存在 XArray 中,則返回 xa_err(-EINVAL);如果記憶體分配失敗,則返回 xa_err(-ENOMEM)。
-
int xas_get_order(struct xa_state *xas)¶
獲取條目的階。
引數
struct xa_state *xasXArray 操作狀態。
描述
在 xas_load 之後呼叫,xas 不應處於錯誤狀態。
返回
一個介於 0 到 63 之間的數字,表示條目的階。
引數
struct xarray *xaXArray。
unsigned long index條目的索引。
返回
一個介於 0 到 63 之間的數字,表示條目的階。
-
int __xa_alloc(struct xarray *xa, u32 *id, void *entry, struct xa_limit limit, gfp_t gfp)¶
在 XArray 中找到儲存此條目的位置。
引數
struct xarray *xaXArray。
u32 *idID 的指標。
void *entry新條目。
struct xa_limit limit分配 ID 的範圍。
gfp_t gfp記憶體分配標誌。
描述
在 limit.min 和 limit.max 之間找到 xa 中的空條目,將索引儲存到 id 指標中,然後將條目儲存在該索引處。併發查詢不會看到未初始化的 id。
僅可在使用 xa_init_flags() 設定了 XA_FLAGS_ALLOC 標誌的 xarray 上操作。
上下文
任何上下文。進入時要求持有 xa_lock。如果 gfp 標誌允許,可能會釋放並重新獲取 xa_lock。
返回
成功則返回 0,如果無法分配記憶體則返回 -ENOMEM,或者如果 limit 中沒有空閒條目則返回 -EBUSY。
-
int __xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry, struct xa_limit limit, u32 *next, gfp_t gfp)¶
在 XArray 中找到儲存此條目的位置。
引數
struct xarray *xaXArray。
u32 *idID 的指標。
void *entry新條目。
struct xa_limit limit已分配 ID 的範圍。
u32 *next指向下一個要分配的 ID 的指標。
gfp_t gfp記憶體分配標誌。
描述
在 limit.min 和 limit.max 之間找到 xa 中的空條目,將索引儲存到 id 指標中,然後將條目儲存在該索引處。併發查詢不會看到未初始化的 id。空條目的搜尋將從 next 開始,如果需要,將迴圈查詢。
僅可在使用 xa_init_flags() 設定了 XA_FLAGS_ALLOC 標誌的 xarray 上操作。
上下文
任何上下文。進入時要求持有 xa_lock。如果 gfp 標誌允許,可能會釋放並重新獲取 xa_lock。
返回
如果分配成功且未迴圈,則返回 0。如果分配成功但在迴圈後,則返回 1;如果無法分配記憶體,則返回 -ENOMEM;如果 limit 中沒有空閒條目,則返回 -EBUSY。
引數
struct xarray *xaXArray。
unsigned long index條目的索引。
xa_mark_t mark標記號。
描述
嘗試在 NULL 條目上設定標記不會成功。
上下文
任何上下文。進入時要求持有 xa_lock。
引數
struct xarray *xaXArray。
unsigned long index條目的索引。
xa_mark_t mark標記號。
上下文
任何上下文。進入時要求持有 xa_lock。
引數
struct xarray *xaXArray。
unsigned long index條目的索引。
xa_mark_t mark標記號。
描述
此函式使用 RCU 讀鎖,因此返回時結果可能已過時。如果需要結果穩定,請使用鎖。
上下文
任何上下文。獲取並釋放 RCU 鎖。
返回
如果 index 處的條目設定了此標記,則返回 True;否則返回 False。
引數
struct xarray *xaXArray。
unsigned long index條目的索引。
xa_mark_t mark標記號。
描述
嘗試在 NULL 條目上設定標記不會成功。
上下文
程序上下文。獲取並釋放 xa_lock。
引數
struct xarray *xaXArray。
unsigned long index條目的索引。
xa_mark_t mark標記號。
描述
清除標記總是成功的。
上下文
程序上下文。獲取並釋放 xa_lock。
-
void *xa_find(struct xarray *xa, unsigned long *indexp, unsigned long max, xa_mark_t filter)¶
在 XArray 中搜索一個條目。
引數
struct xarray *xaXArray。
unsigned long *indexp指向一個索引的指標。
unsigned long max要搜尋的最大索引。
xa_mark_t filter選擇標準。
描述
查詢 xa 中與 filter 匹配且索引不小於 indexp 且不大於 max 的最小索引處的條目。如果找到條目,indexp 將更新為該條目的索引。此函式受 RCU 讀鎖保護,因此可能無法找到同時新增的條目。它不會返回 XA_RETRY_ENTRY;如果需要檢視重試條目,請使用 xas_find()。
上下文
任何上下文。獲取並釋放 RCU 鎖。
返回
如果找到條目則返回該條目,否則返回 NULL。
-
void *xa_find_after(struct xarray *xa, unsigned long *indexp, unsigned long max, xa_mark_t filter)¶
在 XArray 中搜索一個存在的條目。
引數
struct xarray *xaXArray。
unsigned long *indexp指向一個索引的指標。
unsigned long max要搜尋的最大索引。
xa_mark_t filter選擇標準。
描述
查詢 xa 中與 filter 匹配且索引大於 indexp 且不大於 max 的最小索引處的條目。如果找到條目,indexp 將更新為該條目的索引。此函式受 RCU 讀鎖保護,因此可能會遺漏同時新增的條目。它不會返回 XA_RETRY_ENTRY;如果需要檢視重試條目,請使用 xas_find()。
上下文
任何上下文。獲取並釋放 RCU 鎖。
返回
如果找到,則返回指標;否則返回 NULL。
-
unsigned int xa_extract(struct xarray *xa, void **dst, unsigned long start, unsigned long max, unsigned int n, xa_mark_t filter)¶
將選定的條目從 XArray 複製到普通陣列。
引數
struct xarray *xa要從中複製的源 XArray。
void **dst要將條目複製到的緩衝區。
unsigned long startXArray 中符合選擇條件的首個索引。
unsigned long maxXArray 中符合選擇條件的最後一個索引。
unsigned int n要複製的最大條目數。
xa_mark_t filter選擇標準。
描述
從 XArray 複製最多 n 個與 filter 匹配的條目。複製的條目的索引將在 start 和 max 之間(包括兩者)。
filter 可以是一個 XArray 標記值,在這種情況下,帶有該標記的條目將被複制。它也可以是 XA_PRESENT,在這種情況下,所有非 NULL 的條目都將被複制。
返回的條目可能不代表 XArray 在某個時間點的快照。例如,如果另一個執行緒先儲存到索引 5,然後儲存到索引 10,則呼叫 xa_extract() 可能會返回索引 5 的舊內容和索引 10 的新內容。此函式執行期間未修改的索引不會被跳過。
如果需要更強的保證,在呼叫此函式時持有 xa_lock 將防止併發修改。
上下文
任何上下文。獲取並釋放 RCU 鎖。
返回
複製的條目數。
-
void xa_delete_node(struct xa_node *node, xa_update_node_t update)¶
工作集程式碼的私有介面。
引數
struct xa_node *node要從樹中移除的節點。
xa_update_node_t update用於更新祖先節點的函式。
上下文
進入時必須持有 xa_lock 且不會釋放。
引數
struct xarray *xaXArray。
描述
呼叫此函式後,XArray 為空並已釋放為其內部資料結構分配的所有記憶體。您負責釋放 XArray 引用的物件。
上下文
任何上下文。獲取並釋放 xa_lock,中斷安全。