1 #include <Process.hpp>
\r
3 #include <MsgException.hpp>
\r
4 #include <NullPointerException.hpp>
\r
5 #include <HostNotFoundException.hpp>
\r
6 #include <ProcessNotFoundException.hpp>
\r
7 #include <InvalidArgumentException.hpp>
\r
8 #include <BadAllocException.hpp>
\r
9 #include <LogicException.hpp>
\r
12 #include <ApplicationHandler.hpp>
\r
19 #include <msg/msg.h>
\r
20 #include <msg/private.h>
\r
21 #include <msg/mailbox.h>
\r
29 MSG_IMPLEMENT_DYNAMIC(Process, Object);
\r
31 // Default constructor.
\r
34 this->nativeProcess = NULL;
\r
37 Process::Process(const char* hostName, const char* name)
\r
38 throw(InvalidArgumentException, HostNotFoundException)
\r
40 // check the parameters
\r
43 throw NullPointerException("name");
\r
46 throw NullPointerException("hostName");
\r
48 Host host = Host::getByName(hostName);
\r
50 create(host, name, 0, NULL);
\r
53 Process::Process(const Host& rHost, const char* name)
\r
54 throw(NullPointerException)
\r
57 throw NullPointerException("name");
\r
59 create(rHost, name, 0, NULL);
\r
62 Process::Process(const Host& rHost, const char* name, int argc, char** argv)
\r
63 throw(NullPointerException, InvalidArgumentException, LogicException)
\r
66 // check the parameters
\r
69 throw NullPointerException("name");
\r
72 throw InvalidArgumentException("argc (must be positive)");
\r
75 throw LogicException("argv is not NULL but argc is zero");
\r
78 throw LogicException("argv is NULL but argc is not zero");
\r
80 create(rHost, name, argc, argv);
\r
83 Process::Process(const char* hostName, const char* name, int argc, char** argv)
\r
84 throw(NullPointerException, InvalidArgumentException, LogicException, HostNotFoundException)
\r
86 // check the parameters
\r
89 throw NullPointerException("name");
\r
92 throw NullPointerException("hostName");
\r
95 throw InvalidArgumentException("argc (must be positive)");
\r
98 throw LogicException("argv is not NULL but argc is zero");
\r
101 throw LogicException("argv is NULL but argc is not zero");
\r
103 Host host = Host::getByName(hostName);
\r
105 create(host, name, argc, argv);
\r
108 int Process::killAll(int resetPID)
\r
110 return MSG_process_killall(resetPID);
\r
113 void Process::suspend(void)
\r
114 throw(MsgException)
\r
116 if(MSG_OK != MSG_process_suspend(nativeProcess))
\r
117 throw MsgException("MSG_process_suspend() failed");
\r
120 void Process::resume(void)
\r
121 throw(MsgException)
\r
123 if(MSG_OK != MSG_process_resume(nativeProcess))
\r
124 throw MsgException("MSG_process_resume() failed");
\r
127 int Process::isSuspended(void)
\r
129 return MSG_process_is_suspended(nativeProcess);
\r
132 Host& Process::getHost(void)
\r
134 m_host_t nativeHost = MSG_process_get_host(nativeProcess);
\r
136 // return the reference to the Host object
\r
137 return (*((Host*)nativeHost->data));
\r
140 Process& Process::fromPID(int PID)
\r
141 throw(ProcessNotFoundException, InvalidArgumentException, MsgException)
\r
143 // check the parameters
\r
146 throw InvalidArgumentException("PID (the PID of the process to retrieve is not less than 1)");
\r
148 Process* process = NULL;
\r
149 m_process_t nativeProcess = MSG_process_from_PID(PID);
\r
151 if(!nativeProcess)
\r
152 throw ProcessNotFoundException(PID);
\r
154 process = Process::fromNativeProcess(nativeProcess);
\r
157 throw MsgException("Process::fromNativeProcess() failed");
\r
159 return (*process);
\r
162 int Process::getPID(void)
\r
164 return MSG_process_get_PID(nativeProcess);
\r
167 int Process::getPPID(void)
\r
169 return MSG_process_get_PPID(nativeProcess);
\r
172 const char* Process::getName(void) const
\r
174 return nativeProcess->name;
\r
177 Process& Process::currentProcess(void)
\r
178 throw(MsgException)
\r
180 Process* currentProcess = NULL;
\r
181 m_process_t currentNativeProcess = MSG_process_self();
\r
184 if(!currentNativeProcess)
\r
185 throw MsgException("MSG_process_self() failed");
\r
187 currentProcess = Process::fromNativeProcess(currentNativeProcess);
\r
189 if(!currentProcess)
\r
190 throw MsgException("Process::fromNativeProcess() failed");
\r
192 return (*currentProcess);
\r
195 int Process::currentProcessPID(void)
\r
197 return MSG_process_self_PID();
\r
201 int Process::currentProcessPPID(void)
\r
203 return MSG_process_self_PPID();
\r
206 void Process::migrate(const Host& rHost)
\r
207 throw(MsgException)
\r
209 if(MSG_OK != MSG_process_change_host(rHost.nativeHost))
\r
210 throw MsgException("MSG_process_change_host()");
\r
214 void Process::sleep(double seconds)
\r
215 throw(InvalidArgumentException, MsgException)
\r
217 // check the parameters.
\r
219 throw InvalidArgumentException("seconds (must not be less or equals to zero");
\r
221 if(MSG_OK != MSG_process_sleep(seconds))
\r
222 throw MsgException("MSG_process_sleep()");
\r
226 void Process::putTask(const Host& rHost, int channel, const Task& rTask)
\r
227 throw(InvalidArgumentException, MsgException)
\r
229 // check the parameters
\r
232 throw InvalidArgumentException("channel (must not be negative)");
\r
234 if(MSG_OK != MSG_task_put_with_timeout(rTask.nativeTask, rHost.nativeHost, channel, -1.0))
\r
235 throw MsgException("MSG_task_put_with_timeout()");
\r
238 void Process::putTask(const Host& rHost, int channel, const Task& rTask, double timeout)
\r
239 throw(InvalidArgumentException, MsgException)
\r
241 // check the parameters
\r
243 throw InvalidArgumentException("channel (must not be negative)");
\r
245 if(timeout < 0 && timeout != -1.0)
\r
246 throw InvalidArgumentException("timeout (must not be less than zero an different of -1.0)");
\r
248 if(MSG_OK != MSG_task_put_with_timeout(rTask.nativeTask, rHost.nativeHost, channel, timeout))
\r
249 throw MsgException("MSG_task_put_with_timeout() failed");
\r
252 Task& Process::getTask(int channel)
\r
253 throw(InvalidArgumentException, MsgException)
\r
255 // check the parameters
\r
258 throw InvalidArgumentException("channel (must not be negative)");
\r
260 m_task_t nativeTask = NULL;
\r
262 if (MSG_OK != MSG_task_get_ext(&nativeTask, channel, -1.0, NULL))
\r
263 throw MsgException("MSG_task_get_ext() failed");
\r
265 return (*((Task*)(nativeTask->data)));
\r
268 Task& Process::getTask(int channel, double timeout)
\r
269 throw(InvalidArgumentException, MsgException)
\r
271 // check the parameters
\r
273 throw InvalidArgumentException("channel (must not be negative)");
\r
275 if(timeout < 0 && timeout != -1.0)
\r
276 throw InvalidArgumentException("timeout (must not be less than zero an different of -1.0)");
\r
278 m_task_t nativeTask = NULL;
\r
280 if (MSG_OK != MSG_task_get_ext(&nativeTask, channel, timeout, NULL))
\r
281 throw MsgException("MSG_task_get_ext() failed");
\r
283 return (*((Task*)(nativeTask->data)));
\r
286 Task& Process::getTask(int channel, const Host& rHost)
\r
287 throw(InvalidArgumentException, MsgException)
\r
289 // check the parameters
\r
291 throw InvalidArgumentException("channel (must not be negative)");
\r
293 m_task_t nativeTask = NULL;
\r
295 if (MSG_OK != MSG_task_get_ext(&nativeTask, channel, -1.0, rHost.nativeHost))
\r
296 throw MsgException("MSG_task_get_ext() failed");
\r
298 return (*((Task*)(nativeTask->data)));
\r
301 Task& Process::getTask(int channel, double timeout, const Host& rHost)
\r
302 throw(InvalidArgumentException, MsgException)
\r
304 // check the parameters
\r
306 throw InvalidArgumentException("channel (must not be negative)");
\r
308 if(timeout < 0 && timeout != -1.0)
\r
309 throw InvalidArgumentException("timeout (must not be less than zero an different of -1.0)");
\r
311 m_task_t nativeTask = NULL;
\r
313 if (MSG_OK != MSG_task_get_ext(&nativeTask, channel, timeout, rHost.nativeHost))
\r
314 throw MsgException("MSG_task_get_ext() failed");
\r
316 return (*((Task*)(nativeTask->data)));
\r
319 void Process::sendTask(const char* alias, const Task& rTask, double timeout)
\r
320 throw(NullPointerException, InvalidArgumentException, MsgException)
\r
322 // check the parameters
\r
325 throw NullPointerException("alias");
\r
327 if(timeout < 0 && timeout !=-1.0)
\r
328 throw InvalidArgumentException("timeout (the timeout value must not be negative and different than -1.0)");
\r
330 if(MSG_OK != MSG_task_send_with_timeout(rTask.nativeTask, alias ,timeout))
\r
331 throw MsgException("MSG_task_send_with_timeout()");
\r
335 void Process::sendTask(const char* alias, const Task& rTask)
\r
336 throw(NullPointerException, MsgException)
\r
338 // check the parameters
\r
341 throw NullPointerException("alias");
\r
343 if(MSG_OK != MSG_task_send_with_timeout(rTask.nativeTask, alias ,-1.0))
\r
344 throw MsgException("MSG_task_send_with_timeout()");
\r
347 void Process::sendTask(const Task& rTask)
\r
348 throw(BadAllocException, MsgException)
\r
350 char* alias = (char*)calloc( strlen(Host::currentHost().getName()) + strlen(nativeProcess->name) + 2, sizeof(char));
\r
353 throw BadAllocException("alias");
\r
355 sprintf(alias,"%s:%s", Host::currentHost().getName() ,nativeProcess->name);
\r
357 MSG_error_t rv = MSG_task_send_with_timeout(rTask.nativeTask, alias ,-1.0);
\r
362 throw MsgException("MSG_task_send_with_timeout()");
\r
365 void Process::sendTask(const Task& rTask, double timeout)
\r
366 throw(BadAllocException, InvalidArgumentException, MsgException)
\r
368 // check the parameters
\r
370 if(timeout < 0 && timeout !=-1.0)
\r
371 throw InvalidArgumentException("timeout (the timeout value must not be negative and different than -1.0)");
\r
373 char* alias = (char*)calloc(strlen(Host::currentHost().getName()) + strlen(nativeProcess->name) + 2 , sizeof(char));
\r
376 throw BadAllocException("alias");
\r
378 sprintf(alias,"%s:%s", Host::currentHost().getName() ,nativeProcess->name);
\r
380 MSG_error_t rv = MSG_task_send_with_timeout(rTask.nativeTask, alias ,timeout);
\r
385 throw MsgException("MSG_task_send_with_timeout()");
\r
388 Task& Process::receiveTask(const char* alias)
\r
389 throw(NullPointerException, MsgException)
\r
391 // check the parameters
\r
394 throw NullPointerException(alias);
\r
396 m_task_t nativeTask = NULL;
\r
398 if (MSG_OK != MSG_task_receive_ext(&nativeTask,alias, -1.0, NULL))
\r
399 throw MsgException("MSG_task_receive_ext() failed");
\r
401 return (*((Task*)nativeTask->data));
\r
405 Task& Process::receiveTask(void)
\r
406 throw(BadAllocException, MsgException)
\r
409 char* alias = (char*)calloc(strlen(Host::currentHost().getName()) + strlen(nativeProcess->name) + 2, sizeof(char));
\r
412 throw BadAllocException("alias");
\r
414 sprintf(alias,"%s:%s", Host::currentHost().getName() ,nativeProcess->name);
\r
416 m_task_t nativeTask = NULL;
\r
418 MSG_error_t rv = MSG_task_receive_ext(&nativeTask, alias, -1.0, NULL);
\r
423 throw MsgException("MSG_task_receive_ext() failed");
\r
425 return (*((Task*)nativeTask->data));
\r
429 Task& Process::receiveTask(const char* alias, double timeout)
\r
430 throw(NullPointerException, InvalidArgumentException, MsgException)
\r
432 // check the parameters
\r
435 throw NullPointerException("alias");
\r
437 if(timeout < 0 && timeout !=-1.0)
\r
438 throw InvalidArgumentException("timeout (the timeout value must not be negative and different than -1.0)");
\r
440 m_task_t nativeTask = NULL;
\r
442 if(MSG_OK != MSG_task_receive_ext(&nativeTask, alias, timeout, NULL))
\r
443 throw MsgException("MSG_task_receive_ext() failed");
\r
445 return (*((Task*)nativeTask->data));
\r
449 Task& Process::receiveTask(double timeout)
\r
450 throw(InvalidArgumentException, BadAllocException, MsgException)
\r
452 // check the parameters
\r
454 if(timeout < 0 && timeout !=-1.0)
\r
455 throw InvalidArgumentException("timeout (the timeout value must not be negative and different than -1.0)");
\r
458 char* alias = (char*)calloc(strlen(Host::currentHost().getName()) + strlen(nativeProcess->name) + 2, sizeof(char));
\r
461 throw BadAllocException("alias");
\r
463 sprintf(alias,"%s:%s", Host::currentHost().getName() ,nativeProcess->name);
\r
465 m_task_t nativeTask = NULL;
\r
467 MSG_error_t rv = MSG_task_receive_ext(&nativeTask, alias, timeout, NULL);
\r
472 throw MsgException("MSG_task_receive_ext() failed");
\r
474 return (*((Task*)nativeTask->data));
\r
478 Task& Process::receiveTask(const char* alias, double timeout, const Host& rHost)
\r
479 throw(NullPointerException, InvalidArgumentException, MsgException)
\r
481 // check the parameters
\r
484 throw NullPointerException("alias");
\r
486 if(timeout < 0 && timeout !=-1.0)
\r
487 throw InvalidArgumentException("timeout (the timeout value must not be negative and different than -1.0)");
\r
489 m_task_t nativeTask = NULL;
\r
491 if(MSG_OK != MSG_task_receive_ext(&nativeTask, alias, timeout, rHost.nativeHost))
\r
492 throw MsgException("MSG_task_receive_ext() failed");
\r
494 return (*((Task*)nativeTask->data));
\r
498 Task& Process::receiveTask(double timeout, const Host& rHost)
\r
499 throw(BadAllocException, InvalidArgumentException, MsgException)
\r
501 // check the parameters
\r
503 if(timeout < 0 && timeout !=-1.0)
\r
504 throw InvalidArgumentException("timeout (the timeout value must not be negative and different than -1.0)");
\r
506 char* alias = (char*)calloc(strlen(Host::currentHost().getName()) + strlen(nativeProcess->name) + 2, sizeof(char));
\r
509 throw BadAllocException("alias");
\r
511 sprintf(alias,"%s:%s", Host::currentHost().getName() ,nativeProcess->name);
\r
513 m_task_t nativeTask = NULL;
\r
515 MSG_error_t rv = MSG_task_receive_ext(&nativeTask, alias, timeout, rHost.nativeHost);
\r
520 throw MsgException("MSG_task_receive_ext() failed");
\r
522 return (*((Task*)nativeTask->data));
\r
526 Task& Process::receiveTask(const char* alias, const Host& rHost)
\r
527 throw(NullPointerException, MsgException)
\r
530 // check the parameters
\r
533 throw NullPointerException("alias");
\r
535 m_task_t nativeTask = NULL;
\r
537 if(MSG_OK != MSG_task_receive_ext(&nativeTask, alias, -1.0, rHost.nativeHost))
\r
538 throw MsgException("MSG_task_receive_ext() failed");
\r
540 return (*((Task*)nativeTask->data));
\r
543 Task& Process::receiveTask(const Host& rHost)
\r
544 throw(BadAllocException, MsgException)
\r
546 char* alias = (char*)calloc(strlen(Host::currentHost().getName()) + strlen(nativeProcess->name) + 2, sizeof(char));
\r
549 throw BadAllocException("alias");
\r
551 sprintf(alias,"%s:%s", Host::currentHost().getName() ,nativeProcess->name);
\r
553 m_task_t nativeTask = NULL;
\r
555 MSG_error_t rv = MSG_task_receive_ext(&nativeTask, alias, -1.0, rHost.nativeHost);
\r
560 throw MsgException("MSG_task_receive_ext() failed");
\r
562 return (*((Task*)nativeTask->data));
\r
565 /*void Process::create(const Host& rHost, const char* name, int argc, char** argv)
\r
566 throw(HostNotFoundException)
\r
568 smx_process_t nativeCurrentProcess = NULL;
\r
570 // allocate the native process
\r
571 this->nativeProcess = xbt_new0(s_smx_process_t, 1);
\r
573 // allocate the simulation data of the native process
\r
574 smx_simdata_process_t simdata = xbt_new0(s_smx_simdata_process_t, 1);
\r
576 // try to retrieve the host where to createt the process from its name
\r
577 smx_host_t nativeHost = SIMIX_host_get_by_name(rHost.getName());
\r
580 throw HostNotFoundException(rHost.getName());
\r
582 // realloc the list of the argument to add the pointer to this process instance at the end
\r
583 argv = (char**)realloc(argc + 1, sizeof(char*));
\r
585 // add the pointer to this instance at the end of the list of the arguments of the process
\r
586 // so the static method Process::run() (passed as argument of the MSG function xbt_context_new())
\r
587 // can retrieve the concerned process object by the run
\r
588 // so Process::run() can call the method main() of the good process
\r
589 // for more detail see Process::run() method
\r
590 argv[argc] = (char*)this;
\r
593 simdata->smx_host = nativeHost;
\r
594 simdata->mutex = NULL;
\r
595 simdata->cond = NULL;
\r
596 simdata->argc = argc;
\r
597 simdata->argv = argv;
\r
599 // create the context of the process.
\r
600 simdata->context = xbt_context_new(name, Process::run, NULL, NULL, simix_global->cleanup_process_function, nativeProcess, simdata->argc, simdata->argv);
\r
602 // Process structure
\r
603 this->nativeProcess->name = xbt_strdup(name);
\r
604 this->nativeProcess->simdata = simdata;
\r
606 // Set process data
\r
607 this->nativeProcess->data = NULL;
\r
609 // Set process properties
\r
610 simdata->properties = NULL;
\r
612 xbt_swag_insert(this->nativeProcess, nativeHost->simdata->process_list);
\r
614 // fix current_process, about which xbt_context_start mocks around
\r
615 nativeCurrentProcess = simix_global->current_process;
\r
616 xbt_context_start(this->nativeProcess->simdata->context);
\r
617 simix_global->current_process = nativeCurrentProcess;
\r
619 xbt_swag_insert(this->nativeProcess, simix_global->process_list);
\r
620 DEBUG2("Inserting %s(%s) in the to_run list", this->nativeProcess->name, nativeHost->name);
\r
621 xbt_swag_insert(this->nativeProcess, simix_global->process_to_run);
\r
624 void Process::create(const Host& rHost, const char* name, int argc, char** argv)
\r
625 throw(InvalidArgumentException)
\r
627 char alias[MAX_ALIAS_NAME + 1] = {0};
\r
628 msg_mailbox_t mailbox;
\r
631 // try to retrieve the host where to createt the process from its name
\r
632 m_host_t nativeHost = rHost.nativeHost;
\r
635 throw InvalidArgumentException("rHost");
\r
637 /* allocate the data of the simulation */
\r
638 this->nativeProcess = xbt_new0(s_m_process_t,1);
\r
639 this->nativeProcess->simdata = xbt_new0(s_simdata_process_t,1);
\r
640 this->nativeProcess->name = _strdup(name);
\r
641 this->nativeProcess->simdata->m_host = nativeHost;
\r
642 this->nativeProcess->simdata->PID = msg_global->PID++;
\r
644 // realloc the list of the argument to add the pointer to this process instance at the end
\r
646 argv = (char**)realloc(argv , (argc + 1) * sizeof(char*));
\r
648 argv = (char**)calloc(1 ,sizeof(char*));
\r
650 // add the pointer to this instance at the end of the list of the arguments of the process
\r
651 // so the static method Process::run() (passed as argument of the MSG function xbt_context_new())
\r
652 // can retrieve the concerned process object by the run
\r
653 // so Process::run() can call the method main() of the good process
\r
654 // for more detail see Process::run() method
\r
655 argv[argc] = (char*)this;
\r
657 this->nativeProcess->simdata->argc = argc;
\r
658 this->nativeProcess->simdata->argv = argv;
\r
660 this->nativeProcess->simdata->s_process = SIMIX_process_create(
\r
661 this->nativeProcess->name,
\r
663 (void*)this->nativeProcess,
\r
669 if (SIMIX_process_self())
\r
670 {/* someone created me */
\r
671 this->nativeProcess->simdata->PPID = MSG_process_get_PID((m_process_t)SIMIX_process_self()->data);
\r
675 this->nativeProcess->simdata->PPID = -1;
\r
678 this->nativeProcess->simdata->last_errno = MSG_OK;
\r
680 /* add the process to the list of the processes of the simulation */
\r
681 xbt_fifo_unshift(msg_global->process_list, this->nativeProcess);
\r
683 sprintf(alias,"%s:%s",(this->nativeProcess->simdata->m_host->simdata->smx_host)->name,this->nativeProcess->name);
\r
685 mailbox = MSG_mailbox_new(alias);
\r
687 MSG_mailbox_set_hostname(mailbox, this->nativeProcess->simdata->m_host->simdata->smx_host->name);
\r
692 Process* Process::fromNativeProcess(m_process_t nativeProcess)
\r
694 return ((Process*)(nativeProcess->simdata->argv[nativeProcess->simdata->argc]));
\r
697 int Process::run(int argc, char** argv)
\r
700 // the last argument of the process is the pointer to the process to run
\r
701 // for mor detail see Process::create() method
\r
702 return ((Process*)argv[argc])->main(argc, argv);
\r
705 int Process::main(int argc, char** argv)
\r
707 throw LogicException("Process::main() not implemented");
\r
712 } // namespace SimGrid