# linux2021: WayneLin1992
###### tags: `linux2021`
- [ ] 說明程式碼的運作原理
- [ ] 在 Linux kernel 找出類似 `align_up` 的程式碼,並舉例說明其用法
## 測驗 $\beta$
```cpp
#include <stdint.h>
static inline uintptr_t align_up(uintptr_t sz, size_t alignment)
{
uintptr_t mask = alignment - 1;
if ((alignment & mask) == 0) { /* power of two? */
return ((sz + mask) & (~mask));
}
return (((sz + mask) / alignment) * alignment);
}
```
`main`
```cpp
int main()
{
printf("%d \n", align_up(120, 4));
printf("%d \n", align_up(121, 4));
printf("%d \n", align_up(125, 4));
return 0;
}
```
得到下列結果
```shell
120
124
128
```
## 在 Linux kernel 找出類似 `align_up` 的程式碼,說明其用法
在 <include/linux/mm.h> 和 <include/linux/kernel.h> 有定義出
`PAGE_ALIGN` 及 `ALIGN`
`#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)`
:::info
其中 `PAGE_SIZE` 在 <arch/x86/include/asm/page_types.h> 中定義
```cpp
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
<include/uapi/linux/const.h>
#define _AC(X,Y) X
```
可以了解到 PAGE_SIZE 預設在 x86下為 4KB
:::
`#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))`
由此可知內部的實作為 `__ALIGN_KERNEL`
`#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)`
`#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))`
`typeof` 為 gcc 的 extension 將會回傳對應的 x 的 type 。
由此可以知道 `mask = (typeof(x))(a) - 1` 也可以對應到題目的 `mask = alignment - 1;`
### 觀察 kernel 中使用的 `ALIGN` 的部分
- [ ] `videobuf2`
在 <drivers/media/common/videobuf2/videobuf2-core.c> 中有 `__vb2_buf_mem_alloc`
`__vb2_buf_mem_alloc() - allocate video memory for the given buffer`
裡面使用了 `PAGE_ALIGN` 在於決定記憶體配置的大小 size
```cpp
/* Memops alloc requires size to be page aligned. */
unsigned long size = PAGE_ALIGN(vb->planes[plane].length);
```
## 測驗 $\zeta$