Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/aso/aso-sem.c
1811 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#pragma prototyped
23
24
#include "asohdr.h"
25
26
#if defined(_UWIN) && defined(_BLD_ast) || !_aso_semaphore
27
28
NoN(aso_meth_semaphore)
29
30
#else
31
32
#include <sys/stat.h>
33
#include <sys/ipc.h>
34
#include <sys/sem.h>
35
36
#define SPIN 1000000
37
38
typedef union Semun_u
39
{
40
int val;
41
struct semid_ds* ds;
42
unsigned short* array;
43
} Semun_t;
44
45
typedef struct APL_s
46
{
47
int id;
48
size_t size;
49
} APL_t;
50
51
static void*
52
aso_init_semaphore(void* data, const char* details)
53
{
54
APL_t* apl = (APL_t*)data;
55
char* path;
56
char* opt;
57
size_t size;
58
size_t n;
59
int key;
60
int id;
61
int perm;
62
struct sembuf sem;
63
char tmp[64];
64
65
if (apl)
66
{
67
/*
68
* semaphore 0 is the reference count
69
* the id is dropped on last reference
70
*/
71
72
sem.sem_num = 0;
73
sem.sem_op = -1;
74
sem.sem_flg = IPC_NOWAIT;
75
semop(apl->id, &sem, 1);
76
sem.sem_op = 0;
77
if (!semop(apl->id, &sem, 1))
78
semctl(apl->id, 0, IPC_RMID);
79
free(apl);
80
return 0;
81
}
82
perm = S_IRUSR|S_IWUSR;
83
size = 128;
84
if (path = (char*)details)
85
while (opt = strchr(path, ','))
86
{
87
if (strneq(path, "perm=", 5))
88
{
89
if ((n = opt - (path + 5)) >= sizeof(tmp))
90
n = sizeof(tmp) - 1;
91
memcpy(tmp, path + 5, n);
92
tmp[n] = 0;
93
perm = strperm(tmp, NiL, perm);
94
}
95
else if (strneq(path, "size=", 5))
96
{
97
size = strtoul(path + 5, NiL, 0);
98
if (size <= 1)
99
return 0;
100
}
101
path = opt + 1;
102
}
103
key = (!path || !*path || streq(path, "private")) ? IPC_PRIVATE : (strsum(path, 0) & 0x7fff);
104
for (;;)
105
{
106
if ((id = semget(key, size, IPC_CREAT|IPC_EXCL|perm)) >= 0)
107
{
108
/*
109
* initialize all semaphores to 0
110
* this also sets the semaphore 0 ref count
111
*/
112
113
sem.sem_op = 1;
114
sem.sem_flg = 0;
115
for (sem.sem_num = 0; sem.sem_num < size; sem.sem_num++)
116
if (semop(id, &sem, 1) < 0)
117
{
118
(void)semctl(id, 0, IPC_RMID);
119
return 0;
120
}
121
break;
122
}
123
else if (errno == EINVAL && size > 3)
124
size /= 2;
125
else if (errno != EEXIST)
126
return 0;
127
else if ((id = semget(key, size, perm)) >= 0)
128
{
129
struct semid_ds ds;
130
Semun_t arg;
131
unsigned int k;
132
133
/*
134
* make sure all semaphores have been activated
135
*/
136
137
arg.ds = &ds;
138
for (k = 0; k < SPIN; ASOLOOP(k))
139
{
140
if (semctl(id, size-1, IPC_STAT, arg) < 0)
141
return 0;
142
if (ds.sem_otime)
143
break;
144
}
145
if (k > SPIN)
146
return 0;
147
148
/*
149
* bump the ref count
150
*/
151
152
sem.sem_num = 0;
153
sem.sem_op = 1;
154
sem.sem_flg = 0;
155
if (semop(id, &sem, 1) < 0)
156
return 0;
157
break;
158
}
159
else if (errno == EINVAL && size > 3)
160
size /= 2;
161
else
162
return 0;
163
}
164
if (!(apl = newof(0, APL_t, 1, 0)))
165
return 0;
166
apl->id = id;
167
apl->size = size - 1;
168
return apl;
169
}
170
171
static ssize_t
172
aso_lock_semaphore(void* data, ssize_t k, void volatile* p)
173
{
174
APL_t* apl = (APL_t*)data;
175
struct sembuf sem;
176
177
if (!apl)
178
return -1;
179
if (k > 0)
180
sem.sem_op = 1;
181
else
182
{
183
sem.sem_op = -1;
184
k = HASH(p, apl->size) + 1;
185
}
186
sem.sem_num = k;
187
sem.sem_flg = 0;
188
return semop(apl->id, &sem, 1) < 0 ? -1 : k;
189
}
190
191
Asometh_t _aso_meth_semaphore = { "semaphore", ASO_PROCESS|ASO_THREAD, aso_init_semaphore, aso_lock_semaphore };
192
193
#endif
194
195