Properly use acquired permits in Semaphore

Fixes #1423
diff --git a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt
index 160dcac..6ab377d 100644
--- a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt
+++ b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt
@@ -96,7 +96,7 @@
      * and the maximum number of waiting acquirers cannot be greater than 2^31 in any
      * real application.
      */
-    private val _availablePermits = atomic(permits)
+    private val _availablePermits = atomic(permits - acquiredPermits)
     override val availablePermits: Int get() = max(_availablePermits.value, 0)
 
     // The queue of waiting acquirers is essentially an infinite array based on `SegmentQueue`;
diff --git a/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt b/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt
index dc14a12..b4ff88b 100644
--- a/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt
+++ b/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt
@@ -1,9 +1,6 @@
 package kotlinx.coroutines.sync
 
-import kotlinx.coroutines.TestBase
-import kotlinx.coroutines.cancelAndJoin
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.yield
+import kotlinx.coroutines.*
 import kotlin.test.Test
 import kotlin.test.assertEquals
 import kotlin.test.assertFalse
@@ -140,4 +137,35 @@
         job1.cancel()
         finish(6)
     }
+
+    @Test
+    fun testAcquiredPermits() = runTest {
+        val semaphore = Semaphore(5, acquiredPermits = 4)
+        assertEquals(semaphore.availablePermits, 1)
+        semaphore.acquire()
+        assertEquals(semaphore.availablePermits, 0)
+        assertFalse(semaphore.tryAcquire())
+        semaphore.release()
+        assertEquals(semaphore.availablePermits, 1)
+        assertTrue(semaphore.tryAcquire())
+    }
+
+    @Test
+    fun testReleaseAcquiredPermits() = runTest {
+        val semaphore = Semaphore(5, acquiredPermits = 4)
+        assertEquals(semaphore.availablePermits, 1)
+        repeat(4) { semaphore.release() }
+        assertEquals(5, semaphore.availablePermits)
+        assertFailsWith<IllegalStateException> { semaphore.release() }
+        repeat(5) { assertTrue(semaphore.tryAcquire()) }
+        assertFalse(semaphore.tryAcquire())
+    }
+
+    @Test
+    fun testIllegalArguments() {
+        assertFailsWith<IllegalArgumentException> { Semaphore(-1, 0) }
+        assertFailsWith<IllegalArgumentException> { Semaphore(0, 0) }
+        assertFailsWith<IllegalArgumentException> { Semaphore(1, -1) }
+        assertFailsWith<IllegalArgumentException> { Semaphore(1, 2) }
+    }
 }
\ No newline at end of file