contributed by < robertnthu
>
linux2022
Use INIT_LIST_HEAD()
to init struct list_head
Version1
Use list_for_each_safe()
to do q_free()
iteration.
Version2
strcpy()
not safe?
strcpy()
?
strdup()
:
strncpy()
: It can guarentee the length of string is under control.Just amend list_add()
to list_add_tail()
list_entry()
to get value and then strncpy()
trace-01-ops will not pass with check of sp
. After amending if (!sp && bufsize)
to if (bufsize)
, trace-01-ops passed.
Why?
Either the condition '!sp' is redundant or there is possible null pointer dereference: sp. [nullPointerRedundantCheck]
Update
By reference of jasperlin1996's note, i found this bug can be fixed by if (sp != NULL && bufsize)
, which fulfill the requirement better than skip checking sp
.
Similar to q_remove_head()
Same as professor's code
With doubly linked list, we don't need indirect pointer to iterate. Pointer with list_del()
is enough.
val()
, which returns the value of a given node.Version 2
list_del
跟 list_add
來交換兩個 list_head 的位置list_move()
to reorder the queue.tail
and iterate the list.I've tried to use
But it would be in a infinite loop when tail == head->prev
, i think solving this is more complicated than the above version.
Merge sort
list_del()
to remove the head
, since head
is not element_t
. Then use merge_sort()
to sort the list.merge_sort()
find_mid()
and cut_list()
.
find_mid()
use "fast and slow pointer" to get the mid of a linked listcut_list()
is to cut the linked list, returning the pointer that points the next half list.merge_sort()
recurrently.mergeTwoLists()
to merge two lists.
q_sort()
add head
node back and recover the prev
pointer.uintptr_t
merge()
for (;;)
, we needs conditional statement to judge when to get out of the loop.__attribute__
__attribute__((nonnull[(arg-index, ...)]))
[(arg-index,...)]
denotes an optional argument index list.merge_final()
unlikely()
:
__built_expect()
!!(x)
!!(x)
就無法確保值一定是0或1BUILD_BUG_ON_ZERO
在拿到__same_type()
的回傳值時,利用兩個Not
確保回傳值一定是1或0,再乘上-1並回傳。likely
macro 表示這段敘述(x)為 true 的機率比較大(比較常發生),告訴 compiler 將 x==ture 的對應執行程式碼接在判斷後面unlikely
macro 表示這段敘述 (x) 為 true 的機率比較小(不常發生),告訴 compiler 將 x==false 的對應執行程式碼接在判斷後面list_sort()
原文:
The simple eager merge pattern causes bad performance when n is just
over a power of 2. If n=1028, the final merge is between 1024- and
4-element lists, which is wasteful of comparisons. (This is actually
worse on average than n=1025, because a 1204:1 merge will, on average,
end after 512 compares, while 1024:4 will walk 4/5 of the list.)
if (likely(bits))
這個條件判斷的關係,在這個 while 並不會 merge 任何 list。if (likely(bits))
檢查出後面還有東西,就會 merge 最近的兩個 pending list,也就是1-1-2-4變成2-2-4,然後才加入第九個元素,pending list 變成 1-2-2-4bits >>= 1
是把 bits 做 right shift,用來檢查 count 這個數在二進位表示是否有出現連續的 1,如果碰到0就會跳出迴圈,例如 count = 10111,用來表示此時的 pending list 長度分別是 1, 2, 4, 16,那到第四個 iteration,就會跳出來
tail = &(*tail)->prev
是把 tail
指標移到下一個 pending list,因為所有的 list 在這裡都被改成了單向串列,只有 next
才是指向下一個元素,而prev
就被用來指到下一個順位的 listmerge_final
來 merge,並且恢復雙向鏈結加入實做
參考eric88525的開發紀錄
EXPORT_SYMBOL(list_sort);
list_sort()
能夠被所有 linux kernel 的模塊使用,所以此處可以去掉list_sort.c
定義u8
:typedef uint8_t u8;
error: unknown type name ‘u8’
,但都沒能解決,最後直接在 list_sort.c
裡面宣告了測試
比較
(未完成,我想使用 perf ,但 kernel 5.16.11好像並沒有 perf 的 package)
參考:你所不知道的 C 語言: linked list 和非連續記憶體
head
是沒有資料的),所以針對這點做了修改list.h
之後,除了可以不使用 pointer of pointer 外,也能縮短程式加入專案
參考:qtest 命令直譯器的實作
main → run_console → cmd_select → interpret_cmd → parse_args
console.h
裡面的定義
CELE
這個結構都要打struct CELE
,但加上typedef struct CELE cmd_ele, *cmd_ptr
之後,只要用cmd_ele
就能呼叫了qtest.c
有 console_init()
,console.c
有init_cmd()
console.h
裡面多定義了
所以我們只需要在qtest.c
寫一個do_shuffle()
,並在裡面呼叫q_shuffle()
,並在console_init()
加入
do_shuffle()
參考 qtest-命令直譯器的實作
- 首次呼叫
do_XXX
函式時,exception_setup
的功能是建立sigjmp_buf
,並回傳true
。- 回到稍早提及的
if (exception_setup(true))
敘述中,若是第一次回傳,那麼會開始測試函式。若測試函式的過程中,發生任何錯誤 (亦即觸發SIGSEGV
或SIGALRM
一類的 signal),就會立刻跳回 signal handler。signal handler 會印出錯誤訊息,並進行siglongjmp
。- 由
exception_setup
的程式可以知道又是跳到exception_setup(true)
裡面,但這時會回傳false
,因而跳過測試函式,直接結束測試並回傳ok
內含值。- 換言之,
exception_cancel()
後就算再發生SIGALRM
或SIGSEGV
,也不會再有機會回到exception_setup()
裡面。
report()
的參數有什麼功能?error_check()
跟exception_cancel()
有什麼功能?`return ok && !error_check();
又是做什麼的?最後測試程式,確認 shuffle()
功能正常。