owned this note
owned this note
Published
Linked with GitHub
# 2016q3 Homework2 (phonebook-concurrent)
contributed by <`hugikun999`>
## Pthread
* ```#include <pthread.h>```
* 建立出額外的執行緒
* function
(1)
```C
int pthread_create(pthread_t,const pthread_attr_t,void,void)
```
參數1是pthread的指標,參數2是thread的屬性,參數3是function pointer,參數4是function pointer所須要的參數。
(2)
```C
int pthread_cancel (pthread_t)
```
送一個取消的要求給指定的thread,而收到要求的thread要如何處理則取決於它的type和state。state有enable和disable兩種。type有asynchronous和deferred。
參數1是要取消的目標<s>pthread</s>。
>> 不是指標!請熟讀 man page: [pthread_cancel](http://man7.org/linux/man-pages/man3/pthread_cancel.3.html),儘量讀權威資料,否則你會一錯再錯下去! [name=jserv]
>> 已改正 [name=俊逸]
(3)
```C
int pthread_exit(void *retval)
```
<s>關閉</s> 中止一個thread,retval可以拿來存放成功時回傳的值
參數1是設定執行成功時的回傳值。
>> 不是「關閉」,而是「終止」(terminate),以中文意思來說,這兩者根本不同,請注意!這個參數很重要,也不會混淆了。再次詳閱 man page: [pthread_exit](http://man7.org/linux/man-pages/man3/pthread_exit.3.html) [name=jserv]
>> 已改正 [name=俊逸]
(4)
```C
int pthread_join(pthread_t,void)
```
暫停執行join的thread,等目標thread執行完畢join的thread才繼續執行。
參數1是等待的目標thread,參數2是取得目標thread的回傳。
(5)
```C
int pthread_setconcurrency(int new_level)
```
設定concurrency的level
## phonebook-concrrence
### file
(1)file_align.c
```C
static off_t fsize(char *path);
```
要使用off_t必須要```#include <sys/type.h>```,拿來存目標檔案的路徑和名子。
```C
struct stat(char,struct stat)
```
要用stat必須要```#include<sys/stat.h>```,取得有關char所存的檔案名的資訊,並寫到參數2所指的buf。
```C
void *memset(void *s, int c, size_t n)
```
將s中前n個bytes用c填滿。
* 不懂的部份
```C
while (fgets(rbuf, sizeof(rbuf), fd0))
{
memset(wbuf, '\0', pad);
if ((suffix = (pad - strlen(rbuf))) != 0)
strncpy(wbuf, rbuf,strlen(rbuf));
fwrite(wbuf, pad, 1, fd1);
}
```
這個部份應該是拿來將沒有滿的rbuf複製到已事先填滿```\0```的wbuf裡面,但是如果rbuf已經被填滿就會略過if裡面的事,那這樣的話應該是要執行```fwrite(rbuf, pad, 1, fd1)```。
將程式中while的部份改成如下,發現append()的時間變高了1倍多,測試過將```\0```改成填入其它char,但是時間依然很長沒有變短,目前還想不到的可能原因。
```C
while (fgets(rbuf, sizeof(rbuf), fd0))
{
memset(wbuf, '\0', pad);
if ((suffix = (pad - strlen(rbuf))) != 0)
{
strcpy(wbuf, rbuf);
fwrite(wbuf, pad, 1, fd1);
}
fwrite(rbuf, pad, 1, fd1);
}
```
![](https://i.imgur.com/wwLqGbN.png)
>> 程式碼是寫給你修改的,不是給你背誦用,遇到疑惑就修改程式來觀察! [name=jserv]
>> 已經測試過,等等會補。[name=俊逸]
(2)file.c
和```file_align.c```主要差別在```file.c```是一個function,```file_align.c```是一個program。
(3)main.c
```C
__builtin___clear_cache(char *begin,char *end)
```
<s>清除memory中的instruction</s>
清除指定範圍內的instruction cache
>> 請認真看 gcc 手冊: [Other Built-in Functions Provided by GCC](https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html),操作對象是 cache! [name=jserv]
>> 已更正 [name=俊逸]
```C
open(const char *pathname, int flags)
```
pathname給定目標檔案的路徑,會回傳一個很小、非負的整數。O_NONBLOCK可以使檔案為不被鎖的狀態。
```C
mmap(void *addr, size_t lengh, int prot, int flags, int fd, off_t offset)
```
配置一段虛擬記憶體的位址給呼叫的process。addr是開始mapping的起始位置,length是mapping的長度,從fd指向的檔案中的offset位置開使算length,prot是指這個mapping的特性,分為PROT_EXEC、PROT_READ、PORT_WRITE、PORT_NONE,flags可以放MAP_SHARED、MAP_PRIVATE。傳回一個pointer指向新建立的空間。
## check correctness
利用```phonebook_opt.c```中所寫的show_entry()將thread所做出來的link list和原始的dictionary做比較,檢查正確性。發現缺少了兩個名字,而且從輸出的名字看來中間有很多重覆建的名字。
```
lack of:aaaa
lack of:aaaaa
```
## concurrent-ll
### file
(1) atomic_ops_if.h
```C
__sync_val_compare_and_swap(type *ptr, type oldval, type newval)
__sync_bool_compare_and_swap(type *ptr, type oldval, type newval)
```
如果現在的value和oldval是一樣的,則將newval寫到ptr。一個回傳內容,一個回傳true or false。
```C
__sync_fetch_and_add(type *ptr, type value)
__sync_fetch_and_sub(type *ptr, type value)
__sync_add_and_fetch(type *ptr, type value)
__sync_sub_and_fetch(type *ptr, type value)
```
其即是運算
```C
tmp = *ptr;
*ptr += value;
return tmp;
```
一個是回傳更新前的值,一個是回傳更新後的值。
```C
CAS_U64_bool((volatile AO_t *)(a), (AO_t)(e), (AO_t)(v))
```
volatile會告訴compiler這個值可能會在任何時間被更新,即使在code上下文中沒有任何對其修改的動作。
>> AO_t不知道是什麼? [name=俊逸]
>> Check this: http://www.hpl.hp.com/research/linux/atomic_ops/README.txt (全部讀過!) [name=jserv]
>> 了解~ [name=俊逸]
memory barrier:用來確保多thread時不會被out-of-order影響,在屏障前的運算都會在對屏障後發揮效用。
```C
AO_t
```
type of unsigned integers。AO_TS_t會以最好的效能做為分割的依據,有時候是byte,有時候是等同於AO_t,其位置必須以AO_TS_INITALIZER初始化。
(2)getticks.h
```C
__asm__ __volatile__(code : output : input : clobber)
```
rdtsc:read timestamp counter,讀取一個64bits的計數器,它會+1每個clock cycle。
輸出暫存器語法,"="寫入專用,"+"讀寫兩用。