7
7
*
8
8
*
9
9
* IDENTIFICATION
10
- * $Header: /cvsroot/pgsql/src/backend/port/qnx4/Attic/sem.c,v 1.1 1999/12/16 16:52:52 momjian Exp $
10
+ * $Header: /cvsroot/pgsql/src/backend/port/qnx4/Attic/sem.c,v 1.2 2000/03/14 18:12:06 momjian Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
21
21
#include <sys/mman.h>
22
22
#include "postgres.h"
23
23
#include "storage/ipc.h"
24
+ #include "storage/proc.h"
24
25
#include <sys/sem.h>
25
26
26
27
27
- #define SETMAX 32
28
- #define SEMMAX 16
28
+ #define SETMAX ((MAXBACKENDS + PROC_NSEMS_PER_SET - 1) / PROC_NSEMS_PER_SET)
29
+ #define SEMMAX (PROC_NSEMS_PER_SET)
30
+ #define OPMAX 8
29
31
30
- #define MODE 0777
32
+ #define MODE 0700
31
33
#define SHM_INFO_NAME "SysV_Sem_Info"
32
34
33
35
36
+ struct pending_ops {
37
+ int op [OPMAX ];/* array of pending operations */
38
+ int idx ;/* index of first free array member */
39
+ };
40
+
34
41
struct sem_info {
35
42
sem_t sem ;
36
43
struct {
37
- key_t key ;
38
- int nsems ;
39
- sem_t sem [SEMMAX ];/* array of semaphores */
40
- pid_t pid [SEMMAX ];/* array of PIDs */
44
+ key_t key ;
45
+ int nsems ;
46
+ sem_t sem [SEMMAX ];/* array of POSIX semaphores */
47
+ struct sem semV [SEMMAX ];/* array of System V semaphore structures */
48
+ struct pending_ops pendingOps [SEMMAX ];/* array of pending operations */
41
49
}set [SETMAX ];
42
50
};
43
51
@@ -46,7 +54,7 @@ static struct sem_info *SemInfo = ( struct sem_info * )-1;
46
54
47
55
int semctl (int semid ,int semnum ,int cmd ,/*...*/ union semun arg )
48
56
{
49
- int r ;
57
+ int r = 0 ;
50
58
51
59
sem_wait (& SemInfo -> sem );
52
60
@@ -58,30 +66,38 @@ int semctl( int semid, int semnum, int cmd, /*...*/union semun arg )
58
66
}
59
67
60
68
switch (cmd ) {
69
+ case GETNCNT :
70
+ r = SemInfo -> set [semid ].semV [semnum ].semncnt ;
71
+ break ;
72
+
61
73
case GETPID :
62
- r = SemInfo -> set [semid ].pid [semnum ];
74
+ r = SemInfo -> set [semid ].semV [semnum ]. sempid ;
63
75
break ;
64
76
65
77
case GETVAL :
66
- r = SemInfo -> set [semid ].sem [semnum ].value ;
78
+ r = SemInfo -> set [semid ].semV [semnum ].semval ;
67
79
break ;
68
80
69
81
case GETALL :
70
82
for (semnum = 0 ;semnum < SemInfo -> set [semid ].nsems ;semnum ++ ) {
71
- arg .array [semnum ]= SemInfo -> set [semid ].sem [semnum ].value ;
83
+ arg .array [semnum ]= SemInfo -> set [semid ].semV [semnum ].semval ;
72
84
}
73
85
break ;
74
86
75
87
case SETVAL :
76
- SemInfo -> set [semid ].sem [semnum ].value = arg .val ;
88
+ SemInfo -> set [semid ].semV [semnum ].semval = arg .val ;
77
89
break ;
78
90
79
91
case SETALL :
80
92
for (semnum = 0 ;semnum < SemInfo -> set [semid ].nsems ;semnum ++ ) {
81
- SemInfo -> set [semid ].sem [semnum ].value = arg .array [semnum ];
93
+ SemInfo -> set [semid ].semV [semnum ].semval = arg .array [semnum ];
82
94
}
83
95
break ;
84
96
97
+ case GETZCNT :
98
+ r = SemInfo -> set [semid ].semV [semnum ].semzcnt ;
99
+ break ;
100
+
85
101
case IPC_RMID :
86
102
for (semnum = 0 ;semnum < SemInfo -> set [semid ].nsems ;semnum ++ ) {
87
103
if (sem_destroy (& SemInfo -> set [semid ].sem [semnum ] )== -1 ) {
@@ -121,12 +137,16 @@ int semget( key_t key, int nsems, int semflg )
121
137
exist = 1 ;
122
138
fd = shm_open (SHM_INFO_NAME ,O_RDWR |O_CREAT ,MODE );
123
139
}
124
- if (fd == -1 )return fd ;
140
+ if (fd == -1 ) {
141
+ return fd ;
142
+ }
125
143
/* The size may only be set once. Ignore errors. */
126
144
ltrunc (fd ,sizeof (struct sem_info ),SEEK_SET );
127
145
SemInfo = mmap (NULL ,sizeof (struct sem_info ),
128
146
PROT_READ |PROT_WRITE ,MAP_SHARED ,fd ,0 );
129
- if (SemInfo == MAP_FAILED )return -1 ;
147
+ if (SemInfo == MAP_FAILED ) {
148
+ return -1 ;
149
+ }
130
150
if ( !exist ) {
131
151
/* create semaphore for locking */
132
152
sem_init (& SemInfo -> sem ,1 ,1 );
@@ -196,12 +216,12 @@ int semget( key_t key, int nsems, int semflg )
196
216
197
217
sem_post (& SemInfo -> sem );
198
218
199
- return 0 ;
219
+ return semid ;
200
220
}
201
221
202
222
int semop (int semid ,struct sembuf * sops ,size_t nsops )
203
223
{
204
- int i ,j , r = 0 ,r1 ,errno1 = 0 ;
224
+ int i ,r = 0 ,r1 ,errno1 = 0 , op ;
205
225
206
226
sem_wait (& SemInfo -> sem );
207
227
@@ -220,38 +240,67 @@ int semop( int semid, struct sembuf *sops, size_t nsops )
220
240
221
241
for (i = 0 ;i < nsops ;i ++ ) {
222
242
if (sops [i ].sem_op < 0 ) {
223
- if (sops [i ].sem_flg & IPC_NOWAIT ) {
224
- for (j = 0 ;j < - sops [i ].sem_op ;j ++ ) {
225
- if (sem_trywait (& SemInfo -> set [semid ].sem [sops [i ].sem_num ] ) ) {
226
- errno1 = errno ;
227
- r = -1 ;
228
- }
243
+ if (SemInfo -> set [semid ].semV [sops [i ].sem_num ].semval < - sops [i ].sem_op ) {
244
+ if (sops [i ].sem_flg & IPC_NOWAIT ) {
245
+ sem_post (& SemInfo -> sem );
246
+ errno = EAGAIN ;
247
+ return -1 ;
229
248
}
249
+ SemInfo -> set [semid ].semV [sops [i ].sem_num ].semncnt ++ ;
250
+ if (SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].idx >=OPMAX ) {
251
+ /* pending operations array overflow */
252
+ sem_post (& SemInfo -> sem );
253
+ errno = ERANGE ;
254
+ return -1 ;
255
+ }
256
+ SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].op [SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].idx ++ ]= sops [i ].sem_op ;
257
+ /* suspend */
258
+ sem_post (& SemInfo -> sem );/* avoid deadlock */
259
+ r1 = sem_wait (& SemInfo -> set [semid ].sem [sops [i ].sem_num ] );
260
+ sem_wait (& SemInfo -> sem );
261
+ if (r1 ) {
262
+ errno1 = errno ;
263
+ r = r1 ;
264
+ /* remove pending operation */
265
+ SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].op [-- SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].idx ]= 0 ;
266
+ }
267
+ else {
268
+ SemInfo -> set [semid ].semV [sops [i ].sem_num ].semval -= - sops [i ].sem_op ;
269
+ }
270
+ SemInfo -> set [semid ].semV [sops [i ].sem_num ].semncnt -- ;
230
271
}
231
272
else {
232
- for (j = 0 ;j < - sops [i ].sem_op ;j ++ ) {
233
- sem_post (& SemInfo -> sem );/* avoid deadlock */
234
- r1 = sem_wait (& SemInfo -> set [semid ].sem [sops [i ].sem_num ] );
235
- sem_wait (& SemInfo -> sem );
236
- if (r1 ) {
237
- errno1 = errno ;
238
- r = r1 ;
239
- }
240
- }
273
+ SemInfo -> set [semid ].semV [sops [i ].sem_num ].semval -= - sops [i ].sem_op ;
241
274
}
242
275
}
243
276
else if (sops [i ].sem_op > 0 ) {
244
- for (j = 0 ;j < sops [i ].sem_op ;j ++ ) {
245
- if (sem_post (& SemInfo -> set [semid ].sem [sops [i ].sem_num ] ) ) {
246
- errno1 = errno ;
247
- r = -1 ;
277
+ SemInfo -> set [semid ].semV [sops [i ].sem_num ].semval += sops [i ].sem_op ;
278
+ op = sops [i ].sem_op ;
279
+ while (op > 0 && SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].idx > 0 ) {/* operations pending */
280
+ if (SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].op [SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].idx - 1 ]+ op >=0 ) {
281
+ /* unsuspend processes */
282
+ if (sem_post (& SemInfo -> set [semid ].sem [sops [i ].sem_num ] ) ) {
283
+ errno1 = errno ;
284
+ r = -1 ;
285
+ }
286
+ /* adjust pending operations */
287
+ op += SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].op [-- SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].idx ];
288
+ SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].op [SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].idx ]= 0 ;
289
+ }
290
+ else {
291
+ /* adjust pending operations */
292
+ SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].op [SemInfo -> set [semid ].pendingOps [sops [i ].sem_num ].idx - 1 ]+= op ;
293
+ op = 0 ;
248
294
}
249
295
}
250
296
}
251
297
else /* sops[i].sem_op == 0 */ {
252
298
/* not supported */
299
+ sem_post (& SemInfo -> sem );
300
+ errno = ENOSYS ;
301
+ return -1 ;
253
302
}
254
- SemInfo -> set [semid ].pid [sops [i ].sem_num ]= getpid ( );
303
+ SemInfo -> set [semid ].semV [sops [i ].sem_num ]. sempid = getpid ( );
255
304
}
256
305
257
306
sem_post (& SemInfo -> sem );