-
Notifications
You must be signed in to change notification settings - Fork 2
/
increment_thread_htm_signal.c
144 lines (118 loc) · 4.58 KB
/
increment_thread_htm_signal.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
* This code aims to be an example on:
*
* 1. Two level stringinification;
* 2. How to use stringinified value in a comparison instruction resided a inline asm;
* 2. How to call a function from inside a inline asm on PPC64;
* 3. Verify the effact of a SIGTRAP.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <pthread.h>
#define MAX_COUNTER 0x100
#define MAX_THREAD 0x1
// Two levels of expansion to get a macro value stringinified.
#define STR(x) STR1(x)
#define STR1(x) #x
static int state[MAX_COUNTER];
static int counter;
static int* counter_ptr = &counter;
pthread_t thread[MAX_THREAD];
void increment_counter(void)
{
// state[(*counter_ptr)++] = 1;
// *counter_ptr = 0;
}
void failure_msg(void)
{
printf(".\n");
}
void* thread_main_routine(void *arg)
{
// while (counter < MAX_COUNTER)
// increment_counter();
// + HTM (Hardware Transactional Memory) =
/*
asm(
" mflr 14 \n\t"
" mr 16, %0 \n\t" // Save counter_ptr in r16. Maybe use stack instead, since r15 is also volatile?
"increment: tbegin. \n\t"
" beq failure \n\t"
" lwa 15, 0(16) \n\t" // Copy counter to r15.
" cmpwi 15, " STR(MAX_COUNTER) "\n\t"
" blt continue \n\t"
" li 17, 0xBE \n\t" // User-provided 8-bit tabort code. 0xBE means counter reached MAX_COUNTER.
" tabort. 17 \n\t"
"continue: bl increment_counter \n\t"
" tend. \n\t"
" b increment \n\t"
"failure: mfspr 15, 130 \n\t"
" li 17, 32 \n\t"
" srd 15, 15, 17 \n\t"
" addis 17, 0 , 0xBE00 \n\t"
" addi 17, 17, 0x0001 \n\t"
" cmpw 15, 17 \n\t"
" bnel failure_msg \n\t"
" cmpw 15, 17 \n\t" // Can it be removed?
" bne increment \n\t"
" mtlr 14 \n\t"
: // no output
: "r"(counter_ptr)
: "r14","r15", "r16", "r17"
);
*/
return NULL;
}
int main(void)
{
counter = 0; // Just init the counter.
//for (int i = 0; i < MAX_COUNTER; i++)
// state[i] = 0;
/*
for (int i = 0; i < MAX_THREAD; i++)
pthread_create(&thread[i], NULL, &thread_main_routine, NULL);
for (int i = 0; i < MAX_THREAD; i++)
pthread_join(thread[i], NULL);
for (int i = 0; i < MAX_COUNTER; i++)
printf("%d ", state[i]);
*/
asm(
" mflr 14 \n\t"
" mr 16, %0 \n\t" // Save counter_ptr in r16. Maybe use stack instead, since r15 is also volatile?
"increment: tbegin. \n\t"
" beq exit \n\t"
" lwa 15, 0(16) \n\t" // Copy counter to r15.
" cmpwi 15, " STR(MAX_COUNTER) "\n\t"
" blt continue \n\t"
" tcheck 2 \n\t"
" b .-0x4 \n\t"
" li 17, 0xBE \n\t" // User-provided 8-bit tabort code. 0xBE means counter reached MAX_COUNTER.
" tabort. 17 \n\t"
"continue: bl increment_counter \n\t"
" tend. \n\t"
" b increment \n\t"
"failure: mfspr 15, 130 \n\t"
" li 17, 32 \n\t"
" srd 15, 15, 17 \n\t"
" addis 17, 0 , 0xBE00 \n\t"
" addi 17, 17, 0x0001 \n\t"
" cmpw 15, 17 \n\t"
" bnel failure_msg \n\t"
" cmpw 15, 17 \n\t" // Can it be removed?
" bne increment \n\t"
" mtlr 14 \n\t"
"exit: \n\t"
: // no output
: "r"(counter_ptr)
: "r14","r15", "r16", "r17"
);
uint64_t texasr = __builtin_get_texasr();
uint8_t code = texasr >> 56;
printf("code: 0x%X\n", code);
printf("counter: %d\n", counter);
}
/* References:
[1] https://www.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.genprogc/transactional_memory.htm
*/