Author: mturk
Date: Tue Apr 19 11:22:47 2011
New Revision: 1095036
URL: http://svn.apache.org/viewvc?rev=1095036&view=rev
Log:
Implement win32 mutex and test case
Added:
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestMutex.java
(with props)
Modified:
commons/sandbox/runtime/trunk/build.xml
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Mutex.java
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/MutexImpl.java
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Native.java
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Semaphore.java
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsMutex.java
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsMutexImpl.java
commons/sandbox/runtime/trunk/src/main/native/os/win32/procmutex.c
commons/sandbox/runtime/trunk/src/main/native/os/win32/semaphore.c
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestSemaphore.java
Modified: commons/sandbox/runtime/trunk/build.xml
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/build.xml?rev=1095036&r1=1095035&r2=1095036&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/build.xml (original)
+++ commons/sandbox/runtime/trunk/build.xml Tue Apr 19 11:22:47 2011
@@ -406,7 +406,18 @@ The Apache Software Foundation (http://w
<sleep milliseconds="100" />
<runtest groups="init,semaphore.child" name="semaphore.child"/>
</sequential>
- </parallel>
+ </parallel>
+ </target>
+ <target name="testmutex" depends="tests">
+ <parallel>
+ <sequential>
+ <runtest groups="init,mutex.parent" name="mutex.parent"/>
+ </sequential>
+ <sequential>
+ <sleep milliseconds="100" />
+ <runtest groups="init,mutex.child" name="mutex.child"/>
+ </sequential>
+ </parallel>
</target>
<!-- ===================================================================
-->
Modified:
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Mutex.java
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Mutex.java?rev=1095036&r1=1095035&r2=1095036&view=diff
==============================================================================
---
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Mutex.java
(original)
+++
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Mutex.java
Tue Apr 19 11:22:47 2011
@@ -44,4 +44,114 @@ public abstract class Mutex
return impl;
}
+ public static Mutex create(MutexType type, String name)
+ throws IllegalAccessException,
+ IllegalArgumentException,
+ AlreadyExistsException,
+ UnsupportedOperationException,
+ SystemException
+ {
+ if (impl == null)
+ throw new
UnsupportedOperationException(Local.sm.get("mutex.ENOTIMPL"));
+ return impl.create(type, name);
+ }
+
+ public static Mutex create(String name)
+ throws IllegalAccessException,
+ IllegalArgumentException,
+ AlreadyExistsException,
+ UnsupportedOperationException,
+ SystemException
+ {
+ if (impl == null)
+ throw new
UnsupportedOperationException(Local.sm.get("mutex.ENOTIMPL"));
+ return impl.create(MutexType.DEFAULT, name);
+ }
+
+ public static Mutex open(MutexType type, String name)
+ throws IllegalAccessException,
+ IllegalArgumentException,
+ NoSuchObjectException,
+ UnsupportedOperationException,
+ SystemException
+ {
+ if (impl == null)
+ throw new
UnsupportedOperationException(Local.sm.get("mutex.ENOTIMPL"));
+ return impl.open(type, name);
+ }
+
+ public static Mutex open(String name)
+ throws IllegalAccessException,
+ IllegalArgumentException,
+ NoSuchObjectException,
+ UnsupportedOperationException,
+ SystemException
+ {
+ if (impl == null)
+ throw new
UnsupportedOperationException(Local.sm.get("mutex.ENOTIMPL"));
+ return impl.open(MutexType.DEFAULT, name);
+ }
+
+ private static native boolean unlink0(String name);
+ /**
+ * Removes the named semaphore.
+ * The semaphore is destroyed once all other processes that
+ * have the semaphore open close it
+ *
+ * @param name Mutex to destroy.
+ */
+ public static boolean remove(String name)
+ throws NullPointerException
+ {
+ if (name == null)
+ throw new NullPointerException();
+ return unlink0(name);
+ }
+
+ /**
+ * Acquires a permit from this semaphore, blocking until
+ * one is available.
+ *
+ */
+ public abstract void acquire()
+ throws SystemException;
+
+ /**
+ * Acquires a permit from this semaphore, only if one is available
+ * at the time of invocation.
+ *
+ */
+ public abstract boolean tryAcquire()
+ throws SystemException;
+
+ /**
+ * Releases a permit.
+ *
+ */
+ public abstract void release()
+ throws SystemException;
+
+ /**
+ * Closes the semaphore.
+ *
+ */
+ public abstract void close()
+ throws SystemException;
+
+ /**
+ * Get Mutex name.
+ */
+ public String getCanonicalName()
+ {
+ return name;
+ }
+
+ /**
+ * Check if this is Mutex owner.
+ */
+ public boolean isOwner()
+ {
+ return owner;
+ }
+
}
Modified:
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/MutexImpl.java
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/MutexImpl.java?rev=1095036&r1=1095035&r2=1095036&view=diff
==============================================================================
---
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/MutexImpl.java
(original)
+++
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/MutexImpl.java
Tue Apr 19 11:22:47 2011
@@ -32,7 +32,7 @@ public abstract class MutexImpl
static {
impl = init0();
}
-
+
protected MutexImpl()
{
// No Instance
@@ -42,7 +42,7 @@ public abstract class MutexImpl
{
return impl;
}
-
+
public abstract Mutex create(MutexType type, String name)
throws IllegalAccessException,
IllegalArgumentException,
Modified:
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Native.java
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Native.java?rev=1095036&r1=1095035&r2=1095036&view=diff
==============================================================================
---
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Native.java
(original)
+++
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Native.java
Tue Apr 19 11:22:47 2011
@@ -26,7 +26,7 @@ public final class Native
{
private Native()
- {
+ {
}
private static boolean initialized = false;
@@ -75,13 +75,13 @@ public final class Native
}
return initialized;
}
-
+
public static synchronized void terminate()
{
if (initialized) {
initialized = false;
fini0();
- }
+ }
}
}
Modified:
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Semaphore.java
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Semaphore.java?rev=1095036&r1=1095035&r2=1095036&view=diff
==============================================================================
---
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Semaphore.java
(original)
+++
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Semaphore.java
Tue Apr 19 11:22:47 2011
@@ -82,7 +82,7 @@ public abstract class Semaphore
/**
* Acquires a permit from this semaphore, blocking until
* one is available.
- *
+ *
*/
public abstract void acquire()
throws SystemException;
@@ -90,28 +90,28 @@ public abstract class Semaphore
/**
* Acquires a permit from this semaphore, only if one is available
* at the time of invocation.
- *
+ *
*/
public abstract boolean tryAcquire()
throws SystemException;
/**
* Releases a permit.
- *
+ *
*/
public abstract void release()
throws SystemException;
/**
* Clears the Semaphore.
- *
+ *
*/
public abstract void clear()
throws SystemException;
/**
* Closes the semaphore.
- *
+ *
*/
public abstract void close()
throws SystemException;
Modified:
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsMutex.java
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsMutex.java?rev=1095036&r1=1095035&r2=1095036&view=diff
==============================================================================
---
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsMutex.java
(original)
+++
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsMutex.java
Tue Apr 19 11:22:47 2011
@@ -15,6 +15,7 @@
*/
package org.apache.commons.runtime.platform.windows;
+import org.apache.commons.runtime.Errno;
import org.apache.commons.runtime.Mutex;
import org.apache.commons.runtime.Status;
import org.apache.commons.runtime.AlreadyExistsException;
@@ -36,14 +37,104 @@ final class WindowsMutex extends Mutex
{
// No Instance
}
+ // Mutex HANDLE
+ private long handle;
- public WindowsMutex(final String name, boolean owner)
+ private static native long create0(String name, long sd)
+ throws IllegalAccessException,
+ AlreadyExistsException,
+ SystemException;
+ private static native long open0(String name)
+ throws IllegalAccessException,
+ NoSuchObjectException,
+ SystemException;
+ private static native int release0(long mtx);
+
+ public WindowsMutex(final String name, boolean create)
throws IllegalAccessException,
IllegalArgumentException,
AlreadyExistsException,
SystemException
{
- this.owner = true;
+ if (name == null)
+ throw new NullPointerException();
+ this.name = "Global\\" + name.replace('\\', '_');
+ long sa = Security.stdSecurityDescriptor(Win32.MUTEX_ALL_ACCESS |
Win32.GENERIC_RWX,
+ Win32.MUTEX_ALL_ACCESS |
Win32.GENERIC_RWX,
+ Win32.MUTEX_MODIFY_STATE |
Win32.GENERIC_RWR);
+ handle = create0(this.name, sa);
+ owner = true;
+ }
+
+ public WindowsMutex(final String name)
+ throws IllegalAccessException,
+ IllegalArgumentException,
+ NoSuchObjectException,
+ SystemException
+ {
+ if (name == null)
+ throw new NullPointerException();
+ this.name = "Global\\" + name.replace('\\', '_');
+ handle = open0(this.name);
+ owner = false;
+ }
+
+ public void acquire()
+ throws SystemException
+ {
+ if (handle == 0L)
+ throw new ClosedDescriptorException();
+ int rc = Win32.WaitForSingleObject(handle, Win32.INFINITE);
+ if (rc != 0)
+ throw new SystemException(Status.describe(rc));
+ }
+
+ public boolean tryAcquire()
+ throws SystemException
+ {
+ if (handle == 0L)
+ throw new ClosedDescriptorException();
+ int rc = Win32.WaitForSingleObject(handle, 0);
+ if (rc == 0)
+ return true;
+ if (rc == Errno.EBUSY)
+ return false;
+ throw new SystemException(Status.describe(rc));
+ }
+
+ public void release()
+ throws SystemException
+ {
+ if (handle == 0L)
+ throw new ClosedDescriptorException();
+ int rc = release0(handle);
+ if (rc != 0)
+ throw new SystemException(Status.describe(rc));
+ }
+
+ public void close()
+ throws SystemException
+ {
+ if (handle == 0L)
+ throw new ClosedDescriptorException();
+ int rc = Win32.CloseHandle(handle);
+ if (rc != 0)
+ throw new SystemException(Status.describe(rc));
+ handle = 0L;
+ }
+
+ /**
+ * Called by the garbage collector when the object is destroyed.
+ * The class will free internal resources allocated by the Operating
system.
+ * @see Object#finalize()
+ * @throws Throwable the {@code Exception} raised by this method.
+ */
+ @Override
+ protected final void finalize()
+ throws Throwable
+ {
+ if (handle != 0L)
+ Win32.CloseHandle(handle);
}
}
Modified:
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsMutexImpl.java
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsMutexImpl.java?rev=1095036&r1=1095035&r2=1095036&view=diff
==============================================================================
---
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsMutexImpl.java
(original)
+++
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsMutexImpl.java
Tue Apr 19 11:22:47 2011
@@ -48,7 +48,7 @@ final class WindowsMutexImpl extends Mut
case DEFAULT:
return new WindowsMutex(name, true);
}
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException();
}
public Mutex open(MutexType type, String name)
@@ -60,9 +60,9 @@ final class WindowsMutexImpl extends Mut
{
switch (type) {
case DEFAULT:
- return new WindowsMutex(name, false);
+ return new WindowsMutex(name);
}
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException();
}
}
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/procmutex.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/procmutex.c?rev=1095036&r1=1095035&r2=1095036&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/procmutex.c
(original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/procmutex.c Tue Apr
19 11:22:47 2011
@@ -30,6 +30,71 @@ J_DECLARE_CLAZZ = {
J_DECLARE_M_ID(0000) = {
0,
"<init>",
- "(I)V"
+ "()V"
};
+ACR_JNI_EXPORT(jobject, MutexImpl, init0)(JNI_STDARGS)
+{
+ if (_clazzn.u == 1)
+ return (*env)->NewObject(env, _clazzn.i, J4MID(0000));
+ if (AcrLoadClass(env, &_clazzn, 0) != 0) {
+ ACR_THROW_MSG(ACR_EX_EINSTANCE, "WindowsMutexImpl not initialized");
+ return 0;
+ }
+ R_LOAD_METHOD(0000, 0);
+ _clazzn.u = 1;
+ return (*env)->NewObject(env, _clazzn.i, J4MID(0000));
+}
+
+ACR_JNI_EXPORT(jboolean, Mutex, unlink0)(JNI_STDARGS, jstring name)
+{
+ /* Windows mutex is not kernel bound.
+ */
+ return JNI_FALSE;
+}
+
+ACR_WIN_EXPORT(jlong, WindowsMutex, create0)(JNI_STDARGS,
+ jstring name,
+ jlong sd)
+{
+ HANDLE h = 0;
+ SECURITY_ATTRIBUTES sa;
+
+ /* Mark the mutex as non inheritable
+ * with Modify access to Authenticated users
+ */
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = J2P(sd, PSECURITY_DESCRIPTOR);
+ sa.bInheritHandle = FALSE;
+
+ WITH_WSTR(name) {
+ h = CreateMutexW(&sa, FALSE, J2S(name));
+ if (h == 0) {
+ ACR_THROW_BY_ERRNO();
+ }
+ } DONE_WITH_STR(name);
+
+ return P2J(h);
+}
+
+ACR_WIN_EXPORT(jlong, WindowsMutex, open0)(JNI_STDARGS, jstring name)
+{
+ HANDLE h = 0;
+
+ WITH_WSTR(name) {
+ h = OpenMutexW(MAXIMUM_ALLOWED, FALSE, J2S(name));
+ if (h == 0) {
+ ACR_THROW_BY_ERRNO();
+ }
+ } DONE_WITH_STR(name);
+
+ return P2J(h);
+}
+
+ACR_WIN_EXPORT(jint, WindowsMutex, release0)(JNI_STDARGS, jlong mtx)
+{
+ if (ReleaseMutex(J2P(mtx, HANDLE)))
+ return 0;
+ else
+ return ACR_GET_OS_ERROR();
+}
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/semaphore.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/semaphore.c?rev=1095036&r1=1095035&r2=1095036&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/semaphore.c
(original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/semaphore.c Tue Apr
19 11:22:47 2011
@@ -57,7 +57,7 @@ ACR_WIN_EXPORT(jlong, WindowsSemaphore,
jstring name,
jint value, jlong sd)
{
- HANDLE sp = 0;
+ HANDLE h = 0;
int maxval = 32767;
SECURITY_ATTRIBUTES sa;
@@ -71,28 +71,28 @@ ACR_WIN_EXPORT(jlong, WindowsSemaphore,
sa.bInheritHandle = FALSE;
WITH_WSTR(name) {
- sp = CreateSemaphoreW(&sa, (LONG)value, (LONG)maxval, J2S(name));
- if (sp == 0) {
+ h = CreateSemaphoreW(&sa, (LONG)value, (LONG)maxval, J2S(name));
+ if (h == 0) {
ACR_THROW_BY_ERRNO();
}
} DONE_WITH_STR(name);
- return P2J(sp);
+ return P2J(h);
}
ACR_WIN_EXPORT(jlong, WindowsSemaphore, open0)(JNI_STDARGS,
jstring name)
{
- HANDLE sp = 0;
+ HANDLE h = 0;
WITH_WSTR(name) {
- sp = OpenSemaphoreW(READ_CONTROL | SEMAPHORE_MODIFY_STATE, FALSE,
J2S(name));
- if (sp == 0) {
+ h = OpenSemaphoreW(READ_CONTROL | SEMAPHORE_MODIFY_STATE, FALSE,
J2S(name));
+ if (h == 0) {
ACR_THROW_BY_ERRNO();
}
} DONE_WITH_STR(name);
- return P2J(sp);
+ return P2J(h);
}
ACR_WIN_EXPORT(jint, WindowsSemaphore, release0)(JNI_STDARGS, jlong sem)
Added:
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestMutex.java
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestMutex.java?rev=1095036&view=auto
==============================================================================
---
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestMutex.java
(added)
+++
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestMutex.java
Tue Apr 19 11:22:47 2011
@@ -0,0 +1,90 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.runtime;
+
+import java.io.IOException;
+import java.io.File;
+import org.testng.annotations.*;
+import org.testng.Assert;
+
+public class TestMutex extends Assert
+{
+
+ private static final String semname = "acrMutex23";
+
+ @Test(groups = { "mutex.parent" })
+ public void checkMutex()
+ throws Exception
+ {
+ System.out.flush();
+ try {
+ Mutex s = Mutex.create(semname);
+ s.close();
+ } catch (Exception ex) {
+ System.out.println("[parent] Removing stalled mutex " + semname);
+ assertTrue(Mutex.remove(semname));
+ }
+ }
+
+ @Test(groups = { "mutex.parent" })
+ public void createMutex()
+ throws Exception
+ {
+ Mutex s = Mutex.create(semname);
+ assertNotNull(s);
+ System.out.println("[parent] Waiting for a child to attach");
+ System.out.flush();
+ s.acquire();
+ Thread.sleep(2000);
+ System.out.println("[parent] Done.");
+ System.out.flush();
+ s.release();
+ Thread.sleep(100);
+ s.close();
+ }
+
+ @Test(groups = { "mutex.child" })
+ public void openMutex()
+ throws Exception
+ {
+ System.out.println("[child] Attaching child mutex");
+ System.out.flush();
+ Mutex s = null;
+ int step = 125;
+ while (step <= 2000) {
+ try {
+ s = Mutex.open(semname);
+ break;
+ } catch (Exception x) {
+
+ }
+ Thread.sleep(step);
+ step *= 2;
+ }
+ assertNotNull(s);
+ System.out.println("[child] Mutex opened.");
+ System.out.flush();
+ s.acquire();
+ System.out.println("[child] Mutex acquired.");
+ System.out.flush();
+ s.release();
+ s.close();
+ System.out.println("[child] Done.");
+ System.out.flush();
+ }
+
+}
Propchange:
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestMutex.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestSemaphore.java
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestSemaphore.java?rev=1095036&r1=1095035&r2=1095036&view=diff
==============================================================================
---
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestSemaphore.java
(original)
+++
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestSemaphore.java
Tue Apr 19 11:22:47 2011
@@ -35,7 +35,7 @@ public class TestSemaphore extends Asser
Semaphore s = Semaphore.create(semname, 0);
s.close();
} catch (Exception ex) {
- System.out.println("Removing stalled semaphore " + semname);
+ System.out.println("[parent] Removing stalled semaphore " +
semname);
assertTrue(Semaphore.remove(semname));
}
}
@@ -46,10 +46,10 @@ public class TestSemaphore extends Asser
{
Semaphore s = Semaphore.create(semname, 0);
assertNotNull(s);
- System.out.println("Waiting for a child to attach");
+ System.out.println("[parent] Waiting for a child to attach");
System.out.flush();
s.acquire();
- System.out.println("Parent done.");
+ System.out.println("[parent] Done.");
System.out.flush();
s.release();
s.close();
@@ -59,7 +59,7 @@ public class TestSemaphore extends Asser
public void openSemaphore()
throws Exception
{
- System.out.println("Attaching child semaphore");
+ System.out.println("[child] Attaching semaphore");
System.out.flush();
Semaphore s = null;
int step = 125;
@@ -68,7 +68,7 @@ public class TestSemaphore extends Asser
s = Semaphore.open(semname);
break;
} catch (Exception x) {
-
+
}
Thread.sleep(step);
step *= 2;
@@ -76,7 +76,7 @@ public class TestSemaphore extends Asser
assertNotNull(s);
s.release();
s.close();
- System.out.println("Child done.");
+ System.out.println("[child] Done.");
System.out.flush();
}