- kdevelop3 project files
[lightOS.git] / kernel / sharedMemoryManager.cpp
blob21e5dbc0291a05d8abd8af2314bd5f8e3e1e8214
1 /*
2 lightOS kernel
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;
27 using namespace std;
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)
42 if (size == 0)
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();
54 if (address == 0)
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;
63 LOCK(mLock);
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
71 KERNEL_CONTEXT_START;
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();
78 Context.map(page,
79 adjust_pointer(address, i * virtual_memory::page_size),
80 lightOS::context::write | lightOS::context::user);
83 KERNEL_CONTEXT_END;
85 UNLOCK(mLock);
86 return pair<libkernel::shared_memory_id_t, void*>(Memory->id, address);
89 pair<void*, size_t> sharedMemoryManager::transfer( process &dstProcess,
90 process &srcProcess,
91 libkernel::shared_memory_id_t id,
92 size_t flags)
94 if (dstProcess.getId() == srcProcess.getId())
95 return pair<void*, size_t>(0, 0);
97 LOCK(mLock);
99 // Find the shared-memory entity
100 entity *Memory = get_by_id(id);
101 if (Memory == 0)
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())
108 break;
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?
116 void *address = 0;
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;}
120 if (address == 0)
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);
132 UNLOCK(mLock);
134 // Remove the source process, if the ownership should be transfered
135 if (flags == libkernel::shared_memory::transfer_ownership)
136 destroy(srcProcess, id);
138 return result;
141 bool sharedMemoryManager::destroy(process &Process, libkernel::shared_memory_id_t id)
143 LOCK(mLock);
145 // Search for the shared-memory entity
146 for (vector<entity*>::iterator i = mList.begin();i != mList.end();i++)
147 if (i->id == id)
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);
156 else
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
163 i->list.erase(y);
164 break;
167 // Can we delete the shared-memory entity?
168 if (i->list.size() == 0)
170 delete *i;
171 mList.erase(i);
174 UNLOCK(mLock);
175 return true;
178 UNLOCK(mLock);
179 return false;
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;
186 return 0;