1 | /*-------------------------------------------------------------------------
|
---|
2 | *
|
---|
3 | * shm.c
|
---|
4 | * BeOS System V Shared Memory Emulation
|
---|
5 | *
|
---|
6 | * Copyright (c) 1999-2001, Cyril VELTER
|
---|
7 | *
|
---|
8 | *-------------------------------------------------------------------------
|
---|
9 | */
|
---|
10 |
|
---|
11 | #include <sys/shm.h>
|
---|
12 | #include <OS.h>
|
---|
13 | #include <errno.h>
|
---|
14 |
|
---|
15 | /* Emulating SYS shared memory with beos areas. WARNING : fork clone
|
---|
16 | areas in copy on write mode */
|
---|
17 |
|
---|
18 |
|
---|
19 | /* Detach from a shared mem area based on its address */
|
---|
20 | int
|
---|
21 | shmdt(char *shmaddr)
|
---|
22 | {
|
---|
23 | /* Find area id for this address */
|
---|
24 | area_id s;
|
---|
25 |
|
---|
26 | s = area_for(shmaddr);
|
---|
27 |
|
---|
28 | /* Delete area */
|
---|
29 | return delete_area(s);
|
---|
30 | }
|
---|
31 |
|
---|
32 | /* Attach to an existing area */
|
---|
33 | int *
|
---|
34 | shmat(int memId, int m1, int m2)
|
---|
35 | {
|
---|
36 | /* Get our team id */
|
---|
37 | thread_info thinfo;
|
---|
38 | team_info teinfo;
|
---|
39 | area_info ainfo;
|
---|
40 |
|
---|
41 | get_thread_info(find_thread(NULL), &thinfo);
|
---|
42 | get_team_info(thinfo.team, &teinfo);
|
---|
43 |
|
---|
44 | /* Get area teamid */
|
---|
45 | if (get_area_info(memId, &ainfo) != B_OK)
|
---|
46 | printf("AREA %d Invalide\n", memId);
|
---|
47 |
|
---|
48 | if (ainfo.team == teinfo.team)
|
---|
49 | {
|
---|
50 | /*
|
---|
51 | * the area is already in our address space, just return the address
|
---|
52 | */
|
---|
53 | return (int *) ainfo.address;
|
---|
54 | }
|
---|
55 | else
|
---|
56 | {
|
---|
57 | /*
|
---|
58 | * the area is not in our address space, clone it before and return
|
---|
59 | * the address
|
---|
60 | */
|
---|
61 | area_id narea;
|
---|
62 |
|
---|
63 | narea = clone_area(ainfo.name, &(ainfo.address), B_CLONE_ADDRESS, B_READ_AREA | B_WRITE_AREA, memId);
|
---|
64 | get_area_info(narea, &ainfo);
|
---|
65 | return (int *) ainfo.address;
|
---|
66 | }
|
---|
67 | }
|
---|
68 |
|
---|
69 | /* Control a shared mem area */
|
---|
70 | int
|
---|
71 | shmctl(int shmid, int flag, struct shmid_ds * dummy)
|
---|
72 | {
|
---|
73 | if (flag == IPC_RMID)
|
---|
74 | {
|
---|
75 | /* Delete the area */
|
---|
76 | delete_area(shmid);
|
---|
77 | return 0;
|
---|
78 | }
|
---|
79 | if (flag == IPC_STAT)
|
---|
80 | {
|
---|
81 | /* Find any SYSV area with the shmid in its name */
|
---|
82 |
|
---|
83 | area_info inf;
|
---|
84 | team_info infteam;
|
---|
85 | int32 cookteam = 0;
|
---|
86 | char name[50];
|
---|
87 |
|
---|
88 | sprintf(name, "SYSV_IPC %d", shmid);
|
---|
89 |
|
---|
90 | dummy->shm_nattch = 0;
|
---|
91 |
|
---|
92 | while (get_next_team_info(&cookteam, &infteam) == B_OK)
|
---|
93 | {
|
---|
94 | int32 cook = 0;
|
---|
95 |
|
---|
96 | while (get_next_area_info(infteam.team, &cook, &inf) == B_OK)
|
---|
97 | {
|
---|
98 | if (strcmp(name, inf.name) == 0)
|
---|
99 | dummy->shm_nattch++;
|
---|
100 | }
|
---|
101 | }
|
---|
102 |
|
---|
103 | errno = 0;
|
---|
104 | return 0;
|
---|
105 | }
|
---|
106 | errno = EINVAL;
|
---|
107 | return -1;
|
---|
108 | }
|
---|
109 |
|
---|
110 | /* Get an area based on the IPC key */
|
---|
111 | int
|
---|
112 | shmget(int memKey, int size, int flag)
|
---|
113 | {
|
---|
114 | char nom[50];
|
---|
115 | void *Address;
|
---|
116 | area_id parea;
|
---|
117 |
|
---|
118 | /* Area name */
|
---|
119 | sprintf(nom, "SYSV_IPC_SHM : %d", memKey);
|
---|
120 |
|
---|
121 | /* Find area */
|
---|
122 | parea = find_area(nom);
|
---|
123 |
|
---|
124 | /* area exist, just return its id */
|
---|
125 | if (parea != B_NAME_NOT_FOUND)
|
---|
126 | return parea;
|
---|
127 |
|
---|
128 | /* area does not exist and no creation is requested : error */
|
---|
129 | if (flag == 0)
|
---|
130 | return -1;
|
---|
131 |
|
---|
132 | /*
|
---|
133 | * area does not exist and its creation is requested, create it (be sure
|
---|
134 | * to have a 4ko multiple size
|
---|
135 | */
|
---|
136 | return create_area(nom, &Address, B_ANY_ADDRESS, ((size / 4096) + 1) * 4096, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
---|
137 | }
|
---|