From 88094f2e2b7ef07a2b1af1ca5469c7abba173876 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Sat, 28 Oct 2000 18:27:57 +0000 Subject: [PATCH] beos fixes from Cyril VELTER --- src/backend/port/beos/sem.c | 128 ++++++++++++---------- src/backend/port/beos/shm.c | 62 ++++------- src/backend/port/beos/support.c | 162 +++++++++++++++++----------- src/backend/postmaster/postmaster.c | 14 ++- src/backend/tcop/postgres.c | 9 +- src/include/port/beos.h | 108 +++++++++---------- 6 files changed, 261 insertions(+), 222 deletions(-) diff --git a/src/backend/port/beos/sem.c b/src/backend/port/beos/sem.c index 17472759f0..d26369b3ee 100644 --- a/src/backend/port/beos/sem.c +++ b/src/backend/port/beos/sem.c @@ -13,160 +13,179 @@ #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 */ -// Controle d'un pool de sémaphores -// On considere que le semId utilisé correspond bien a une area de notre adress space -// Les informations du pool de sémaphore sont stockés dans cette area int semctl(int semId,int semNum,int flag,union semun semun) { - - // Recherche de l'adresse de base de l'area int32* Address; area_info info; -// printf("semctl : semid %d, semnum %d, cmd %d\n",semId,semNum,flag); + + /* Try to find the pool */ if (get_area_info(semId,&info)!=B_OK) { -// printf("area not found\n"); + /* pool is invalid (BeOS area id is invalid) */ errno=EINVAL; return -1; } + + /* Get the pool address */ Address=(int32*)info.address; - // semnum peut etre égal à 0 - // semun.array contient la valeur de départ du sémaphore - // si flag = set_all il faut définir la valeur du sémaphore sue semun.array + /* 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; -// printf("setall %d\n",Address[0]); for (i=0;i 0) - acquire_sem_etc(Address[i+1],cnt,0,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; } - /* si flag = SET_VAL il faut définir la valeur du sémaphore sur semun.val*/ + /* 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); -// printf("semctl set val id : %d val : %d = %d\n",semId,semun.val,cnt); + + /* Compute and set the new count (relative to the old one) */ cnt-=semun.val; if (cnt > 0) - acquire_sem_etc(Address[semNum+1],cnt,0,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; } - /* si flag=rm_id il faut supprimer le sémaphore*/ + /* Delete the pool */ if (flag==IPC_RMID) { long i; - // Suppression des sémaphores (ils appartienent au kernel maintenant) + thread_info ti; -// printf("remove set\n"); get_thread_info(find_thread(NULL),&ti); + + /* Loop over all semaphore to delete them */ for (i=0;i500) { errno=ENOSPC; return -1; } - - // Creation de la zone de mémoire partagée + + /* 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++) { - // Creation des sémaphores 1 par 1 + /* 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)) @@ -176,44 +195,43 @@ int semget(int semKey, int semNum, int flags) } } -// printf("returned %d\n",parea); return parea; } - // Le pool n'existe pas et pas de demande de création else { -// printf("set does not exist no creat requested\n"); + /* Area does not exist and no creation is requested */ errno=ENOENT; return -1; } } } -// Opération sur le pool de sémaphores +/* Acquire or release in the semaphore pool */ int semop(int semId, struct sembuf *sops, int nsops) { - // Recherche de l'adresse du pool - int32* Address; + int32* Address; /*Pool address*/ area_info info; long i; -// printf("semop id : %d n: %d\n",semId,sops->sem_op); + /* 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; } - // Execution de l'action + /* Perform acquire or release */ for(i=0;i 0) { diff --git a/src/backend/port/beos/shm.c b/src/backend/port/beos/shm.c index 1611d204f9..ee5b67fc9c 100644 --- a/src/backend/port/beos/shm.c +++ b/src/backend/port/beos/shm.c @@ -12,26 +12,25 @@ #include #include -// Detachement d'une zone de mémoire partagée -// On detruit le clone de l'area dans notre adress-space +/* Emulating SYS shared memory with beos areas. WARNING : fork clone +areas in copy on write mode */ + + +/* Detach from a shared mem area based on its address */ int shmdt(char* shmaddr) { - // Recherche de l'id de l'area présente à cette adresse + /* Find area id for this address */ area_id s; s=area_for(shmaddr); -// printf("detach area %d\n",s); - - // Suppression de l'area + + /* Delete area */ return delete_area(s); } -// Attachement à une zone de mémoire partagée -// L'area doit bien partie de notre adress-space et on retourne directement l'adress +/* Attach to an existing area */ int* shmat(int memId,int m1,int m2) { -// printf("shmat %d %d %d\n",memId,m1,m2); - - // Lecture de notre team_id + /* Get our team id */ thread_info thinfo; team_info teinfo; area_info ainfo; @@ -39,74 +38,59 @@ int* shmat(int memId,int m1,int m2) get_thread_info(find_thread(NULL),&thinfo); get_team_info(thinfo.team,&teinfo); - // Lecture du teamid de l'area + /* Get area teamid */ if (get_area_info(memId,&ainfo)!=B_OK) printf("AREA %d Invalide\n",memId); if (ainfo.team==teinfo.team) { - //retour de l'adresse -// printf("attach area %d add %d\n",memId,ainfo.address); + /* the area is already in our address space, just return the address */ return (int*)ainfo.address; } else { - // Clone de l'area + /* the area is not in our address space, clone it before and return the address */ area_id narea; narea = clone_area(ainfo.name,&(ainfo.address),B_CLONE_ADDRESS,B_READ_AREA | B_WRITE_AREA,memId); get_area_info(narea,&ainfo); -// printf("attach area %d in %d add %d\n",memId,narea,ainfo.address); return (int*)ainfo.address; } } -// Utilisé uniquement pour supprimer une zone de mémoire partagée -// On fait la meme chose que le detach mais avec un id direct +/* Control a shared mem area : Used only to delete it */ int shmctl(int shmid,int flag, struct shmid_ds* dummy) { -// printf("shmctl %d %d \n",shmid,flag); + /* Delete the area */ delete_area(shmid); return 0; } -// Recupération d'une area en fonction de sa référence -// L'area source est identifiée par son nom (convention à moi : SYSV_IPC_SHM : "memId) +/* Get an area based on the IPC key */ int shmget(int memKey,int size,int flag) { - int32 n_size; char nom[50]; - area_id parea; void* Address; - area_id a; - - n_size=((size/4096)+1)*4096; - -// printf("shmget %d %d %d %d\n",memKey,size,flag,nsize); + area_id parea; - // Determination du nom que doit avoir l'area + /* Area name */ sprintf(nom,"SYSV_IPC_SHM : %d",memKey); - - // Recherche de cette area + /* Find area */ parea=find_area(nom); - // L'area existe + /* area exist, just return its id */ if (parea!=B_NAME_NOT_FOUND) { -// printf("area found\n"); return parea; } - // L'area n'existe pas et on n'en demande pas la création : erreur + /* area does not exist and no creation is requested : error */ if (flag==0) { -// printf("area %s not found\n",nom); return -1; } - // L'area n'existe pas mais on demande sa création - a=create_area(nom,&Address,B_ANY_ADDRESS,n_size,B_NO_LOCK,B_READ_AREA | B_WRITE_AREA); -// printf("area %s : %d created addresse %d\n",nom,a,Address); - return a; + /* area does not exist and its creation is requested, create it (be sure to have a 4ko multiple size */ + return create_area(nom,&Address,B_ANY_ADDRESS,((size/4096)+1)*4096,B_NO_LOCK,B_READ_AREA | B_WRITE_AREA); } diff --git a/src/backend/port/beos/support.c b/src/backend/port/beos/support.c index d517dd7af3..3de7b65204 100644 --- a/src/backend/port/beos/support.c +++ b/src/backend/port/beos/support.c @@ -11,47 +11,48 @@ #include "postgres.h" /* Support Globals */ -char* self_binary=NULL; port_id beos_dl_port_in=0; port_id beos_dl_port_out=0; sem_id beos_shm_sem; +/* Global var containing the postgres path */ +extern char pg_pathname[]; + + +/* Shared library loading doesn't work after fork in beos. The solution is to use an exact +copy of the process and use it to perform the loading, then just map the Text and Data segment +of the add-on in our address space. Both process must have the exact same memory mapping, so +we use the postgres executable. When it's lauched with the -beossupportserver parameter, the +postgres executable just run a loop to wait command on a port. Its only action is to load the addon, +the beos_dl_open will then remap the good areas in the backend address space. */ + + image_id beos_dl_open(char * filename) { image_id im; - /* Start the support server */ - if (self_binary==NULL) - { - /* Can't start support server without binary name */ - elog(NOTICE, "Error loading BeOS support server : can't find binary"); - return B_ERROR; - } - else + /* If a port doesn't exist, lauch support server */ + if ((beos_dl_port_in<=0)||(beos_dl_port_out<=0)) { - /* If a port doesn't exist, lauch support server */ + /* Create communication port */ + beos_dl_port_in=create_port(50,"beos_support_in"); + beos_dl_port_out=create_port(50,"beos_support_in"); + + if ((beos_dl_port_in<=0)||(beos_dl_port_out<=0)) { - /* Create communication port */ - beos_dl_port_in=create_port(50,"beos_support_in"); - beos_dl_port_out=create_port(50,"beos_support_in"); - + elog(NOTICE, "Error loading BeOS support server : can't create communication ports"); + return B_ERROR; + } + else + { + char Cmd[4000]; + + /* Build arg list */ + sprintf(Cmd,"%s -beossupportserver %d %d &",pg_pathname,(int)beos_dl_port_in,(int)beos_dl_port_out); - if ((beos_dl_port_in<=0)||(beos_dl_port_out<=0)) - { - elog(NOTICE, "Error loading BeOS support server : can't create communication ports"); - return B_ERROR; - } - else - { - char Cmd[4000]; - - /* Build arg list */ - sprintf(Cmd,"%s -beossupportserver %d %d &",self_binary,(int)beos_dl_port_in,(int)beos_dl_port_out); - - /* Lauch process */ - system(Cmd); - } + /* Lauch process */ + system(Cmd); } } @@ -132,12 +133,14 @@ void beos_startup(int argc,char** argv) { if (strlen(argv[0]) >= 10 && !strcmp(argv[0] + strlen(argv[0]) - 10, "postmaster")) { - /* Shared memory cloning protection semaphore */ + /* We are in the postmaster, create the protection semaphore for shared mem remapping */ beos_shm_sem=create_sem(1,"beos_shm_sem"); } if (argc > 1 && strcmp(argv[1], "-beossupportserver") == 0) { + /* We are in the support server, run it ... */ + port_id port_in; port_id port_out; @@ -211,48 +214,77 @@ void beos_startup(int argc,char** argv) } -void beos_backend_startup(char * binary) + +/* The behavior of fork is borken on beos regarding shared memory. In fact +all shared memory areas are clones in copy on write mode in the new process. + +We need to do a remapping of these areas. Just afer the fork we performe the +following actions : + + * Find all areas with a name begining by SYS_V_IPC_ in our process + (areas created by the SYSV IPC emulation functions). The name is + followed by the IPC KEY in decimal format + + * For each area we do : + + * 1 : Get its name + * 2 : destroy it + * 3 : find another area with the exact same name + * 4 : clone it in our address space with a different name + + There is a race condition in 3-4 : if there two fork in a very short + time, in step 3 we might end up with two areas with the same name, and no + possibility to find the postmaster one. So the whole process is protected + by a semaphore which is acquires just before the fork and released in case + of fork failure or just after the end of the remapping.*/ + +void beos_before_backend_startup(void) +{ + /* Just before forking, acquire the semaphore */ + if(acquire_sem(beos_shm_sem)!=B_OK) + exit(1); /* Fatal error, exiting with error */ +} + +void beos_backend_startup_failed(void) +{ + /* The foek failed, just release the semaphore */ + release_sem(beos_shm_sem); +} + + +void beos_backend_startup(void) { - team_id ct; - thread_info inft; char nom[50]; char nvnom[50]; area_info inf; int32 cook=0; - /* remember full path binary name to load dl*/ - self_binary=strdup(binary); + /* Perform the remapping process */ - /* find the current team */ - get_thread_info(find_thread(NULL),&inft); - ct=inft.team; - - /* find all area with a name begining by pgsql and destroy / clone then */ - - /* This operation must be done by only one backend at a time */ - if(acquire_sem(beos_shm_sem)==B_OK) + /* Loop in all our team areas */ + while (get_next_area_info(0, &cook, &inf) == B_OK) { - while (get_next_area_info(0, &cook, &inf) == B_OK) + strcpy(nom,inf.name); + strcpy(nvnom,inf.name); + nom[9]=0; + nvnom[5]='i'; + /* Is it a SYS V area ? */ + if (!strcmp(nom,"SYSV_IPC_")) { - strcpy(nom,inf.name); - strcpy(nvnom,inf.name); - nom[9]=0; - nvnom[5]='i'; - if (!strcmp(nom,"SYSV_IPC_")) - { - void* add; - area_id ar; - add=inf.address; - delete_area(inf.area); - ar=find_area(inf.name); - clone_area(nvnom,&add,B_CLONE_ADDRESS,B_READ_AREA|B_WRITE_AREA,ar); - } - } - release_sem(beos_shm_sem); - } - else - { - /* Fatal error, exiting with error */ - exit(1); - } + void* area_address; + area_id area_postmaster; + /* Get the area address */ + area_address=inf.address; + /* Destroy the bad area */ + delete_area(inf.area); + /* Find the postmaster area */ + area_postmaster=find_area(inf.name); + /* Clone it at the exact same address */ + clone_area(nvnom,&area_address,B_CLONE_ADDRESS,B_READ_AREA|B_WRITE_AREA,area_postmaster); + } + } + + /* remapping done release semaphore to allow other backend to startup */ + + release_sem(beos_shm_sem); } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 51ec3b8885..d74cbf9e84 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.175 2000/10/25 22:27:25 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.176 2000/10/28 18:27:55 momjian Exp $ * * NOTES * @@ -1719,8 +1719,16 @@ BackendStartup(Port *port) fflush(stdout); fflush(stderr); +#ifdef __BEOS__ + /* Specific beos actions before backend startup */ + beos_before_backend_startup(); +#endif if ((pid = fork()) == 0) { /* child */ +#ifdef __BEOS__ + /* Specific beos backend stratup actions */ + beos_backend_startup(); +#endif if (DoBackend(port)) { fprintf(stderr, "%s child[%d]: BackendStartup: backend startup failed\n", @@ -1734,6 +1742,10 @@ BackendStartup(Port *port) /* in parent */ if (pid < 0) { +#ifdef __BEOS__ + /* Specific beos backend stratup actions */ + beos_backend_startup_failed(); +#endif fprintf(stderr, "%s: BackendStartup: fork failed: %s\n", progname, strerror(errno)); return STATUS_ERROR; diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 8fb2d1a2af..b024d604dc 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.183 2000/10/28 01:07:00 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.184 2000/10/28 18:27:56 momjian Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -1480,11 +1480,6 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha if (IsUnderPostmaster) { -#ifdef __BEOS__ - /* Specific beos backend stratup actions */ - beos_backend_startup(argv[0]); -#endif - /* noninteractive case: nothing should be left after switches */ if (errs || argc != optind || DBName == NULL) { @@ -1636,7 +1631,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.183 $ $Date: 2000/10/28 01:07:00 $\n"); + puts("$Revision: 1.184 $ $Date: 2000/10/28 18:27:56 $\n"); } /* diff --git a/src/include/port/beos.h b/src/include/port/beos.h index 60f46e3b9c..b27015d46e 100644 --- a/src/include/port/beos.h +++ b/src/include/port/beos.h @@ -1,4 +1,6 @@ #include +#include "kernel/image.h" + #define USE_POSIX_TIME #define HAS_TEST_AND_SET @@ -6,68 +8,64 @@ typedef unsigned char slock_t; #define AF_UNIX 1 /* no domain sockets on BeOS */ -#ifdef __cplusplus -extern "C" { -#endif - #include "kernel/image.h" - - #undef HAVE_UNION_SEMUN - #define HAVE_UNION_SEMUN 1 - #undef HAVE_SYS_SEM_H - #undef HAVE_SYS_SHM_H +/* SYS V emulation */ - union semun - { - int val; - struct semid_ds *buf; - unsigned short *array; - }; - /* SYS V emulation */ +#undef HAVE_UNION_SEMUN +#define HAVE_UNION_SEMUN 1 - #define IPC_RMID 256 - #define IPC_CREAT 512 - #define IPC_EXCL 1024 - #define IPC_PRIVATE 234564 +#define IPC_RMID 256 +#define IPC_CREAT 512 +#define IPC_EXCL 1024 +#define IPC_PRIVATE 234564 - #define EACCESS 2048 - #define EIDRM 4096 +#define EACCESS 2048 +#define EIDRM 4096 - #define SETALL 8192 - #define GETNCNT 16384 - #define GETVAL 65536 - #define SETVAL 131072 +#define SETALL 8192 +#define GETNCNT 16384 +#define GETVAL 65536 +#define SETVAL 131072 - struct sembuf - { - int sem_flg; - int sem_op; - int sem_num; - }; +union semun +{ + int val; + struct semid_ds *buf; + unsigned short *array; +}; - int semctl(int semId,int semNum,int flag,union semun); - int semget(int semKey, int semNum, int flags); - int semop(int semId, struct sembuf *sops, int flag); +struct sembuf +{ + int sem_flg; + int sem_op; + int sem_num; +}; - struct shmid_ds - { - int dummy; - }; +struct shmid_ds +{ + int dummy; +}; - int shmdt(char* shmaddr); - int* shmat(int memId,int m1,int m2); - int shmctl(int shmid,int flag, struct shmid_ds* dummy); - int shmget(int memKey,int size,int flag); +int semctl(int semId,int semNum,int flag,union semun); +int semget(int semKey, int semNum, int flags); +int semop(int semId, struct sembuf *sops, int flag); + +int shmdt(char* shmaddr); +int* shmat(int memId,int m1,int m2); +int shmctl(int shmid,int flag, struct shmid_ds* dummy); +int shmget(int memKey,int size,int flag); + +/* Support functions */ - /* Support functions */ - /* Specific beos action made on postgres/postmaster startup */ - void beos_startup(int argc,char** argv); - /* Load a shared library */ - image_id beos_dl_open(char * filename); - /* UnLoad a shared library */ - status_t beos_dl_close(image_id im); - /* Specific beos action made on backend startup */ - void beos_backend_startup(char* binary); -#ifdef __cplusplus -} -#endif \ No newline at end of file +/* Specific beos action made on postgres/postmaster startup */ +void beos_startup(int argc,char** argv); +/* Load a shared library */ +image_id beos_dl_open(char * filename); +/* UnLoad a shared library */ +status_t beos_dl_close(image_id im); +/* Specific beos action made on backend startup */ +void beos_before_backend_startup(void); +/* Specific beos action made on backend startup */ +void beos_backend_startup(void); +/* Specific beos action made on backend startup failure*/ +void beos_backend_startup_failed(void); -- 2.40.0