/*------------------------------------------------------------------------- * * sem.c * BeOS System V Semaphores Emulation * * Copyright (c) 1999-2000, Cyril VELTER * *------------------------------------------------------------------------- */ #include "postgres.h" #include #include #include #include "utils/elog.h" /* Control of a semaphore pool. The pool is an area in which we stored all the semIds of the pool. The first 4 bytes are the number of semaphore allocated in the pool followed by SemIds */ int semctl(int semId,int semNum,int flag,union semun semun) { int32* Address; area_info info; /* Try to find the pool */ if (get_area_info(semId,&info)!=B_OK) { /* pool is invalid (BeOS area id is invalid) */ errno=EINVAL; return -1; } /* Get the pool address */ Address=(int32*)info.address; /* semNum might be 0 */ /* semun.array contain the sem initial values */ /* Fix the count of all sem of the pool to semun.array */ if (flag==SETALL) { long i; for (i=0;i 0) while(acquire_sem_etc(Address[i+1],cnt,0,0)==B_INTERRUPTED); if (cnt < 0) release_sem_etc(Address[i+1],-cnt,0); } return 1; } /* Fix the count of one semaphore to semun.val */ if (flag==SETVAL) { int32 cnt; /* Get the current count */ get_sem_count(Address[semNum+1],&cnt); /* Compute and set the new count (relative to the old one) */ cnt-=semun.val; if (cnt > 0) while(acquire_sem_etc(Address[semNum+1],cnt,0,0)==B_INTERRUPTED); if (cnt < 0) release_sem_etc(Address[semNum+1],-cnt,0); return 1; } /* Delete the pool */ if (flag==IPC_RMID) { long i; thread_info ti; get_thread_info(find_thread(NULL),&ti); /* Loop over all semaphore to delete them */ for (i=0;i500) { errno=ENOSPC; return -1; } /* Create the shared memory area which will hold the pool */ parea=create_area(Nom,&Ad,B_ANY_ADDRESS,4096,B_NO_LOCK,B_READ_AREA | B_WRITE_AREA); if ((parea==B_BAD_VALUE)|| (parea==B_NO_MEMORY)||(parea==B_ERROR)) { errno=ENOMEM; return -1; } /* fill up informations (sem number and sem ids) */ Address=(int32*)Ad; Address[0]=semNum; for (i=1;i<=Address[0];i++) { /* Create the semaphores */ Address[i]=create_sem(0,Nom); if ((Address[i]==B_BAD_VALUE)|| (Address[i]==B_NO_MEMORY)||(Address[i]==B_NO_MORE_SEMS)) { errno=ENOMEM; return -1; } } return parea; } else { /* Area does not exist and no creation is requested */ errno=ENOENT; return -1; } } } /* Acquire or release in the semaphore pool */ int semop(int semId, struct sembuf *sops, int nsops) { int32* Address; /*Pool address*/ area_info info; long i; /* Get the pool address (semId IS an area id) */ get_area_info(semId,&info); Address=(int32*)info.address; /* Check the validity of semId (it should be an area id) */ if ((semId==B_BAD_VALUE)||(semId==B_NO_MEMORY)||(semId==B_ERROR)) { errno=EINVAL; return -1; } /* Perform acquire or release */ for(i=0;i 0) { release_sem_etc(Address[sops[i].sem_num+1],sops[i].sem_op,0); } } return 0; }