77 *
88 *
99 * 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 $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
2121#include <sys/mman.h>
2222#include "postgres.h"
2323#include "storage/ipc.h"
24+ #include "storage/proc.h"
2425#include <sys/sem.h>
2526
2627
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
2931
30- #define MODE 0777
32+ #define MODE 0700
3133#define SHM_INFO_NAME "SysV_Sem_Info"
3234
3335
36+ struct pending_ops {
37+ int op [OPMAX ];/* array of pending operations */
38+ int idx ;/* index of first free array member */
39+ };
40+
3441struct sem_info {
3542sem_t sem ;
3643struct {
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 */
4149 }set [SETMAX ];
4250};
4351
@@ -46,7 +54,7 @@ static struct sem_info *SemInfo = ( struct sem_info * )-1;
4654
4755int semctl (int semid ,int semnum ,int cmd ,/*...*/ union semun arg )
4856{
49- int r ;
57+ int r = 0 ;
5058
5159sem_wait (& SemInfo -> sem );
5260
@@ -58,30 +66,38 @@ int semctl( int semid, int semnum, int cmd, /*...*/union semun arg )
5866 }
5967
6068switch (cmd ) {
69+ case GETNCNT :
70+ r = SemInfo -> set [semid ].semV [semnum ].semncnt ;
71+ break ;
72+
6173case GETPID :
62- r = SemInfo -> set [semid ].pid [semnum ];
74+ r = SemInfo -> set [semid ].semV [semnum ]. sempid ;
6375break ;
6476
6577case GETVAL :
66- r = SemInfo -> set [semid ].sem [semnum ].value ;
78+ r = SemInfo -> set [semid ].semV [semnum ].semval ;
6779break ;
6880
6981case GETALL :
7082for (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 ;
7284 }
7385break ;
7486
7587case SETVAL :
76- SemInfo -> set [semid ].sem [semnum ].value = arg .val ;
88+ SemInfo -> set [semid ].semV [semnum ].semval = arg .val ;
7789break ;
7890
7991case SETALL :
8092for (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 ];
8294 }
8395break ;
8496
97+ case GETZCNT :
98+ r = SemInfo -> set [semid ].semV [semnum ].semzcnt ;
99+ break ;
100+
85101case IPC_RMID :
86102for (semnum = 0 ;semnum < SemInfo -> set [semid ].nsems ;semnum ++ ) {
87103if (sem_destroy (& SemInfo -> set [semid ].sem [semnum ] )== -1 ) {
@@ -121,12 +137,16 @@ int semget( key_t key, int nsems, int semflg )
121137exist = 1 ;
122138fd = shm_open (SHM_INFO_NAME ,O_RDWR |O_CREAT ,MODE );
123139 }
124- if (fd == -1 )return fd ;
140+ if (fd == -1 ) {
141+ return fd ;
142+ }
125143/* The size may only be set once. Ignore errors. */
126144ltrunc (fd ,sizeof (struct sem_info ),SEEK_SET );
127145SemInfo = mmap (NULL ,sizeof (struct sem_info ),
128146PROT_READ |PROT_WRITE ,MAP_SHARED ,fd ,0 );
129- if (SemInfo == MAP_FAILED )return -1 ;
147+ if (SemInfo == MAP_FAILED ) {
148+ return -1 ;
149+ }
130150if ( !exist ) {
131151/* create semaphore for locking */
132152sem_init (& SemInfo -> sem ,1 ,1 );
@@ -196,12 +216,12 @@ int semget( key_t key, int nsems, int semflg )
196216
197217sem_post (& SemInfo -> sem );
198218
199- return 0 ;
219+ return semid ;
200220}
201221
202222int semop (int semid ,struct sembuf * sops ,size_t nsops )
203223{
204- int i ,j , r = 0 ,r1 ,errno1 = 0 ;
224+ int i ,r = 0 ,r1 ,errno1 = 0 , op ;
205225
206226sem_wait (& SemInfo -> sem );
207227
@@ -220,38 +240,67 @@ int semop( int semid, struct sembuf *sops, size_t nsops )
220240
221241for (i = 0 ;i < nsops ;i ++ ) {
222242if (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 ;
229248 }
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 -- ;
230271 }
231272else {
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 ;
241274 }
242275 }
243276else 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 ;
248294 }
249295 }
250296 }
251297else /* sops[i].sem_op == 0 */ {
252298/* not supported */
299+ sem_post (& SemInfo -> sem );
300+ errno = ENOSYS ;
301+ return -1 ;
253302 }
254- SemInfo -> set [semid ].pid [sops [i ].sem_num ]= getpid ( );
303+ SemInfo -> set [semid ].semV [sops [i ].sem_num ]. sempid = getpid ( );
255304 }
256305
257306sem_post (& SemInfo -> sem );