# 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。 輸出暫存器語法,"="寫入專用,"+"讀寫兩用。