/*
	Copyright 2003 by Marc J. Rochkind. All rights reserved.
	May be copied only for purposes and under conditions described
	on the Web page www.basepath.com/aup/copyright.htm.

	The Example Files are provided "as is," without any warranty;
	without even the implied warranty of merchantability or fitness
	for a particular purpose. The author and his publisher are not
	responsible for any damages, direct or incidental, resulting
	from the use or non-use of these Example Files.

	The Example Files may contain defects, and some contain deliberate
	coding mistakes that were included for educational reasons.
	You are responsible for determining if and how the Example Files
	are to be used.

*/

#include "defs.h"
#include <semaphore.h>
#include <sys/mman.h>
#include "JtuxPosixIPC.h" // generated by javah
#include "jtux_util.h"
#include "JNI_macros.h"

JNIEXPORT jlong JNICALL Java_jtux_UPosixIPC_mmap(JNIEnv *env, jclass obj,
  jlong addr, jint len, jint prot, jint flags, jint fd, jlong off)
{
	void *p;

	if ((p = mmap((void *)(intptr_t)addr, len, prot, flags, fd, off)) == MAP_FAILED)
		JTHROW_null(NULL)
	return (intptr_t)p;
}


JNIEXPORT void JNICALL Java_jtux_UPosixIPC_munmap(JNIEnv *env, jclass obj,
   jlong addr, jint len)
{
	JTHROW_neg1(munmap((void *)(intptr_t)addr, len))
}

/* Not needed... yet!
JNIEXPORT jlong JNICALL Java_jtux_UPosixIPC_sem_1alloc(JNIEnv *env, jclass obj)
{
	sem_t *sem;

	JTHROW_null(sem = malloc(sizeof(sem_t)))
	return (intptr_t)sem;
}
*/

JNIEXPORT void JNICALL Java_jtux_UPosixIPC_sem_1close(JNIEnv *env, jclass obj,
  jlong sem)
{
	JTHROW_neg1(sem_close((sem_t *)(intptr_t)sem))
}

JNIEXPORT void JNICALL Java_jtux_UPosixIPC_sem_1destroy(JNIEnv *env, jclass obj,
  jlong sem)
{
	JTHROW_neg1(sem_destroy((sem_t *)(intptr_t)sem))
}

JNIEXPORT void JNICALL Java_jtux_UPosixIPC_sem_1getvalue(JNIEnv *env, jclass obj,
  jlong sem, jobject valuep)
{
	int value_c, r;
	jclass cls = (*env)->FindClass(env, "jtux/UUtil$IntHolder");

	JTHROW_neg1(r = sem_getvalue((sem_t *)(intptr_t)sem, &value_c))
	if (valuep != NULL && r != -1) {
		if (!field_ctoj_int(env, cls, "value", valuep, value_c))
			return;
	}
}

JNIEXPORT void JNICALL Java_jtux_UPosixIPC_sem_1init(JNIEnv *env, jclass obj,
  jlong sem, jint pshared, jint value)
{
	JTHROW_neg1(sem_init((sem_t *)(intptr_t)sem, pshared, value))
}

JNIEXPORT jlong JNICALL Java_jtux_UPosixIPC_sem_1open__Ljava_lang_String_2I(JNIEnv *env, jclass obj,
  jstring name, jint flags)
{
	JSTR_GET_DECL(name_c, name)
	sem_t *sem;

	JSTR_NULLTEST_V(name_c, 0)
	if ((sem = sem_open(name_c, flags)) == SEM_FAILED)
		JTHROW_null(NULL)
	JSTR_REL(name_c, name)
	return (intptr_t)sem;
}

JNIEXPORT jlong JNICALL Java_jtux_UPosixIPC_sem_1open__Ljava_lang_String_2III(JNIEnv *env, jclass obj,
  jstring name, jint flags, jint perms, jint value)
{
	JSTR_GET_DECL(name_c, name)
	sem_t *sem;

	JSTR_NULLTEST_V(name_c, 0)
	if ((sem = sem_open(name_c, flags, perms, value)) == SEM_FAILED)
		JTHROW_null(NULL)
	JSTR_REL(name_c, name)
	return (intptr_t)sem;
}

JNIEXPORT void JNICALL Java_jtux_UPosixIPC_sem_1post(JNIEnv *env, jclass obj,
  jlong sem)
{
	JTHROW_neg1(sem_post((sem_t *)(intptr_t)sem))
}

JNIEXPORT void JNICALL Java_jtux_UPosixIPC_sem_1timedwait(JNIEnv *env, jclass obj,
  jlong sem, jobject tmout)
{
#if _XOPEN_VERSION >= 600 || true
// Following compiled but not tested
	jclass cls_timespec = (*env)->FindClass(env, "jtux/UProcess$s_timespec");
	struct timespec tmout_c;
	long sec;

	if (!field_jtoc_long(env, cls_timespec, "tv_sec", tmout, &sec))
		return;
	tmout_c.tv_sec = (time_t)sec;
	if (!field_jtoc_long(env, cls_timespec, "tv_nsec", tmout, &tmout_c.tv_nsec))
		return;
	JTHROW_neg1(sem_timedwait((sem_t *)(intptr_t)sem, &tmout_c))
#else
	(void)setup_throw_errno(env, ENOSYS);
#endif
}

JNIEXPORT void JNICALL Java_jtux_UPosixIPC_sem_1trywait(JNIEnv *env, jclass obj,
  jlong sem)
{
	JTHROW_neg1(sem_trywait((sem_t *)(intptr_t)sem))
}

JNIEXPORT void JNICALL Java_jtux_UPosixIPC_sem_1unlink(JNIEnv *env, jclass obj,
  jstring name)
{
	JSTR_GET_DECL(name_c, name)

	JSTR_NULLTEST(name_c)
	JTHROW_neg1(sem_unlink(name_c))
	JSTR_REL(name_c, name)
}

JNIEXPORT void JNICALL Java_jtux_UPosixIPC_sem_1wait(JNIEnv *env, jclass obj,
  jlong sem)
{
	JTHROW_neg1(sem_wait((sem_t *)(intptr_t)sem))
}


JNIEXPORT jint JNICALL Java_jtux_UPosixIPC_shm_1open(JNIEnv *env, jclass obj,
  jstring name, jint flags, jint perms)
{
	JSTR_GET_DECL(name_c, name)
	int fd;

	JSTR_NULLTEST_V(name_c, -1)
	JTHROW_neg1(fd = shm_open(name_c, flags, perms))
	JSTR_REL(name_c, name)
	return fd;
}

JNIEXPORT void JNICALL Java_jtux_UPosixIPC_shm_1unlink(JNIEnv *env, jclass obj,
  jstring name)
{
	JSTR_GET_DECL(name_c, name)

	JSTR_NULLTEST(name_c)
	JTHROW_neg1(shm_unlink(name_c))
	JSTR_REL(name_c, name)
}
