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
|
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <errno.h>
#include "runtime.h"
#include "go-assert.h"
void
runtime_initlock(Lock *l)
{
l->key = 0;
if(sem_init(&l->sem, 0, 0) != 0)
runtime_throw("sem_init failed");
}
static uint32
runtime_xadd(uint32 volatile *val, int32 delta)
{
uint32 oval, nval;
for(;;){
oval = *val;
nval = oval + delta;
if(runtime_cas(val, oval, nval))
return nval;
}
}
// noinline so that runtime_lock doesn't have to split the stack.
static void runtime_lock_full(Lock *l) __attribute__ ((noinline));
static void
runtime_lock_full(Lock *l)
{
for(;;){
if(sem_wait(&l->sem) == 0)
return;
if(errno != EINTR)
runtime_throw("sem_wait failed");
}
}
void
runtime_lock(Lock *l)
{
if(m != nil) {
if(m->locks < 0)
runtime_throw("lock count");
m->locks++;
}
if(runtime_xadd(&l->key, 1) > 1) // someone else has it; wait
runtime_lock_full(l);
}
static void runtime_unlock_full(Lock *l) __attribute__ ((noinline));
static void
runtime_unlock_full(Lock *l)
{
if(sem_post(&l->sem) != 0)
runtime_throw("sem_post failed");
}
void
runtime_unlock(Lock *l)
{
if(m != nil) {
m->locks--;
if(m->locks < 0)
runtime_throw("lock count");
}
if(runtime_xadd(&l->key, -1) > 0) // someone else is waiting
runtime_unlock_full(l);
}
void
runtime_destroylock(Lock *l)
{
sem_destroy(&l->sem);
}
#ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4
// For targets which don't have the required sync support. Really
// this should be provided by gcc itself. FIXME.
static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
_Bool
__sync_bool_compare_and_swap_4(uint32*, uint32, uint32)
__attribute__((visibility("hidden")));
_Bool
__sync_bool_compare_and_swap_4(uint32* ptr, uint32 old, uint32 new)
{
int i;
_Bool ret;
i = pthread_mutex_lock(&sync_lock);
__go_assert(i == 0);
if(*ptr != old) {
ret = 0;
} else {
*ptr = new;
ret = 1;
}
i = pthread_mutex_unlock(&sync_lock);
__go_assert(i == 0);
return ret;
}
#endif
|