Files
swift-mirror/stdlib/private/SwiftPrivatePthreadExtras/PthreadBarriers.swift
Zhuowei Zhang 7c502b6344 Port to Android
This adds an Android target for the stdlib. It is also the first
example of cross-compiling outside of Darwin.

Mailing list discussions:

1. https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151207/000171.html
2. https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000492.html

The Android variant of Swift may be built using the following `build-script`
invocation:

```
$ utils/build-script \
  -R \                                           # Build in ReleaseAssert mode.
  --android \                                    # Build for Android.
  --android-ndk ~/android-ndk-r10e \             # Path to an Android NDK.
  --android-ndk-version 21 \
  --android-icu-uc ~/libicu-android/armeabi-v7a/libicuuc.so \
  --android-icu-uc-include ~/libicu-android/armeabi-v7a/icu/source/common \
  --android-icu-i18n ~/libicu-android/armeabi-v7a/libicui18n.so \
  --android-icu-i18n-include ~/libicu-android/armeabi-v7a/icu/source/i18n/
```

Android builds have the following dependencies, as can be seen in
the build script invocation:

1. An Android NDK of version 21 or greater, available to download
   here: http://developer.android.com/ndk/downloads/index.html.
2. A libicu compatible with android-armv7.
2016-04-12 19:26:21 -04:00

132 lines
3.6 KiB
Swift

//===--- PthreadBarriers.swift --------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
#elseif os(Linux) || os(FreeBSD) || os(Android)
import Glibc
#endif
//
// Implement pthread barriers.
//
// (OS X does not implement them.)
//
public struct _stdlib_pthread_barrierattr_t {
public init() {}
}
public func _stdlib_pthread_barrierattr_init(
_ attr: UnsafeMutablePointer<_stdlib_pthread_barrierattr_t>
) -> CInt {
return 0
}
public func _stdlib_pthread_barrierattr_destroy(
_ attr: UnsafeMutablePointer<_stdlib_pthread_barrierattr_t>
) -> CInt {
return 0
}
public var _stdlib_PTHREAD_BARRIER_SERIAL_THREAD: CInt {
return 1
}
public struct _stdlib_pthread_barrier_t {
var mutex: UnsafeMutablePointer<pthread_mutex_t>? = nil
var cond: UnsafeMutablePointer<pthread_cond_t>? = nil
/// The number of threads to synchronize.
var count: CUnsignedInt = 0
/// The number of threads already waiting on the barrier.
///
/// This shared variable is protected by `mutex`.
var numThreadsWaiting: CUnsignedInt = 0
public init() {}
}
public func _stdlib_pthread_barrier_init(
_ barrier: UnsafeMutablePointer<_stdlib_pthread_barrier_t>,
_ attr: UnsafeMutablePointer<_stdlib_pthread_barrierattr_t>?,
_ count: CUnsignedInt
) -> CInt {
barrier.pointee = _stdlib_pthread_barrier_t()
if count == 0 {
errno = EINVAL
return -1
}
barrier.pointee.mutex = UnsafeMutablePointer(allocatingCapacity: 1)
if pthread_mutex_init(barrier.pointee.mutex!, nil) != 0 {
// FIXME: leaking memory.
return -1
}
barrier.pointee.cond = UnsafeMutablePointer(allocatingCapacity: 1)
if pthread_cond_init(barrier.pointee.cond!, nil) != 0 {
// FIXME: leaking memory, leaking a mutex.
return -1
}
barrier.pointee.count = count
return 0
}
public func _stdlib_pthread_barrier_destroy(
_ barrier: UnsafeMutablePointer<_stdlib_pthread_barrier_t>
) -> CInt {
if pthread_cond_destroy(barrier.pointee.cond!) != 0 {
// FIXME: leaking memory, leaking a mutex.
return -1
}
if pthread_mutex_destroy(barrier.pointee.mutex!) != 0 {
// FIXME: leaking memory.
return -1
}
barrier.pointee.cond!.deinitialize()
barrier.pointee.cond!.deallocateCapacity(1)
barrier.pointee.mutex!.deinitialize()
barrier.pointee.mutex!.deallocateCapacity(1)
return 0
}
public func _stdlib_pthread_barrier_wait(
_ barrier: UnsafeMutablePointer<_stdlib_pthread_barrier_t>
) -> CInt {
if pthread_mutex_lock(barrier.pointee.mutex!) != 0 {
return -1
}
barrier.pointee.numThreadsWaiting += 1
if barrier.pointee.numThreadsWaiting < barrier.pointee.count {
// Put the thread to sleep.
if pthread_cond_wait(barrier.pointee.cond!, barrier.pointee.mutex!) != 0 {
return -1
}
if pthread_mutex_unlock(barrier.pointee.mutex!) != 0 {
return -1
}
return 0
} else {
// Reset thread count.
barrier.pointee.numThreadsWaiting = 0
// Wake up all threads.
if pthread_cond_broadcast(barrier.pointee.cond!) != 0 {
return -1
}
if pthread_mutex_unlock(barrier.pointee.mutex!) != 0 {
return -1
}
return _stdlib_PTHREAD_BARRIER_SERIAL_THREAD
}
}