/*
 * Copyright (c) 2003 Sun Microsystems, Inc.
 * Copyright 2010 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * 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.
 *    * Neither the name of Google Inc. 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
 * OWNER 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.
 *
 * This was open sourced by Sun Microsystems, which got it via Cobalt
 * Networks.  It has been fairly extensively modified since then.
 */

#ifndef _GNU_SOURCE
#  define _GNU_SOURCE 1
#endif
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.h>
#include <sched.h>

#include "csem.h"

#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* union semun is defined by including <sys/sem.h> */
#else
/* according to X/OPEN we have to define it ourselves */
union semun {
	int val;                    /* value for SETVAL */
	struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
	unsigned short int *array;  /* array for GETALL, SETALL */
	struct seminfo *__buf;      /* buffer for IPC_INFO */
};
#endif

/*
 * On some platforms semctl(SETVAL) sets sem_otime, on other platforms it
 * does not.  Figure out what this platform does.
 *
 * Returns 0 if semctl(SETVAL) does not set sem_otime
 * Returns 1 if semctl(SETVAL) does set sem_otime
 * Returns -1 on error
 */
static int
does_semctl_set_otime(void)
{
	int sem_id;
	int ret;

	/* create a test semaphore */
	sem_id = semget(IPC_PRIVATE, 1, S_IRUSR|S_IWUSR);
	if (sem_id < 0) {
		return -1;  // COV_NF_LINE
	}

	/* set the value */
	if (csem_setval(sem_id, 1) < 0) {
		csem_destroy(sem_id);  // COV_NF_LINE
		return -1;             // COV_NF_LINE
	}

	/* read sem_otime */
	ret = (csem_get_otime(sem_id) > 0) ? 1 : 0;

	/* clean up */
	csem_destroy(sem_id);

	return ret;
}

int
csem_create(key_t key, unsigned val)
{
	static int need_otime_hack = -1;
	int sem_id;

	/* see if we need to trigger a semop to set sem_otime */
	if (need_otime_hack < 0) {
		int ret = does_semctl_set_otime();
		if (ret < 0) {
			return -1;  // COV_NF_LINE
		}
		need_otime_hack = !ret;
	}

	/* create it or fail */
	sem_id = semget(key, 1, IPC_CREAT|IPC_EXCL | S_IRUSR|S_IWUSR);
	if (sem_id < 0) {
		return -1;
	}

	/* initalize the value */
	if (need_otime_hack) {
		val++;
	}
	if (csem_setval(sem_id, val) < 0) {
		csem_destroy(sem_id);  // COV_NF_LINE
		return -1;             // COV_NF_LINE
	}

	if (need_otime_hack) {
		/* force sem_otime to change */
		csem_down(sem_id);
	}

	return sem_id;
}

/* how many times to loop, waiting for sem_otime */
#define MAX_OTIME_LOOPS 1000

int
csem_get(key_t key)
{
	int sem_id;
	int i;

	/* CSEM_PRIVATE needs to go through csem_create() to get an
	 * initial value */
	if (key == CSEM_PRIVATE) {
		errno = EINVAL;  // COV_NF_LINE
		return -1;       // COV_NF_LINE
	}

	/* get the (assumed existing) semaphore */
	sem_id = semget(key, 1, S_IRUSR|S_IWUSR);
	if (sem_id < 0) {
		return -1;
	}

	/* loop until sem_otime != 0, which means it has been initialized */
	for (i = 0; i < MAX_OTIME_LOOPS; i++) {
		time_t otime = csem_get_otime(sem_id);
		if (otime < 0) {
			/* error */
			return -1;  // COV_NF_LINE
		}
		if (otime > 0) {
			/* success */
			return sem_id;
		}
		/* retry */
		sched_yield();  // COV_NF_LINE
	}

	/* fell through - error */
	return -1;  // COV_NF_LINE
}

int
csem_get_or_create(key_t key, unsigned val)
{
	int sem_id;

	/* try to create the semaphore */
	sem_id = csem_create(key, val);
	if (sem_id >= 0 || errno != EEXIST) {
		/* it either succeeded or got an error */
		return sem_id;
	}

	/* it must exist already - get it */
	sem_id = csem_get(key);
	if (sem_id < 0) {
		return -1;  // COV_NF_LINE
	}

	return sem_id;
}

int
csem_destroy(int sem_id)
{
	return semctl(sem_id, 0, IPC_RMID);
}

int
csem_getval(int sem_id)
{
	return semctl(sem_id, 0, GETVAL);
}

int
csem_setval(int sem_id, unsigned val)
{
	union semun arg;
	arg.val = val;
	if (semctl(sem_id, 0, SETVAL, arg) < 0) {
		return -1;  // COV_NF_LINE
	}
	return 0;
}

static int
csem_up_undoflag(int sem_id, int undoflag)
{
	struct sembuf sops;
	sops.sem_num = 0;
	sops.sem_op = 1;
	sops.sem_flg = undoflag;
	return semop(sem_id, &sops, 1);
}
int
csem_up(int sem_id)
{
	return csem_up_undoflag(sem_id, 0);
}
int
csem_up_undo(int sem_id)
{
	return csem_up_undoflag(sem_id, SEM_UNDO);
}

static int
csem_down_undoflag(int sem_id, int undoflag)
{
	struct sembuf sops;
	sops.sem_num = 0;
	sops.sem_op = -1;
	sops.sem_flg = undoflag;
	return semop(sem_id, &sops, 1);
}
int
csem_down(int sem_id)
{
	return csem_down_undoflag(sem_id, 0);
}
int
csem_down_undo(int sem_id)
{
	return csem_down_undoflag(sem_id, SEM_UNDO);
}

static int
csem_down_timeout_undoflag(int sem_id, struct timespec *timeout, int undoflag)
{
	struct sembuf sops;
	sops.sem_num = 0;
	sops.sem_op = -1;
	sops.sem_flg = undoflag;
	return semtimedop(sem_id, &sops, 1, timeout);
}
int
csem_down_timeout(int sem_id, struct timespec *timeout)
{
	return csem_down_timeout_undoflag(sem_id, timeout, 0);
}
int
csem_down_timeout_undo(int sem_id, struct timespec *timeout)
{
	return csem_down_timeout_undoflag(sem_id, timeout, SEM_UNDO);
}

time_t
csem_get_otime(int sem_id)
{
	union semun arg;
	struct semid_ds ds;
	arg.buf = &ds;
	if (semctl(sem_id, 0, IPC_STAT, arg) < 0) {
		return -1;  // COV_NF_LINE
	}
	return ds.sem_otime;
}
