# 2019q1 Homework1 (list)
contributed by < `joey-ycpeng` >
## 自我檢查事項
### 1. 為何 Linux 採用 macro 來實作 linked list?一般的 function call 有何成本?
Anwser:
1. macro 等於把程式碼~~嵌入~~展開(ref: [Macro-Expansion](https://gcc.gnu.org/onlinedocs/cppinternals/Macro-Expansion.html#Macro-expansion-overview))執行,不需要 call function 所需的 overhead
:::warning
「展開」(expand) 和「嵌入」(embed) 這兩個詞彙意義不同,回頭看 C preprocessor 用了哪個詞。工程人員用語務必精準,及早脫離「文組^TM^」
:notes: jserv
:::
2. function call 有以下步驟:
1. 將 arguments 反序 push 到 stack
2. call function (push return address & jump to callee)
3. function 保留 stack 給 local variables
4. function 執行
5. function 執行完畢返回 return address
:::danger
查閱 Linux x86_64 application binary interface (ABI) 的規格,確保「將 arguments 反序 push 到 stack」是否總是正確
:notes: jserv
:::
> [name=Yu-Cheng Peng][time=Tue, Mar 5, 2019 12:26 AM]
> 根據 [System V ABI - AMD64 Architecture Processor Supplement](https://www.uclibc.org/docs/psABI-x86_64.pdf)
>> **3.2.3 Parameter Passing**
>> * "Arguments of types (signed and unsigned) *Bool, char, short, int, long, long long*, and pointers are in the **INTEGER** class."
>>
>> * "**INTEGER** This class consists of integral types that fit into one of the general purpose registers"
>> * "Passing Once arguments are classified, the registers get assigned (in left-to-rightorder) for passing as follows:
>> ... If the class is **INTEGER**, the next available register of the sequence ==*%rdi,%rsi, %rdx, %rcx, %r8* and %r9== is used."
>>
> 以此解釋下面 `call.c`:
> 1.
```clike=
$ cat call.c
int callee(int a, int b, int c)
{
return (a+b+c);
}
int main(void)
{
callee(1, 2, 3);
return 0;
}
$ gcc -S call.c
$ cat call.s
.file "call.c"
.text
.globl callee
.type callee, @function
callee:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl %edx, -12(%rbp)
movl -4(%rbp), %edx
movl -8(%rbp), %eax
addl %eax, %edx
movl -12(%rbp), %eax
addl %edx, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size callee, .-callee
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $3, %edx
movl $2, %esi
movl $1, %edi
call callee
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
```
---
### 2. Linux 應用 linked list 在哪些場合?舉三個案例並附上對應程式碼,需要解說,以及揣摩對應的考量
---
### 3. GNU extension 的 [typeof](https://gcc.gnu.org/onlinedocs/gcc/Typeof.html) 有何作用?在程式碼中扮演什麼角色?
Anwser:
1. 作用: 拿到定義的 type
* e.g. `int x=0; typeof(x) y=1;`,`y`也是`int`
2. 角色:
* 讓程式不會依靠特定資料的 type 也能運作,不會因為 type 變了而需要修改
* e.g. `container_of`
---
### 4. 解釋以下巨集的原理
```clike
#define container_of(ptr, type, member) \
__extension__({ \
const __typeof__(((type *) 0)->member) *__pmember = (ptr); \
(type *) ((char *) __pmember - offsetof(type, member)); \
})
```
Answer:
1. (type *) 0` :
* 一個指向位址 0 的 `type` 類型指標
2. `((type *) 0)->member)`:
* `type` 類型下的 `member`
3. `__typeof__(((type *) 0)->member)`:
* `member` 所屬的類型
4. `const __typeof__(((type *) 0)->member) *__pmember = (ptr)`:
* 宣告一個 `member` 所屬的類型常量的指標 `__pmember`
* Assign `ptr` to `__pmember`
5. `offsetof(type, member)`:
* `member` 在 `type` 類型裡的 byte offset
6. `(char *) __pmember - offsetof(type, member)`:
* 由 __pmember 所在位址往回推算到 type 類型的起點位址
7. `(type *) ((char *) __pmember - offsetof(type, member));`:
* 將起點位址轉型成指向 `type` 類型的指標
8. `__extension__({...;})`:
* `__extension__` 告訴 GCC 不要對 C 以外的擴充功能發出警告
* 小括弧()是利用 GCC 的 [Statement-Expression](https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html) 將轉型的指標變成整個 macro 最後的 value
* **結論: `container_off(ptr, type, member)` 回傳一個指向 `struct type` 物件的指標,這個物件的 `member` 指向 `ptr`**
---
### 5. 除了你熟悉的 add 和 delete 操作,`list.h` 還定義一系列操作,為什麼呢?這些有什麼益處?
* 可以對 list 做 element 的增減,尋找
* 使用者不需要管實做,專注在更高層次的程式碼
### 6. `LIST_POISONING` 這樣的設計有何意義?
### 7. linked list 採用環狀是基於哪些考量?
### 8. 什麼情境會需要對 linked list 做排序呢?舉出真實世界的應用,最好在作業系統核心出現
### 9. 什麼情境會需要需要找到 [第 k 大/小元素](https://www.geeksforgeeks.org/kth-smallestlargest-element-unsorted-array/) 呢?又,你打算如何實作?
### 10. `list_for_each_safe` 和 `list_for_each` 的差異在哪?"safe" 在執行時期的影響為何?
### 11. for_each 風格的開發方式對程式開發者的影響為何?
* 提示:對照其他程式語言,如 Perl 和 Python
### 12. 程式註解裡頭大量存在 `@` 符號,這有何意義?你能否應用在後續的程式開發呢?
* 提示: 對照看 Doxygen
### 13. `tests/` 目錄底下的 unit test 的作用為何?就軟體工程來說的精神為何?
### 14. `tests/` 目錄的 unit test 可如何持續精進和改善呢?
---
## 實做 merge sort
* 支援 `qtest`
###### tags: `homework`