/*
 * IPRPC - Inter Process Remote Procedure Call
 *
 * Copyright (C) 2012-2013 by Hiroyuki KAJIURA. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 *
 *     1:Redistributions of source code must retain the above copyright notice, 
 *       this list of conditions and the following disclaimer.
 *     2:Redistributions in binary form must reproduce the above copyright notice, 
 *       this list of conditions and the following disclaimer in the documentation 
 *       and/or other materials provided with the distribution.
 *     3:Neither the name of copyright owner nor the names of its contributors 
 *       may be used to endorse or promote products derived from this software 
 *       without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef IPCSYSCALL_H_
#define IPCSYSCALL_H_

#ifdef	IPC_SYSCALL_MAIN
#define	extern
#endif	/* IPC_SYSCALL_MAIN */

//#include	<stdio.h>
#include	<stdlib.h>
#include	<unistd.h>
#include	<time.h>
#include	<sys/time.h>
#include	<pthread.h>
#include	<sys/mman.h>
#include	<sys/stat.h>
#include	<sys/types.h>
#include	<fcntl.h>
#include	<errno.h>
#include	<sys/wait.h>
#ifdef	_LINUX_
#include	<bits/local_lim.h>
#else	/* _LINUX_ */
#include	<limits.h>
#endif	/* _LINUX_ */
#include	<sched.h>
#include	<semaphore.h>
#include	<signal.h>

#include	"ipcType.h"

typedef pthread_t					RpcTaskID_t;
typedef pthread_attr_t					RpcTaskAttribute_t;
typedef struct sched_param				RpcTaskSchedParam_t;
typedef pthread_mutex_t					RpcMutexID_t;
typedef pthread_mutexattr_t				RpcMutexAttribute_t;
typedef pthread_cond_t					RpcCondID_t;
typedef pthread_condattr_t				RpcCondAttribute_t;
typedef sem_t						RpcSem_t;

typedef enum {
	RPC_SCHED_PRIO_UNKNOWN = 0,
	RPC_SCHED_PRIO_IDLE = 0,
	RPC_SCHED_PRIO_BATCH = 0,
	RPC_SCHED_PRIO_OTHER = 0,
	RPC_SCHED_PRIO_LOW_L = 10,
	RPC_SCHED_PRIO_LOW_M = 20,
	RPC_SCHED_PRIO_LOW_H = 30,
	RPC_SCHED_PRIO_MID_L = 40,
	RPC_SCHED_PRIO_MID_M = 50,
	RPC_SCHED_PRIO_MID_H = 60,
	RPC_SCHED_PRIO_HGH_L = 70,
	RPC_SCHED_PRIO_HGH_M = 80,
	RPC_SCHED_PRIO_HGH_H = 90,
	RPC_SCHED_PRIO_URGENT = 99,
	RPC_SHCED_PRIO_MAX
} RpcSchedPriority_t;

typedef void *(*RPC_TaskStartRoutine_t)(void*);

extern RpcResult_t RPC_CreateTask(RpcTaskID_t *taskId, RpcTaskAttribute_t *taskAttr, RPC_TaskStartRoutine_t startRoutine, void *arg);
extern void RPC_ExitTask(void *retVal);
extern RpcResult_t RPC_JoinTask(RpcTaskID_t taskId, void **retval);
extern RpcResult_t RPC_DetachTask(RpcTaskID_t taskId);
extern RpcResult_t RPC_CancelTask(RpcTaskID_t taskId);
extern RpcResult_t RPC_SetCancelState(int state, int *oldState);
extern RpcResult_t RPC_SetCancelType(int type, int *oldType);
extern RpcResult_t RPC_TestCancel(void);
extern RpcTaskID_t RPC_TaskSelf(void);
//extern RpcResult_t RPC_TaskPushCleanup(void (*routine)(void*), void *arg);
//extern RpcResult_t RPC_TaskPopCleanup(int execute);
//extern RpcResult_t RPC_TaskPushClenaupDeferNP(void (*routine)(void*), void *arg);
//extern RpcResult_t RPC_TaskPopCleanupRestoreNP(int execute);

#define	RPC_TaskPushCleanup(routine,arg)		pthread_cleanup_push(routine,arg)
#define	RPC_TaskPopCleanup(execute)			pthread_cleanup_pop(execute)
#define	RPC_TaskPushClenaupDeferNP(routine,arg)		pthread_cleanup_push_defer_np(routine, arg)
#define	RPC_TaskPopCleanupRestoreNP(execute)		pthread_cleanup_pop_defer_np(execute)

extern RpcResult_t RPC_TaskAttrInit(RpcTaskAttribute_t *taskAttr);
extern RpcResult_t RPC_TaskAttrSetDetachState(RpcTaskAttribute_t *taskAttr, int detachState);
extern RpcResult_t RPC_TaskAttrGetDetachState(RpcTaskAttribute_t *taskAttr, int *detachState);
extern RpcResult_t RPC_TaskAttrSetSchedPolicy(RpcTaskAttribute_t *taskAttr, int policy);
extern RpcResult_t RPC_TaskAttrGetSchedPolicy(RpcTaskAttribute_t *taskAttr, int *policy);
extern RpcResult_t RPC_TaskAttrSetSchedParam(RpcTaskAttribute_t *taskAttr, RpcTaskSchedParam_t *schedParam);
extern RpcResult_t RPC_TaskAttrGetSchedParam(RpcTaskAttribute_t *taskAttr, RpcTaskSchedParam_t *schedParam);
extern RpcResult_t RPC_TaskAttrSetInheritSched(RpcTaskAttribute_t *taskAttr, int inherit);
extern RpcResult_t RPC_TaskAttrGetInheritSched(RpcTaskAttribute_t *taskAttr, int *inherit);
extern RpcResult_t RPC_TaskAttrDestroy(RpcTaskAttribute_t *taskAttr);
extern RpcResult_t RPC_TaskAttrSetStackSize(RpcTaskAttribute_t *taskAttr, int stackSize);
extern RpcResult_t RPC_TaskAttrGetStackSize(RpcTaskAttribute_t *taskAttr, int *stackSize);
extern RpcResult_t RPC_TaskAttrSetStack(RpcTaskAttribute_t *taskAttr, void *stackAddr, int stackSize);
extern RpcResult_t RPC_TaskAttrGetStack(RpcTaskAttribute_t *taskAttr, void **stackAddr, int *stackSize);

extern RpcResult_t RPC_TaskYield(void);
extern RpcResult_t RPC_TaskSleep(struct timeval *sleepTime,struct timeval *remainTime);

extern RpcResult_t RPC_InitMutex(RpcMutexID_t *mutexID, RpcMutexAttribute_t *mutexAttr);
extern RpcResult_t RPC_MutexLock(RpcMutexID_t *mutexID);
extern RpcResult_t RPC_MutexUnlock(RpcMutexID_t *mutexID);
extern RpcResult_t RPC_MutexLockTry(RpcMutexID_t *mutexID);
extern RpcResult_t RPC_MutexDestroy(RpcMutexID_t *mutexID);
extern RpcResult_t RPC_MutexTimedLock(RpcMutexID_t *mutexID,struct timespec *absTime);

extern RpcResult_t RPC_MutexAttrInit(RpcMutexAttribute_t *mutexAttr);
extern RpcResult_t RPC_MutexAttrSetType(RpcMutexAttribute_t *mutexAttr, int kind);
extern RpcResult_t RPC_MutexAttrGetType(RpcMutexAttribute_t *mutexAttr, int *kind);
extern RpcResult_t RPC_MutexAttrDestroy(RpcMutexAttribute_t *mutexAttr);
extern RpcResult_t RPC_MutexAttrGetPshared(RpcMutexAttribute_t *mutexAttr, int *pshared);
extern RpcResult_t RPC_MutexAttrSetPshared(RpcMutexAttribute_t *mutexAttr, int pshared);

extern RpcResult_t RPC_InitCond(RpcCondID_t *condID, RpcCondAttribute_t *condAttr);
extern RpcResult_t RPC_CondSignal(RpcCondID_t *condID);
extern RpcResult_t RPC_CondBroadcast(RpcCondID_t *condID);
extern RpcResult_t RPC_CondWait(RpcCondID_t *condID, RpcMutexID_t *mutexID);
extern RpcResult_t RPC_CondWaitTimeout(RpcCondID_t *condID, RpcMutexID_t *mutexID, struct timespec *abstime);
extern RpcResult_t RPC_CondDestroy(RpcCondID_t *condID);

extern RpcResult_t RPC_CondAttrInit(RpcCondAttribute_t *condAttr);
extern RpcResult_t RPC_CondAttrDestroy(RpcCondAttribute_t *condAttr);
extern RpcResult_t RPC_CondAttrGetPshared(RpcCondAttribute_t *condAttr, int *pshared);
extern RpcResult_t RPC_CondAttrSetPshared(RpcCondAttribute_t *condAttr, int pshared);

extern RpcResult_t RPC_SemInit(RpcSem_t *sem, int pshared, int value);
extern RpcResult_t RPC_SemPost(RpcSem_t *sem);
extern RpcResult_t RPC_SemWait(RpcSem_t *sem);
extern RpcResult_t RPC_SemWaitTry(RpcSem_t *sem);
extern RpcResult_t RPC_SemTimedWait(RpcSem_t *sem,struct timespec *absTime);
extern RpcResult_t RPC_SemGetValue(RpcSem_t *sem,int *value);
extern RpcResult_t RPC_SemDestroy(RpcSem_t *sem);

extern RpcResult_t RPC_ShmOpen(char *name, int oflag, mode_t mode, int *fd, uint32_t *errCode);
extern RpcResult_t RPC_ShmUnlink(char *name, uint32_t *errCode);
extern RpcResult_t RPC_ShmClose(int fd, uint32_t *errCode);
extern RpcResult_t RPC_ShmMap(void *addr, int length, int prot, int flag, int fd, off_t offset, void **allocAddr, uint32_t *errCode);
extern RpcResult_t RPC_ShmUnmap(void *addr,int length, uint32_t *errCode);
extern RpcResult_t RPC_ShmFtruncate(int fd, off_t length, uint32_t *errCode);
extern RpcResult_t RPC_ShmFstat(int fd, struct stat *buff, uint32_t *errCode);
extern RpcResult_t RPC_ShmFchown(int fd, uid_t owner, gid_t group, uint32_t *errCode);
extern RpcResult_t RPC_ShmFchmod(int fd, mode_t mode, uint32_t *errCode);

extern void *RPC_AllocMem(uint32_t size);
extern void *RPC_ReallocMem(void *memP, uint32_t newSize);
extern void RPC_FreeMem(void *memP);

extern RpcResult_t RPC_GetTimeOfDay(struct timeval *time, struct timezone *timeZone,uint32_t *errCode);
extern RpcResult_t RPC_SetTimeOfDay(struct timeval *time, struct timezone *timeZone,uint32_t *errCode);

extern void RPC_Srand(uint32_t seed);
extern uint32_t RPC_Rand(void);

extern uint32_t RPC_GetPid(void);
extern RpcResult_t RPC_Fork(int32_t *pid,uint32_t *errCOde);
extern RpcResult_t RPC_Exec(char *filePath,char *argv[],char *envp[],uint32_t *errCode);
extern RpcResult_t RPC_Wait(int32_t *pid, int *status,uint32_t *errCode);
extern RpcResult_t RPC_WaitPid(int32_t *pid,int *status,int options,uint32_t *errCode);
extern void RPC_Exit(int32_t status);
extern RpcResult_t RPC_Kill(int32_t pid,int32_t sig,uint32_t *errCode);

#define	RPC_WNOHANG					WNOHANG
#define	RPC_WUNTRACED					WUNTRACED
#define	RPC_WCONTINUED					WCONTINUED

#define	RPC_WIFEXITED(status)				WIFEXITED(status)
#define	RPC_WEXITSTATUS(status)				WEXITSTATUS(status)
#define	RPC_WIFSIGNALED(status)				WIFSIGNALED(status)
#define	RPC_WTERMSIG(status)				WTERMSIG(status)
#define	RPC_WCOREDUMP(status)				WCOREDUMP(status)
#define	RPC_WIFSTOPPED(status)				WIFSTOPPED(status)
#define	RPC_WSTOPSIG(status)				WSTIPSIG(status)
#define	RPC_WIFCONTINUED(status)			WIFCONTINUED(status)

#endif /* IPCSYSCALL_H_ */
