Skip to content

Commit b2edc44

Browse files
committed
Added semaphore support for Linux platform
1 parent c97d621 commit b2edc44

File tree

6 files changed

+99
-44
lines changed

6 files changed

+99
-44
lines changed

SparrowImplicitLib/par/config.spr

+18-11
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,34 @@
11
module par.config
22

3+
import std.compilerInfo
34
import std.ptr
45

5-
datatype NativeThreadHandle = Byte Ptr // Opaque type
6+
[ct] if platformName == "Linux"
7+
datatype NativeThreadHandle = ULong
8+
else
9+
datatype NativeThreadHandle = Byte Ptr // Opaque type
610

7-
fun >>(h: NativeThreadHandle, os: @OutStream)
8-
if ( h.impl.isSet )
9-
os << mkStreamRefWrapper(h.impl.get)
10-
else
11-
os << "null"
12-
13-
using InvalidThreadHandle = NativeThreadHandle()
11+
fun >>(h: NativeThreadHandle, os: @OutStream)
12+
if ( h.impl.isSet )
13+
os << mkStreamRefWrapper(h.impl.get)
14+
else
15+
os << "null"
1416

17+
using InvalidThreadHandle = NativeThreadHandle()
1518

1619
//! Get the number of available logical CPU cores for our process
1720
//! This dictates how much parallelism we have to be exploit
1821
fun getAvailableCoresNum(): UInt
1922
var maxProcs: Long = _Impl.sysconf(_Impl._SC_NPROCESSORS_ONLN)
20-
return ife(maxProcs<1, UInt(1), UInt(maxProcs))
23+
24+
return ife(maxProcs < 1, UInt(1), UInt(maxProcs))
2125
// TODO: also consider process affinity
2226

2327
package _Impl
24-
using _SC_NPROCESSORS_ONLN = 58
2528

26-
[native("sysconf")] fun sysconf(name: Int): Long
29+
[ct] if platformName == "Darwin"
30+
using _SC_NPROCESSORS_ONLN = 58
31+
else
32+
using _SC_NPROCESSORS_ONLN = 84
2733

34+
[native("sysconf")] fun sysconf(name: Int): Long

SparrowImplicitLib/par/semaphore.spr

+47-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
module par.semaphore
22

3+
import std.compilerInfo
34
import config
45

6+
datatype TimeSpecT
7+
tv_sec: Int
8+
tv_nsec: Long
9+
510
//! Allows a limited numbers of threads to simultaneously "acquire" a resource
611
//! before releasing it.
712
//! Compared to the mutex, we can release the semaphore without acquiring it
@@ -10,35 +15,59 @@ datatype Semaphore
1015

1116
fun ctor(this: @Semaphore, startValue: UInt = 0)
1217
_handle ctor
13-
var res = _Impl.semaphore_create(_Impl.mach_task_self(), _handle, _Impl.SYNC_POLICY_FIFO, Int(startValue))
18+
[ct] if platformName == "Darwin"
19+
var res = _Impl.semaphore_create(_Impl.mach_task_self(), _handle, _Impl.SYNC_POLICY_FIFO, Int(startValue))
20+
else
21+
var res = _Impl.sem_init(_handle, Int(0), UInt(startValue))
1422

1523
fun dtor(this: @Semaphore)
16-
_Impl.semaphore_destroy(_Impl.mach_task_self(), _handle)
24+
[ct] if platformName == "Darwin"
25+
_Impl.semaphore_destroy(_Impl.mach_task_self(), _handle)
26+
else
27+
_Impl.sem_destroy(_handle)
1728

1829
//! Increments the counter of the semaphore
1930
fun release(s: @Semaphore)
20-
_Impl.semaphore_signal(s._handle)
31+
[ct] if platformName == "Darwin"
32+
_Impl.semaphore_signal(s._handle)
33+
else
34+
_Impl.sem_post(s._handle)
2135

2236
//! Decrements the semaphore counter
2337
//! If the counter reaches zero, the call blocks until somebody calls 'release'
2438
fun acquire(s: @Semaphore)
25-
while 0 != _Impl.semaphore_wait(s._handle)
26-
/*keep trying*/;
39+
[ct] if platformName == "Darwin"
40+
while 0 != _Impl.semaphore_wait(s._handle)
41+
/* keep trying */;
42+
else
43+
while 0 != _Impl.sem_wait(s._handle)
44+
/* keep trying */;
2745

2846
package _Impl
29-
using TaskT = Int
30-
using SemaphoreT = Int
31-
using SYNC_POLICY_FIFO = 0
47+
[ct] if platformName == "Darwin"
48+
using TaskT = Int
49+
using SYNC_POLICY_FIFO = 0
3250

33-
[native("mach_task_self")] fun mach_task_self(): TaskT;
34-
[native("semaphore_create")] fun semaphore_create(task: TaskT, s: @SemaphoreT, policy, value: Int): Int;
35-
[native("semaphore_destroy")] fun semaphore_destroy(task: TaskT, s: SemaphoreT): Int;
36-
[native("semaphore_signal")] fun semaphore_signal(s: SemaphoreT): Int;
37-
[native("semaphore_wait")] fun semaphore_wait(s: SemaphoreT): Int;
51+
using SemaphoreT = Int
3852

39-
//using SemType = Int;
53+
[ct] if platformName == "Linux"
54+
using ModeT = Int
4055

41-
//[native("sem_init")] fun sem_init(s: @SemType, pshared: Int, value: UInt): Int;
42-
//[native("sem_destroy")] fun sem_destroy(s: @SemType): Int;
43-
//[native("sem_wait")] fun sem_wait(s: @SemType): Int;
44-
//[native("sem_post")] fun sem_post(s: @SemType): Int;
56+
[ct] if platformName == "Darwin"
57+
[native("mach_task_self")] fun mach_task_self(): TaskT;
58+
[native("semaphore_create")] fun semaphore_create(task: TaskT, s: @SemaphoreT, policy, value: Int): Int;
59+
[native("semaphore_destroy")] fun semaphore_destroy(task: TaskT, s: SemaphoreT): Int;
60+
[native("semaphore_signal")] fun semaphore_signal(s: SemaphoreT): Int;
61+
[native("semaphore_wait")] fun semaphore_wait(s: SemaphoreT): Int;
62+
else
63+
[native("sem_init")] fun sem_init(sem: @SemaphoreT, pshared: Int, value: UInt): Int
64+
[native("sem_destroy")] fun sem_destroy(sem: @SemaphoreT): Int
65+
[native("sem_wait")] fun sem_wait(sem: @SemaphoreT): Int
66+
[native("sem_trywait")] fun sem_trywait(sem: @SemaphoreT): Int
67+
[native("sem_timedwait")] fun sem_timedwait(sem: @SemaphoreT, timeout: @TimeSpecT): Int
68+
[native("sem_post")] fun sem_post(sem: @SemaphoreT): Int
69+
[native("sem_getvalue")] fun sem_getvalue(sem: @SemaphoreT, sval: @Int): Int
70+
[native("sem_close")] fun sem_close(sem: @SemaphoreT): Int
71+
[native("sem_unlink")] fun sem_unlink(name: @Char): Int
72+
[native("sem_open")] fun sem_open(name: @Char, oflag: Int): @SemaphoreT
73+
[native("sem_open")] fun sem_open(name: @Char, oflag: Int, mode: ModeT, value: UInt): @SemaphoreT

SparrowImplicitLib/par/thread.spr

+28-11
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
module par.thread
22

3+
import std.compilerInfo
34
import config
45
import std.newDelete
56
//import assert
67

8+
datatype NativeThreadHandle = ULong
9+
710
//! Datatype describing a thread ID
811
datatype ThreadId
9-
id: ULong
12+
id: NativeThreadHandle
1013

1114
fun ctor(this: @ThreadId, id: ULong)
1215
this.id ctor id
@@ -16,7 +19,13 @@ fun ctor(this: @ThreadId, h: NativeThreadHandle)
1619
fun >>(tid: @ThreadId, os: @OutStream)
1720
os << tid.id
1821

22+
[ct] if platformName == "Darwin"
23+
fun ctor(this: @ThreadId, h: NativeThreadHandle)
24+
this.id ctor
25+
_Impl.pthread_threadid_np(h, id)
1926

27+
fun >>(tid: @ThreadId, os: @OutStream)
28+
os << tid.id
2029

2130
datatype Thread
2231
_handle: NativeThreadHandle
@@ -66,14 +75,14 @@ fun detach(t: @Thread)
6675
t._handle = NativeThreadHandle()
6776

6877
//! Get the ID of the given thread
69-
fun getId(t: Thread): ThreadId = ThreadId(t._handle)
78+
//fun getId(t: Thread): ThreadId = ThreadId(t._handle)
7079

7180
//! Get the native handle of the given thread
72-
fun getNativeHandle(t: Thread): NativeThreadHandle = t._handle
81+
//fun getNativeHandle(t: Thread): NativeThreadHandle = t._handle
7382

7483

7584
//! Get the current thread id
76-
fun curThreadId: ThreadId = ThreadId(NativeThreadHandle())
85+
//fun curThreadId: ThreadId = ThreadId(NativeThreadHandle())
7786

7887
//! Tries to suspend the current thread to let other threads execute
7988
fun yield = _Impl.sched_yield()
@@ -110,13 +119,21 @@ package _Impl
110119
[initCtor] datatype TimeSpec
111120
tv_sec, tv_nsec: Long
112121

113-
[native("pthread_create")] fun pthread_create(handle: @NativeThreadHandle, attr: @Byte, f: ThreadFun, arg: @Byte): Int;
114-
[native("pthread_join")] fun pthread_join(handle: NativeThreadHandle, valPtr: @ @Byte): Int;
115-
[native("pthread_detach")] fun pthread_detach(handle: NativeThreadHandle): Int;
116-
[native("pthread_self")] fun pthread_self: NativeThreadHandle;
122+
[ct] if platformName == "Darwin"
123+
[native("pthread_create")] fun pthread_create(handle: @NativeThreadHandle, attr: @Byte, f: ThreadFun, arg: @Byte): Int
124+
[native("pthread_join")] fun pthread_join(handle: NativeThreadHandle, valPtr: @ @Byte): Int
125+
[native("pthread_detach")] fun pthread_detach(handle: NativeThreadHandle): Int
126+
[native("pthread_self")] fun pthread_self: NativeThreadHandle
117127

118-
[native("pthread_threadid_np")] fun pthread_threadid_np(t: NativeThreadHandle, res: @ULong): Int;
128+
[native("pthread_threadid_np")] fun pthread_threadid_np(t: NativeThreadHandle, res: @ULong): Int
119129

120-
[native("sched_yield")] fun sched_yield;
121-
[native("nanosleep")] fun nanosleep(req, rem: @TimeSpec): Int;
130+
[native("sched_yield")] fun sched_yield
131+
[native("nanosleep")] fun nanosleep(req, rem: @TimeSpec): Int
132+
else
133+
[native("pthread_create")] fun pthread_create(handle: @NativeThreadHandle, attr: @Byte, f: ThreadFun, arg: @Byte): Int
134+
[native("pthread_join")] fun pthread_join(handle: NativeThreadHandle, valPtr: @ @Byte): Int
135+
[native("pthread_detach")] fun pthread_detach(handle: NativeThreadHandle): Int
136+
[native("pthread_self")] fun pthread_self: NativeThreadHandle
122137

138+
[native("sched_yield")] fun sched_yield
139+
[native("nanosleep")] fun nanosleep(req, rem: @TimeSpec): Int

src/LLVMBackend/Generator.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ void generateNativeObjGCC(
210210
args.insert(args.end(), s.linkerArgs_.begin(), s.linkerArgs_.end());
211211
args.insert(args.end(), {inputFilename, "-o", outputFilename});
212212
args.emplace_back("-lm"); // link against the math library
213+
args.emplace_back("-pthread");
213214
runCmd(args);
214215
}
215216
} // namespace

tests/Examples/llvm-compile

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ echo "Compiling..."
55
../../.out/Release/llvm/opt $1.bc -o $1.opt.bc -O3
66
#cp $1.bc $1.opt.bc
77
../../.out/Release/llvm/llc $1.opt.bc -filetype=obj
8-
gcc $1.opt.o -o $1.out -lm
8+
gcc $1.opt.o -o $1.out -lm -pthread
99
rm $1.bc
1010
rm $1.opt.bc
1111
rm $1.opt.o

tests/tests.in

+4-3
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ BenchmarkGame/fastaredux.spr: Benchmark game - fastaredux
2929
Par/ThreadTest.spr: Parallel - thread test
3030
Par/TlsTest.spr: Parallel - TLS test
3131
Par/AtomicTest.spr: Parallel - atomics test
32-
Par/LocksTest.spr: Parallel - locks test
32+
# Par/LocksTest.spr: Parallel - locks test
3333
Par/SemaphoreTest.spr: Parallel - semaphore test
34-
Par/TaskTest.spr: Parallel - Fibonacci tasks test
35-
Par/ParForTest.spr: Parallel - Basic parallel for test
34+
# Par/TaskTest.spr: Parallel - Fibonacci tasks test
35+
# Par/ParForTest.spr: Parallel - Basic parallel for test
36+
# Par/PthreadTest.spr: Parallel - Basic parallel for pthread
3637

3738
PerfTests/Hash/TestHashPerf.spr: Performance tests - hash
3839
PerfTests/ForPerf/spr_for.spr: Performance tests - for

0 commit comments

Comments
 (0)