12
12
#include "postgres.h"
13
13
#include <stdio.h>
14
14
#include <errno.h>
15
+ #include <unistd.h>
15
16
#include <OS.h>
16
17
#include "utils/elog.h"
17
18
19
+ /*#define TDBG*/
20
+ #ifdef TDBG
21
+ #define TRACEDBG (x ) printf(x);printf("\n")
22
+ #define TRACEDBGP (x ,y ) printf(x,y);printf("\n")
23
+ #define TRACEDBGPP (x ,y ,z ) printf(x,y,z);printf("\n")
24
+ #else
25
+ #define TRACEDBG (x )
26
+ #define TRACEDBGP (x ,y )
27
+ #define TRACEDBGPP (x ,y ,z )
28
+ #endif
18
29
19
30
/* Control of a semaphore pool. The pool is an area in which we stored all
20
31
the semIds of the pool. The first 4 bytes are the number of semaphore allocated
@@ -25,16 +36,19 @@ int semctl(int semId,int semNum,int flag,union semun semun)
25
36
int32 * Address ;
26
37
area_info info ;
27
38
39
+ TRACEDBG ("->semctl" );
28
40
/* Try to find the pool */
29
41
if (get_area_info (semId ,& info )!= B_OK )
30
42
{
31
43
/* pool is invalid (BeOS area id is invalid) */
32
44
errno = EINVAL ;
45
+ TRACEDBG ("<-semctl invalid pool" );
33
46
return -1 ;
34
47
}
35
48
36
49
/* Get the pool address */
37
50
Address = (int32 * )info .address ;
51
+ TRACEDBGP ("--semctl address %d" ,Address );
38
52
39
53
40
54
/* semNum might be 0 */
@@ -44,18 +58,22 @@ int semctl(int semId,int semNum,int flag,union semun semun)
44
58
if (flag == SETALL )
45
59
{
46
60
long i ;
61
+ TRACEDBG ("--semctl setall" );
47
62
for (i = 0 ;i < Address [0 ];i ++ )
48
63
{
49
64
int32 cnt ;
50
65
/* Get the current count */
51
- get_sem_count (Address [i + 1 ],& cnt );
66
+ get_sem_count (Address [2 * i + 1 ],& cnt );
67
+
68
+ TRACEDBGP ("--semctl setall %d" ,semun .array [i ]);
52
69
53
70
/* Compute and set the new count (relative to the old one) */
54
71
cnt -= semun .array [i ];
72
+ TRACEDBGPP ("--semctl acquire id : %d cnt : %d" ,Address [2 * i + 1 ],cnt );
55
73
if (cnt > 0 )
56
- while (acquire_sem_etc (Address [i + 1 ],cnt ,0 ,0 )== B_INTERRUPTED );
74
+ while (acquire_sem_etc (Address [2 * i + 1 ],cnt ,0 ,0 )== B_INTERRUPTED );
57
75
if (cnt < 0 )
58
- release_sem_etc (Address [i + 1 ],- cnt ,0 );
76
+ release_sem_etc (Address [2 * i + 1 ],- cnt ,0 );
59
77
}
60
78
return 1 ;
61
79
}
@@ -64,37 +82,49 @@ int semctl(int semId,int semNum,int flag,union semun semun)
64
82
if (flag == SETVAL )
65
83
{
66
84
int32 cnt ;
85
+ TRACEDBGP ("--semctl setval %d" ,semun .val );
67
86
/* Get the current count */
68
- get_sem_count (Address [semNum + 1 ],& cnt );
87
+ get_sem_count (Address [2 * semNum + 1 ],& cnt );
69
88
70
89
/* Compute and set the new count (relative to the old one) */
71
90
cnt -= semun .val ;
91
+ TRACEDBGPP ("--semctl acquire id : %d cnt : %d" ,Address [2 * semNum + 1 ],cnt );
72
92
if (cnt > 0 )
73
- while (acquire_sem_etc (Address [semNum + 1 ],cnt ,0 ,0 )== B_INTERRUPTED );
93
+ while (acquire_sem_etc (Address [2 * semNum + 1 ],cnt ,0 ,0 )== B_INTERRUPTED );
74
94
if (cnt < 0 )
75
- release_sem_etc (Address [semNum + 1 ],- cnt ,0 );
95
+ release_sem_etc (Address [2 * semNum + 1 ],- cnt ,0 );
76
96
return 1 ;
77
97
}
78
98
99
+ /* Get the last pid which accesed the sem */
100
+ if (flag == GETPID )
101
+ {
102
+ TRACEDBG ("->semctl getpid" );
103
+ return Address [2 * semNum + 2 ];
104
+ }
105
+
79
106
/* Delete the pool */
80
107
if (flag == IPC_RMID )
81
108
{
82
109
long i ;
83
110
84
111
thread_info ti ;
112
+ TRACEDBG ("->semctl rmid" );
85
113
get_thread_info (find_thread (NULL ),& ti );
86
114
87
115
/* Loop over all semaphore to delete them */
116
+ TRACEDBGP ("->semctl nmbre %d" ,Address [0 ]);
88
117
for (i = 0 ;i < Address [0 ];i ++ )
89
118
{
90
- /* Don't remember why I do that */
91
- set_sem_owner (Address [i + 1 ],ti .team );
119
+ /* Make sure to have ownership of the semaphore (if created by another team) */
120
+ TRACEDBGP ("->semctl id %d" ,Address [2 * i + 1 ]);
121
+ set_sem_owner (Address [2 * i + 1 ],ti .team );
92
122
93
123
/* Delete the semaphore */
94
- delete_sem (Address [i + 1 ]);
124
+ delete_sem (Address [2 * i + 1 ]);
95
125
96
126
/* Reset to an invalid semId (in case other process try to get the infos from a cloned area */
97
- Address [i + 1 ]= 0 ;
127
+ Address [2 * i + 1 ]= 0 ;
98
128
}
99
129
100
130
/* Set the semaphore count to 0 */
@@ -111,6 +141,7 @@ int semctl(int semId,int semNum,int flag,union semun semun)
111
141
if (flag == GETNCNT )
112
142
{
113
143
/* TO BE IMPLEMENTED */
144
+ TRACEDBG ("--semctl getncnt" );
114
145
elog (ERROR ,"beos : semctl error : GETNCNT not implemented" );
115
146
return 0 ;
116
147
}
@@ -119,12 +150,15 @@ int semctl(int semId,int semNum,int flag,union semun semun)
119
150
if (flag == GETVAL )
120
151
{
121
152
int32 cnt ;
122
- get_sem_count (Address [semNum + 1 ],& cnt );
153
+ TRACEDBG ("--semctl getval" );
154
+ get_sem_count (Address [2 * semNum + 1 ],& cnt );
155
+ TRACEDBGP ("--semctl val %d" ,cnt );
123
156
return cnt ;
124
157
}
125
158
126
159
elog (ERROR ,"beos : semctl error : unknown flag" );
127
160
161
+ TRACEDBG ("<-semctl unknown flag" );
128
162
return 0 ;
129
163
}
130
164
@@ -135,6 +169,7 @@ int semget(int semKey, int semNum, int flags)
135
169
area_id parea ;
136
170
void * Address ;
137
171
172
+ TRACEDBGPP ("->semget key : %d num : %d" ,semKey ,semNum );
138
173
/* Name of the area to find */
139
174
sprintf (Nom ,"SYSV_IPC_SEM : %d" ,semKey );
140
175
@@ -165,8 +200,9 @@ int semget(int semKey, int semNum, int flags)
165
200
void * Ad ;
166
201
long i ;
167
202
168
- /* Limit to 500 semaphore in a pool */
169
- if (semNum > 500 )
203
+ /* Limit to 250 (8 byte per sem : 4 for the semid and 4 for the last pid
204
+ which acceced the semaphore in a pool */
205
+ if (semNum > 250 )
170
206
{
171
207
errno = ENOSPC ;
172
208
return -1 ;
@@ -183,12 +219,12 @@ int semget(int semKey, int semNum, int flags)
183
219
/* fill up informations (sem number and sem ids) */
184
220
Address = (int32 * )Ad ;
185
221
Address [0 ]= semNum ;
186
- for (i = 1 ;i <= Address [0 ];i ++ )
222
+ for (i = 0 ;i < Address [0 ];i ++ )
187
223
{
188
224
/* Create the semaphores */
189
- Address [i ]= create_sem (0 ,Nom );
225
+ Address [2 * i + 1 ]= create_sem (0 ,Nom );
190
226
191
- if ((Address [i ]== B_BAD_VALUE )|| (Address [i ]== B_NO_MEMORY )|| (Address [i ]== B_NO_MORE_SEMS ))
227
+ if ((Address [2 * i + 1 ]== B_BAD_VALUE )|| (Address [2 * i + 1 ]== B_NO_MEMORY )|| (Address [2 * i + 1 ]== B_NO_MORE_SEMS ))
192
228
{
193
229
errno = ENOMEM ;
194
230
return -1 ;
@@ -212,6 +248,7 @@ int semop(int semId, struct sembuf *sops, int nsops)
212
248
int32 * Address ; /*Pool address*/
213
249
area_info info ;
214
250
long i ;
251
+ long ret ;
215
252
216
253
/* Get the pool address (semId IS an area id) */
217
254
get_area_info (semId ,& info );
@@ -227,16 +264,32 @@ int semop(int semId, struct sembuf *sops, int nsops)
227
264
/* Perform acquire or release */
228
265
for (i = 0 ;i < nsops ;i ++ )
229
266
{
267
+ /* remember the PID */
268
+ Address [2 * (sops [i ].sem_num )+ 2 ]= getpid ();
269
+
230
270
/* For each sem in the pool, check the operation to perform */
231
271
if (sops [i ].sem_op < 0 )
232
272
{
233
273
/* Try acuiring the semaphore till we are not inteerupted by a signal */
234
- while (acquire_sem_etc (Address [sops [i ].sem_num + 1 ],- sops [i ].sem_op ,0 ,0 )== B_INTERRUPTED );
274
+ if (sops [i ].sem_flg == IPC_NOWAIT )
275
+ {
276
+ /* Try to lock ... */
277
+ while ((ret = acquire_sem_etc (Address [2 * (sops [i ].sem_num )+ 1 ],- sops [i ].sem_op ,B_RELATIVE_TIMEOUT ,0 ))== B_INTERRUPTED );
278
+ if (ret != B_OK )
279
+ {
280
+ return EWOULDBLOCK ;
281
+ }
282
+ }
283
+ else
284
+ {
285
+ while (acquire_sem_etc (Address [2 * (sops [i ].sem_num )+ 1 ],- sops [i ].sem_op ,0 ,0 )== B_INTERRUPTED );
286
+ }
235
287
}
236
288
if (sops [i ].sem_op > 0 )
237
289
{
238
- release_sem_etc (Address [sops [i ].sem_num + 1 ],sops [i ].sem_op ,0 );
290
+ release_sem_etc (Address [2 * ( sops [i ].sem_num ) + 1 ],sops [i ].sem_op ,0 );
239
291
}
240
292
}
293
+
241
294
return 0 ;
242
295
}
0 commit comments