beos fixes from Cyril VELTER

This commit is contained in:
Bruce Momjian 2000-10-28 18:27:57 +00:00
parent 5b0740d3fc
commit 88094f2e2b
6 changed files with 267 additions and 228 deletions

View File

@ -13,160 +13,179 @@
#include <stdio.h>
#include <errno.h>
#include <OS.h>
#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<Address[0];i++)
{
int32 cnt;
/* Get the current count */
get_sem_count(Address[i+1],&cnt);
// printf("Set de ALl %d %d = %d\n",Address[i+1],semun.array[i],cnt);
/* Compute and set the new count (relative to the old one) */
cnt-=semun.array[i];
if (cnt > 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;i<Address[0];i++)
{
/* Don't remember why I do that */
set_sem_owner(Address[i+1],ti.team);
/* Delete the semaphore */
delete_sem(Address[i+1]);
/* Reset to an invalid semId (in case other process try to get the infos from a cloned area */
Address[i+1]=0;
}
// Il faudrait supprimer en boucle toutes les area portant le même nom
/* Set the semaphore count to 0 */
Address[0]=0;
/* Delete the area (it might be cloned by other process. Let them live with it,
in all cases semIds are 0 so if another process try to use it, it will fail */
delete_area(semId);
return 1;
}
/* si flag = GETNCNT il faut renvoyer le semaphore count*/
/* Get the current semaphore count */
if (flag==GETNCNT)
{
// printf("getncnt : impossible sur BeOS\n");
return 0; // a faire (peut etre impossible sur Beos)
/* TO BE IMPLEMENTED */
elog(ERROR,"beos : semctl error : GETNCNT not implemented");
return 0;
}
/* si flag = GETVAL il faut renvoyer la valeur du sémaphore*/
/* Get the current semaphore count of the first semaphore in the pool */
if (flag==GETVAL)
{
int32 cnt;
get_sem_count(Address[semNum+1],&cnt);
// printf("semctl getval id : %d cnt : %d\n",semId,cnt);
return cnt;
}
// printf("semctl erreur\n");
elog(ERROR,"beos : semctl error : unknown flag");
return 0;
}
// L'area dans laquelle est stockée le pool est identifiée par son nom (convention à moi : SYSV_IPC_SEM : "semId)
/* Find a pool id based on IPC key */
int semget(int semKey, int semNum, int flags)
{
char Nom[50];
area_id parea;
void* Address;
// printf("semget get k: %d n: %d fl:%d\n",semKey,semNum,flags);
// Construction du nom que doit avoir l'area
/* Name of the area to find */
sprintf(Nom,"SYSV_IPC_SEM : %d",semKey);
// Recherche de l'area
/* find area */
parea=find_area(Nom);
// L'area existe
/* Test of area existance */
if (parea!=B_NAME_NOT_FOUND)
{
// printf("area found\n");
// On demande une creatrion d'un pool existant : erreur
/* Area exist and creation is requested, error */
if ((flags&IPC_CREAT)&&(flags&IPC_EXCL))
{
// printf("creat asking exist\n");
errno=EEXIST;
return -1;
}
// Clone de l'area et renvoi de son ID
/* Get an area clone (in case it's not in our address space) */
/* TODO : a check of address space might be done to avoid duplicate areas in the same address space*/
parea=clone_area(Nom,&Address,B_ANY_ADDRESS,B_READ_AREA | B_WRITE_AREA,parea);
return parea;
}
// L'area n'existe pas
else
{
// printf("set don't exist\n");
// Demande de creation
/* Area does not exist, but creation is requested, so create it */
if (flags&IPC_CREAT)
{
int32* Address;
thread_info ti;
void* Ad;
long i;
// printf("create set\n");
// On ne peut pas creer plus de 500 semaphores dans un pool (limite tout à fait arbitraire de ma part)
/* Limit to 500 semaphore in a pool */
if (semNum>500)
{
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<nsops;i++)
{
// printf("semid %d, n %d\n",Address[sops[i].sem_num+1],sops[i].sem_op);
/* For each sem in the pool, check the operation to perform */
if (sops[i].sem_op < 0)
{
acquire_sem_etc(Address[sops[i].sem_num+1],-sops[i].sem_op,0,0);
/* Try acuiring the semaphore till we are not inteerupted by a signal */
while (acquire_sem_etc(Address[sops[i].sem_num+1],-sops[i].sem_op,0,0)==B_INTERRUPTED);
}
if (sops[i].sem_op > 0)
{

View File

@ -12,26 +12,25 @@
#include <stdio.h>
#include <OS.h>
// 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;
area_id parea;
// printf("shmget %d %d %d %d\n",memKey,size,flag,nsize);
// 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);
}

View File

@ -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)
/* If a port doesn't exist, lauch support server */
if ((beos_dl_port_in<=0)||(beos_dl_port_out<=0))
{
/* 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 */
/* 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);
}

View File

@ -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;

View File

@ -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");
}
/*

View File

@ -1,4 +1,6 @@
#include <kernel/OS.h>
#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"
/* 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 EACCESS 2048
#define EIDRM 4096
#define SETALL 8192
#define GETNCNT 16384
#define GETVAL 65536
#define SETVAL 131072
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
struct sembuf
{
int sem_flg;
int sem_op;
int sem_num;
};
struct shmid_ds
{
int dummy;
};
#undef HAVE_UNION_SEMUN
#define HAVE_UNION_SEMUN 1
#undef HAVE_SYS_SEM_H
#undef HAVE_SYS_SHM_H
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);
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
/* SYS V emulation */
#define IPC_RMID 256
#define IPC_CREAT 512
#define IPC_EXCL 1024
#define IPC_PRIVATE 234564
#define EACCESS 2048
#define EIDRM 4096
#define SETALL 8192
#define GETNCNT 16384
#define GETVAL 65536
#define SETVAL 131072
struct sembuf
{
int sem_flg;
int sem_op;
int sem_num;
};
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 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 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 */
/* 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
/* 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_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);