3 Copyright (C) 2006-2009 Jörg Pfähler
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <kernel/log.hpp>
20 #include <kernel/sharedMemoryManager.hpp>
21 #include <lightOS/c++utils.hpp>
22 #include <kernel/processor.hpp>
23 #include <kernel/page_allocator.hpp>
25 #include <kernel/virtual_memory.hpp>
26 using namespace kernel
;
28 using kernel::virtual_memory
;
30 SINGLETON_INSTANCE(kernel::sharedMemoryManager
);
32 kernel::sharedMemoryManager::sharedMemoryManager()
36 kernel::sharedMemoryManager::~sharedMemoryManager()
40 pair
<libkernel::shared_memory_id_t
, void*> sharedMemoryManager::create(process
&Process
, size_t size
)
44 LOG("sharedMemoryManager: shared-memory region of size 0");
45 return pair
<libkernel::shared_memory_id_t
, void*>(0, 0);
47 if (size
> virtual_memory::page_size
* 1024)
49 ERROR("sharedMemoryManager: shared-memory region too big");
50 return pair
<libkernel::shared_memory_id_t
, void*>(0, 0);
53 void *address
= Process
.allocate_shared_memory_region();
56 ERROR("sharedMemoryManager: no shared-memory region available");
57 return pair
<libkernel::shared_memory_id_t
, void*>(0, 0);
60 size_t pageCount
= size
/ virtual_memory::page_size
;
61 if ((size
% virtual_memory::page_size
) != 0)++pageCount
;
65 // Create a shared-memory entity
66 entity
*Memory
= new entity(generateSharedMemoryId(), size
);
67 Memory
->list
.push_back(make_pair(Process
.getId(), address
));
68 mList
.push_back(Memory
);
70 // Allocate the pages and map them into the address space
73 context
&Context
= Process
.getContext();
74 page_allocator
&PageAllocator
= page_allocator::instance();
75 for (size_t i
= 0;i
< pageCount
;i
++)
77 void *page
= PageAllocator
.allocate();
79 adjust_pointer(address
, i
* virtual_memory::page_size
),
80 lightOS::context::write
| lightOS::context::user
);
86 return pair
<libkernel::shared_memory_id_t
, void*>(Memory
->id
, address
);
89 pair
<void*, size_t> sharedMemoryManager::transfer( process
&dstProcess
,
91 libkernel::shared_memory_id_t id
,
94 if (dstProcess
.getId() == srcProcess
.getId())
95 return pair
<void*, size_t>(0, 0);
99 // Find the shared-memory entity
100 entity
*Memory
= get_by_id(id
);
102 return pair
<void*, size_t>(0, 0);
104 // Check, whether the src process has this shared memory entity
105 vector
<pair
<libkernel::process_id_t
, void*> >::const_iterator i
= Memory
->list
.begin();
106 for (;i
!= Memory
->list
.end();i
++)
107 if ((*i
).first
== srcProcess
.getId())
109 if (i
== Memory
->list
.end())
111 ERROR("sharedMemoryManager: source process does not own the shared-memory entity");
112 return pair
<void*, size_t>(0, 0);
115 // Is it already mapped in the destination process?
117 for (vector
<pair
<libkernel::process_id_t
, void*> >::iterator y
= Memory
->list
.begin();y
!= Memory
->list
.end();y
++)
118 if ((*y
).first
== dstProcess
.getId()){address
= (*y
).second
;break;}
121 // Allocate a shared-memory region
122 address
= dstProcess
.allocate_shared_memory_region();
124 // Map the shared-memory entity in the destination process
125 srcProcess
.getContext().copy_shared_memory((*i
).second
, dstProcess
.getContext(), address
, flags
);
127 // Add the destination process to the list
128 Memory
->list
.push_back(pair
<libkernel::process_id_t
, void*>(dstProcess
.getId(), address
));
130 pair
<void*, size_t> result(address
, Memory
->size
);
134 // Remove the source process, if the ownership should be transfered
135 if (flags
== libkernel::shared_memory::transfer_ownership
)
136 destroy(srcProcess
, id
);
141 bool sharedMemoryManager::destroy(process
&Process
, libkernel::shared_memory_id_t id
)
145 // Search for the shared-memory entity
146 for (vector
<entity
*>::iterator i
= mList
.begin();i
!= mList
.end();i
++)
149 // Search for the process
150 for(vector
<pair
<libkernel::process_id_t
, void*> >::iterator y
=i
->list
.begin();y
!= i
->list
.end();y
++)
151 if ((*y
).first
== Process
.getId())
153 // Free or just unmap the shared-memory entity?
154 if (i
->list
.size() == 1)
155 Process
.getContext().free_shared_memory((*y
).second
, i
->size
);
157 Process
.getContext().unmap_shared_memory((*y
).second
);
159 // Free the shared-memory region
160 Process
.free_shared_memory_region((*y
).second
);
162 // Remove the process from the list
167 // Can we delete the shared-memory entity?
168 if (i
->list
.size() == 0)
182 sharedMemoryManager::entity
*sharedMemoryManager::get_by_id(libkernel::shared_memory_id_t id
)
184 for (vector
<entity
*>::iterator i
= mList
.begin();i
!= mList
.end();i
++)
185 if (i
->id
== id
)return *i
;