-
Notifications
You must be signed in to change notification settings - Fork 0
/
shared_memory_manager.c
300 lines (263 loc) · 10.1 KB
/
shared_memory_manager.c
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
#include <inc/mmu.h>
#include <inc/error.h>
#include <inc/string.h>
#include <inc/assert.h>
#include <inc/environment_definitions.h>
#include <kern/shared_memory_manager.h>
#include <kern/memory_manager.h>
#include <kern/syscall.h>
#include <kern/kheap.h>
//2019
//==================================================================================//
//============================== GIVEN FUNCTIONS ===================================//
//==================================================================================//
//===========================
// [1] Create "shares" array:
//===========================
//Dynamically allocate the array of shared objects
//initialize the array of shared objects by 0's and empty = 1
void create_shares_array(uint32 numOfElements)
{
shares = kmalloc(numOfElements*sizeof(struct Share));
if (shares == NULL)
{
panic("Kernel runs out of memory\nCan't create the array of shared objects.");
}
for (int i = 0; i < MAX_SHARES; ++i)
{
memset(&(shares[i]), 0, sizeof(struct Share));
shares[i].empty = 1;
}
}
//===========================
// [2] Allocate Share Object:
//===========================
//Allocates a new (empty) shared object from the "shares" array
//It dynamically creates the "framesStorage"
//Return:
// a) if succeed:
// 1. allocatedObject (pointer to struct Share) passed by reference
// 2. sharedObjectID (its index in the array) as a return parameter
// b) E_NO_SHARE if the the array of shares is full (i.e. reaches "MAX_SHARES")
int allocate_share_object(struct Share **allocatedObject)
{
int32 sharedObjectID = -1 ;
for (int i = 0; i < MAX_SHARES; ++i)
{
if (shares[i].empty)
{
sharedObjectID = i;
break;
}
}
if (sharedObjectID == -1)
{
//try to increase double the size of the "shares" array
if (USE_KHEAP == 1)
{
shares = krealloc(shares, 2*MAX_SHARES);
if (shares == NULL)
{
*allocatedObject = NULL;
return E_NO_SHARE;
}
else
{
sharedObjectID = MAX_SHARES;
MAX_SHARES *= 2;
}
}
else
{
*allocatedObject = NULL;
return E_NO_SHARE;
}
}
*allocatedObject = &(shares[sharedObjectID]);
shares[sharedObjectID].empty = 0;
if (USE_KHEAP == 1)
{
shares[sharedObjectID].framesStorage = kmalloc(PAGE_SIZE);
if (shares[sharedObjectID].framesStorage == NULL)
{
panic("Kernel runs out of memory\nCan't create the framesStorage.");
}
memset(shares[sharedObjectID].framesStorage, 0, PAGE_SIZE);
}
return sharedObjectID;
}
//=========================
// [3] Get Share Object ID:
//=========================
//Search for the given shared object in the "shares" array
//Return:
// a) if found: SharedObjectID (index of the shared object in the array)
// b) else: E_SHARED_MEM_NOT_EXISTS
int get_share_object_ID(int32 ownerID, char* name)
{
int i=0;
for(; i< MAX_SHARES; ++i)
{
if (shares[i].empty)
continue;
if(shares[i].ownerID == ownerID && strcmp(name, shares[i].name)==0)
{
return i;
}
}
return E_SHARED_MEM_NOT_EXISTS;
}
//==============================
// [4] Get Size of Share Object:
//==============================
//Search for the given shared object in the "shares" array
//Return:
// a) If found, return size of shared object
// b) Else, return E_SHARED_MEM_NOT_EXISTS
int getSizeOfSharedObject(int32 ownerID, char* shareName)
{
int shareObjectID = get_share_object_ID(ownerID, shareName);
if (shareObjectID == E_SHARED_MEM_NOT_EXISTS)
return E_SHARED_MEM_NOT_EXISTS;
else
return shares[shareObjectID].size;
return 0;
}
//=========================
// [5] Delete Share Object:
//=========================
//delete the given sharedObjectID from the "shares" array
//Return:
// a) 0 if succeed
// b) E_SHARED_MEM_NOT_EXISTS if the shared object is not exists
int free_share_object(uint32 sharedObjectID)
{
if (sharedObjectID >= MAX_SHARES)
return E_SHARED_MEM_NOT_EXISTS;
//panic("deleteSharedObject: not implemented yet");
clear_frames_storage(shares[sharedObjectID].framesStorage);
if (USE_KHEAP == 1)
kfree(shares[sharedObjectID].framesStorage);
memset(&(shares[sharedObjectID]), 0, sizeof(struct Share));
shares[sharedObjectID].empty = 1;
return 0;
}
//===========================================================
//==================================================================================//
//============================ REQUIRED FUNCTIONS ==================================//
//==================================================================================//
//=========================
// [1] Create Share Object:
//=========================
int createSharedObject(int32 ownerID, char* shareName, uint32 size, uint8 isWritable, void* virtual_address)
{
//TODO: [PROJECT 2019 - MS2 - [6] Shared Variables: Creation] createSharedObject() [Kernel Side]
struct Env* myenv = curenv; //The calling environment
// This function should create the shared object at the given virtual address with the given size
// and return the ShareObjectID
// RETURN:
// a) ShareObjectID (its index in "shares" array) if success
// b) E_SHARED_MEM_EXISTS if the shared object already exists
// c) E_NO_SHARE if the number of shared objects reaches max "MAX_SHARES"
// Steps:
// 1) Allocate a new share object (use allocate_share_object())
if(get_share_object_ID(ownerID, shareName) != E_SHARED_MEM_NOT_EXISTS)
return E_SHARED_MEM_EXISTS;
struct Share *nShareObj;
int nInd;
nInd = allocate_share_object(&nShareObj);
if(nInd == E_NO_SHARE)
return E_NO_SHARE;
else{
// 2) Allocate the required space in the physical memory on a PAGE boundary
uint32 required_num_pages = size/PAGE_SIZE + (size % PAGE_SIZE != 0);
virtual_address = ROUNDDOWN(virtual_address,PAGE_SIZE);
struct Frame_Info *ptr_framInfo;
for(int i = 0, va = (uint32)virtual_address; i < required_num_pages; i++, va += PAGE_SIZE){
int check = allocate_frame(&ptr_framInfo);
// 3) Map the allocated space on the given "virtual_address" on the current environment "myenv": object OWNER,
// with writable permissions
map_frame(curenv->env_page_directory, ptr_framInfo, (void*)va, PERM_USER|PERM_PRESENT|PERM_WRITEABLE);
// d) Add all allocated frames to "frames_storage" of this shared object to keep track of them for later use
// (use: add_frame_to_storage())
add_frame_to_storage(nShareObj->framesStorage, ptr_framInfo, i);
}
}
// 4) Initialize the share object with the following:
// a) Set the data members of the object with suitable values (ownerID, name, size, ...)
strcpy(nShareObj->name, shareName);
nShareObj->ownerID = ownerID;
nShareObj->size = size;
// b) Set references to 1 (as there's 1 user environment that use the object now - OWNER)
nShareObj->references = 1;
// c) Store the object's isWritable flag (0:ReadOnly, 1:Writable) for later use by getSharedObject()
nShareObj->isWritable = isWritable;
// 5) If succeed: return the ID of the shared object (i.e. its index in the "shares" array)
// Else, return suitable error
//change this "return" according to your answer
return nInd;
}
//======================
// [2] Get Share Object:
//======================
int getSharedObject(int32 ownerID, char* shareName, void* virtual_address)
{
//TODO: [PROJECT 2019 - MS2 - [6] Shared Variables: Get] getSharedObject() [Kernel Side]
struct Env* myenv = curenv; //The calling environment
// This function should share the required object in the heap of the current environment
// starting from the given virtual_address with the specified permissions of the object: read_only/writable
// and return the ShareObjectID
// RETURN:
// a) sharedObjectID (its index in the array) if success
// b) E_SHARED_MEM_NOT_EXISTS if the shared object is not exists
// Steps:
// 1) Get the shared object from the "shares" array (use get_share_object_ID())
uint32 ObjID = get_share_object_ID(ownerID, shareName);
if(ObjID == E_SHARED_MEM_NOT_EXISTS)
return E_SHARED_MEM_NOT_EXISTS;
uint32 size = getSizeOfSharedObject(ownerID, shareName);
uint32 Obj_frames_num = size/PAGE_SIZE + (size % PAGE_SIZE != 0);
for(int i = 0, va = (uint32)virtual_address; i < Obj_frames_num; i++, va += PAGE_SIZE){
// 2) Get its physical frames from the frames_storage
// (use: get_frame_from_storage())
struct Frame_Info *curFrame = get_frame_from_storage(shares[ObjID].framesStorage, i);
// 3) Share these frames with the current environment "myenv" starting from the given "virtual_address"
// 4) make sure that read-only object must be shared "read only", use the flag isWritable to make it either read-only or writable
if(shares[ObjID].isWritable == 1)
map_frame(myenv->env_page_directory, curFrame, (void*)va, PERM_USER|PERM_PRESENT|PERM_WRITEABLE);
else
map_frame(myenv->env_page_directory, curFrame, (void*)va, PERM_USER|PERM_PRESENT);
}
// 5) Update references
shares[ObjID].references++;
// 6) If succeed: return the ID of the shared object (i.e. its index in the "shares" array)
// Else, return suitable error
return ObjID;
}
//==================================================================================//
//============================== BONUS FUNCTIONS ===================================//
//==================================================================================//
//===================
// Free Share Object:
//===================
int freeSharedObject(int32 sharedObjectID, void *startVA)
{
struct Env* myenv = curenv; //The calling environment
//TODO: [PROJECT 2019 - BONUS4] Free Shared Variable [Kernel Side]
// your code is here, remove the panic and write your code
panic("freeSharedObject() is not implemented yet...!!");
// This function should free (delete) the shared object from the User Heapof the current environment
// If this is the last shared env, then the "frames_store" should be cleared and the shared object should be deleted
// RETURN:
// a) 0 if success
// b) E_SHARED_MEM_NOT_EXISTS if the shared object is not exists
// Steps:
// 1) Get the shared object from the "shares" array (use get_share_object_ID())
// 2) Unmap it from the current environment "myenv"
// 3) If one or more table becomes empty, remove it
// 4) Update references
// 5) If this is the last share, delete the share object (use free_share_object())
// 6) Flush the cache "tlbflush()"
//change this "return" according to your answer
return 0;
}