1/**
2 * \file
3 * \brief Spinning synchronizations
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#ifndef BOMP_SPIN_H
16#define BOMP_SPIN_H
17
18#include <barrelfish/barrelfish.h>
19/* #include <string.h> */
20#include <omp.h>
21
22/** \brief spinlock */
23typedef volatile unsigned int bomp_lock_t;
24
25static inline void bomp_lock(bomp_lock_t *lock)
26{
27#ifdef __k1om__
28    /* The Xeon Phi does not support pause instruction. we use delay instead
29     * which does the same thing as pause but with a variable amount of delay.
30     * 750 cycles for now.
31     */
32    uint32_t wait = 750;
33    __asm__ __volatile__("0:\n\t"
34                    "cmpq $0, %0\n\t"
35                    "je 1f\n\t"
36                    "delay %1\n\t"
37                    "jmp 0b\n\t"
38                    "1:\n\t"
39                    "lock btsq $0, %0\n\t"
40                    "jc 0b\n\t"
41                    : "+m" (*lock), "=r"(wait) : : "memory", "cc");
42#else
43    __asm__ __volatile__("0:\n\t"
44                    "cmpq $0, %0\n\t"
45                    "je 1f\n\t"
46                    "pause\n\t"
47                    "jmp 0b\n\t"
48                    "1:\n\t"
49                    "lock btsq $0, %0\n\t"
50                    "jc 0b\n\t"
51                    : "+m" (*lock) : : "memory", "cc");
52#endif
53}
54
55static inline void bomp_unlock(bomp_lock_t *lock)
56{
57    *lock = 0;
58}
59
60static inline void bomp_lock_init(bomp_lock_t *lock)
61{
62    /* nop */
63}
64
65struct bomp_barrier
66{
67    unsigned max;
68    volatile unsigned cycle;
69    volatile unsigned counter;
70};
71
72static inline void bomp_barrier_init(struct bomp_barrier *barrier,
73                                     int count)
74{
75    barrier->max = count;
76    barrier->cycle = 0;
77    barrier->counter = 0;
78}
79
80static inline void bomp_clear_barrier(struct bomp_barrier *barrier)
81{
82    /* nop */
83}
84
85static inline void bomp_barrier_wait(struct bomp_barrier *barrier)
86{
87    int cycle = barrier->cycle;
88    if (__sync_fetch_and_add(&barrier->counter, 1) == barrier->max - 1) {
89        barrier->counter = 0;
90        barrier->cycle = !barrier->cycle;
91    } else {
92        uint64_t waitcnt = 0;
93
94        while (cycle == barrier->cycle) {
95            if (waitcnt == 0x400) {
96                waitcnt = 0;
97                thread_yield();
98            }
99            waitcnt++;
100        }
101    }
102}
103
104#endif /* BOMP_SPIN_H */
105