Merge pull request #306 from compnerd/signed

Attempt to be better with signed conversions
diff --git a/INSTALL.md b/INSTALL.md
index 9940c2c..a426bcf 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -129,9 +129,21 @@
 Typical configuration line for FreeBSD 8.x and 9.x to build libdispatch with
 clang and blocks support:
 
-	sh autogen.sh
-	./configure CC=clang --with-blocks-runtime=/usr/local/lib
-	make check
+    ```
+    cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DWITH_BLOCKS_RUNTIME=/usr/local/lib <path-to-source>
+    ninja
+    ninja test
+    ```
+
+### Building for android
+
+Note that this assumes that you are building on Linux.  It requires that you
+have the android NDK available.  It has been tested against API Level 21.
+
+    ```
+    cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=21 -DCMAKE_ANDROID_NDK=<path to android NDK> <path-to-source>
+    ninja
+    ```
 
 ### Building and installing for Linux
 
@@ -140,7 +152,7 @@
 
 1. The first thing to do is install required packages:
 
-    `sudo apt-get install autoconf libtool pkg-config clang systemtap-sdt-dev libbsd-dev linux-libc-dev`
+    `sudo apt-get install cmake ninja-build clang systemtap-sdt-dev libbsd-dev linux-libc-dev`
 
     Note: compiling libdispatch requires clang 3.8 or better and
 the gold linker. If the default clang on your Ubuntu version is
@@ -148,11 +160,11 @@
 On older Ubuntu releases, you may need to install binutils-gold
 to get the gold linker.
 
-2. Build (as in the general instructions above)
+2. Build
 
     ```
-    sh autogen.sh
-    ./configure
-    make
-    make install
+    cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ <path-to-source>
+    ninja
+    ninja install
     ```
+
diff --git a/src/event/event_epoll.c b/src/event/event_epoll.c
index 5b8fe79..db8626e 100644
--- a/src/event/event_epoll.c
+++ b/src/event/event_epoll.c
@@ -270,7 +270,7 @@
 			if (_dispatch_epoll_update(dmn, events, EPOLL_CTL_MOD) < 0) {
 				dmn = NULL;
 			} else {
-				dmn->dmn_events = events;
+				dmn->dmn_events |= events;
 				dmn->dmn_disarmed_events &= ~events;
 			}
 		}
diff --git a/src/swift/Time.swift b/src/swift/Time.swift
index d7d49c9..b6cd33c 100644
--- a/src/swift/Time.swift
+++ b/src/swift/Time.swift
@@ -2,7 +2,7 @@
 //
 // This source file is part of the Swift.org open source project
 //
-// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2017 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
@@ -78,13 +78,14 @@
 	}
 }
 
-public func <(a: DispatchTime, b: DispatchTime) -> Bool {
-	if a.rawValue == ~0 || b.rawValue == ~0 { return false }
-	return a.rawValue < b.rawValue
-}
+extension DispatchTime {
+	public static func < (a: DispatchTime, b: DispatchTime) -> Bool {
+		return a.rawValue < b.rawValue
+	}
 
-public func ==(a: DispatchTime, b: DispatchTime) -> Bool {
-	return a.rawValue == b.rawValue
+	public static func ==(a: DispatchTime, b: DispatchTime) -> Bool {
+		return a.rawValue == b.rawValue
+	}
 }
 
 public struct DispatchWallTime : Comparable {
@@ -106,19 +107,56 @@
 	}
 }
 
-public func <(a: DispatchWallTime, b: DispatchWallTime) -> Bool {
-	if b.rawValue == ~0 {
-		return a.rawValue != ~0
-	} else if a.rawValue == ~0 {
-		return false
+extension DispatchWallTime {
+	public static func <(a: DispatchWallTime, b: DispatchWallTime) -> Bool {
+		let negativeOne: dispatch_time_t = ~0
+		if b.rawValue == negativeOne {
+			return a.rawValue != negativeOne
+		} else if a.rawValue == negativeOne {
+			return false
+		}
+		return -Int64(bitPattern: a.rawValue) < -Int64(bitPattern: b.rawValue)
 	}
-	return -Int64(bitPattern: a.rawValue) < -Int64(bitPattern: b.rawValue)
+
+	public static func ==(a: DispatchWallTime, b: DispatchWallTime) -> Bool {
+		return a.rawValue == b.rawValue
+	}
 }
 
-public func ==(a: DispatchWallTime, b: DispatchWallTime) -> Bool {
-	return a.rawValue == b.rawValue
+// Returns m1 * m2, clamped to the range [Int64.min, Int64.max].
+// Because of the way this function is used, we can always assume
+// that m2 > 0.
+private func clampedInt64Product(_ m1: Int64, _ m2: Int64) -> Int64 {
+	assert(m2 > 0, "multiplier must be positive")
+	let (result, overflow) = m1.multipliedReportingOverflow(by: m2)
+	if overflow {
+		return m1 > 0 ? Int64.max : Int64.min
+	}
+	return result
 }
 
+// Returns its argument clamped to the range [Int64.min, Int64.max].
+private func toInt64Clamped(_ value: Double) -> Int64 {
+	if value.isNaN { return Int64.max }
+	if value >= Double(Int64.max) { return Int64.max }
+	if value <= Double(Int64.min) { return Int64.min }
+	return Int64(value)
+}
+
+/// Represents a time interval that can be used as an offset from a `DispatchTime`
+/// or `DispatchWallTime`.
+///
+/// For example:
+/// 	let inOneSecond = DispatchTime.now() + DispatchTimeInterval.seconds(1)
+///
+/// If the requested time interval is larger then the internal representation
+/// permits, the result of adding it to a `DispatchTime` or `DispatchWallTime`
+/// is `DispatchTime.distantFuture` and `DispatchWallTime.distantFuture`
+/// respectively. Such time intervals compare as equal:
+///
+/// 	let t1 = DispatchTimeInterval.seconds(Int.max)
+///		let t2 = DispatchTimeInterval.milliseconds(Int.max)
+///		let result = t1 == t2   // true
 public enum DispatchTimeInterval {
 	case seconds(Int)
 	case milliseconds(Int)
@@ -129,9 +167,9 @@
 
 	internal var rawValue: Int64 {
 		switch self {
-		case .seconds(let s): return Int64(s) * Int64(NSEC_PER_SEC)
-		case .milliseconds(let ms): return Int64(ms) * Int64(NSEC_PER_MSEC)
-		case .microseconds(let us): return Int64(us) * Int64(NSEC_PER_USEC)
+		case .seconds(let s): return clampedInt64Product(Int64(s), Int64(NSEC_PER_SEC))
+		case .milliseconds(let ms): return clampedInt64Product(Int64(ms), Int64(NSEC_PER_MSEC))
+		case .microseconds(let us): return clampedInt64Product(Int64(us), Int64(NSEC_PER_USEC))
 		case .nanoseconds(let ns): return Int64(ns)
 		case .never: return Int64.max
 		}
@@ -158,16 +196,12 @@
 }
 
 public func +(time: DispatchTime, seconds: Double) -> DispatchTime {
-	let interval = seconds * Double(NSEC_PER_SEC)
-	let t = CDispatch.dispatch_time(time.rawValue,
-		interval.isInfinite || interval.isNaN ? Int64.max : Int64(interval))
+	let t = CDispatch.dispatch_time(time.rawValue, toInt64Clamped(seconds * Double(NSEC_PER_SEC)));
 	return DispatchTime(rawValue: t)
 }
 
 public func -(time: DispatchTime, seconds: Double) -> DispatchTime {
-	let interval = -seconds * Double(NSEC_PER_SEC)
-	let t = CDispatch.dispatch_time(time.rawValue,
-		interval.isInfinite || interval.isNaN ? Int64.min : Int64(interval))
+	let t = CDispatch.dispatch_time(time.rawValue, toInt64Clamped(-seconds * Double(NSEC_PER_SEC)));
 	return DispatchTime(rawValue: t)
 }
 
@@ -182,15 +216,11 @@
 }
 
 public func +(time: DispatchWallTime, seconds: Double) -> DispatchWallTime {
-	let interval = seconds * Double(NSEC_PER_SEC)
-	let t = CDispatch.dispatch_time(time.rawValue,
-		interval.isInfinite || interval.isNaN ? Int64.max : Int64(interval))
+	let t = CDispatch.dispatch_time(time.rawValue, toInt64Clamped(seconds * Double(NSEC_PER_SEC)));
 	return DispatchWallTime(rawValue: t)
 }
 
 public func -(time: DispatchWallTime, seconds: Double) -> DispatchWallTime {
-	let interval = -seconds * Double(NSEC_PER_SEC)
-	let t = CDispatch.dispatch_time(time.rawValue,
-		interval.isInfinite || interval.isNaN ? Int64.min : Int64(interval))
+	let t = CDispatch.dispatch_time(time.rawValue, toInt64Clamped(-seconds * Double(NSEC_PER_SEC)));
 	return DispatchWallTime(rawValue: t)
 }