forked from csimmend/Pipelined_transpose
-
Notifications
You must be signed in to change notification settings - Fork 0
/
threads.c
98 lines (83 loc) · 2 KB
/
threads.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
/*
* This file is part of a small series of tutorial,
* which aims to demonstrate key features of the GASPI
* standard by means of small but expandable examples.
* Conceptually the tutorial follows a MPI course
* developed by EPCC and HLRS.
*
* Contact point for the MPI tutorial:
* Contact point for the GASPI tutorial:
*/
#include <stdlib.h>
#include <omp.h>
#include "assert.h"
#include "mm_pause.h"
/* fetch/add wrapper */
int my_add_and_fetch(volatile int *ptr, int val)
{
#ifdef GCC_EXTENSION
int t = __sync_add_and_fetch(ptr, val);
ASSERT(t >= 0);
return t;
#else
int t;
//#pragma omp atomic capture
#pragma omp critical (add_and_fetch)
{
t = *ptr;
*ptr += val;
}
t += val;
ASSERT(t >= 0);
return t;
#endif
}
int my_fetch_and_add(volatile int *ptr, int val)
{
#ifdef GCC_EXTENSION
int t = __sync_fetch_and_add(ptr, val);
ASSERT(t >= 0);
return t;
#else
int t;
//#pragma omp atomic capture
#pragma omp critical (fetch_and_add)
{
t = *ptr;
*ptr += val;
}
ASSERT(t >= 0);
return t;
#endif
}
int this_is_the_first_thread(void)
{
static volatile int shared_counter = 0;
static int local_next = 0;
#pragma omp threadprivate(local_next)
const int nthreads = omp_get_num_threads(),
first = local_next;
if(nthreads == 1)
return 1;
while(shared_counter < local_next)
_mm_pause();
local_next += nthreads;
return(my_fetch_and_add(&shared_counter,1) == first);
}
int this_is_the_last_thread(void)
{
static volatile int shared_counter = 0;
static int local_next = 0;
#pragma omp threadprivate(local_next)
int const nthreads = omp_get_num_threads();
if(nthreads == 1)
return 1;
while(shared_counter < local_next)
_mm_pause();
local_next += nthreads;
return (my_add_and_fetch(&shared_counter,1) == local_next);
}