# linux2021: reggiehsu111 contributed by < [`reggiehsu111`](https://github.com/reggiehsu111) > ###### tags: `linux2021` ## Problem $\alpha - 1$ ## Problem $\alpha - 2$ ## Problem $\beta - 1$ Source code for `alignment.c`: ```cpp 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); } ``` ### Explanation - The function returns the smallest aligned address (divisible by alignment) that is larger or equal to sz. - First notice that the function takes in a `uintptr_t` type sz and a `size_t` type alignment. The two types can be different as suggested in [this post](https://stackoverflow.com/questions/1464174/size-t-vs-uintptr-t). `size_t` is bounded by `SIZE_MAX`, which is 2^64-1 in my computer. Therefore, the size of `uintptr_t` and `size_t` are both 8 bytes in my computer. - If the alignment is a power of two: - The bit representations are: - alignment: `0...010..0` - mask: `0...001..1` - If sz is a multiple of `alignment`, `sz + mask` doesn't carry to the `log2(alignment) + 1` bit, so when performing `& ~mask`, the right most `log2(alignment)` bits will become 0s. Otherwise, `(sz + mask) & ~mask` will increment the `log2(alignment) + 1` bit, giving the desired output. - If the `alignment` is not a power of two: - `(sz + mask) / alignment` will discard the fraction part of the result, so when multiplied back with `* alignment`, only when sz is a multiple of `alignment` will the result be the same as sz (because the fraction of `sz + mask / alignment` is 0). ## Problem $\beta - 2$ - Not sure right now how to correctly search the linux source code, but found this: https://github.com/torvalds/linux/blob/f40ddce8/arch/arm/mm/alignment.c#L1 and will check this later ## Problem $\gamma - 1$ ```cpp= int main(void) { for (int i = 0; i < 12; i++) { fork(); printf("-"); } fflush(stdout); return 0; } ``` ### Explanation - As suggested in [this post](https://unix.stackexchange.com/questions/447898/why-does-a-program-with-fork-sometimes-print-its-output-multiple-times/447904), when a child process is forked, the unflushed buffer is inherited by the child process. Because `stdout` is line-buffered ([meaning](https://www.ibm.com/docs/en/zos/2.3.0?topic=output-buffering-c-streams)) by default, the buffer isn't flushed until a newline character is reached, or manually flushed by `fflush`. ```graphviz digraph { rankdir=TB; node [shape=record]; example [label="{ <p_num> process appearing # | <iter> nth iteration|<-s> # of '-'s in buffer}"] subgraph { p_1B [label="{ <p_num> P1 | <iter> Before loop | <-s> 0}"]; p_10 [label="{ <p_num> P1 | <iter> iter 0 | <-s> 1}"]; p_20 [label="{ <p_num> P2 | <iter> iter 0 | <-s> 1}"]; p_11 [label="{ <p_num> P1 | <iter> iter 1 | <-s> 2}"]; p_21 [label="{ <p_num> P2 | <iter> iter 1 | <-s> 2}"]; p_31 [label="{ <p_num> P3 | <iter> iter 1 | <-s> 2}"]; p_41 [label="{ <p_num> P4 | <iter> iter 1 | <-s> 2}"]; p_1B->p_10; p_1B->p_20; p_10->p_11; p_10->p_31; p_20->p_21; p_20->p_41; } } ``` - From the graph above, we see that for each iteration, the number of `-` in the buffer will increment by 1 in each process, so the total number of `-` in all processes' buffers on ith iteration will be: $i*2^i$. For i = 12, we get a total number of 49152 `-` to be flushed at the end.