---
# System prepended metadata

title: 2019-06-04 劉溢茗

---

# 2019-06-04 劉溢茗 

## Q1: 給定兩個整數 x 及 y，用 bitwise operator 做出兩者平均值
`int mean(int x, int y) {  ... }`
Hint: 可用 `&`, `^`, `|`, `+`. `>>`, `<<` 等運算子
=>
```clike=
int mean(int x,int y){
 // int od1 = 1 & x; 
 // int od2 = 1 & y;
 // int z = ( >>1) + (od2 >>1)
// x^=1; 
// y^=1; 

return (((x ^ y)>>1) + (x & y));
// if (od1 && od2){
//         mean++;
//     }
}
```

---

## Q2: 以 Linux 核心的 [include/list.h](https://github.com/torvalds/linux/blob/master/include/linux/list.h) 實作出兩個節點互換 (不得複製節點內全部的資料)
Hint: 考慮到 HEAD 可能跟其他節點互換
=>
swapping node x and node y
```clike=
static inline void _swap(struct list_head *head,
                         struct list_head *x, 
                         struct list_head *y){
    if (list_empty(head) || x==y) return;
    struct list_head tmp;
    // if(list_is_first(x,head)){
    //     head = y;
    // }else if(list_is_first(y,head)){
    //     head = x;
    // }
    list_replace(y,&tmp);
    list_replace(x,y);
    list_replace(&tmp,x);
}
```

---
![](https://i.imgur.com/QZAoEqd.jpg)

假設上圖 head(x) 和 y 進行交換後

![](https://i.imgur.com/pdc39aw.jpg)

結果如上，會造成 first entry 位置改變

### 版本 2:

```clike
#include "list.h"
#include <stdio.h>
#include <stdlib.h>

struct listitem {
  struct list_head list;
  int i;
};

static inline void _swap(struct list_head *list, struct list_head *x,struct list_head *y) {
    if (list_empty(list) || x==y) return;
    list_replace(y,&tmp);
    list_replace(x,y);
    list_replace(&tmp,x);
}

int main() {
    struct list_head *list;
    struct listitem *entry, *next, *item;
    INIT_LIST_HEAD(list);
    
    for (int i = 0; i < 4; i++) {
    item = (struct listitem *)malloc(sizeof(struct listitem));
    item->i = i;
    list_add_tail(&item->list, list);
    }
    
    struct list_head *x
    _swap(list, list, &(list->prev->prev)->list);
    
    list_for_each_entry_safe(entry, next, list, list) {
    list_del(&entry->list);
    free(entry);
    }
}
```


##### 上述程式碼預期行為

![](https://i.imgur.com/F27nhi5.jpg)

* _swap 後

![](https://i.imgur.com/lem1My9.jpg)

因為只動指標的關係，不會影響節點內部的資料
但是 swap 後 first entry 由 0 變 3

:::danger
先改善標注方式，原本的 head~1~ 在操作後應改為 head~2~, 由於 linked list 主要用途就是在「非連續的記憶體單元之間連接」，所以這裡的 swap 本該只做前後關聯的調整。

回頭思考 [How does the kernel implements Linked Lists?](https://kernelnewbies.org/FAQ/LinkedLists)，我們應該善用 Linux 核心提供的 macro / inlined functions 來實作。

請愛用 GraphViz。
:notes: jserv
:::

---

## Q3: 在 Linux 核心中，要取得 (acquire) semaphore，該用哪個 API?
* `(a)` `up()`
* `(b)` `up_trylock()`
* `(c)` `up_interruptible()`
* `(d)` `down()`
* `(e)` `down_tryonce()`
* `(f)` `down_trylock()`
* `(g)` `down_interrupt()` 

----
