semaphore.c 2.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
#include <errno.h>
#include <sys/fcntl.h>

#include <rtthread.h>
#include "semaphore.h"

int sem_close(sem_t *sem)
{
	if (!sem) return EINVAL;

	/* delete semaphore allocated in sem_open */
	rt_sem_delete(sem);
	return 0;
}

int sem_destroy(sem_t *sem)
{
	rt_err_t result;

	if (!sem) return EINVAL;

	/* check whether semaphore is busy or not */
	result = rt_sem_trytake(sem);
	if (result != RT_EOK) return EBUSY;

	rt_memset(sem, 0, sizeof(sem_t));
	return 0;
}

int sem_unlink(const char *name)
{
	return EACCES;
}

int sem_getvalue(sem_t *sem, int *sval)
{
	RT_ASSERT(sem != RT_NULL);
	if (sval) *sval = sem->value;
}

int sem_init(sem_t *sem, int pshared, unsigned int value)
{
	rt_err_t result;
	char name[RT_NAME_MAX];
	static rt_uint16_t psem_number = 0;

	RT_ASSERT(sem != RT_NULL);

	rt_snprintf(name, sizeof(name), "psem%02d", psem_number++);
	result = rt_sem_init(sem, name, value, RT_IPC_FLAG_FIFO);
	if (result == RT_EOK)
	{
		/* detach kernel object */
		rt_object_detach(&(sem->parent.parent));
		return 0;
	}

	return ENOSPC;
}

sem_t *sem_open(const char *name, int oflag, ...)
{
	rt_sem_t sem;

	sem = RT_NULL;
66
	if (oflag & O_CREAT)
67 68 69 70 71 72 73
	{
		sem = rt_sem_create(name, 1, RT_IPC_FLAG_FIFO);
		if (sem == RT_NULL)
			rt_set_errno(ENOSPC);
	}

	/* find semaphore */
74
	if (oflag & O_EXCL)
75
	{
76 77
		sem = (rt_sem_t)rt_object_find(name, RT_Object_Class_Semaphore);
		if (sem == RT_NULL) rt_set_errno(ENOSPC);
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
	}

	return sem;
}

int sem_post(sem_t *sem)
{
	rt_sem_release(sem);
}

int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
{
	rt_err_t result;
	rt_int32_t tick;

	if (!sem || !abs_timeout) return EINVAL;

	/* calculate os tick */
	tick = abs_timeout->tv_sec/RT_TICK_PER_SECOND + (abs_timeout->tv_nsec/1000) * (1000/RT_TICK_PER_SECOND);
	
	result = rt_sem_take(sem, tick);
	if (result == -RT_ETIMEOUT) return ETIMEDOUT;
	if (result == RT_EOK) return 0;

	return EINTR;
}

int sem_trywait(sem_t *sem)
{
	rt_err_t result;

	if (!sem) return EINVAL;

	result = rt_sem_take(sem, RT_WAITING_FOREVER);
	if (result == -RT_ETIMEOUT) return EAGAIN;
	if (result == RT_EOK) return 0;

	return EINTR;
}

int sem_wait(sem_t *sem)
{
	rt_err_t result;

	result = rt_sem_take(sem, RT_WAITING_FOREVER);
	if (result == RT_EOK) return 0;

	return EINTR;
}