---
# System prepended metadata

title: 'linux2021: WayneLin1992'
tags: [linux2021]

---

# 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$

