1/*-------------------------------------------------------------------------
2 * drawElements Thread Library
3 * ---------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Unix implementation of semaphore using named semaphores.
22 *//*--------------------------------------------------------------------*/
23
24#include "deSemaphore.h"
25
26#if (DE_OS == DE_OS_IOS || DE_OS == DE_OS_OSX)
27
28#include "deMemory.h"
29#include "deString.h"
30
31#include <semaphore.h>
32#include <unistd.h>
33
34typedef struct NamedSemaphore_s
35{
36	sem_t*	semaphore;
37} NamedSemaphore;
38
39static void NamedSemaphore_getName (const NamedSemaphore* sem, char* buf, int bufSize)
40{
41	deSprintf(buf, bufSize, "/desem-%d-%p", getpid(), (void*)sem);
42}
43
44DE_STATIC_ASSERT(sizeof(deSemaphore) >= sizeof(NamedSemaphore*));
45
46deSemaphore deSemaphore_create (int initialValue, const deSemaphoreAttributes* attributes)
47{
48	NamedSemaphore*	sem		= (NamedSemaphore*)deCalloc(sizeof(NamedSemaphore));
49	char			name[128];
50	deUint32		mode	= 0700;
51
52	DE_UNREF(attributes);
53
54	if (!sem)
55		return 0;
56
57	NamedSemaphore_getName(sem, name, DE_LENGTH_OF_ARRAY(name));
58
59	sem->semaphore = sem_open(name, O_CREAT|O_EXCL, mode, initialValue);
60
61	if (sem->semaphore == SEM_FAILED)
62	{
63		deFree(sem);
64		return 0;
65	}
66
67	return (deSemaphore)sem;
68}
69
70void deSemaphore_destroy (deSemaphore semaphore)
71{
72	NamedSemaphore* sem			= (NamedSemaphore*)semaphore;
73	char			name[128];
74	int				res;
75
76	NamedSemaphore_getName(sem, name, DE_LENGTH_OF_ARRAY(name));
77
78	res = sem_close(sem->semaphore);
79	DE_ASSERT(res == 0);
80	res = sem_unlink(name);
81	DE_ASSERT(res == 0);
82	DE_UNREF(res);
83	deFree(sem);
84}
85
86void deSemaphore_increment (deSemaphore semaphore)
87{
88	sem_t*	sem		= ((NamedSemaphore*)semaphore)->semaphore;
89	int		res		= sem_post(sem);
90	DE_ASSERT(res == 0);
91	DE_UNREF(res);
92}
93
94void deSemaphore_decrement (deSemaphore semaphore)
95{
96	sem_t*	sem		= ((NamedSemaphore*)semaphore)->semaphore;
97	int		res		= sem_wait(sem);
98	DE_ASSERT(res == 0);
99	DE_UNREF(res);
100}
101
102deBool deSemaphore_tryDecrement (deSemaphore semaphore)
103{
104	sem_t* sem = ((NamedSemaphore*)semaphore)->semaphore;
105	return (sem_trywait(sem) == 0);
106}
107
108#endif /* DE_OS */
109