├── .gitignore
└── CodeInSlides
├── chapter3
├── Makefile
├── ProcessBasicAPI-fork.c
├── ProcessBasicAPI-races.c
├── ProcessBasicAPI-shell.c
├── ThreadBasicAPI-calcShareData.c
└── ThreadBasicAPI-create.c
├── chapter4
├── ATMProblemShow-mutex.c
├── ATMProblemShow.c
├── BoundedBuffer-monitor-mesatest.c
├── BoundedBuffer-monitor.c
├── BoundedBuffer-mutex.c
├── BoundedBuffer-semaphore.c
├── ConcurrentQuickSort-Iteration.cpp
├── ConcurrentQuickSort-Recursive-broken.c
├── ConcurrentQuickSort-Recursive.c
├── ConcurrentWget-OnDemand.c
├── ConcurrentWget-ThreadPool.c
├── Deadlock.c
├── DynamicAssignJob.c
├── HeteroThreads.c
├── HomoThreads.c
├── Makefile
├── MultiCat.sh
├── PreAssignJob.c
├── Problems-CPUOoO.c
├── Problems-CompilerOptimization-O1.s
├── Problems-CompilerOptimization-O2.s
├── Problems-CompilerOptimization.c
├── Statistics_for_x&y.py
└── testUrl.in
├── chapter5
├── Makefile
├── Measure-ALU-O1.s
├── Measure-ALU-O2.s
├── Measure-ALU-broken-O0.s
├── Measure-ALU-broken-O1.s
├── Measure-ALU-broken-O2.s
├── Measure-ALU-broken-simplified-O0.s
├── Measure-ALU-broken-simplified-O1.s
├── Measure-ALU-broken-simplified-O2.s
├── Measure-ALU-broken-simplified.c
├── Measure-ALU-broken.c
├── Measure-ALU.c
├── Measure-mutex-CTXswitch.c
├── Measure-mutex-syscall.c
└── PrintToMonitor.c
├── chapter7
├── CountResult.sh
├── HighConcurrent-client.c
├── HighConcurrent-epoll-server.c
├── HighConcurrent-normal-server.c
├── Makefile
├── TCP-client-reliable.c
├── TCP-client-thread-recv.c
├── TCP-client-thread-send.c
├── TCP-client.c
├── TCP-server-reliable.c
├── TCP-server-thread-recv.c
├── TCP-server-thread-send.c
├── TCP-server.c
├── UDP-client.c
├── UDP-server.c
├── echo-client.c
├── echo-server.c
└── kv.go
└── miscellaneous
├── MemLayout.c
├── contextswitch
├── .gitignore
├── COPYING
├── Makefile
├── README
├── cpubench.sh
├── timectxsw.c
├── timectxsw2.c
├── timectxswws.c
├── timesyscall.c
├── timetctxsw.c
└── timetctxsw2.c
└── multipipe-popen
├── multipipe-popen.c
└── testProgram.c
/.gitignore:
--------------------------------------------------------------------------------
1 | /CodeInSlides/chapter3/ProcessBasicAPI-fork
2 | /CodeInSlides/chapter3/ThreadBasicAPI-calcShareData
3 | /CodeInSlides/chapter4/ATMProblemShow
4 | /CodeInSlides/chapter4/ATMProblemShow-mutex
5 | /CodeInSlides/chapter4/BoundedBuffer-monitor
6 | /CodeInSlides/chapter4/BoundedBuffer-mutex
7 | /CodeInSlides/chapter4/BoundedBuffer-semaphore
8 | /CodeInSlides/chapter3/ProcessBasicAPI-races
9 | /CodeInSlides/chapter3/ProcessBasicAPI-shell
10 | /CodeInSlides/chapter3/ThreadBasicAPI-create
11 | /CodeInSlides/chapter4/BoundedBuffer-monitor-mesatest
12 | /CodeInSlides/chapter4/Deadlock
13 | /CodeInSlides/chapter4/testInput/*.txt
14 | /CodeInSlides/chapter4/PreAssignJob
15 | /CodeInSlides/chapter4/DynamicAssignJob
16 | /CodeInSlides/chapter4/HomoThreads
17 | /CodeInSlides/chapter4/*.log
18 | /CodeInSlides/chapter4/HeteroThreads
19 | *.html
20 | *.log
21 | /CodeInSlides/chapter4/ConcurrentWget-ThreadPool
22 | /CodeInSlides/chapter4/ConcurrentWget-OnDemand
23 | /CodeInSlides/chapter4/ConcurrentQuickSort-Recursive
24 | /CodeInSlides/chapter4/*.txt
25 | /CodeInSlides/chapter4/ConcurrentQuickSort-Iteration
26 | /CodeInSlides/chapter5/Measure-ALU
27 | /CodeInSlides/chapter5/Measure-ALU-broken
28 | /CodeInSlides/chapter5/Measure-mutex
29 | /CodeInSlides/chapter5/Measure-mutex-CTXswitch
30 | /CodeInSlides/chapter5/Measure-mutex-syscall
31 | /CodeInSlides/chapter5/Measure-ALU-broken-simplified
32 | /CodeInSlides/chapter4/*.data
33 | /CodeInSlides/chapter5/PrintToMonitor
34 | /CodeInSlides/miscellaneous/multipipe-popen/multipipe-popen
35 | /CodeInSlides/miscellaneous/multipipe-popen/testProgram
36 | /CodeInSlides/chapter4/*.old
37 | /CodeInSlides/chapter4/ConcurrentQuickSort-Recursive-broken
38 | /CodeInSlides/chapter7/UDP-client
39 | /CodeInSlides/chapter7/UDP-server
40 | /CodeInSlides/chapter7/TCP-client
41 | /CodeInSlides/chapter7/TCP-server
42 | /CodeInSlides/chapter7/TCP-client-reliable
43 | /CodeInSlides/chapter7/TCP-server-reliable
44 | /CodeInSlides/chapter7/TCP-client-thread-write
45 | /CodeInSlides/chapter7/TCP-server-thread-write
46 | /CodeInSlides/chapter7/TCP-client-thread-recv
47 | /CodeInSlides/chapter7/TCP-server-thread-recv
48 | /CodeInSlides/chapter7/TCP-client-thread-send
49 | /CodeInSlides/chapter7/TCP-server-thread-send
50 | *.DS_Store
51 |
--------------------------------------------------------------------------------
/CodeInSlides/chapter3/Makefile:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2010 Benoit Sigoure
2 | #
3 | # This program is free software: you can redistribute it and/or modify
4 | # it under the terms of the GNU General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version.
7 | #
8 | # This program is distributed in the hope that it will be useful,
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | # GNU General Public License for more details.
12 | #
13 | # You should have received a copy of the GNU General Public License
14 | # along with this program. If not, see .
15 |
16 | CC = gcc
17 | CFLAGS = -O2 -pthread
18 |
19 | # the build target executable:
20 | TARGETS = ProcessBasicAPI-fork ProcessBasicAPI-shell ProcessBasicAPI-races ThreadBasicAPI-create ThreadBasicAPI-calcShareData
21 |
22 | all: $(TARGETS)
23 |
24 | clean:
25 | $(RM) $(TARGETS)
26 |
27 |
--------------------------------------------------------------------------------
/CodeInSlides/chapter3/ProcessBasicAPI-fork.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | int main(int argc, char *argv[])
9 | {
10 | pid_t cpid, mypid;
11 | int status=0;
12 | pid_t pid = getpid(); /* get current processes PID */
13 | printf("Parent pid: %d\n", pid);
14 | cpid = fork();
15 | if (cpid > 0) { /* Parent Process */
16 | mypid = getpid();
17 | printf("[%d] parent of [%d]\n", mypid, cpid);
18 | printf("Parent exit\n");
19 | } else if (cpid == 0) { /* Child Process */
20 | mypid = getpid();
21 | printf("[%d] child\n", mypid);
22 | printf("Child exit\n");
23 | } else {
24 | perror("Fork failed");
25 | exit(1);
26 | }
27 | exit(0);
28 | }
29 |
30 | // usleep(1000);
31 | // wait(&status);
--------------------------------------------------------------------------------
/CodeInSlides/chapter3/ProcessBasicAPI-races.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | int main()
10 | {
11 | int i;
12 | pid_t mypid;
13 | pid_t cpid = fork();
14 | if (cpid > 0) {
15 | mypid = getpid();
16 | printf("[%d] parent of [%d]\n", mypid, cpid);
17 | for (i=0; i<10; i++) {
18 | printf("[%d] parent: %d\n", mypid, i);
19 | usleep(1000);
20 | }
21 | } else if (cpid == 0) {
22 | mypid = getpid();
23 | printf("[%d] child\n", mypid);
24 | for (i=0; i>-10; i--) {
25 | printf("[%d] child: %d\n", mypid, i);
26 | usleep(1000);
27 | }
28 | }
29 |
30 | return 0;
31 | }
--------------------------------------------------------------------------------
/CodeInSlides/chapter3/ProcessBasicAPI-shell.c:
--------------------------------------------------------------------------------
1 | // From https://codereview.stackexchange.com/questions/67746/simple-shell-in-c
2 |
3 | // ps --forest -o pid,tty,stat,time,cmd -g pid
4 | // Show child process of pid
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | void parseCmd(char* cmd, char** params);
15 | int executeCmd(char** params);
16 |
17 | #define MAX_COMMAND_LENGTH 100
18 | #define MAX_NUMBER_OF_PARAMS 10
19 |
20 | int main()
21 | {
22 | char cmd[MAX_COMMAND_LENGTH + 1];
23 | char* params[MAX_NUMBER_OF_PARAMS + 1];
24 |
25 | int cmdCount = 0;
26 |
27 | while(1) {
28 | // Print command prompt
29 | char* username = getenv("USER");
30 | printf("%s@shell %d> ", username, ++cmdCount);
31 |
32 | // Read command from standard input, exit on Ctrl+D
33 | if(fgets(cmd, sizeof(cmd), stdin) == NULL) break;
34 |
35 | // Remove trailing newline character, if any
36 | if(cmd[strlen(cmd)-1] == '\n') {
37 | cmd[strlen(cmd)-1] = '\0';
38 | }
39 |
40 | // Split cmd into array of parameters
41 | parseCmd(cmd, params);
42 |
43 | // Exit?
44 | if(strcmp(params[0], "exit") == 0) break;
45 |
46 | // Execute command
47 | if(executeCmd(params) == 0) break;
48 | }
49 |
50 | return 0;
51 | }
52 |
53 | // Split cmd into array of parameters
54 | void parseCmd(char* cmd, char** params)
55 | {
56 | for(int i = 0; i < MAX_NUMBER_OF_PARAMS; i++) {
57 | params[i] = strsep(&cmd, " ");
58 | if(params[i] == NULL) break;
59 | }
60 | }
61 |
62 | int executeCmd(char** params)
63 | {
64 | // Fork process
65 | pid_t pid = fork();
66 |
67 | // Error
68 | if (pid == -1) {
69 | char* error = strerror(errno);
70 | printf("fork: %s\n", error);
71 | return 1;
72 | }
73 |
74 | // Child process
75 | else if (pid == 0) {
76 | // Execute command
77 | execvp(params[0], params);
78 |
79 | // Error occurred
80 | char* error = strerror(errno);
81 | printf("shell: %s: %s\n", params[0], error);
82 | return 0;
83 | }
84 |
85 | // Parent process
86 | else {
87 | // Wait for child process to finish
88 | int childStatus;
89 | waitpid(pid, &childStatus, 0);
90 | return 1;
91 | }
92 | }
--------------------------------------------------------------------------------
/CodeInSlides/chapter3/ThreadBasicAPI-calcShareData.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define NUM_ARR_SIZE 5000
9 |
10 | int num[NUM_ARR_SIZE];
11 |
12 | void* calcSum1(void* args) {
13 | int sum=0;
14 | for(int i=0;i<2500;i++)
15 | sum=sum+num[i];
16 | pthread_t tid = pthread_self();
17 | printf("[%ld] worker thread: \t %d\n", pthread_self(), sum);
18 | }
19 |
20 | void* calcSum2(void* args) {
21 | int sum=0;
22 | for(int i=2500;ifirst;
69 | // int last=para->last;
70 | // int sum=0;
71 | // for(int i=first;iresult=sum;
80 | // }
81 |
82 |
83 | // int main(int argc, char *argv[])
84 | // {
85 | // int numOfWorkerThread=1;
86 | // if(argc>=2)
87 | // numOfWorkerThread=atoi(argv[1]);
88 | // if(numOfWorkerThread>NUM_ARR_SIZE)
89 | // numOfWorkerThread=NUM_ARR_SIZE;
90 |
91 | // for(int i=0;i
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | void* myfunc(void* args) {
9 | pthread_t tid = pthread_self();
10 | printf("[%ld] child. Exit\n", tid);
11 | }
12 |
13 | int main(int argc, char *argv[])
14 | {
15 |
16 | pthread_t th;
17 | if(pthread_create(&th, NULL, myfunc, NULL)!=0)
18 | {
19 | perror("pthread_create failed");
20 | exit(1);
21 | }
22 |
23 | pthread_t mytid = pthread_self();
24 |
25 | printf("Parent tid: %ld\n", mytid);
26 | printf("[%ld] parent of [%ld]. Exit\n", mytid, th);
27 |
28 | // pthread_join(th, NULL);
29 |
30 | exit(0);
31 | }
--------------------------------------------------------------------------------
/CodeInSlides/chapter4/ATMProblemShow-mutex.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define TEST_ITERATIONS 1000
9 |
10 | int accountBalance=0;
11 | int amount=10;
12 |
13 | pthread_mutex_t accountBalanceLock;
14 |
15 | void* threadDeposit(void* args) {
16 | for(int i=0;i
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define TEST_ITERATIONS 1000
9 |
10 | int accountBalance=0;
11 | int amount=10;
12 |
13 | void* threadDeposit(void* args) {
14 | for(int i=0;i
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define IF_PRINT_DEBUG 0
9 | #define BUF_CAPACITY 10
10 |
11 | int producerNum=1;
12 | int consumerNum=1;
13 | int TEST_COKE_NUM=100000;
14 |
15 | int bufSize=0;
16 |
17 | pthread_mutex_t mutex;
18 | pthread_cond_t cndFull;
19 | pthread_cond_t cndEmpty;
20 |
21 | void* Producer(void* args) {
22 | for(int i=0;iBUF_CAPACITY)
34 | fprintf(stderr,"[%ld] producer: OVERFLOW! enqueue a coke, bufSize %d\n",pthread_self(),bufSize);
35 | if(IF_PRINT_DEBUG)
36 | printf("[%ld] producer: enqueue a coke, bufSize %d\n",pthread_self(),bufSize);
37 | if(IF_PRINT_DEBUG)
38 | printf("[%ld] producer: wakeup waiting consumers\n",pthread_self());
39 | pthread_cond_broadcast(&cndEmpty);
40 | pthread_mutex_unlock(&mutex);
41 | }
42 | }
43 |
44 | void* Consumer(void* args) {
45 | for(int i=0;i=3)
70 | {
71 | producerNum=atoi(argv[1]);
72 | consumerNum=atoi(argv[2]);
73 | }
74 | if(argc>=4)
75 | {
76 | TEST_COKE_NUM=atoi(argv[3]);
77 | }
78 |
79 | pthread_cond_init(&cndFull,NULL);
80 | pthread_cond_init(&cndEmpty,NULL);
81 | pthread_mutex_init(&mutex,NULL);
82 |
83 | printf("Before run: \t\t coke_num \t\t %d\n", bufSize);
84 |
85 | pthread_t th1[producerNum];
86 | for(int i=0;i
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define IF_PRINT_DEBUG 0
9 | #define BUF_CAPACITY 10
10 |
11 | int producerNum=1;
12 | int consumerNum=1;
13 | int TEST_COKE_NUM=100000;
14 |
15 | int bufSize=0;
16 |
17 | pthread_mutex_t mutex;
18 | pthread_cond_t cndFull;
19 | pthread_cond_t cndEmpty;
20 |
21 | void* Producer(void* args) {
22 | for(int i=0;i=3)
66 | {
67 | producerNum=atoi(argv[1]);
68 | consumerNum=atoi(argv[2]);
69 | }
70 | if(argc>=4)
71 | {
72 | TEST_COKE_NUM=atoi(argv[3]);
73 | }
74 |
75 | pthread_cond_init(&cndFull,NULL);
76 | pthread_cond_init(&cndEmpty,NULL);
77 | pthread_mutex_init(&mutex,NULL);
78 |
79 | printf("Before run: \t\t coke_num \t\t %d\n", bufSize);
80 |
81 | pthread_t th1[producerNum];
82 | for(int i=0;i
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define IF_PRINT_DEBUG 0
9 | #define BUF_CAPACITY 10
10 |
11 | int producerNum=1;
12 | int consumerNum=1;
13 | int TEST_COKE_NUM=100000;
14 |
15 | int bufSize=0;
16 |
17 | pthread_mutex_t mutex;
18 |
19 | void* Producer(void* args) {
20 | for(int i=0;i=3)
62 | {
63 | producerNum=atoi(argv[1]);
64 | consumerNum=atoi(argv[2]);
65 | }
66 | if(argc>=4)
67 | {
68 | TEST_COKE_NUM=atoi(argv[3]);
69 | }
70 |
71 | pthread_mutex_init(&mutex,NULL);
72 |
73 | printf("Before run: \t\t coke_num \t\t %d\n", bufSize);
74 |
75 | pthread_t th1[producerNum];
76 | for(int i=0;i
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #define IF_PRINT_DEBUG 0
10 | #define BUF_CAPACITY 10
11 |
12 | int producerNum=1;
13 | int consumerNum=1;
14 | int TEST_COKE_NUM=100000;
15 |
16 | int bufSize=0;
17 |
18 | sem_t fullSlots;
19 | sem_t emptySlots;
20 | pthread_mutex_t mutex;
21 |
22 | void* Producer(void* args) {
23 | for(int i=0;i=3)
55 | {
56 | producerNum=atoi(argv[1]);
57 | consumerNum=atoi(argv[2]);
58 | }
59 | if(argc>=4)
60 | {
61 | TEST_COKE_NUM=atoi(argv[3]);
62 | }
63 |
64 | sem_init(&fullSlots, 0, 0);
65 | sem_init(&emptySlots, 0, BUF_CAPACITY);
66 | pthread_mutex_init(&mutex,NULL);
67 |
68 | printf("Before run: \t\t coke_num \t\t %d\n", bufSize);
69 |
70 | pthread_t th1[producerNum];
71 | for(int i=0;i
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #define IF_PRINT_DEBUG 0
15 | #define CONCURRENT_THREAD_NUM 4
16 | #define MIN_ARRAY_LEN_FOR_CREATE_A_THREAD_TO_SORT 100000
17 |
18 | typedef struct {
19 | int* array;
20 | int left;
21 | int right;
22 | } SortJob;
23 |
24 | std::stack sortJobStackGlobal;
25 | pthread_mutex_t sortJobStackMutex=PTHREAD_MUTEX_INITIALIZER;
26 | sem_t sortJobStackEmptySlots;
27 | int ifThreadBusy[CONCURRENT_THREAD_NUM];
28 | //ifThreadBusy[i] indicates if a thread is doing sorting job
29 | //If all ifThreadBusy[i]==0, then the whole sort has finished and we can exit
30 | int ifAllThreadExit;//Flag for main thread to notify worker exit
31 |
32 | double time_diff(struct timeval x , struct timeval y);
33 | void swap(int* array,int first,int second);
34 | int PartSort(int* array,int left,int right);
35 | void* QuickSortParallel(void* args);
36 | void QuickSortSequential(int* array, int left, int right);
37 | int createAThreadToQuickSort(int *array, int left, int right, pthread_t *th);
38 |
39 | void initParallelSort(int *array, int sortArrayLen)
40 | {
41 | SortJob job;
42 | job.array=array;
43 | job.left=0;
44 | job.right=sortArrayLen-1;
45 | sortJobStackGlobal.push(job);
46 | for(int i=0;i= array[key])
87 | --right;
88 | swap(array,left,right);
89 | }
90 | swap(array,left,key);
91 | return left;
92 | }
93 |
94 | void* QuickSortParallel(void* args)
95 | {
96 | int *threadID=(int *) args;
97 | if(IF_PRINT_DEBUG==2)
98 | printf("Thread[%d] start.\n",*threadID);
99 | SortJob job;
100 | while(1)
101 | {
102 | sem_wait(&sortJobStackEmptySlots);
103 | pthread_mutex_lock(&sortJobStackMutex);
104 | if(ifAllThreadExit==1) {
105 | if(IF_PRINT_DEBUG==2)
106 | printf("Thread[%d] exit.\n",*threadID);
107 | pthread_mutex_unlock(&sortJobStackMutex);
108 | break;
109 | }
110 | job = sortJobStackGlobal.top();
111 | sortJobStackGlobal.pop();
112 | int left=job.left;
113 | int right=job.right;
114 | ifThreadBusy[*threadID]=1;
115 | pthread_mutex_unlock(&sortJobStackMutex);
116 | if(right-left>=MIN_ARRAY_LEN_FOR_CREATE_A_THREAD_TO_SORT)
117 | {
118 | int index = PartSort(job.array,left,right);
119 | if(IF_PRINT_DEBUG==2)
120 | printf("Thread[%d]: PartSort[%d-%d] ifThreadBusy=%d\n"
121 | ,*threadID,job.left,job.right,ifThreadBusy[*threadID]);
122 | pthread_mutex_lock(&sortJobStackMutex);
123 | if((index - 1) > left)//左子序列
124 | {
125 | job.left=left;
126 | job.right=index - 1;
127 | sortJobStackGlobal.push(job);
128 | sem_post(&sortJobStackEmptySlots);
129 | if(IF_PRINT_DEBUG==2)
130 | printf("Thread[%d]: push[%d-%d] ifThreadBusy=%d\n"
131 | ,*threadID,job.left,job.right,ifThreadBusy[*threadID]);
132 | }
133 | if((index + 1) < right)//右子序列
134 | {
135 | job.left=index + 1;
136 | job.right=right;
137 | sortJobStackGlobal.push(job);
138 | sem_post(&sortJobStackEmptySlots);
139 | if(IF_PRINT_DEBUG==2)
140 | printf("Thread[%d]: push[%d-%d] ifThreadBusy=%d\n"
141 | ,*threadID,job.left,job.right,ifThreadBusy[*threadID]);
142 | }
143 | ifThreadBusy[*threadID]=0;
144 | pthread_mutex_unlock(&sortJobStackMutex);
145 | }
146 | else
147 | {
148 | if(IF_PRINT_DEBUG==2)
149 | printf("Thread[%d]: QuickSortSequential[%d-%d] ifThreadBusy=%d\n"
150 | ,*threadID,job.left,job.right,ifThreadBusy[*threadID]);
151 | QuickSortSequential(job.array,left,right);
152 | pthread_mutex_lock(&sortJobStackMutex);
153 | ifThreadBusy[*threadID]=0;
154 | pthread_mutex_unlock(&sortJobStackMutex);
155 | }
156 | }
157 | }
158 |
159 | void QuickSortSequential(int* array, int left, int right)
160 | {
161 | SortJob job;
162 | job.array=array;
163 | job.left=left;
164 | job.right=right;
165 | std::stack sortJobStack;
166 | sortJobStack.push(job);
167 | while(1)
168 | {
169 | if(sortJobStack.empty())
170 | break;
171 | job = sortJobStack.top();
172 | sortJobStack.pop();
173 | int left=job.left;
174 | int right=job.right;
175 |
176 | int index = PartSort(job.array,job.left,job.right);
177 | if((index - 1) > left)//左子序列
178 | {
179 | job.left=left;
180 | job.right=index - 1;
181 | sortJobStack.push(job);
182 | }
183 | if((index + 1) < right)//右子序列
184 | {
185 | job.left=index + 1;
186 | job.right=right;
187 | sortJobStack.push(job);
188 | }
189 | }
190 | }
191 |
192 | void waitSortDoneAndNotifyAllThreadsToExit()
193 | {
194 | while(1)
195 | {
196 | usleep(10000);//Check every 10ms
197 | pthread_mutex_lock(&sortJobStackMutex);
198 | if(sortJobStackGlobal.empty())
199 | {
200 | int exit=1;
201 | for(int i=0;i=2)
291 | sortArrayLen=atoi(argv[1]);
292 | int sortTimes=1;
293 | if(argc>=3)
294 | sortTimes=atoi(argv[2]);
295 |
296 | srand(time(NULL));
297 |
298 | doSortTest(sortArrayLen,sortTimes,1);//Sequential sort
299 | doSortTest(sortArrayLen,sortTimes,0);//Parallel sort
300 |
301 | return 0;
302 | }
303 |
304 |
--------------------------------------------------------------------------------
/CodeInSlides/chapter4/ConcurrentQuickSort-Recursive-broken.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #define IF_PRINT_DEBUG 0
12 |
13 | int concurrentThreadNum=0;
14 | int maxConcurrentThreadNumEverAppeared=0;
15 | int totalThreadCreated=0;
16 |
17 | pthread_mutex_t threadNumMutex=PTHREAD_MUTEX_INITIALIZER;
18 | // To strictly limit the concurrent thread num, we should use this mutex
19 | // However, this may hurt performance a little.
20 | // As such, you can delete this mutex.
21 | // If so, the concurrent thread num may exceed the limit a little, but not affect the correctness
22 |
23 | double time_diff(struct timeval x , struct timeval y);
24 | void swap(int* array,int first,int second);
25 | int PartSort(int* array,int left,int right);
26 | void* QuickSortParallel(void* args);
27 | void QuickSortSequential(int* array, int left, int right);
28 | int createAThreadToQuickSort(int *array, int left, int right, pthread_t *th);
29 |
30 |
31 | double time_diff(struct timeval x , struct timeval y)
32 | {
33 | double x_ms , y_ms , diff;
34 | x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
35 | y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
36 | diff = (double)y_ms - (double)x_ms;
37 | if(diff<0)
38 | {
39 | fprintf(stderr, "ERROR! time_diff<0\n");
40 | exit(1);
41 | }
42 | return diff;
43 | }
44 |
45 | void swap(int* array,int first,int second)
46 | {
47 | int tmp;
48 | tmp=array[first];
49 | array[first]=array[second];
50 | array[second]=tmp;
51 | }
52 |
53 | //左右指针法
54 | int PartSort(int* array,int left,int right)
55 | {
56 | int key = right;
57 | while(left < right)
58 | {
59 | while(left < right && array[left] <= array[key])
60 | ++left;
61 | while(left < right && array[right] >= array[key])
62 | --right;
63 | swap(array,left,right);
64 | }
65 | swap(array,left,key);
66 | return left;
67 | }
68 |
69 | typedef struct {
70 | int* array;
71 | int left;
72 | int right;
73 | } SortArgs;
74 |
75 | void* QuickSortParallel(void* args)
76 | {
77 | SortArgs* para = (SortArgs*) args;
78 | int *array=para->array;
79 | int left=para->left;
80 | int right=para->right;
81 | free(para);
82 |
83 | if(left >= right)
84 | return NULL;
85 |
86 | int index = PartSort(array,left,right);
87 |
88 | pthread_t th1;
89 | int re1=createAThreadToQuickSort(array,left,index-1,&th1);
90 | pthread_t th2;
91 | int re2=createAThreadToQuickSort(array,index+1,right,&th2);
92 | if(re1==1) {
93 | pthread_join(th1, NULL);
94 | pthread_mutex_lock(&threadNumMutex);
95 | concurrentThreadNum--;
96 | pthread_mutex_unlock(&threadNumMutex);
97 | }
98 | if(re2==1) {
99 | pthread_join(th2, NULL);
100 | pthread_mutex_lock(&threadNumMutex);
101 | concurrentThreadNum--;
102 | pthread_mutex_unlock(&threadNumMutex);
103 | }
104 | }
105 |
106 | void QuickSortSequential(int* array, int left, int right)
107 | {
108 | if(left >= right)
109 | return;
110 |
111 | int index = PartSort(array,left,right);
112 |
113 | QuickSortSequential(array,left,index-1);
114 | QuickSortSequential(array,index+1,right);
115 | }
116 |
117 | void* QuickSortSequentialThread(void* args)
118 | {
119 | SortArgs* para = (SortArgs*) args;
120 | int *array=para->array;
121 | int left=para->left;
122 | int right=para->right;
123 | free(para);
124 |
125 | // printf("QuickSortSequentialThread: left %d, right %d\n",left,right);
126 |
127 | if(left >= right)
128 | return NULL;
129 |
130 | int index = PartSort(array,left,right);
131 |
132 | QuickSortSequential(array,left,index-1);
133 | QuickSortSequential(array,index+1,right);
134 | }
135 |
136 |
137 | //Do not create thread if there are too many concurrent threads
138 | //Return 1 if create new thread, else return 0
139 | int createAThreadToQuickSort(int *array, int left, int right, pthread_t *th)
140 | {
141 | int re=0;
142 |
143 | SortArgs *sortPara = malloc(sizeof(SortArgs));
144 | sortPara->array=array;
145 | sortPara->left=left;
146 | sortPara->right=right;
147 | if(pthread_create(th, NULL, QuickSortParallel, sortPara)!=0)
148 | // if(pthread_create(th, NULL, QuickSortSequentialThread, sortPara)!=0)
149 | {
150 | //Cannot create thread, sort sequentially
151 | QuickSortSequential(array,left,right);
152 | re=0;
153 | }
154 | else
155 | {
156 | //Create a thread, return 1 so the outer function will wait me
157 | re=1;
158 | }
159 | return re;
160 | }
161 |
162 | void doSortTest(int sortArrayLen, int runTimes, int ifSequential)//ifSequential 0 for parallel version, else for sequential version
163 | {
164 | int *array=malloc(sizeof(array[0])*sortArrayLen);
165 |
166 | double totalSortTime=0;
167 | for(int n=0;narray=array;
190 | sortPara->left=0;
191 | sortPara->right=sortArrayLen-1;
192 | QuickSortParallel(sortPara);
193 | printf("RUN[%d] Parallel sort done. ",n);
194 | }
195 | else {
196 | QuickSortSequential(array,0,sortArrayLen-1);
197 | printf("RUN[%d] Sequential sort done. ",n);
198 | }
199 | gettimeofday(&tvEnd,NULL);
200 | totalSortTime=totalSortTime+time_diff(tvStart,tvEnd);
201 | printf("Spend %.5lf s.\n",time_diff(tvStart,tvEnd)/1E6);
202 | if(IF_PRINT_DEBUG)
203 | {
204 | printf("RUN[%d] Sorted:\n",n);
205 | for(int i=0;i=2)
225 | sortArrayLen=atoi(argv[1]);
226 | int sortTimes=1;
227 | if(argc>=3)
228 | sortTimes=atoi(argv[2]);
229 |
230 | srand(time(NULL));
231 |
232 | doSortTest(sortArrayLen,sortTimes,1);//Sequential sort
233 | doSortTest(sortArrayLen,sortTimes,0);//Parallel sort
234 |
235 | return 0;
236 | }
237 |
238 |
--------------------------------------------------------------------------------
/CodeInSlides/chapter4/ConcurrentQuickSort-Recursive.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #define IF_PRINT_DEBUG 0
12 |
13 | #define MIN_ARRAY_LEN_FOR_CREATE_A_THREAD_TO_SORT 100000
14 | #define MAX_CONCURRENT_THREAD_NUM 1000
15 | int concurrentThreadNum=0;
16 | int maxConcurrentThreadNumEverAppeared=0;
17 | int totalThreadCreated=0;
18 |
19 | pthread_mutex_t threadNumMutex=PTHREAD_MUTEX_INITIALIZER;
20 | // To strictly limit the concurrent thread num, we should use this mutex
21 | // However, this may hurt performance a little.
22 | // As such, you can delete this mutex.
23 | // If so, the concurrent thread num may exceed the limit a little, but not affect the correctness
24 |
25 | double time_diff(struct timeval x , struct timeval y);
26 | void swap(int* array,int first,int second);
27 | int PartSort(int* array,int left,int right);
28 | void* QuickSortParallel(void* args);
29 | void QuickSortSequential(int* array, int left, int right);
30 | int createAThreadToQuickSort(int *array, int left, int right, pthread_t *th);
31 |
32 |
33 | double time_diff(struct timeval x , struct timeval y)
34 | {
35 | double x_ms , y_ms , diff;
36 | x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
37 | y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
38 | diff = (double)y_ms - (double)x_ms;
39 | if(diff<0)
40 | {
41 | fprintf(stderr, "ERROR! time_diff<0\n");
42 | exit(1);
43 | }
44 | return diff;
45 | }
46 |
47 | void swap(int* array,int first,int second)
48 | {
49 | int tmp;
50 | tmp=array[first];
51 | array[first]=array[second];
52 | array[second]=tmp;
53 | }
54 |
55 | //左右指针法
56 | int PartSort(int* array,int left,int right)
57 | {
58 | int key = right;
59 | while(left < right)
60 | {
61 | while(left < right && array[left] <= array[key])
62 | ++left;
63 | while(left < right && array[right] >= array[key])
64 | --right;
65 | swap(array,left,right);
66 | }
67 | swap(array,left,key);
68 | return left;
69 | }
70 |
71 | typedef struct {
72 | int* array;
73 | int left;
74 | int right;
75 | } SortArgs;
76 |
77 | void* QuickSortParallel(void* args)
78 | {
79 | SortArgs* para = (SortArgs*) args;
80 | int *array=para->array;
81 | int left=para->left;
82 | int right=para->right;
83 | free(para);
84 |
85 | if(left >= right)
86 | return NULL;
87 |
88 | int index = PartSort(array,left,right);
89 |
90 | pthread_t th1;
91 | int re1=createAThreadToQuickSort(array,left,index-1,&th1);
92 | pthread_t th2;
93 | int re2=createAThreadToQuickSort(array,index+1,right,&th2);
94 | if(re1==1) {
95 | pthread_join(th1, NULL);
96 | pthread_mutex_lock(&threadNumMutex);
97 | concurrentThreadNum--;
98 | pthread_mutex_unlock(&threadNumMutex);
99 | }
100 | if(re2==1) {
101 | pthread_join(th2, NULL);
102 | pthread_mutex_lock(&threadNumMutex);
103 | concurrentThreadNum--;
104 | pthread_mutex_unlock(&threadNumMutex);
105 | }
106 | }
107 |
108 | void QuickSortSequential(int* array, int left, int right)
109 | {
110 | if(left >= right)
111 | return;
112 |
113 | int index = PartSort(array,left,right);
114 |
115 | QuickSortSequential(array,left,index-1);
116 | QuickSortSequential(array,index+1,right);
117 | }
118 |
119 | //Do not create thread if there are too many concurrent threads
120 | //Return 1 if create new thread, else return 0
121 | int createAThreadToQuickSort(int *array, int left, int right, pthread_t *th)
122 | {
123 | int re=0;
124 | pthread_mutex_lock(&threadNumMutex);
125 | if(concurrentThreadNum=MIN_ARRAY_LEN_FOR_CREATE_A_THREAD_TO_SORT)
127 | {
128 | totalThreadCreated++;
129 | concurrentThreadNum++;
130 | if(concurrentThreadNum>maxConcurrentThreadNumEverAppeared)
131 | maxConcurrentThreadNumEverAppeared=concurrentThreadNum;
132 | if(IF_PRINT_DEBUG)
133 | printf("Create thread [%d] to sort[%d-%d]\n",totalThreadCreated,left,right);
134 | pthread_mutex_unlock(&threadNumMutex);
135 |
136 | SortArgs *sortPara = malloc(sizeof(SortArgs));
137 | sortPara->array=array;
138 | sortPara->left=left;
139 | sortPara->right=right;
140 | if(pthread_create(th, NULL, QuickSortParallel, sortPara)!=0)
141 | {
142 | perror("pthread_create failed");
143 | exit(1);
144 | }
145 | re=1;
146 | }
147 | else
148 | {
149 | pthread_mutex_unlock(&threadNumMutex);
150 | QuickSortSequential(array,left,right);
151 | }
152 | return re;
153 | }
154 |
155 | void doSortTest(int sortArrayLen, int runTimes, int ifSequential)//ifSequential 0 for parallel version, else for sequential version
156 | {
157 | int *array=malloc(sizeof(array[0])*sortArrayLen);
158 |
159 | double totalSortTime=0;
160 | for(int n=0;narray=array;
183 | sortPara->left=0;
184 | sortPara->right=sortArrayLen-1;
185 | QuickSortParallel(sortPara);
186 | printf("RUN[%d] Parallel sort done. Create %d threads in total. The max concurrency ever appeared is %d. "
187 | ,n,totalThreadCreated,maxConcurrentThreadNumEverAppeared);
188 | }
189 | else {
190 | QuickSortSequential(array,0,sortArrayLen-1);
191 | printf("RUN[%d] Sequential sort done. ",n);
192 | }
193 | gettimeofday(&tvEnd,NULL);
194 | totalSortTime=totalSortTime+time_diff(tvStart,tvEnd);
195 | printf("Spend %.5lf s.\n",time_diff(tvStart,tvEnd)/1E6);
196 | if(IF_PRINT_DEBUG)
197 | {
198 | printf("RUN[%d] Sorted:\n",n);
199 | for(int i=0;i=2)
219 | sortArrayLen=atoi(argv[1]);
220 | int sortTimes=1;
221 | if(argc>=3)
222 | sortTimes=atoi(argv[2]);
223 |
224 | srand(time(NULL));
225 |
226 | doSortTest(sortArrayLen,sortTimes,1);//Sequential sort
227 | doSortTest(sortArrayLen,sortTimes,0);//Parallel sort
228 |
229 | return 0;
230 | }
231 |
232 |
--------------------------------------------------------------------------------
/CodeInSlides/chapter4/ConcurrentWget-OnDemand.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #define MAX_CONCURRENT_INPUT_NUM 10000
13 | #define MAX_URL_LENGTH 1024
14 |
15 | #define OUTPUT_FOLDER_NAME "testOutput"
16 |
17 | long int totalNumOfJobsDone=0;
18 | int totalThreadsCreated=0;
19 | int concurrentThreadsNow=0;
20 | int maxConcurrentThreads=0;
21 | pthread_mutex_t counterMutex=PTHREAD_MUTEX_INITIALIZER;
22 |
23 | double time_diff(struct timeval x , struct timeval y)
24 | {
25 | double x_ms , y_ms , diff;
26 | x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
27 | y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
28 | diff = (double)y_ms - (double)x_ms;
29 | if(diff<0)
30 | {
31 | fprintf(stderr, "ERROR! time_diff<0\n");
32 | exit(1);
33 | }
34 | return diff;
35 | }
36 |
37 | void initOutputFolder()
38 | {
39 | char command[1000];
40 | sprintf(command,"rm -rf %s",OUTPUT_FOLDER_NAME);
41 | int status=system(command);
42 | mkdir(OUTPUT_FOLDER_NAME, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
43 | }
44 |
45 | typedef struct {
46 | char *job;
47 | long int jobID;
48 | } ThreadParas;
49 |
50 | void* processJobsOnDemandThread(void* args) {
51 | pthread_mutex_lock(&counterMutex);
52 | totalThreadsCreated++;
53 | concurrentThreadsNow++;
54 | if(concurrentThreadsNow>maxConcurrentThreads)
55 | maxConcurrentThreads=concurrentThreadsNow;
56 | pthread_mutex_unlock(&counterMutex);
57 | ThreadParas* para = (ThreadParas*) args;
58 | char *job=para->job;
59 | long int jobID=para->jobID;
60 |
61 | struct timeval tvStart,tvEnd;
62 | gettimeofday(&tvStart,NULL);
63 | char command[MAX_URL_LENGTH+1000];
64 | memset(command,0,(MAX_URL_LENGTH+1000)*sizeof(command[0]));
65 | sprintf(command,"wget %s -O %s/%05ld.html > %s/%05ld.log 2>&1",job,OUTPUT_FOLDER_NAME,jobID,OUTPUT_FOLDER_NAME,jobID);
66 | // printf("thread[%ld]: %s\n",jobID,command);
67 | int status=system(command);//get the URL page
68 |
69 | //Log time spent
70 | gettimeofday(&tvEnd,NULL);
71 | memset(command,0,(MAX_URL_LENGTH+1000)*sizeof(command[0]));
72 | sprintf(command,"echo \"[RESULT]: get URL %s , spend %.3lf s\" >> %s/%05ld.log"
73 | ,job,time_diff(tvStart,tvEnd)/1E6,OUTPUT_FOLDER_NAME,jobID);
74 | status=system(command);
75 |
76 | free(job);
77 | free(para);
78 | pthread_mutex_lock(&counterMutex);
79 | totalNumOfJobsDone++;
80 | concurrentThreadsNow--;
81 | pthread_mutex_unlock(&counterMutex);
82 | }
83 |
84 | void waitForAllJobsDone(int finalJobID)
85 | {
86 | //Lazily wait all the worker threads finish their wget jobs
87 | while(1)
88 | {
89 | usleep(10000);//Check per 10 ms
90 | pthread_mutex_lock(&counterMutex);
91 | if(totalNumOfJobsDone==finalJobID)//All jobs done
92 | {
93 | pthread_mutex_unlock(&counterMutex);
94 | break;
95 | }
96 | pthread_mutex_unlock(&counterMutex);
97 | }
98 | }
99 |
100 | int main(int argc, char *argv[])
101 | {
102 | initOutputFolder();
103 | printf("Start to wget urls ...\n");
104 |
105 | long int nextJobID=0;
106 | ThreadParas *thPara;
107 | while(1)
108 | {
109 | thPara=malloc(sizeof(ThreadParas));
110 | thPara->job=malloc(MAX_URL_LENGTH*sizeof(thPara->job[0]));
111 | memset(thPara->job,0,MAX_URL_LENGTH*sizeof(thPara->job[0]));
112 | if(scanf("%s",thPara->job)==EOF)
113 | break;
114 | thPara->jobID=nextJobID;
115 | nextJobID++;
116 | pthread_t th;
117 | if(pthread_create(&th, NULL, processJobsOnDemandThread, thPara)!=0)
118 | {
119 | perror("pthread_create failed");
120 | exit(1);
121 | }
122 | }
123 |
124 | waitForAllJobsDone(nextJobID);
125 | printf("Finish all jobs! Get %ld URLs in total!\n",totalNumOfJobsDone);
126 | printf("Create %d on-demand threads in total. There are %d max concurrent threads!\n"
127 | ,totalThreadsCreated,maxConcurrentThreads);
128 | //In real project, do free the memory and destroy mutexes and semaphores
129 | exit(0);
130 | }
--------------------------------------------------------------------------------
/CodeInSlides/chapter4/ConcurrentWget-ThreadPool.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #define MAX_CONCURRENT_INPUT_NUM 10000
13 | #define MAX_URL_LENGTH 1024
14 |
15 | #define OUTPUT_FOLDER_NAME "testOutput"
16 |
17 | long int totalNumOfJobsDone=0;
18 | pthread_mutex_t jobNumMutex=PTHREAD_MUTEX_INITIALIZER;
19 |
20 | double time_diff(struct timeval x , struct timeval y)
21 | {
22 | double x_ms , y_ms , diff;
23 | x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
24 | y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
25 | diff = (double)y_ms - (double)x_ms;
26 | if(diff<0)
27 | {
28 | fprintf(stderr, "ERROR! time_diff<0\n");
29 | exit(1);
30 | }
31 | return diff;
32 | }
33 |
34 | typedef unsigned char BYTE;
35 | int *threadFlags;
36 |
37 | typedef struct {
38 | char **jobs;
39 | int head;
40 | int tail;
41 | long int inCount;
42 | long int outCount;
43 | pthread_mutex_t mutex;
44 | sem_t fullSlots;
45 | sem_t emptySlots;
46 | int queueCapacity;
47 | } JobQueue;
48 |
49 | JobQueue inJobQueue;
50 |
51 | void initJobQueue()
52 | {
53 | inJobQueue.jobs=malloc(MAX_CONCURRENT_INPUT_NUM*sizeof(inJobQueue.jobs[0]));
54 | for(int i=0;i %s/%05ld.log 2>&1",job,OUTPUT_FOLDER_NAME,jobID,OUTPUT_FOLDER_NAME,jobID);
113 | // printf("thread[%d]: %s\n",*id,command);
114 | int status=system(command);//get the URL page
115 |
116 | //Log time spent
117 | gettimeofday(&tvEnd,NULL);
118 | memset(command,0,(MAX_URL_LENGTH+1000)*sizeof(command[0]));
119 | sprintf(command,"echo \"[RESULT]: get URL %s , spend %.3lf s\" >> %s/%05ld.log"
120 | ,job,time_diff(tvStart,tvEnd)/1E6,OUTPUT_FOLDER_NAME,jobID);
121 | status=system(command);
122 |
123 | pthread_mutex_lock(&jobNumMutex);
124 | totalNumOfJobsDone++;
125 | pthread_mutex_unlock(&jobNumMutex);
126 | }
127 | }
128 |
129 | void waitForAllJobsDone(int finalJobID)
130 | {
131 | //Lazily wait all the worker threads finish their wget jobs
132 | while(1)
133 | {
134 | usleep(10000);//Check per 10 ms
135 | pthread_mutex_lock(&jobNumMutex);
136 | if(totalNumOfJobsDone==finalJobID)//All jobs done
137 | {
138 | pthread_mutex_unlock(&jobNumMutex);
139 | break;
140 | }
141 | pthread_mutex_unlock(&jobNumMutex);
142 | }
143 | }
144 |
145 | int main(int argc, char *argv[])
146 | {
147 | int numOfWorkerThread=1;
148 | if(argc>=2)
149 | numOfWorkerThread=atoi(argv[1]);
150 |
151 | initJobQueue();
152 | initOutputFolder();
153 |
154 | printf("Start to wget urls ...\n");
155 |
156 | threadFlags=malloc(numOfWorkerThread*sizeof(threadFlags[0]));
157 | pthread_t th[numOfWorkerThread];
158 | int threadID[numOfWorkerThread];
159 | for(int i=0;i
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define ITERATION_PER_THREAD 10
9 |
10 | typedef struct
11 | {
12 | pthread_mutex_t mutex; // lock for this resource
13 | int processTime; // process time for this resource (in microseconds)
14 | } Resource;
15 | Resource *globalResources; // Shared resources among threads. resources[i] is resource type i
16 |
17 | pthread_mutex_t bigMutex; // lock for all global resources
18 |
19 | void processResource(Resource resource)
20 | {
21 | usleep(resource.processTime); // Use sleep to emulate processing time for a resource
22 | }
23 |
24 | typedef struct
25 | {
26 | int threadID;
27 | int totalResourceNum;
28 | int numOfResourceNeeded;//How many resources this thread needs to process
29 | int *resourceAccessOrder;
30 | // resourceAccessOrder[i] is the ith resource's type that this thread needs to process
31 | int ifUseBigLock;// 1 means grab all resources before processing
32 | } ThreadArgs;
33 |
34 | void printThreadArgs(ThreadArgs args)
35 | {
36 | printf("Thread %d args: \t\t totalResourceNum %d, numOfResourceNeeded %d, resourceAccessOrder("
37 | ,args.threadID ,args.totalResourceNum ,args.numOfResourceNeeded);
38 | fflush(stdout);
39 | for(int j=0;jthreadID;
53 | int numOfResourceNeeded=para->numOfResourceNeeded;
54 | int *resourceAccessOrder=para->resourceAccessOrder;
55 | int ifUseBigLock=para->ifUseBigLock;
56 | for(int i=0;i=0;j--)
83 | {
84 | int resourceType=resourceAccessOrder[j];
85 | pthread_mutex_unlock(&(globalResources[resourceType].mutex));
86 | }
87 | }
88 | }
89 | }
90 |
91 | void pickKDifferentIntLessThanN(int k, int n, int *result)
92 | {
93 | //Fisher-Yates shuffling algorithm to get a random permutation of int 0...n-1
94 | int *r = malloc(n*sizeof(int));
95 | // initial range of numbers
96 | for(int i=0;i= 0; --i)
100 | {
101 | //generate a random number [0, n-1]
102 | int j = rand() % (i+1);
103 |
104 | //swap the last element with element at random index
105 | int temp = r[i];
106 | r[i] = r[j];
107 | r[j] = temp;
108 | }
109 |
110 | for(int i=0;iresourceAccessOrder=malloc((thPara->numOfResourceNeeded)*sizeof(int));
124 | pickKDifferentIntLessThanN(thPara->numOfResourceNeeded, thPara->totalResourceNum, thPara->resourceAccessOrder);
125 | if(ifSortAccess==1)//ifSortAccess: 1 all use the same ascending order
126 | qsort(thPara->resourceAccessOrder, thPara->numOfResourceNeeded, sizeof(int), compare);
127 | }
128 |
129 | int main(int argc, char *argv[])
130 | {
131 | if(argc<3)
132 | {
133 | fprintf(stderr, "Usage: exe numOfWorkerThread totalResourceNum\n");
134 | exit(1);
135 | }
136 | int numOfWorkerThread=atoi(argv[1]);
137 | int totalResourceNum=atoi(argv[2]);
138 | int resourceNeededPerThread=1;
139 | if(argc>3)
140 | resourceNeededPerThread=atoi(argv[3]);
141 | int ifUseBigLock=0;
142 | if(argc>4)
143 | ifUseBigLock=atoi(argv[4]);
144 | int ifSortAccess=0;
145 | if(argc>5)
146 | ifSortAccess=atoi(argv[5]);
147 |
148 | srand(time(NULL));
149 |
150 | if(ifUseBigLock)
151 | pthread_mutex_init(&bigMutex,NULL);
152 | globalResources=malloc(sizeof(Resource)*totalResourceNum);
153 | for(int i=0;i
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #define INPUT_JOB_NUM 10
12 | #define INPUT_FOLDER_NAME "testInput"
13 |
14 | #define THE_HEAVY_JOB_ID 1
15 | int THE_HEAVY_WEIGHT=1;
16 |
17 | #define CHUNK_SIZE 4096
18 | #define TOTAL_CHUNK_NUM 10240
19 |
20 | typedef unsigned char BYTE;
21 |
22 | char inJob[INPUT_JOB_NUM][256];
23 | int nextJobToBeDone=0;
24 | pthread_mutex_t jobQueueMutex=PTHREAD_MUTEX_INITIALIZER;
25 |
26 | double time_diff(struct timeval x , struct timeval y)
27 | {
28 | double x_ms , y_ms , diff;
29 | x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
30 | y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
31 | diff = (double)y_ms - (double)x_ms;
32 | if(diff<0)
33 | {
34 | fprintf(stderr, "ERROR! time_diff<0\n");
35 | exit(1);
36 | }
37 | return diff;
38 | }
39 |
40 | long int generateJobs()
41 | {
42 | char command[1000];
43 | sprintf(command,"rm -rf %s",INPUT_FOLDER_NAME);
44 | int status=system(command);
45 | mkdir(INPUT_FOLDER_NAME, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
46 | BYTE writeBuf[CHUNK_SIZE];
47 | int writeSize=0;
48 | for(int i=0;i=INPUT_JOB_NUM)
94 | {
95 | pthread_mutex_unlock(&jobQueueMutex);
96 | return -1;
97 | }
98 | currentJobID=nextJobToBeDone;
99 | nextJobToBeDone++;
100 | pthread_mutex_unlock(&jobQueueMutex);
101 | return currentJobID;
102 | }
103 |
104 | void processAJob(int jobID, long int *sum)
105 | {
106 | BYTE readBuf[CHUNK_SIZE]={0};
107 | int readSize=0;
108 | FILE *fp;
109 | if((fp = fopen(inJob[jobID],"r"))==NULL)
110 | {
111 | perror("fopen ERROR!");
112 | exit(1);
113 | }
114 | while(1)//Read until EOF
115 | {
116 | readSize=fread(readBuf, 1, CHUNK_SIZE, fp);
117 | if(readSize<0){
118 | perror("read ERROR!");
119 | exit(1);
120 | }
121 | else if(readSize==0){ //EOF
122 | break;
123 | }
124 | for(int j=0;j0)
154 | printf(",");
155 | printf("%d",whichJobIHaveDone[i]);
156 | }
157 | printf("]): \t %ld\n", sum);
158 | para->result=sum;
159 | }
160 |
161 | int main(int argc, char *argv[])
162 | {
163 | int numOfWorkerThread=1;
164 | if(argc>=2)
165 | numOfWorkerThread=atoi(argv[1]);
166 | if(numOfWorkerThread>INPUT_JOB_NUM)
167 | numOfWorkerThread=INPUT_JOB_NUM;
168 | if(argc>=3)
169 | THE_HEAVY_WEIGHT=atoi(argv[2]);
170 |
171 | struct timeval tvGenStart,tvEnd;
172 | struct timeval tvMainStartCacl,tvMainEndCacl;
173 | struct timeval tvWorkerStartCacl,tvWorkerEndCacl;
174 |
175 | printf("Generating input jobs ...\n");
176 | gettimeofday(&tvGenStart,NULL);
177 | long int totalBytes=generateJobs();
178 | gettimeofday(&tvEnd,NULL);
179 | printf("Generating input jobs done. Spend %.5lf s to finish. Total test input data size is %lf MBs\n",time_diff(tvGenStart,tvEnd)/1E6,(double)totalBytes/1E6);
180 |
181 | printf("Main thread start doing jobs ...\n");
182 | gettimeofday(&tvMainStartCacl,NULL);
183 | ThreadParas thParaMain;
184 | calcSum(&thParaMain);
185 | gettimeofday(&tvMainEndCacl,NULL);
186 | printf("Main thread finish jobs. Spend %.5lf s to finish.\n",time_diff(tvMainStartCacl,tvMainEndCacl)/1E6);
187 |
188 | nextJobToBeDone=0;
189 | printf("Worker threads start doing jobs ...\n");
190 | gettimeofday(&tvWorkerStartCacl,NULL);
191 | pthread_t th[numOfWorkerThread];
192 | ThreadParas thPara[numOfWorkerThread];
193 | for(int i=0;i
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #define INPUT_JOB_NUM 102400
13 | #define CHUNK_SIZE 4096
14 |
15 | typedef unsigned char BYTE;
16 |
17 | BYTE **inJob;
18 | int nextJobToBeDone=0;
19 | pthread_mutex_t jobQueueMutex=PTHREAD_MUTEX_INITIALIZER;
20 |
21 | sem_t fullSlots;
22 |
23 | long int *subJob;
24 | int subJobNum=0;
25 | int nextSubJobToBeDone=0;
26 | pthread_mutex_t subJobQueueMutex=PTHREAD_MUTEX_INITIALIZER;
27 |
28 | double time_diff(struct timeval x , struct timeval y)
29 | {
30 | double x_ms , y_ms , diff;
31 | x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
32 | y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
33 | diff = (double)y_ms - (double)x_ms;
34 | if(diff<0)
35 | {
36 | fprintf(stderr, "ERROR! time_diff<0\n");
37 | exit(1);
38 | }
39 | return diff;
40 | }
41 |
42 | long int generateJobs()
43 | {
44 | long int totalBytes=0;
45 | inJob=malloc(INPUT_JOB_NUM*sizeof(BYTE *));
46 | for(int i=0;i=INPUT_JOB_NUM)
64 | {
65 | pthread_mutex_unlock(&jobQueueMutex);
66 | return -1;
67 | }
68 | currentJobID=nextJobToBeDone;
69 | nextJobToBeDone++;
70 | pthread_mutex_unlock(&jobQueueMutex);
71 | return currentJobID;
72 | }
73 |
74 | void inputASubJob(long int sum)
75 | {
76 | pthread_mutex_lock(&subJobQueueMutex);
77 | if(subJobNum>=INPUT_JOB_NUM)
78 | {
79 | pthread_mutex_unlock(&subJobQueueMutex);
80 | fprintf(stderr, "subJobNum %d ERROR, exceeding INPUT_JOB_NUM %d\n", subJobNum, INPUT_JOB_NUM);
81 | exit(1);
82 | }
83 | subJob[subJobNum]=sum;
84 | subJobNum++;
85 | pthread_mutex_unlock(&subJobQueueMutex);
86 | sem_post(&fullSlots);
87 | }
88 |
89 | void processAJob(int jobID, long int *sum)
90 | {
91 | for(int j=0;jresult=sum;
119 | }
120 |
121 | void initSubJobQueue()
122 | {
123 | subJob=malloc(INPUT_JOB_NUM*sizeof(long int));
124 | }
125 |
126 | int recvASubJob()
127 | {
128 | int currentJobID=0;
129 | sem_wait(&fullSlots);
130 | pthread_mutex_lock(&subJobQueueMutex);
131 | currentJobID=nextSubJobToBeDone;
132 | nextSubJobToBeDone++;
133 | pthread_mutex_unlock(&subJobQueueMutex);
134 | return currentJobID;
135 | }
136 |
137 | void processASubJob(int jobID)
138 | {
139 | fprintf(stderr,"%ld\n",subJob[jobID]);
140 | }
141 |
142 | void* fprintSum(void* args) {
143 | int subJobID=0;
144 | long int numOfJobsIHaveDone=0;//Remember how many jobs I have done
145 | while(1)
146 | {
147 | subJobID=recvASubJob();
148 | processASubJob(subJobID);
149 | numOfJobsIHaveDone++;
150 | if(subJobID==INPUT_JOB_NUM-1)//All job done
151 | break;
152 | }
153 | pthread_t tid = pthread_self();
154 | printf("[%ld] thread (fprint %ld subJobs[])\n"
155 | , pthread_self(), numOfJobsIHaveDone);
156 | }
157 |
158 | int main(int argc, char *argv[])
159 | {
160 | int numOfWorkerThread=1;
161 | if(argc>=2)
162 | numOfWorkerThread=atoi(argv[1]);
163 | if(numOfWorkerThread>INPUT_JOB_NUM)
164 | numOfWorkerThread=INPUT_JOB_NUM;
165 |
166 | struct timeval tvGenStart,tvEnd;
167 | struct timeval tvWorkerStartCacl,tvWorkerEndCacl;
168 |
169 | printf("Generating input jobs ...\n");
170 | gettimeofday(&tvGenStart,NULL);
171 | long int totalBytes=generateJobs();
172 | gettimeofday(&tvEnd,NULL);
173 | printf("Generating input jobs done. Spend %.5lf s to finish. Total test input data size is %lf MBs\n",time_diff(tvGenStart,tvEnd)/1E6,(double)totalBytes/1E6);
174 |
175 | sem_init(&fullSlots, 0, 0);
176 | initSubJobQueue();
177 | nextJobToBeDone=0;
178 | nextSubJobToBeDone=0;
179 | printf("Worker threads start doing jobs ...\n");
180 | gettimeofday(&tvWorkerStartCacl,NULL);
181 | pthread_t th[numOfWorkerThread];
182 | ThreadParas thPara[numOfWorkerThread];
183 | for(int i=0;i
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #define INPUT_JOB_NUM 102400
12 | #define CHUNK_SIZE 4096
13 |
14 | typedef unsigned char BYTE;
15 |
16 | BYTE **inJob;
17 | int nextJobToBeDone=0;
18 | pthread_mutex_t jobQueueMutex=PTHREAD_MUTEX_INITIALIZER;
19 |
20 | double time_diff(struct timeval x , struct timeval y)
21 | {
22 | double x_ms , y_ms , diff;
23 | x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
24 | y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
25 | diff = (double)y_ms - (double)x_ms;
26 | if(diff<0)
27 | {
28 | fprintf(stderr, "ERROR! time_diff<0\n");
29 | exit(1);
30 | }
31 | return diff;
32 | }
33 |
34 | long int generateJobs()
35 | {
36 | long int totalBytes=0;
37 | inJob=malloc(INPUT_JOB_NUM*sizeof(BYTE *));
38 | for(int i=0;i=INPUT_JOB_NUM)
56 | {
57 | pthread_mutex_unlock(&jobQueueMutex);
58 | return -1;
59 | }
60 | currentJobID=nextJobToBeDone;
61 | nextJobToBeDone++;
62 | pthread_mutex_unlock(&jobQueueMutex);
63 | return currentJobID;
64 | }
65 |
66 | void processAJob(int jobID, long int *sum)
67 | {
68 | for(int j=0;jresult=sum;
96 | }
97 |
98 | int main(int argc, char *argv[])
99 | {
100 | int numOfWorkerThread=1;
101 | if(argc>=2)
102 | numOfWorkerThread=atoi(argv[1]);
103 | if(numOfWorkerThread>INPUT_JOB_NUM)
104 | numOfWorkerThread=INPUT_JOB_NUM;
105 |
106 | struct timeval tvGenStart,tvEnd;
107 | struct timeval tvWorkerStartCacl,tvWorkerEndCacl;
108 |
109 | printf("Generating input jobs ...\n");
110 | gettimeofday(&tvGenStart,NULL);
111 | long int totalBytes=generateJobs();
112 | gettimeofday(&tvEnd,NULL);
113 | printf("Generating input jobs done. Spend %.5lf s to finish. Total test input data size is %lf MBs\n",time_diff(tvGenStart,tvEnd)/1E6,(double)totalBytes/1E6);
114 |
115 | nextJobToBeDone=0;
116 | printf("Worker threads start doing jobs ...\n");
117 | gettimeofday(&tvWorkerStartCacl,NULL);
118 | pthread_t th[numOfWorkerThread];
119 | ThreadParas thPara[numOfWorkerThread];
120 | for(int i=0;i.
15 |
16 | CC = gcc
17 | CPPFLAGS = -O2 -pthread
18 |
19 | # the build target executable:
20 | TARGETS = ATMProblemShow ATMProblemShow-mutex \
21 | BoundedBuffer-mutex BoundedBuffer-semaphore BoundedBuffer-monitor BoundedBuffer-monitor-mesatest \
22 | Deadlock PreAssignJob DynamicAssignJob HomoThreads HeteroThreads \
23 | ConcurrentWget-ThreadPool ConcurrentWget-OnDemand \
24 | ConcurrentQuickSort-Recursive-broken ConcurrentQuickSort-Recursive ConcurrentQuickSort-Iteration \
25 | Problems-CompilerOptimization Problems-CPUOoO
26 |
27 | all: $(TARGETS)
28 |
29 | clean:
30 | $(RM) $(TARGETS)
31 |
32 |
--------------------------------------------------------------------------------
/CodeInSlides/chapter4/MultiCat.sh:
--------------------------------------------------------------------------------
1 | if [ "x$1$2" == "x$1" ]
2 | then
3 | echo "Input arg1[filename], arg2[times]"
4 | exit
5 | fi
6 |
7 | for ((i=0;i<$2;i++))
8 | do
9 | cat $1
10 | done
--------------------------------------------------------------------------------
/CodeInSlides/chapter4/PreAssignJob.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #define INPUT_JOB_NUM 10
12 | #define INPUT_FOLDER_NAME "testInput"
13 |
14 | #define THE_HEAVY_JOB_ID 1
15 | int THE_HEAVY_WEIGHT=1;
16 |
17 | #define CHUNK_SIZE 4096
18 | #define TOTAL_CHUNK_NUM 10240
19 |
20 | typedef unsigned char BYTE;
21 |
22 | char inJob[INPUT_JOB_NUM][256];
23 |
24 | double time_diff(struct timeval x , struct timeval y)
25 | {
26 | double x_ms , y_ms , diff;
27 | x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
28 | y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
29 | diff = (double)y_ms - (double)x_ms;
30 | if(diff<0)
31 | {
32 | fprintf(stderr, "ERROR! time_diff<0\n");
33 | exit(1);
34 | }
35 | return diff;
36 | }
37 |
38 | long int generateJobs()
39 | {
40 | char command[1000];
41 | sprintf(command,"rm -rf %s",INPUT_FOLDER_NAME);
42 | int status=system(command);
43 | mkdir(INPUT_FOLDER_NAME, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
44 | BYTE writeBuf[CHUNK_SIZE];
45 | int writeSize=0;
46 | for(int i=0;ifirst;
119 | int last=para->last;
120 | long int sum=0;
121 | for(int i=first;iresult=sum;
132 | }
133 |
134 | int main(int argc, char *argv[])
135 | {
136 | int numOfWorkerThread=1;
137 | if(argc>=2)
138 | numOfWorkerThread=atoi(argv[1]);
139 | if(numOfWorkerThread>INPUT_JOB_NUM)
140 | numOfWorkerThread=INPUT_JOB_NUM;
141 | if(argc>=3)
142 | THE_HEAVY_WEIGHT=atoi(argv[2]);
143 |
144 | struct timeval tvGenStart,tvEnd;
145 | struct timeval tvMainStartCacl,tvMainEndCacl;
146 | struct timeval tvWorkerStartCacl,tvWorkerEndCacl;
147 |
148 | printf("Generating input jobs ...\n");
149 | gettimeofday(&tvGenStart,NULL);
150 | long int totalBytes=generateJobs();
151 | gettimeofday(&tvEnd,NULL);
152 | printf("Generating input jobs done. Spend %.5lf s to finish. Total test input data size is %lf MBs\n",time_diff(tvGenStart,tvEnd)/1E6,(double)totalBytes/1E6);
153 |
154 | printf("Main thread start doing jobs ...\n");
155 | gettimeofday(&tvMainStartCacl,NULL);
156 | ThreadParas thParaMain;
157 | thParaMain.first=0;
158 | thParaMain.last=INPUT_JOB_NUM;
159 | calcSum(&thParaMain);
160 | gettimeofday(&tvMainEndCacl,NULL);
161 | printf("Main thread finish jobs. Spend %.5lf s to finish.\n",time_diff(tvMainStartCacl,tvMainEndCacl)/1E6);
162 |
163 | printf("Worker threads start doing jobs ...\n");
164 | gettimeofday(&tvWorkerStartCacl,NULL);
165 | pthread_t th[numOfWorkerThread];
166 | ThreadParas thPara[numOfWorkerThread];
167 | for(int i=0;i
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | long TEST_TIMES=1000000;
9 | #define PRINT_STEP 10000
10 |
11 | int x=0,y=0;
12 | void* thread_1(void* args) {
13 | x = 1; printf("y=%d\n", y);
14 | }
15 |
16 | void* thread_2(void* args) {
17 | y = 1; printf("x=%d\n", x);
18 | }
19 |
20 | int main(int argc, char *argv[])
21 | {
22 | if(argc>=2)
23 | TEST_TIMES=atoi(argv[1]);
24 |
25 | pthread_t th1;
26 | pthread_t th2;
27 | for(int i=0;i:
8 | 630: 48 83 ec 08 sub $0x8,%rsp
9 | 634: 48 8b 05 ad 09 20 00 mov 0x2009ad(%rip),%rax # 200fe8 <__gmon_start__>
10 | 63b: 48 85 c0 test %rax,%rax
11 | 63e: 74 02 je 642 <_init+0x12>
12 | 640: ff d0 callq *%rax
13 | 642: 48 83 c4 08 add $0x8,%rsp
14 | 646: c3 retq
15 |
16 | Disassembly of section .plt:
17 |
18 | 0000000000000650 <.plt>:
19 | 650: ff 35 4a 09 20 00 pushq 0x20094a(%rip) # 200fa0 <_GLOBAL_OFFSET_TABLE_+0x8>
20 | 656: ff 25 4c 09 20 00 jmpq *0x20094c(%rip) # 200fa8 <_GLOBAL_OFFSET_TABLE_+0x10>
21 | 65c: 0f 1f 40 00 nopl 0x0(%rax)
22 |
23 | 0000000000000660 :
24 | 660: ff 25 4a 09 20 00 jmpq *0x20094a(%rip) # 200fb0
25 | 666: 68 00 00 00 00 pushq $0x0
26 | 66b: e9 e0 ff ff ff jmpq 650 <.plt>
27 |
28 | 0000000000000670 <__printf_chk@plt>:
29 | 670: ff 25 42 09 20 00 jmpq *0x200942(%rip) # 200fb8 <__printf_chk@GLIBC_2.3.4>
30 | 676: 68 01 00 00 00 pushq $0x1
31 | 67b: e9 d0 ff ff ff jmpq 650 <.plt>
32 |
33 | 0000000000000680 :
34 | 680: ff 25 3a 09 20 00 jmpq *0x20093a(%rip) # 200fc0
35 | 686: 68 02 00 00 00 pushq $0x2
36 | 68b: e9 c0 ff ff ff jmpq 650 <.plt>
37 |
38 | 0000000000000690 :
39 | 690: ff 25 32 09 20 00 jmpq *0x200932(%rip) # 200fc8
40 | 696: 68 03 00 00 00 pushq $0x3
41 | 69b: e9 b0 ff ff ff jmpq 650 <.plt>
42 |
43 | 00000000000006a0 :
44 | 6a0: ff 25 2a 09 20 00 jmpq *0x20092a(%rip) # 200fd0
45 | 6a6: 68 04 00 00 00 pushq $0x4
46 | 6ab: e9 a0 ff ff ff jmpq 650 <.plt>
47 |
48 | Disassembly of section .plt.got:
49 |
50 | 00000000000006b0 <__cxa_finalize@plt>:
51 | 6b0: ff 25 42 09 20 00 jmpq *0x200942(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5>
52 | 6b6: 66 90 xchg %ax,%ax
53 |
54 | Disassembly of section .text:
55 |
56 | 00000000000006c0 :
57 | 6c0: 53 push %rbx
58 | 6c1: 48 8d 15 a8 01 00 00 lea 0x1a8(%rip),%rdx # 870
59 | 6c8: 31 c9 xor %ecx,%ecx
60 | 6ca: 31 f6 xor %esi,%esi
61 | 6cc: 48 83 ec 20 sub $0x20,%rsp
62 | 6d0: 48 89 e3 mov %rsp,%rbx
63 | 6d3: 48 89 df mov %rbx,%rdi
64 | 6d6: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
65 | 6dd: 00 00
66 | 6df: 48 89 44 24 18 mov %rax,0x18(%rsp)
67 | 6e4: 31 c0 xor %eax,%eax
68 | 6e6: e8 75 ff ff ff callq 660
69 | 6eb: 85 c0 test %eax,%eax
70 | 6ed: 75 50 jne 73f
71 | 6ef: 48 8d 7b 08 lea 0x8(%rbx),%rdi
72 | 6f3: 48 8d 15 76 01 00 00 lea 0x176(%rip),%rdx # 870
73 | 6fa: 31 c9 xor %ecx,%ecx
74 | 6fc: 31 f6 xor %esi,%esi
75 | 6fe: e8 5d ff ff ff callq 660
76 | 703: 85 c0 test %eax,%eax
77 | 705: 75 38 jne 73f
78 | 707: 48 8b 3c 24 mov (%rsp),%rdi
79 | 70b: 31 f6 xor %esi,%esi
80 | 70d: e8 7e ff ff ff callq 690
81 | 712: 48 8b 7c 24 08 mov 0x8(%rsp),%rdi
82 | 717: 31 f6 xor %esi,%esi
83 | 719: e8 72 ff ff ff callq 690
84 | 71e: 48 8b 15 f3 08 20 00 mov 0x2008f3(%rip),%rdx # 201018
85 | 725: 48 8d 35 d8 01 00 00 lea 0x1d8(%rip),%rsi # 904 <_IO_stdin_used+0x4>
86 | 72c: bf 01 00 00 00 mov $0x1,%edi
87 | 731: 31 c0 xor %eax,%eax
88 | 733: e8 38 ff ff ff callq 670 <__printf_chk@plt>
89 | 738: 31 ff xor %edi,%edi
90 | 73a: e8 61 ff ff ff callq 6a0
91 | 73f: 48 8d 3d c9 01 00 00 lea 0x1c9(%rip),%rdi # 90f <_IO_stdin_used+0xf>
92 | 746: e8 35 ff ff ff callq 680
93 | 74b: bf 01 00 00 00 mov $0x1,%edi
94 | 750: e8 4b ff ff ff callq 6a0
95 | 755: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
96 | 75c: 00 00 00
97 | 75f: 90 nop
98 |
99 | 0000000000000760 <_start>:
100 | 760: 31 ed xor %ebp,%ebp
101 | 762: 49 89 d1 mov %rdx,%r9
102 | 765: 5e pop %rsi
103 | 766: 48 89 e2 mov %rsp,%rdx
104 | 769: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
105 | 76d: 50 push %rax
106 | 76e: 54 push %rsp
107 | 76f: 4c 8d 05 7a 01 00 00 lea 0x17a(%rip),%r8 # 8f0 <__libc_csu_fini>
108 | 776: 48 8d 0d 03 01 00 00 lea 0x103(%rip),%rcx # 880 <__libc_csu_init>
109 | 77d: 48 8d 3d 3c ff ff ff lea -0xc4(%rip),%rdi # 6c0
110 | 784: ff 15 56 08 20 00 callq *0x200856(%rip) # 200fe0 <__libc_start_main@GLIBC_2.2.5>
111 | 78a: f4 hlt
112 | 78b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
113 |
114 | 0000000000000790 :
115 | 790: 48 8d 3d 79 08 20 00 lea 0x200879(%rip),%rdi # 201010 <__TMC_END__>
116 | 797: 55 push %rbp
117 | 798: 48 8d 05 71 08 20 00 lea 0x200871(%rip),%rax # 201010 <__TMC_END__>
118 | 79f: 48 39 f8 cmp %rdi,%rax
119 | 7a2: 48 89 e5 mov %rsp,%rbp
120 | 7a5: 74 19 je 7c0
121 | 7a7: 48 8b 05 2a 08 20 00 mov 0x20082a(%rip),%rax # 200fd8 <_ITM_deregisterTMCloneTable>
122 | 7ae: 48 85 c0 test %rax,%rax
123 | 7b1: 74 0d je 7c0
124 | 7b3: 5d pop %rbp
125 | 7b4: ff e0 jmpq *%rax
126 | 7b6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
127 | 7bd: 00 00 00
128 | 7c0: 5d pop %rbp
129 | 7c1: c3 retq
130 | 7c2: 0f 1f 40 00 nopl 0x0(%rax)
131 | 7c6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
132 | 7cd: 00 00 00
133 |
134 | 00000000000007d0 :
135 | 7d0: 48 8d 3d 39 08 20 00 lea 0x200839(%rip),%rdi # 201010 <__TMC_END__>
136 | 7d7: 48 8d 35 32 08 20 00 lea 0x200832(%rip),%rsi # 201010 <__TMC_END__>
137 | 7de: 55 push %rbp
138 | 7df: 48 29 fe sub %rdi,%rsi
139 | 7e2: 48 89 e5 mov %rsp,%rbp
140 | 7e5: 48 c1 fe 03 sar $0x3,%rsi
141 | 7e9: 48 89 f0 mov %rsi,%rax
142 | 7ec: 48 c1 e8 3f shr $0x3f,%rax
143 | 7f0: 48 01 c6 add %rax,%rsi
144 | 7f3: 48 d1 fe sar %rsi
145 | 7f6: 74 18 je 810
146 | 7f8: 48 8b 05 f1 07 20 00 mov 0x2007f1(%rip),%rax # 200ff0 <_ITM_registerTMCloneTable>
147 | 7ff: 48 85 c0 test %rax,%rax
148 | 802: 74 0c je 810
149 | 804: 5d pop %rbp
150 | 805: ff e0 jmpq *%rax
151 | 807: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
152 | 80e: 00 00
153 | 810: 5d pop %rbp
154 | 811: c3 retq
155 | 812: 0f 1f 40 00 nopl 0x0(%rax)
156 | 816: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
157 | 81d: 00 00 00
158 |
159 | 0000000000000820 <__do_global_dtors_aux>:
160 | 820: 80 3d e9 07 20 00 00 cmpb $0x0,0x2007e9(%rip) # 201010 <__TMC_END__>
161 | 827: 75 2f jne 858 <__do_global_dtors_aux+0x38>
162 | 829: 48 83 3d c7 07 20 00 cmpq $0x0,0x2007c7(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5>
163 | 830: 00
164 | 831: 55 push %rbp
165 | 832: 48 89 e5 mov %rsp,%rbp
166 | 835: 74 0c je 843 <__do_global_dtors_aux+0x23>
167 | 837: 48 8b 3d ca 07 20 00 mov 0x2007ca(%rip),%rdi # 201008 <__dso_handle>
168 | 83e: e8 6d fe ff ff callq 6b0 <__cxa_finalize@plt>
169 | 843: e8 48 ff ff ff callq 790
170 | 848: c6 05 c1 07 20 00 01 movb $0x1,0x2007c1(%rip) # 201010 <__TMC_END__>
171 | 84f: 5d pop %rbp
172 | 850: c3 retq
173 | 851: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
174 | 858: f3 c3 repz retq
175 | 85a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
176 |
177 | 0000000000000860 :
178 | 860: 55 push %rbp
179 | 861: 48 89 e5 mov %rsp,%rbp
180 | 864: 5d pop %rbp
181 | 865: e9 66 ff ff ff jmpq 7d0
182 | 86a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
183 |
184 | 0000000000000870 :
185 | 870: 48 81 05 9d 07 20 00 addq $0x5f5e100,0x20079d(%rip) # 201018
186 | 877: 00 e1 f5 05
187 | 87b: c3 retq
188 | 87c: 0f 1f 40 00 nopl 0x0(%rax)
189 |
190 | 0000000000000880 <__libc_csu_init>:
191 | 880: 41 57 push %r15
192 | 882: 41 56 push %r14
193 | 884: 49 89 d7 mov %rdx,%r15
194 | 887: 41 55 push %r13
195 | 889: 41 54 push %r12
196 | 88b: 4c 8d 25 f6 04 20 00 lea 0x2004f6(%rip),%r12 # 200d88 <__frame_dummy_init_array_entry>
197 | 892: 55 push %rbp
198 | 893: 48 8d 2d f6 04 20 00 lea 0x2004f6(%rip),%rbp # 200d90 <__init_array_end>
199 | 89a: 53 push %rbx
200 | 89b: 41 89 fd mov %edi,%r13d
201 | 89e: 49 89 f6 mov %rsi,%r14
202 | 8a1: 4c 29 e5 sub %r12,%rbp
203 | 8a4: 48 83 ec 08 sub $0x8,%rsp
204 | 8a8: 48 c1 fd 03 sar $0x3,%rbp
205 | 8ac: e8 7f fd ff ff callq 630 <_init>
206 | 8b1: 48 85 ed test %rbp,%rbp
207 | 8b4: 74 20 je 8d6 <__libc_csu_init+0x56>
208 | 8b6: 31 db xor %ebx,%ebx
209 | 8b8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
210 | 8bf: 00
211 | 8c0: 4c 89 fa mov %r15,%rdx
212 | 8c3: 4c 89 f6 mov %r14,%rsi
213 | 8c6: 44 89 ef mov %r13d,%edi
214 | 8c9: 41 ff 14 dc callq *(%r12,%rbx,8)
215 | 8cd: 48 83 c3 01 add $0x1,%rbx
216 | 8d1: 48 39 dd cmp %rbx,%rbp
217 | 8d4: 75 ea jne 8c0 <__libc_csu_init+0x40>
218 | 8d6: 48 83 c4 08 add $0x8,%rsp
219 | 8da: 5b pop %rbx
220 | 8db: 5d pop %rbp
221 | 8dc: 41 5c pop %r12
222 | 8de: 41 5d pop %r13
223 | 8e0: 41 5e pop %r14
224 | 8e2: 41 5f pop %r15
225 | 8e4: c3 retq
226 | 8e5: 90 nop
227 | 8e6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
228 | 8ed: 00 00 00
229 |
230 | 00000000000008f0 <__libc_csu_fini>:
231 | 8f0: f3 c3 repz retq
232 |
233 | Disassembly of section .fini:
234 |
235 | 00000000000008f4 <_fini>:
236 | 8f4: 48 83 ec 08 sub $0x8,%rsp
237 | 8f8: 48 83 c4 08 add $0x8,%rsp
238 | 8fc: c3 retq
239 |
--------------------------------------------------------------------------------
/CodeInSlides/chapter4/Problems-CompilerOptimization.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define n 100000000
9 | long sum = 0;
10 |
11 | void* do_sum(void* args) {
12 | for (int i = 0; i < n; i++) sum++;
13 | }
14 |
15 | int main(int argc, char *argv[])
16 | {
17 | pthread_t th[2];
18 | for(int i=0;i<2;i++)
19 | {
20 | if(pthread_create(&th[i], NULL, do_sum, NULL)!=0)
21 | {
22 | perror("pthread_create failed");
23 | exit(1);
24 | }
25 | }
26 | for(int i=0;i<2;i++)
27 | pthread_join(th[i], NULL);
28 |
29 | printf("sum = %ld\n", sum);
30 | exit(0);
31 | }
--------------------------------------------------------------------------------
/CodeInSlides/chapter4/Statistics_for_x&y.py:
--------------------------------------------------------------------------------
1 | import argparse
2 |
3 |
4 | default_input_path = './test.log'
5 |
6 |
7 |
8 | def parse_args():
9 | parser = argparse.ArgumentParser(description='Statistics for x&y of one file')
10 | parser.add_argument( '-i', '--input', type=str, default=default_input_path,
11 | help='The input file for testing. Default: ./test.log')
12 |
13 | args = parser.parse_args()
14 | return args
15 |
16 |
17 | def main():
18 | args = parse_args()
19 | with open(args.input, 'r', encoding='utf-8') as file:
20 | lines = file.read()
21 |
22 | lines = lines.replace('\r','').replace('\n\n', '\n').split('\n')[:-1]
23 | # print(lines)
24 | lines_number = len(lines)
25 | print('totally read %d lines.' % lines_number)
26 |
27 | judge_table = {}
28 | judge_table['x=0'] = 0
29 | judge_table['x=1'] = 2
30 | judge_table['y=0'] = 0
31 | judge_table['y=1'] = 1
32 | x_flag = False
33 | y_flag = False
34 | result_table = ['x=0, y=0', 'x=0, y=1', 'x=1, y=0', 'x=1, y=1', 'invalid']
35 | result_count = [0, 0, 0, 0, 0]
36 | correct_count = 0
37 |
38 |
39 | current_line_index = 0
40 | while current_line_index < lines_number:
41 | x_flag = False
42 | y_flag = False
43 | result_type = 0
44 | for index_tail in range(2):
45 | line_invalid_flag = False
46 | tmp_line_index = current_line_index + index_tail
47 | tmp_line = lines[tmp_line_index]
48 | # print(tmp_line)
49 | if tmp_line == 'x=0' or tmp_line == 'x=1':
50 | x_flag = True
51 | elif tmp_line == 'y=0' or tmp_line == 'y=1':
52 | y_flag = True
53 | else:
54 | line_invalid_flag = True
55 | if not line_invalid_flag:
56 | result_type = result_type + judge_table[tmp_line]
57 |
58 | if not(x_flag and y_flag):
59 | result_type = 4
60 | else:
61 | correct_count += 1
62 | result_count[result_type] += 1
63 |
64 | current_line_index = current_line_index + 2
65 |
66 | for type_index in range(4):
67 | print('Type: {}:\n In total {} case(s). {}%'.format(result_table[type_index], result_count[type_index], result_count[type_index]*100 / correct_count ) )
68 | print('Type: {}:\n In total {} case(s).'.format(result_table[4], result_count[4]) )
69 | pass
70 |
71 |
72 |
73 | if __name__ == '__main__':
74 | main()
75 | pass
--------------------------------------------------------------------------------
/CodeInSlides/chapter4/testUrl.in:
--------------------------------------------------------------------------------
1 | https://www.baidu.com/
2 | https://www.sina.com.cn/
3 | https://www.163.com/
4 | https://www.sohu.com/
5 | https://www.taobao.com/
6 | https://www.jd.com/
7 |
--------------------------------------------------------------------------------
/CodeInSlides/chapter5/Makefile:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2010 Benoit Sigoure
2 | #
3 | # This program is free software: you can redistribute it and/or modify
4 | # it under the terms of the GNU General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version.
7 | #
8 | # This program is distributed in the hope that it will be useful,
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | # GNU General Public License for more details.
12 | #
13 | # You should have received a copy of the GNU General Public License
14 | # along with this program. If not, see .
15 |
16 | CC = gcc
17 | CFLAGS = -O2 -pthread
18 |
19 | # the build target executable:
20 | TARGETS = Measure-ALU Measure-ALU-broken Measure-ALU-broken-simplified Measure-mutex-syscall Measure-mutex-CTXswitch\
21 | PrintToMonitor
22 |
23 | all: $(TARGETS)
24 |
25 | clean:
26 | $(RM) $(TARGETS)
27 |
28 |
--------------------------------------------------------------------------------
/CodeInSlides/chapter5/Measure-ALU-broken-simplified-O1.s:
--------------------------------------------------------------------------------
1 |
2 | Measure-ALU-broken-simplified: file format elf64-x86-64
3 |
4 |
5 | Disassembly of section .init:
6 |
7 | 00000000000004b8 <_init>:
8 | 4b8: 48 83 ec 08 sub $0x8,%rsp
9 | 4bc: 48 8b 05 25 0b 20 00 mov 0x200b25(%rip),%rax # 200fe8 <__gmon_start__>
10 | 4c3: 48 85 c0 test %rax,%rax
11 | 4c6: 74 02 je 4ca <_init+0x12>
12 | 4c8: ff d0 callq *%rax
13 | 4ca: 48 83 c4 08 add $0x8,%rsp
14 | 4ce: c3 retq
15 |
16 | Disassembly of section .plt:
17 |
18 | 00000000000004d0 <.plt>:
19 | 4d0: ff 35 f2 0a 20 00 pushq 0x200af2(%rip) # 200fc8 <_GLOBAL_OFFSET_TABLE_+0x8>
20 | 4d6: ff 25 f4 0a 20 00 jmpq *0x200af4(%rip) # 200fd0 <_GLOBAL_OFFSET_TABLE_+0x10>
21 | 4dc: 0f 1f 40 00 nopl 0x0(%rax)
22 |
23 | Disassembly of section .plt.got:
24 |
25 | 00000000000004e0 <__cxa_finalize@plt>:
26 | 4e0: ff 25 12 0b 20 00 jmpq *0x200b12(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5>
27 | 4e6: 66 90 xchg %ax,%ax
28 |
29 | Disassembly of section .text:
30 |
31 | 00000000000004f0 <_start>:
32 | 4f0: 31 ed xor %ebp,%ebp
33 | 4f2: 49 89 d1 mov %rdx,%r9
34 | 4f5: 5e pop %rsi
35 | 4f6: 48 89 e2 mov %rsp,%rdx
36 | 4f9: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
37 | 4fd: 50 push %rax
38 | 4fe: 54 push %rsp
39 | 4ff: 4c 8d 05 aa 01 00 00 lea 0x1aa(%rip),%r8 # 6b0 <__libc_csu_fini>
40 | 506: 48 8d 0d 33 01 00 00 lea 0x133(%rip),%rcx # 640 <__libc_csu_init>
41 | 50d: 48 8d 3d e6 00 00 00 lea 0xe6(%rip),%rdi # 5fa
42 | 514: ff 15 c6 0a 20 00 callq *0x200ac6(%rip) # 200fe0 <__libc_start_main@GLIBC_2.2.5>
43 | 51a: f4 hlt
44 | 51b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
45 |
46 | 0000000000000520 :
47 | 520: 48 8d 3d e9 0a 20 00 lea 0x200ae9(%rip),%rdi # 201010 <__TMC_END__>
48 | 527: 55 push %rbp
49 | 528: 48 8d 05 e1 0a 20 00 lea 0x200ae1(%rip),%rax # 201010 <__TMC_END__>
50 | 52f: 48 39 f8 cmp %rdi,%rax
51 | 532: 48 89 e5 mov %rsp,%rbp
52 | 535: 74 19 je 550
53 | 537: 48 8b 05 9a 0a 20 00 mov 0x200a9a(%rip),%rax # 200fd8 <_ITM_deregisterTMCloneTable>
54 | 53e: 48 85 c0 test %rax,%rax
55 | 541: 74 0d je 550
56 | 543: 5d pop %rbp
57 | 544: ff e0 jmpq *%rax
58 | 546: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
59 | 54d: 00 00 00
60 | 550: 5d pop %rbp
61 | 551: c3 retq
62 | 552: 0f 1f 40 00 nopl 0x0(%rax)
63 | 556: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
64 | 55d: 00 00 00
65 |
66 | 0000000000000560 :
67 | 560: 48 8d 3d a9 0a 20 00 lea 0x200aa9(%rip),%rdi # 201010 <__TMC_END__>
68 | 567: 48 8d 35 a2 0a 20 00 lea 0x200aa2(%rip),%rsi # 201010 <__TMC_END__>
69 | 56e: 55 push %rbp
70 | 56f: 48 29 fe sub %rdi,%rsi
71 | 572: 48 89 e5 mov %rsp,%rbp
72 | 575: 48 c1 fe 03 sar $0x3,%rsi
73 | 579: 48 89 f0 mov %rsi,%rax
74 | 57c: 48 c1 e8 3f shr $0x3f,%rax
75 | 580: 48 01 c6 add %rax,%rsi
76 | 583: 48 d1 fe sar %rsi
77 | 586: 74 18 je 5a0
78 | 588: 48 8b 05 61 0a 20 00 mov 0x200a61(%rip),%rax # 200ff0 <_ITM_registerTMCloneTable>
79 | 58f: 48 85 c0 test %rax,%rax
80 | 592: 74 0c je 5a0
81 | 594: 5d pop %rbp
82 | 595: ff e0 jmpq *%rax
83 | 597: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
84 | 59e: 00 00
85 | 5a0: 5d pop %rbp
86 | 5a1: c3 retq
87 | 5a2: 0f 1f 40 00 nopl 0x0(%rax)
88 | 5a6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
89 | 5ad: 00 00 00
90 |
91 | 00000000000005b0 <__do_global_dtors_aux>:
92 | 5b0: 80 3d 59 0a 20 00 00 cmpb $0x0,0x200a59(%rip) # 201010 <__TMC_END__>
93 | 5b7: 75 2f jne 5e8 <__do_global_dtors_aux+0x38>
94 | 5b9: 48 83 3d 37 0a 20 00 cmpq $0x0,0x200a37(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5>
95 | 5c0: 00
96 | 5c1: 55 push %rbp
97 | 5c2: 48 89 e5 mov %rsp,%rbp
98 | 5c5: 74 0c je 5d3 <__do_global_dtors_aux+0x23>
99 | 5c7: 48 8b 3d 3a 0a 20 00 mov 0x200a3a(%rip),%rdi # 201008 <__dso_handle>
100 | 5ce: e8 0d ff ff ff callq 4e0 <__cxa_finalize@plt>
101 | 5d3: e8 48 ff ff ff callq 520
102 | 5d8: c6 05 31 0a 20 00 01 movb $0x1,0x200a31(%rip) # 201010 <__TMC_END__>
103 | 5df: 5d pop %rbp
104 | 5e0: c3 retq
105 | 5e1: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
106 | 5e8: f3 c3 repz retq
107 | 5ea: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
108 |
109 | 00000000000005f0 :
110 | 5f0: 55 push %rbp
111 | 5f1: 48 89 e5 mov %rsp,%rbp
112 | 5f4: 5d pop %rbp
113 | 5f5: e9 66 ff ff ff jmpq 560
114 |
115 | 00000000000005fa :
116 | 5fa: b8 00 ca 9a 3b mov $0x3b9aca00,%eax
117 | 5ff: 83 e8 01 sub $0x1,%eax
118 | 602: 75 fb jne 5ff
119 | 604: b8 00 ca 9a 3b mov $0x3b9aca00,%eax
120 | 609: 83 e8 01 sub $0x1,%eax
121 | 60c: 75 fb jne 609
122 | 60e: b8 00 ca 9a 3b mov $0x3b9aca00,%eax
123 | 613: 83 e8 01 sub $0x1,%eax
124 | 616: 75 fb jne 613
125 | 618: b8 00 ca 9a 3b mov $0x3b9aca00,%eax
126 | 61d: 83 e8 01 sub $0x1,%eax
127 | 620: 75 fb jne 61d
128 | 622: b8 00 ca 9a 3b mov $0x3b9aca00,%eax
129 | 627: 83 e8 01 sub $0x1,%eax
130 | 62a: 75 fb jne 627
131 | 62c: b8 00 00 00 00 mov $0x0,%eax
132 | 631: c3 retq
133 | 632: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
134 | 639: 00 00 00
135 | 63c: 0f 1f 40 00 nopl 0x0(%rax)
136 |
137 | 0000000000000640 <__libc_csu_init>:
138 | 640: 41 57 push %r15
139 | 642: 41 56 push %r14
140 | 644: 49 89 d7 mov %rdx,%r15
141 | 647: 41 55 push %r13
142 | 649: 41 54 push %r12
143 | 64b: 4c 8d 25 9e 07 20 00 lea 0x20079e(%rip),%r12 # 200df0 <__frame_dummy_init_array_entry>
144 | 652: 55 push %rbp
145 | 653: 48 8d 2d 9e 07 20 00 lea 0x20079e(%rip),%rbp # 200df8 <__init_array_end>
146 | 65a: 53 push %rbx
147 | 65b: 41 89 fd mov %edi,%r13d
148 | 65e: 49 89 f6 mov %rsi,%r14
149 | 661: 4c 29 e5 sub %r12,%rbp
150 | 664: 48 83 ec 08 sub $0x8,%rsp
151 | 668: 48 c1 fd 03 sar $0x3,%rbp
152 | 66c: e8 47 fe ff ff callq 4b8 <_init>
153 | 671: 48 85 ed test %rbp,%rbp
154 | 674: 74 20 je 696 <__libc_csu_init+0x56>
155 | 676: 31 db xor %ebx,%ebx
156 | 678: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
157 | 67f: 00
158 | 680: 4c 89 fa mov %r15,%rdx
159 | 683: 4c 89 f6 mov %r14,%rsi
160 | 686: 44 89 ef mov %r13d,%edi
161 | 689: 41 ff 14 dc callq *(%r12,%rbx,8)
162 | 68d: 48 83 c3 01 add $0x1,%rbx
163 | 691: 48 39 dd cmp %rbx,%rbp
164 | 694: 75 ea jne 680 <__libc_csu_init+0x40>
165 | 696: 48 83 c4 08 add $0x8,%rsp
166 | 69a: 5b pop %rbx
167 | 69b: 5d pop %rbp
168 | 69c: 41 5c pop %r12
169 | 69e: 41 5d pop %r13
170 | 6a0: 41 5e pop %r14
171 | 6a2: 41 5f pop %r15
172 | 6a4: c3 retq
173 | 6a5: 90 nop
174 | 6a6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
175 | 6ad: 00 00 00
176 |
177 | 00000000000006b0 <__libc_csu_fini>:
178 | 6b0: f3 c3 repz retq
179 |
180 | Disassembly of section .fini:
181 |
182 | 00000000000006b4 <_fini>:
183 | 6b4: 48 83 ec 08 sub $0x8,%rsp
184 | 6b8: 48 83 c4 08 add $0x8,%rsp
185 | 6bc: c3 retq
186 |
--------------------------------------------------------------------------------
/CodeInSlides/chapter5/Measure-ALU-broken-simplified-O2.s:
--------------------------------------------------------------------------------
1 |
2 | Measure-ALU-broken-simplified: file format elf64-x86-64
3 |
4 |
5 | Disassembly of section .init:
6 |
7 | 00000000000004b8 <_init>:
8 | 4b8: 48 83 ec 08 sub $0x8,%rsp
9 | 4bc: 48 8b 05 25 0b 20 00 mov 0x200b25(%rip),%rax # 200fe8 <__gmon_start__>
10 | 4c3: 48 85 c0 test %rax,%rax
11 | 4c6: 74 02 je 4ca <_init+0x12>
12 | 4c8: ff d0 callq *%rax
13 | 4ca: 48 83 c4 08 add $0x8,%rsp
14 | 4ce: c3 retq
15 |
16 | Disassembly of section .plt:
17 |
18 | 00000000000004d0 <.plt>:
19 | 4d0: ff 35 f2 0a 20 00 pushq 0x200af2(%rip) # 200fc8 <_GLOBAL_OFFSET_TABLE_+0x8>
20 | 4d6: ff 25 f4 0a 20 00 jmpq *0x200af4(%rip) # 200fd0 <_GLOBAL_OFFSET_TABLE_+0x10>
21 | 4dc: 0f 1f 40 00 nopl 0x0(%rax)
22 |
23 | Disassembly of section .plt.got:
24 |
25 | 00000000000004e0 <__cxa_finalize@plt>:
26 | 4e0: ff 25 12 0b 20 00 jmpq *0x200b12(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5>
27 | 4e6: 66 90 xchg %ax,%ax
28 |
29 | Disassembly of section .text:
30 |
31 | 00000000000004f0 :
32 | 4f0: 31 c0 xor %eax,%eax
33 | 4f2: c3 retq
34 | 4f3: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
35 | 4fa: 00 00 00
36 | 4fd: 0f 1f 00 nopl (%rax)
37 |
38 | 0000000000000500 <_start>:
39 | 500: 31 ed xor %ebp,%ebp
40 | 502: 49 89 d1 mov %rdx,%r9
41 | 505: 5e pop %rsi
42 | 506: 48 89 e2 mov %rsp,%rdx
43 | 509: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
44 | 50d: 50 push %rax
45 | 50e: 54 push %rsp
46 | 50f: 4c 8d 05 6a 01 00 00 lea 0x16a(%rip),%r8 # 680 <__libc_csu_fini>
47 | 516: 48 8d 0d f3 00 00 00 lea 0xf3(%rip),%rcx # 610 <__libc_csu_init>
48 | 51d: 48 8d 3d cc ff ff ff lea -0x34(%rip),%rdi # 4f0