aboutsummaryrefslogtreecommitdiff
path: root/src/backend/port/beos/shm.c
blob: b30fc2b6b370e1c64da3281c42800db0242e47c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*-------------------------------------------------------------------------
 *
 * shm.c
 *	  BeOS System V Shared Memory Emulation
 *
 * Copyright (c) 1999-2001, Cyril VELTER
 * 
 *-------------------------------------------------------------------------
 */

#include "postgres.h"
#include <stdio.h>
#include <OS.h>
#include <errno.h>

/* 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)
{
	/* Find area id for this address */
	area_id s;
	s=area_for(shmaddr);

	/* Delete area */
	return delete_area(s);
}

/* Attach to an existing area */
int* shmat(int memId,int m1,int m2)
{
	/* Get our team id */
	thread_info thinfo;
	team_info teinfo;
	area_info ainfo; 
	
	get_thread_info(find_thread(NULL),&thinfo);
	get_team_info(thinfo.team,&teinfo);
	
	/* Get area teamid */
	if (get_area_info(memId,&ainfo)!=B_OK)
		printf("AREA %d Invalide\n",memId);
	
	if (ainfo.team==teinfo.team)
	{
		/* the area is already in our address space, just return the address */
		return (int*)ainfo.address;
	}	
	else
	{
		/* 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);	
		return (int*)ainfo.address;
	}
}

/* Control a shared mem area */
int shmctl(int shmid, int flag, struct shmid_ds* dummy)
{
	if (flag == IPC_RMID)
	{
		/* Delete the area */
		delete_area(shmid);
		return 0;
	}
	if (flag == IPC_STAT)
	{
		/* Find any SYSV area with the shmid in its name */

		area_info inf;
		team_info infteam;
		int32 cookteam=0;
		char name[50];
		sprintf(name,"SYSV_IPC %d",shmid);	
	
		dummy->shm_nattch=0;
		
		while (get_next_team_info(&cookteam, &infteam) == B_OK)
		{ 
			int32 cook=0;
			while (get_next_area_info(infteam.team, &cook, &inf) == B_OK)
			{
				if (strcmp(name,inf.name) == 0)
				{
					dummy->shm_nattch++;	
				}
			}
		}
			
		errno = 0;
		return 0;
	}
	errno = EINVAL;
	return -1;
}

/* Get an area based on the IPC key */
int shmget(int memKey,int size,int flag)
{
	char nom[50];
	void* Address;
	area_id parea;

	/* Area name */
	sprintf(nom,"SYSV_IPC_SHM : %d",memKey);

	/* Find area */
	parea=find_area(nom);
	
	/* area exist, just return its id */
	if (parea!=B_NAME_NOT_FOUND)
	{
		return parea;
	}	

	/* area does not exist and no creation is requested : error */
	if (flag==0)
	{
		return -1;
	}
	
	/* 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);		
}