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/arch/arch.hpp>
20 #include <kernel/log.hpp>
21 #include <kernel/process.hpp>
22 #include <kernel/port_manager.hpp>
23 #include <libarch/scoped_lock.hpp>
24 using namespace kernel
;
27 //FIXME: Use lists to speed things up
29 SINGLETON_INSTANCE(kernel::port_manager
);
31 kernel::port_manager::port_manager()
35 kernel::port_manager::~port_manager()
39 libkernel::port_id_t
port_manager::create(process
&Process
)
41 port
*Port
= new port(generatePortId(), &Process
);
42 SCOPED_LOCK(mLock
, scope
);
47 bool port_manager::create( process
&Process
,
48 libkernel::port_id_t Id
)
50 SCOPED_LOCK(mLock
, scope
);
52 // Does the port already exist?
53 if (get_port_by_id(Id
) != 0)
57 port
*Port
= new port(Id
, &Process
);
62 bool port_manager::send(libkernel::port_id_t port
,
63 const libkernel::message_t
&msg
,
64 const process
*Process
)
68 // Does the destination port exist at all?
69 port_manager::port
*Port
= get_port_by_id(msg
.port
);
76 // Is it the kernel that is sending a message?
77 if (Process
!= 0 && port
!= libkernel::message_port::kernel
)
79 // Does the source port really exist and does the process own that port?
80 port_manager::port
*srcPort
= get_port_by_id(port
);
81 if (srcPort
== 0 || (Process
!= 0 && srcPort
->owner
!= Process
))
85 ERROR("port_manager::send(): source port #" << dec(port
) << " non-existent or not owned by the process");
90 // Is the thread already waiting for this message?
91 // TODO: multiple wait messages not supported
92 if (Port
->waiter
!= 0 &&
93 Port
->waiter
->status() == thread::wait_for_port
&&
94 match(port
, msg
, Port
->waiter_msg
) == true)
97 Port
->waiter
->unblock(msg
.port
, port
, msg
.type
, msg
.param1
, msg
.param2
, msg
.param3
);
98 remove_thread_wait(*Port
->waiter
);
104 // Enqueue the message
105 libkernel::message_t
*Msg
= new libkernel::message_t(port
, msg
.type
, msg
.param1
, msg
.param2
, msg
.param3
);
106 Port
->msg
.push_back(Msg
);
112 bool port_manager::peek(libkernel::port_id_t port
,
113 libkernel::message_t
&msg
,
114 const process
&Process
)
118 // Does the port exist and does it belong to this process?
119 port_manager::port
*Port
= get_port_by_id(port
);
120 if (Port
== 0 || Port
->owner
!= &Process
)
124 ERROR("port_manager::peek(): port #" << dec(port
) << " non-existent or not owned by the process");
128 // Any messages in the queue?
129 if (Port
->msg
.size() == 0)
135 libkernel::message_t
*Message
= Port
->msg
.front();
137 Port
->msg
.erase(Port
->msg
.begin());
144 bool port_manager::get( libkernel::port_id_t port
,
145 libkernel::message_t
&msg
,
148 if (peek(port
, msg
, Thread
.getProcess()) == true)return true;
152 // Does the port exist and does it belong to this process?
153 port_manager::port
*Port
= get_port_by_id(port
);
154 if (Port
== 0 || Port
->owner
!= &Thread
.getProcess())
158 ERROR("port_manager::get(): port #" << dec(port
) << " non-existent or not owned by the process");
162 Port
->waiter
= &Thread
;
163 Port
->waiter_msg
.port
= 0;
164 Port
->waiter_msg
.type
= 0;
165 Port
->waiter_msg
.param1
= 0;
166 Port
->waiter_msg
.param2
= 0;
167 Port
->waiter_msg
.param3
= 0;
168 Port
->waiter
->block(thread::wait_for_port
);
174 bool port_manager::wait(libkernel::port_id_t
&port
,
175 libkernel::message_t
&msg
,
182 // Go through the ports
183 for (vector
<port_manager::port
*>::iterator i
=list
.begin();i
!= list
.end();i
++)
184 if (i
->waiter
== &Thread
)
186 // Go through the messages of that port
187 for (vector
<libkernel::message_t
*>::iterator y
= i
->msg
.begin();y
!= i
->msg
.end();y
++)
189 if (match(y
->port
, **y
, i
->waiter_msg
) == true)
195 // Delete the message
199 // Remove this thread from all the other port waits
200 remove_thread_wait(*i
->waiter
);
209 // Are there any port the thread is waiting for?
219 Thread
.block(thread::wait_for_port
);
225 bool port_manager::add_wait(libkernel::port_id_t port
,
226 const libkernel::message_t
&msg
,
231 // Does the port exist and does it belong to this process?
232 port_manager::port
*Port
= get_port_by_id(port
);
233 if (Port
== 0 || Port
->owner
!= &Thread
.getProcess())
237 ERROR("port_manager::add_wait(): port #" << dec(port
) << " non-existent or not owned by the process");
242 Port
->waiter
= &Thread
;
245 Port
->waiter_msg
= msg
;
251 bool port_manager::transfer(libkernel::port_id_t port
,
252 const process
&Process
,
253 libkernel::process_id_t receiver
)
257 // Does the port exist and dies it belong to this process
258 port_manager::port
*Port
= get_port_by_id(port
);
259 if (Port
== 0 || Port
->owner
!= &Process
)
263 ERROR("port_manager::transfer(): port #" << dec(port
) << " non-existent or not owned by the process");
267 // Get the receiving process
268 process
*recProcess
= process::get_process(receiver
);
275 // Set the port owner
276 Port
->owner
= recProcess
;
281 libkernel::process_id_t
port_manager::get_processId(libkernel::port_id_t id
)
286 port
*Port
= get_port_by_id(id
);
294 libkernel::process_id_t pid
= Port
->owner
->getId();
300 libkernel::thread_id_t
port_manager::get_waiting_threadId(libkernel::port_id_t id
)
305 port
*Port
= get_port_by_id(id
);
314 libkernel::thread_id_t tid
= Port
->waiter
->getId();
320 bool port_manager::destroy(libkernel::port_id_t port
)
324 for (vector
<port_manager::port
*>::iterator i
= list
.begin();i
!= list
.end();i
++)
338 void port_manager::destroy_process_ports(const process
&Process
)
342 for (vector
<port_manager::port
*>::iterator i
=list
.begin();i
!= list
.end();)
343 if (i
->owner
== &Process
)
353 port_manager::port
*port_manager::get_port_by_id(libkernel::port_id_t id
)
355 for (vector
<port_manager::port
*>::iterator i
=list
.begin();i
!= list
.end();i
++)
356 if (i
->id
== id
)return *i
;
360 void port_manager::destroy(port
*Port
)
362 for (vector
<libkernel::message_t
*>::iterator y
= Port
->msg
.begin();y
!= Port
->msg
.end();y
++)
367 void port_manager::remove_thread_wait(const thread
&Thread
)
369 for (vector
<port_manager::port
*>::iterator i
=list
.begin();i
!= list
.end();i
++)
370 if (i
->waiter
== &Thread
)
374 bool port_manager::match(libkernel::port_id_t port
,
375 const libkernel::message_t
&msg1
,
376 const libkernel::message_t
&msg2
)
379 if (msg2
.port
!= port
)
382 if (MESSAGE_TYPE(msg2
.type
) != MESSAGE_TYPE(msg1
.type
))
384 if (msg2
.param1
!= 0)
385 if (msg2
.param1
!= msg1
.param1
)
387 if (msg2
.param2
!= 0)
388 if (msg2
.param2
!= msg1
.param2
)
390 if (msg2
.param3
!= 0)
391 if (msg2
.param3
!= msg1
.param3
)