Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
30633f23
Commit
30633f23
authored
Jun 10, 2014
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add safepoints, which for now are for GIL checking
Once the GRWL is added, will also be for GC safepoints.
parent
d8c0bbd8
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
60 additions
and
6 deletions
+60
-6
src/codegen/irgen.cpp
src/codegen/irgen.cpp
+13
-0
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+4
-0
src/codegen/irgen/irgenerator.h
src/codegen/irgen/irgenerator.h
+1
-0
src/codegen/opt/inliner.cpp
src/codegen/opt/inliner.cpp
+4
-1
src/codegen/runtime_hooks.cpp
src/codegen/runtime_hooks.cpp
+3
-0
src/codegen/runtime_hooks.h
src/codegen/runtime_hooks.h
+2
-0
src/core/threading.cpp
src/core/threading.cpp
+24
-1
src/core/threading.h
src/core/threading.h
+1
-0
src/runtime/builtin_modules/time.cpp
src/runtime/builtin_modules/time.cpp
+4
-0
test/tests/thread_contention_test.py
test/tests/thread_contention_test.py
+4
-4
No files found.
src/codegen/irgen.cpp
View file @
30633f23
...
...
@@ -564,6 +564,10 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
emitter
->
getBuilder
()
->
SetInsertPoint
(
llvm_entry_blocks
[
source
->
cfg
->
getStartingBlock
()]);
}
generator
->
unpackArguments
(
arg_names
,
cf
->
spec
->
arg_types
);
// Function-entry safepoint:
// TODO might be more efficient to do post-call safepoints?
generator
->
doSafePoint
();
}
else
if
(
entry_descriptor
&&
block
==
entry_descriptor
->
backedge
->
target
)
{
assert
(
block
->
predecessors
.
size
()
>
1
);
assert
(
osr_entry_block
);
...
...
@@ -653,6 +657,15 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
}
}
for
(
CFGBlock
*
predecessor
:
block
->
predecessors
)
{
if
(
predecessor
->
idx
>
block
->
idx
)
{
// Loop safepoint:
// TODO does it matter which side of the backedge these are on?
generator
->
doSafePoint
();
break
;
}
}
generator
->
run
(
block
);
const
IRGenerator
::
EndingState
&
ending_st
=
generator
->
getEndingSymbolTable
();
...
...
src/codegen/irgen/irgenerator.cpp
View file @
30633f23
...
...
@@ -2092,6 +2092,10 @@ public:
doStmt
(
block
->
body
[
i
],
exc_info
);
}
}
void
doSafePoint
()
override
{
emitter
.
getBuilder
()
->
CreateCall
(
g
.
funcs
.
allowGLReadPreemption
);
}
};
IRGenerator
*
createIRGenerator
(
IRGenState
*
irstate
,
std
::
unordered_map
<
CFGBlock
*
,
llvm
::
BasicBlock
*>&
entry_blocks
,
...
...
src/codegen/irgen/irgenerator.h
View file @
30633f23
...
...
@@ -189,6 +189,7 @@ public:
virtual
void
copySymbolsFrom
(
SymbolTable
*
st
)
=
0
;
virtual
void
run
(
const
CFGBlock
*
block
)
=
0
;
virtual
EndingState
getEndingSymbolTable
()
=
0
;
virtual
void
doSafePoint
()
=
0
;
};
class
IREmitter
;
...
...
src/codegen/opt/inliner.cpp
View file @
30633f23
...
...
@@ -56,7 +56,10 @@ public:
}
else
if
(
llvm
::
GlobalVariable
*
gv
=
llvm
::
dyn_cast
<
llvm
::
GlobalVariable
>
(
v
))
{
// llvm::errs() << " is gv\n";
assert
(
gv
->
getLinkage
()
!=
llvm
::
GlobalVariable
::
PrivateLinkage
);
r
=
new_module
->
getOrInsertGlobal
(
gv
->
getName
(),
gv
->
getType
()
->
getElementType
());
llvm
::
GlobalVariable
*
new_gv
=
llvm
::
cast
<
llvm
::
GlobalVariable
>
(
new_module
->
getOrInsertGlobal
(
gv
->
getName
(),
gv
->
getType
()
->
getElementType
()));
RELEASE_ASSERT
(
!
gv
->
isThreadLocal
(),
"I don't think MCJIT supports thread-local variables yet"
);
new_gv
->
setThreadLocalMode
(
gv
->
getThreadLocalMode
());
r
=
new_gv
;
}
else
if
(
llvm
::
GlobalAlias
*
alias
=
llvm
::
dyn_cast
<
llvm
::
GlobalAlias
>
(
v
))
{
#if LLVMREV < 209040
llvm
::
Value
*
addressee
=
llvm
::
cast
<
llvm
::
Constant
>
(
materializeValueFor
(
alias
->
getAliasedGlobal
()));
...
...
src/codegen/runtime_hooks.cpp
View file @
30633f23
...
...
@@ -30,6 +30,7 @@
#include "codegen/irgen.h"
#include "codegen/irgen/hooks.h"
#include "codegen/irgen/util.h"
#include "core/threading.h"
#include "core/types.h"
#include "runtime/float.h"
#include "runtime/gc_runtime.h"
...
...
@@ -143,6 +144,8 @@ void initGlobalFuncs(GlobalState& g) {
g
.
funcs
.
malloc
=
addFunc
((
void
*
)
malloc
,
g
.
i8_ptr
,
g
.
i64
);
g
.
funcs
.
free
=
addFunc
((
void
*
)
free
,
g
.
void_
,
g
.
i8_ptr
);
g
.
funcs
.
allowGLReadPreemption
=
addFunc
((
void
*
)
threading
::
allowGLReadPreemption
,
g
.
void_
);
GET
(
boxCLFunction
);
GET
(
unboxCLFunction
);
GET
(
createUserClass
);
...
...
src/codegen/runtime_hooks.h
View file @
30633f23
...
...
@@ -22,6 +22,8 @@ class Value;
namespace
pyston
{
struct
GlobalFuncs
{
llvm
::
Value
*
allowGLReadPreemption
;
llvm
::
Value
*
printf
,
*
my_assert
,
*
malloc
,
*
free
;
llvm
::
Value
*
boxInt
,
*
unboxInt
,
*
boxFloat
,
*
unboxFloat
,
*
boxStringPtr
,
*
boxCLFunction
,
*
unboxCLFunction
,
...
...
src/core/threading.cpp
View file @
30633f23
...
...
@@ -147,7 +147,8 @@ static void* _thread_start(void* _arg) {
pthread_attr_t
thread_attrs
;
int
code
=
pthread_getattr_np
(
current_thread
,
&
thread_attrs
);
RELEASE_ASSERT
(
code
==
0
,
""
);
if
(
code
)
err
(
1
,
NULL
);
void
*
stack_start
;
size_t
stack_size
;
...
...
@@ -275,13 +276,35 @@ void registerMainThread() {
#if THREADING_USE_GIL
static
pthread_mutex_t
gil
=
PTHREAD_MUTEX_INITIALIZER
;
static
std
::
atomic
<
int
>
threads_waiting_on_gil
(
0
);
void
acquireGLWrite
()
{
threads_waiting_on_gil
++
;
pthread_mutex_lock
(
&
gil
);
threads_waiting_on_gil
--
;
}
void
releaseGLWrite
()
{
pthread_mutex_unlock
(
&
gil
);
}
#define GIL_CHECK_INTERVAL 1000
// Note: this doesn't need to be an atomic, since it should
// only be accessed by the thread that holds the gil:
int
gil_check_count
=
0
;
void
allowGLReadPreemption
()
{
// Can read this variable with relaxed consistency; not a huge problem if
// we accidentally read a stale value for a little while.
if
(
!
threads_waiting_on_gil
.
load
(
std
::
memory_order_relaxed
))
return
;
gil_check_count
++
;
if
(
gil_check_count
>=
GIL_CHECK_INTERVAL
)
{
gil_check_count
=
0
;
releaseGLRead
();
acquireGLRead
();
}
}
#endif
}
// namespace threading
...
...
src/core/threading.h
View file @
30633f23
...
...
@@ -62,6 +62,7 @@ void acquireGLRead();
void
releaseGLRead
();
void
acquireGLWrite
();
void
releaseGLWrite
();
void
allowGLReadPreemption
();
// Note: promoteGL is free to drop the lock and then reacquire
void
promoteGL
();
void
demoteGL
();
...
...
src/runtime/builtin_modules/time.cpp
View file @
30633f23
...
...
@@ -14,6 +14,7 @@
#include <cmath>
#include <ctime>
#include <err.h>
#include <sys/time.h>
#include "codegen/compvars.h"
...
...
@@ -55,6 +56,9 @@ Box* timeSleep(Box* arg) {
{
threading
::
GLReadReleaseRegion
_allow_threads
;
code
=
nanosleep
(
&
req
,
NULL
);
if
(
code
)
err
(
1
,
NULL
);
}
RELEASE_ASSERT
(
code
==
0
,
"%d"
,
code
);
...
...
test/tests/thread_contention_test.py
View file @
30633f23
from
thread
import
start_new_thread
import
time
work
=
[]
done
=
[]
...
...
@@ -12,13 +11,14 @@ def run(num):
print
"starting!"
nthreads
=
2
N
=
100000
for
i
in
xrange
(
nthreads
):
work
.
append
(
1000000
)
work
.
append
(
N
)
for
i
in
xrange
(
nthreads
):
t
=
start_new_thread
(
run
,
(
1000000
,))
t
=
start_new_thread
(
run
,
(
N
,))
while
len
(
done
)
<
nthreads
:
time
.
sleep
(
0
)
pass
# print work
assert
sum
(
work
)
==
0
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment