From c6367952505ec169142f91d8e97fddb9eaa0cc5a Mon Sep 17 00:00:00 2001 From: donassbr Date: Thu, 1 Mar 2007 10:40:15 +0000 Subject: [PATCH] Simix Initial structure git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@3178 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- src/include/simix/datatypes.h | 115 ++++++++ src/simix/private.h | 144 +++++++++ src/simix/smx_action.c | 41 +++ src/simix/smx_config.c | 85 ++++++ src/simix/smx_deployment.c | 137 +++++++++ src/simix/smx_environment.c | 93 ++++++ src/simix/smx_host.c | 198 +++++++++++++ src/simix/smx_process.c | 529 ++++++++++++++++++++++++++++++++++ src/simix/smx_synchro.c | 74 +++++ 9 files changed, 1416 insertions(+) create mode 100644 src/include/simix/datatypes.h create mode 100644 src/simix/private.h create mode 100644 src/simix/smx_action.c create mode 100644 src/simix/smx_config.c create mode 100644 src/simix/smx_deployment.c create mode 100644 src/simix/smx_environment.c create mode 100644 src/simix/smx_host.c create mode 100644 src/simix/smx_process.c create mode 100644 src/simix/smx_synchro.c diff --git a/src/include/simix/datatypes.h b/src/include/simix/datatypes.h new file mode 100644 index 0000000000..d83d22a536 --- /dev/null +++ b/src/include/simix/datatypes.h @@ -0,0 +1,115 @@ +/* $Id$ */ + +/* Copyright (c) 2002,2003,2004 Arnaud Legrand. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#ifndef SIMIX_DATATYPE_H +#define SIMIX_DATATYPE_H +#include "xbt/misc.h" +#include "xbt/swag.h" + +SG_BEGIN_DECL() + +/* ******************************** Host ************************************ */ +/** @defgroup m_datatypes_management_details Details on SIMIX datatypes + @ingroup m_datatypes_management*/ + +typedef struct s_simdata_host *simdata_host_t; +/** @brief Host datatype + @ingroup m_datatypes_management_details */ +typedef struct s_smx_host { + char *name; /**< @brief host name if any */ + simdata_host_t simdata; /**< @brief simulator data */ + void *data; /**< @brief user data */ +} s_smx_host_t; +/** @brief Host datatype + @ingroup m_datatypes_management + + A location (or host) is any possible place where + a process may run. Thus it is represented as a physical + resource with computing capabilities, some mailboxes + to enable running process to communicate with remote ones, and + some private data that can be only accessed by local + process. + + \see m_host_management + @{ */ +typedef struct s_smx_host *smx_host_t; +/** @} */ + + +/* ******************************** Syncro ************************************ */ + +typedef struct s_smx_mutex *smx_mutex_t; +typedef struct s_smx_cond *smx_cond_t; + + +/********************************** Action *************************************/ +typedef struct s_simdata_action *simdata_action_t; +/** @brief Action datatype + @ingroup m_datatypes_management_details */ +typedef struct s_smx_action { + int number; /**< @brief action name if any */ + simdata_action_t simdata; /**< @brief simulator data */ + void *data; /**< @brief user data */ +} s_smx_action_t; + +typedef struct s_smx_action *smx_action_t; + + +/* ****************************** Process *********************************** */ +typedef struct s_simdata_process *simdata_process_t; +/** @brief Process datatype + @ingroup m_datatypes_management_details @{ */ +typedef struct s_smx_process { + char *name; /**< @brief process name if any */ + simdata_process_t simdata; /**< @brief simulator data */ + s_xbt_swag_hookup_t process_hookup; + void *data; /**< @brief user data */ +} s_smx_process_t; +/** @} */ +/** @brief Agent datatype + @ingroup m_datatypes_management + + An agent may be defined as a code, with some private + data, executing in a location. + \see m_process_management + @{ */ +typedef struct s_smx_process *smx_process_t; +/** @} */ + +/** @brief Agent code + @ingroup m_datatypes_management + The code of an agent is a m_process_code_t, i.e. a function with no arguments + returning no value. + \see m_process_management + @{ */ +typedef int(*smx_process_code_t)(int argc,char *argv[]) ; +/** @} */ + + +/* ***************************** Error handling ***************************** */ +/** @brief Error handling + @ingroup m_datatypes_management + @{ +*/ +typedef enum { + SIMIX_OK = 0, /**< @brief Everything is right. Keep on going this way ! */ + SIMIX_WARNING, /**< @brief Mmmh! Something must be not perfectly clean. But I + may be a paranoid freak... ! */ + SIMIX_TRANSFER_FAILURE, /**< @brief There has been a problem during you action + transfer. Either the network is down or the remote host has been + shutdown. */ + SIMIX_HOST_FAILURE, /**< @brief System shutdown. The host on which you are + running has just been rebooted. Free your datastructures and + return now !*/ + SIMIX_ACTION_CANCELLED, /**< @brief Cancelled action. This action has been cancelled + by somebody!*/ + SIMIX_FATAL /**< @brief You've done something wrong. You'd better look at it... */ +} SIMIX_error_t; +/** @} */ + +SG_END_DECL() +#endif diff --git a/src/simix/private.h b/src/simix/private.h new file mode 100644 index 0000000000..63cadc5c35 --- /dev/null +++ b/src/simix/private.h @@ -0,0 +1,144 @@ +/* $Id$ */ + +/* Copyright (c) 2002,2004,2004 Arnaud Legrand. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#ifndef SIMIX_PRIVATE_H +#define SIMIX_PRIVATE_H + +#include "simix/simix.h" +#include "surf/surf.h" +#include "xbt/fifo.h" +#include "xbt/dynar.h" +#include "xbt/swag.h" +#include "xbt/dict.h" +#include "xbt/context.h" +#include "xbt/config.h" + +/**************** datatypes **********************************/ + +typedef struct s_simdata_host { + void *host; /* SURF modeling */ + xbt_swag_t process_list; +} s_simdata_host_t; + +/********************************* Simix Global ******************************/ + +typedef struct SIMIX_Global { + xbt_fifo_t host; + xbt_swag_t process_to_run; + xbt_swag_t process_list; + /* xbt_swag_t process_sleeping; */ + + smx_process_t current_process; + xbt_dict_t registered_functions; +/* FILE *paje_output; + int session; */ +} s_SIMIX_Global_t, *SIMIX_Global_t; + +extern SIMIX_Global_t simix_global; + +/******************************* Process *************************************/ + +typedef struct s_simdata_process { + smx_host_t host; /* the host on which the process is running */ + xbt_context_t context; /* the context that executes the scheduler fonction */ + int blocked; + int suspended; + smx_host_t put_host; /* used for debugging purposes */ + int argc; /* arguments number if any */ + char **argv; /* arguments table if any */ + SIMIX_error_t last_errno; /* the last value returned by a MSG_function */ +// int paje_state; /* the number of states stacked with Paje */ +} s_simdata_process_t; + +typedef struct process_arg { + const char *name; + smx_process_code_t code; + void *data; + smx_host_t host; + int argc; + char **argv; + double kill_time; +} s_process_arg_t, *process_arg_t; + +/********************************* Mutex and Conditional ****************************/ + +typedef struct s_smx_mutex { + xbt_swag_t sleeping; + int using; + +} s_smx_mutex_t; + +typedef struct s_smx_cond { + s_smx_mutex_t * mutex; + xbt_swag_t sleeping; //process +} s_smx_cond_t; + +/********************************* Action **************************************/ + +typedef struct s_simdata_action { + surf_action_t surf_action; /* SURF modeling of computation */ + + xbt_fifo_t cond_list; /* conditional variables that must be signaled when the action finish. */ + smx_host_t source; + + double priority; + double rate; + + /*int using;*/ + + /******* Parallel Tasks Only !!!! *******/ + /* + int host_nb; + void * *host_list; *//* SURF modeling */ + /* + double *comp_amount; + double *comm_amount; + */ +} s_simdata_action_t; + + + +/******************************* Configuration support **********************************/ + +void simix_config_init(void); /* create the config set, call this before use! */ +void simix_config_finalize(void); /* destroy the config set, call this at cleanup. */ +extern int _simix_init_status; /* 0: beginning of time; + 1: pre-inited (cfg_set created); + 2: inited (running) */ +extern xbt_cfg_t _simix_cfg_set; + + + + + + +#define PROCESS_SET_ERRNO(val) (SIMIX_process_self()->simdata->last_errno=val) +#define PROCESS_GET_ERRNO() (SIMIX_process_self()->simdata->last_errno) +#define SIMIX_RETURN(val) do {PROCESS_SET_ERRNO(val);return(val);} while(0) +/* #define CHECK_ERRNO() ASSERT((PROCESS_GET_ERRNO()!=MSG_HOST_FAILURE),"Host failed, you cannot call this function.") */ + +#define CHECK_HOST() xbt_assert0(surf_workstation_resource->extension_public-> \ + get_state(MSG_host_self()->simdata->host)==SURF_CPU_ON,\ + "Host failed, you cannot call this function.") + +smx_host_t __SIMIX_host_create(const char *name, void *workstation, void *data); +void __SIMIX_host_destroy(smx_host_t host); + +int __SIMIX_process_block(double max_duration, const char *info); +SIMIX_error_t __SIMIX_process_unblock(smx_process_t process); +int __SIMIX_process_isBlocked(smx_process_t process); + +void __SIMIX_display_process_status(void); + +/* +void __MSG_task_execute(smx_process_t process, m_task_t task); +MSG_error_t __MSG_wait_for_computation(smx_process_t process, m_task_t task); +MSG_error_t __MSG_task_wait_event(smx_process_t process, m_task_t task); +*/ + + +#endif diff --git a/src/simix/smx_action.c b/src/simix/smx_action.c new file mode 100644 index 0000000000..540c5f7bb6 --- /dev/null +++ b/src/simix/smx_action.c @@ -0,0 +1,41 @@ +/* $Id$ */ + +/* Copyright (c) 2007 Arnaud Legrand, Bruno Donnassolo. + All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "private.h" +#include "xbt/log.h" + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_action, simix, + "Logging specific to SIMIX (action)"); + +/************************************* Actions *********************************/ + +smx_action_t SIMIX_communicate(smx_host_t sender,smx_host_t receiver, double size) +{ + return xbt_new0(s_smx_action_t,1); +} + +smx_action_t SIMIX_execute(smx_host_t host,double amount) +{ + return xbt_new0(s_smx_action_t,1); +} + +SIMIX_error_t SIMIX_action_cancel(smx_action_t action) +{ + + return SIMIX_OK; +} + +void SIMIX_action_set_priority(smx_action_t action, double priority) +{ + return; +} + +SIMIX_error_t SIMIX_action_destroy(smx_action_t action) +{ + return SIMIX_OK; +} diff --git a/src/simix/smx_config.c b/src/simix/smx_config.c new file mode 100644 index 0000000000..106e9ec45e --- /dev/null +++ b/src/simix/smx_config.c @@ -0,0 +1,85 @@ +/* $Id$ */ + +/* simix_config.c - support for SIMIX user configuration */ + +/* Copyright (c) 2005 Martin Quinson. */ +/* All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "private.h" +#include "xbt/sysdep.h" +#include "xbt/log.h" + +int _simix_init_status = 0; /* 0: beginning of time; + 1: pre-inited (cfg_set created); + 2: inited (running) */ +xbt_cfg_t _simix_cfg_set = NULL; + +/* callback of the surf_workstation_model variable */ +static void _simix_cfg_cb__surf_workstation_model(const char *name, int pos) +{ + char *val; + + xbt_assert0(_simix_init_status<2, "Cannot change the model after the initialization"); + + val = xbt_cfg_get_string (_simix_cfg_set, name); + /* New Module missing */ + xbt_assert1(!strcmp(val, "CLM03") || + !strcmp(val, "KCCFLN05") || + !strcmp(val, "KCCFLN05_proportionnal"), + "Unknown workstation model: %s (either 'CLM03' or 'KCCFLN05'",val); +} + +/* create the config set and register what should be */ +void simix_config_init(void) +{ + + if (_simix_init_status) + return; /* Already inited, nothing to do */ + + _simix_init_status = 1; + _simix_cfg_set = xbt_cfg_new(); + + xbt_cfg_register (_simix_cfg_set, + "surf_workstation_model", xbt_cfgelm_string, 1,1, + &_simix_cfg_cb__surf_workstation_model,NULL); + + xbt_cfg_set_string(_simix_cfg_set,"surf_workstation_model", "KCCFLN05"); +} + +void simix_config_finalize(void) +{ + + if (!_simix_init_status) + return; /* Not initialized yet. Nothing to do */ + + xbt_cfg_free(&_simix_cfg_set); + _simix_init_status = 0; +} + +/** \brief set a configuration variable + * + * Currently existing configuation variable: + * - surf_workstation_model (string): Model of workstation to use. + * Possible values (defaults to "KCCFLN05"): + * - "CLM03": realistic TCP behavior + basic CPU model (see [CML03 at CCGrid03]) + support for parallel tasks + * - "KCCFLN05": realistic TCP behavior + basic CPU model (see [CML03 at CCGrid03]) + failure handling + interference between communications and computations if precised in the platform file. + * + * Example: + * MSG_config("surf_workstation_model","KCCFLN05"); + */ +void SIMIX_config(const char *name, ...) +{ + va_list pa; + + if (!_simix_init_status) { + simix_config_init(); + } + + va_start(pa,name); + xbt_cfg_set_vargs(_simix_cfg_set,name,pa); + va_end(pa); + +} diff --git a/src/simix/smx_deployment.c b/src/simix/smx_deployment.c new file mode 100644 index 0000000000..bdc7a87cb4 --- /dev/null +++ b/src/simix/smx_deployment.c @@ -0,0 +1,137 @@ +/* $Id$ */ + +/* Copyright (c) 2007 Arnaud Legrand, Bruno Donnassolo. + All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + + +#include "private.h" +#include "xbt/sysdep.h" +#include "xbt/log.h" +#include "surf/surfxml_parse_private.h" + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_deployment, simix, + "Logging specific to SIMIX (deployment)"); +static int parse_argc = -1 ; +static char **parse_argv = NULL; +static smx_process_code_t parse_code = NULL; +static smx_host_t parse_host = NULL; +static double start_time = 0.0; +static double kill_time = -1.0; + +static void parse_process_init(void) +{ + parse_host = SIMIX_get_host_by_name(A_surfxml_process_host); + xbt_assert1(parse_host, "Unknown host %s",A_surfxml_process_host); + parse_code = SIMIX_get_registered_function(A_surfxml_process_function); + xbt_assert1(parse_code, "Unknown function %s",A_surfxml_process_function); + parse_argc = 0 ; + parse_argv = NULL; + parse_argc++; + parse_argv = xbt_realloc(parse_argv, (parse_argc) * sizeof(char *)); + parse_argv[(parse_argc) - 1] = xbt_strdup(A_surfxml_process_function); + surf_parse_get_double(&start_time,A_surfxml_process_start_time); + surf_parse_get_double(&kill_time,A_surfxml_process_kill_time); +} + +static void parse_argument(void) +{ + parse_argc++; + parse_argv = xbt_realloc(parse_argv, (parse_argc) * sizeof(char *)); + parse_argv[(parse_argc) - 1] = xbt_strdup(A_surfxml_argument_value); +} + +static void parse_process_finalize(void) +{ + process_arg_t arg = NULL; + smx_process_t process = NULL; + if(start_time>SIMIX_get_clock()) { + arg = xbt_new0(s_process_arg_t,1); + arg->name = parse_argv[0]; + arg->code = parse_code; + arg->data = NULL; + arg->host = parse_host; + arg->argc = parse_argc; + arg->argv = parse_argv; + arg-> kill_time = kill_time; + + DEBUG3("Process %s(%s) will be started at time %f", arg->name, + arg->host->name,start_time); + surf_timer_resource->extension_public->set(start_time, (void*) &SIMIX_process_create_with_arguments, + arg); + } + if((start_time<0) || (start_time==SIMIX_get_clock())) { + DEBUG2("Starting Process %s(%s) right now", parse_argv[0], + parse_host->name); + process = SIMIX_process_create_with_arguments(parse_argv[0], parse_code, + NULL, parse_host, + parse_argc,parse_argv); + if(kill_time > SIMIX_get_clock()) { + surf_timer_resource->extension_public->set(kill_time, + (void*) &SIMIX_process_kill, + (void*) process); + } + } +} + +/** \ingroup msg_easier_life + * \brief An application deployer. + * + * Creates the process described in \a file. + * \param file a filename of a xml description of the application. This file + * follows this DTD : + * + * \include surfxml.dtd + * + * Here is a small example of such a platform + * + * \include small_deployment.xml + * + * Have a look in the directory examples/msg/ to have a bigger example. + */ +void SIMIX_launch_application(const char *file) +{ + xbt_assert0(simix_global,"SIMIX_global_init_args has to be called before SIMIX_launch_application."); + STag_surfxml_process_fun = parse_process_init; + ETag_surfxml_argument_fun = parse_argument; + ETag_surfxml_process_fun = parse_process_finalize; + surf_parse_open(file); + xbt_assert1((!surf_parse()),"Parse error in %s",file); + surf_parse_close(); +} + +/** \ingroup msg_easier_life + * \brief Registers a #m_process_code_t code in a global table. + * + * Registers a code function in a global table. + * This table is then used by #MSG_launch_application. + * \param name the reference name of the function. + * \param code the function + */ +void SIMIX_function_register(const char *name,smx_process_code_t code) +{ + xbt_assert0(simix_global,"SIMIX_global_init has to be called before SIMIX_function_register."); + + xbt_dict_set(simix_global->registered_functions,name,code,NULL); +} + +/** \ingroup msg_easier_life + * \brief Registers a #m_process_t code in a global table. + * + * Registers a code function in a global table. + * This table is then used by #MSG_launch_application. + * \param name the reference name of the function. + */ +smx_process_code_t SIMIX_get_registered_function(const char *name) +{ + smx_process_code_t code = NULL; + + xbt_assert0(simix_global,"SIMIX_global_init has to be called before SIMIX_get_registered_function."); + + code = xbt_dict_get_or_null(simix_global->registered_functions,name); + + return code; +} + diff --git a/src/simix/smx_environment.c b/src/simix/smx_environment.c new file mode 100644 index 0000000000..56047924b0 --- /dev/null +++ b/src/simix/smx_environment.c @@ -0,0 +1,93 @@ +/* $Id$ */ + +/* Copyright (c) 2007 Arnaud Legrand, Bruno Donnassolo. + All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "private.h" +#include "xbt/sysdep.h" +#include "xbt/log.h" +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_environment, simix, + "Logging specific to SIMIX (environment)"); +/** \defgroup msg_easier_life Platform and Application management + * \brief This section describes functions to manage the platform creation + * and the application deployment. You should also have a look at + * \ref MSG_examples to have an overview of their usage. + * \htmlonly \endhtmlonly + * + */ + +/********************************* SIMIX **************************************/ + +/** \ingroup msg_easier_life + * \brief A name directory service... + * + * Finds a m_host_t using its name. + * \param name the name of an host. + * \return the corresponding host + */ +smx_host_t SIMIX_get_host_by_name(const char *name) +{ + xbt_fifo_item_t i = NULL; + smx_host_t host = NULL; + + xbt_assert0(((simix_global != NULL) + && (simix_global->host != NULL)), "Environment not set yet"); + + xbt_fifo_foreach(simix_global->host,i,host,smx_host_t) { + if(strcmp(host->name, name) == 0) return host; + } + return NULL; +} + +/** \ingroup msg_easier_life + * \brief A platform constructor. + * + * Creates a new platform, including hosts, links and the + * routing_table. + * \param file a filename of a xml description of a platform. This file + * follows this DTD : + * + * \include surfxml.dtd + * + * Here is a small example of such a platform + * + * \include small_platform.xml + * + * Have a look in the directory examples/msg/ to have a big example. + */ +void SIMIX_create_environment(const char *file) +{ + xbt_dict_cursor_t cursor = NULL; + char *name = NULL; + void *workstation = NULL; + char *workstation_model_name; + + simix_config_init(); /* make sure that our configuration set is created */ + surf_timer_resource_init(file); + + /* which model do you want today? */ + workstation_model_name = xbt_cfg_get_string (_simix_cfg_set, "surf_workstation_model"); + + DEBUG1("Model : %s", workstation_model_name); + if (!strcmp(workstation_model_name,"KCCFLN05")) { + surf_workstation_resource_init_KCCFLN05(file); + } + else if (!strcmp(workstation_model_name,"KCCFLN05_proportionnal")) { + surf_workstation_resource_init_KCCFLN05_proportionnal(file); + } else if (!strcmp(workstation_model_name,"CLM03")) { + surf_workstation_resource_init_CLM03(file); + } else { + xbt_assert0(0,"The impossible happened (once again)"); + } + _simix_init_status = 2; /* inited; don't change settings now */ + + xbt_dict_foreach(workstation_set, cursor, name, workstation) { + __SIMIX_host_create(name, workstation, NULL); + } + + return; +} + diff --git a/src/simix/smx_host.c b/src/simix/smx_host.c new file mode 100644 index 0000000000..2326036bab --- /dev/null +++ b/src/simix/smx_host.c @@ -0,0 +1,198 @@ +/* $Id$ */ + +/* Copyright (c) 2002,2003,2004 Arnaud Legrand. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "private.h" +#include "xbt/sysdep.h" +#include "xbt/log.h" + +/** \defgroup m_host_management Management functions of Hosts + * \brief This section describes the host structure of MSG + * + * \htmlonly \endhtmlonly + * (#m_host_t) and the functions for managing it. + * + * A location (or host) is any possible place where + * a process may run. Thus it may be represented as a + * physical resource with computing capabilities, some + * mailboxes to enable running process to communicate with + * remote ones, and some private data that can be only + * accessed by local process. + * \see m_host_t + */ + +/********************************* Host **************************************/ +smx_host_t __SIMIX_host_create(const char *name, + void *workstation, + void *data) +{ + simdata_host_t simdata = xbt_new0(s_simdata_host_t,1); + smx_host_t host = xbt_new0(s_smx_host_t,1); + s_smx_process_t proc; + + /* Host structure */ + host->name = xbt_strdup(name); + host->simdata = simdata; + host->data = data; + + simdata->host = workstation; + + simdata->process_list = xbt_swag_new(xbt_swag_offset(proc, process_hookup)); + /* Update global variables */ + + xbt_fifo_unshift(simix_global->host, host); + + return host; +} + +/** \ingroup m_host_management + * + * \brief Set the user data of a #m_host_t. + * + * This functions checks whether some data has already been associated to \a host + or not and attach \a data to \a host if it is possible. + */ +SIMIX_error_t SIMIX_host_set_data(smx_host_t host, void *data) +{ + xbt_assert0((host!=NULL), "Invalid parameters"); + xbt_assert0((host->data == NULL), "Data already set"); + + /* Assign data */ + host->data = data; + + return SIMIX_OK; +} + +/** \ingroup m_host_management + * + * \brief Return the user data of a #m_host_t. + * + * This functions checks whether \a host is a valid pointer or not and return + the user data associated to \a host if it is possible. + */ +void *SIMIX_host_get_data(smx_host_t host) +{ + + xbt_assert0((host != NULL), "Invalid parameters"); + + /* Return data */ + return (host->data); +} + +/** \ingroup m_host_management + * + * \brief Return the name of the #m_host_t. + * + * This functions checks whether \a host is a valid pointer or not and return + its name. + */ +const char *SIMIX_host_get_name(smx_host_t host) +{ + + xbt_assert0((host != NULL) && (host->simdata != NULL), "Invalid parameters"); + + /* Return data */ + return (host->name); +} + +/** \ingroup m_host_management + * + * \brief Return the location on which the current process is executed. + */ +smx_host_t SIMIX_host_self(void) +{ + return SIMIX_process_get_host(SIMIX_process_self()); +} + +/* + * Real function for destroy a host. + * MSG_host_destroy is just a front_end that also removes it from + * msg_global->host + */ +void __SIMIX_host_destroy(smx_host_t host) +{ + simdata_host_t simdata = NULL; + + xbt_assert0((host != NULL), "Invalid parameters"); + + + /* Clean Simulator data */ + simdata = (host)->simdata; + + xbt_assert0((xbt_swag_size(simdata->process_list)==0), + "Some process are still running on this host"); + xbt_swag_free(simdata->process_list); + + free(simdata); + + /* Clean host structure */ + free(host->name); + free(host); + + return; +} + +/** \ingroup m_host_management + * \brief Return the current number of #m_host_t. + */ +int SIMIX_get_host_number(void) +{ + return (xbt_fifo_size(simix_global->host)); +} + +/** \ingroup m_host_management + * \brief Return a array of all the #m_host_t. + */ +smx_host_t *SIMIX_get_host_table(void) +{ + return ((smx_host_t *)xbt_fifo_to_array(simix_global->host)); +} + +/** \ingroup m_host_management + * \brief Return the number of MSG tasks currently running on a + * #m_host_t. The external load is not taken in account. + */ +/* +int MSG_get_host_msgload(m_host_t h) +{ + xbt_assert0((h!= NULL), "Invalid parameters"); + xbt_assert0(0, "Not implemented yet"); + + return(0); +// return(surf_workstation_resource->extension_public->get_load(h->simdata->host)); +} +*/ + +/** \ingroup m_host_management + * \brief Return the speed of the processor (in Mflop/s), regardless of + the current load on the machine. + */ +double SIMIX_get_host_speed(smx_host_t h) +{ + xbt_assert0((h!= NULL), "Invalid parameters"); + + return(surf_workstation_resource-> + extension_public->get_speed(h->simdata->host,1.0)); +} + +/** \ingroup msg_gos_functions + * \brief Determine if a host is available. + * + * \param h host to test + */ +int SIMIX_host_is_avail (smx_host_t h) +{ + e_surf_cpu_state_t cpustate; + xbt_assert0((h!= NULL), "Invalid parameters"); + + cpustate = + surf_workstation_resource->extension_public->get_state(h->simdata->host); + + xbt_assert0((cpustate == SURF_CPU_ON || cpustate == SURF_CPU_OFF), + "Invalid cpu state"); + + return (cpustate==SURF_CPU_ON); +} diff --git a/src/simix/smx_process.c b/src/simix/smx_process.c new file mode 100644 index 0000000000..936f38527d --- /dev/null +++ b/src/simix/smx_process.c @@ -0,0 +1,529 @@ +/* $Id$ */ + +/* Copyright (c) 2002,2003,2004 Arnaud Legrand. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "private.h" +#include "xbt/sysdep.h" +#include "xbt/log.h" +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix, + "Logging specific to SIMIX (process)"); +/** \defgroup m_process_management Management Functions of Agents + * \brief This section describes the agent structure of MSG + * (#m_process_t) and the functions for managing it. + * \htmlonly \endhtmlonly + * + * We need to simulate many independent scheduling decisions, so + * the concept of process is at the heart of the + * simulator. A process may be defined as a code, with + * some private data, executing in a location. + * \see m_process_t + */ + +/******************************** Process ************************************/ +/** \ingroup m_process_management + * \brief Creates and runs a new #m_process_t. + * + * Does exactly the same as #MSG_process_create_with_arguments but without + providing standard arguments (\a argc, \a argv, \a start_time, \a kill_time). + * \sa MSG_process_create_with_arguments + */ +smx_process_t SIMIX_process_create(const char *name, + smx_process_code_t code, void *data, + smx_host_t host) +{ + return SIMIX_process_create_with_arguments(name, code, data, host, -1, NULL); +} + +static void SIMIX_process_cleanup(void *arg) +{ + xbt_swag_remove(arg, simix_global->process_list); + xbt_swag_remove(arg, simix_global->process_to_run); + xbt_swag_remove(arg, ((smx_process_t) arg)->simdata->host->simdata->process_list); + free(((smx_process_t) arg)->name); + ((smx_process_t) arg)->name = NULL; + free(((smx_process_t) arg)->simdata); + ((smx_process_t) arg)->simdata = NULL; + free(arg); +} + +/** \ingroup m_process_management + * \brief Creates and runs a new #m_process_t. + + * A constructor for #m_process_t taking four arguments and returning the + * corresponding object. The structure (and the corresponding thread) is + * created, and put in the list of ready process. + * \param name a name for the object. It is for user-level information + and can be NULL. + * \param code is a function describing the behavior of the agent. It + should then only use functions described in \ref + m_process_management (to create a new #m_process_t for example), + in \ref m_host_management (only the read-only functions i.e. whose + name contains the word get), in \ref m_task_management (to create + or destroy some #m_task_t for example) and in \ref + msg_gos_functions (to handle file transfers and task processing). + * \param data a pointer to any data one may want to attach to the new + object. It is for user-level information and can be NULL. It can + be retrieved with the function \ref MSG_process_get_data. + * \param host the location where the new agent is executed. + * \param argc first argument passed to \a code + * \param argv second argument passed to \a code + * \see m_process_t + * \return The new corresponding object. + */ +smx_process_t SIMIX_process_create_with_arguments(const char *name, + smx_process_code_t code, void *data, + smx_host_t host, int argc, char **argv) +{ + simdata_process_t simdata = xbt_new0(s_simdata_process_t,1); + smx_process_t process = xbt_new0(s_smx_process_t,1); + smx_process_t self = NULL; + + xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters"); + /* Simulator Data */ + + simdata->host = host; + simdata->argc = argc; + simdata->argv = argv; + simdata->context = xbt_context_new(code, NULL, NULL, + SIMIX_process_cleanup, process, + simdata->argc, simdata->argv); + + if((self=simix_global->current_process)) { + //simdata->PPID = MSG_process_get_PID(self); + } else { + // simdata->PPID = -1; + } + simdata->last_errno=SIMIX_OK; + + + /* Process structure */ + process->name = xbt_strdup(name); + process->simdata = simdata; + process->data = data; + + xbt_swag_insert_at_head(process, host->simdata->process_list); + + /* *************** FIX du current_process !!! *************** */ + self = simix_global->current_process; + xbt_context_start(process->simdata->context); + simix_global->current_process = self; + + xbt_swag_insert_at_head(process,simix_global->process_list); + DEBUG2("Inserting %s(%s) in the to_run list",process->name, + host->name); + xbt_swag_insert_at_head(process,simix_global->process_to_run); + + return process; +} + +/** \ingroup m_process_management + * \param process poor victim + * + * This function simply kills a \a process... scarry isn't it ? :) + */ +void SIMIX_process_kill(smx_process_t process) +{ + //int i; + simdata_process_t p_simdata = process->simdata; + //simdata_host_t h_simdata= p_simdata->host->simdata; + //int _cursor; + //smx_process_t proc = NULL; + + DEBUG2("Killing %s on %s",process->name, p_simdata->host->name); + + /* + + if(p_simdata->waiting_task) { + xbt_dynar_foreach(p_simdata->waiting_task->simdata->sleeping,_cursor,proc) { + if(proc==process) + xbt_dynar_remove_at(p_simdata->waiting_task->simdata->sleeping,_cursor,&proc); + } + if(p_simdata->waiting_task->simdata->compute) + surf_workstation_resource->common_public-> + action_free(p_simdata->waiting_task->simdata->compute); + else if (p_simdata->waiting_task->simdata->comm) { + surf_workstation_resource->common_public-> + action_change_state(p_simdata->waiting_task->simdata->comm,SURF_ACTION_FAILED); + surf_workstation_resource->common_public-> + action_free(p_simdata->waiting_task->simdata->comm); + } else { + xbt_die("UNKNOWN STATUS. Please report this bug."); + } + } + + if ((i==msg_global->max_channel) && (process!=MSG_process_self()) && + (!p_simdata->waiting_task)) { + xbt_die("UNKNOWN STATUS. Please report this bug."); + } +*/ + xbt_swag_remove(process,simix_global->process_to_run); + xbt_swag_remove(process,simix_global->process_list); + xbt_context_free(process->simdata->context); + + if(process==SIMIX_process_self()) { + /* I just killed myself */ + xbt_context_yield(); + } +} + +/** \ingroup m_process_management + * \brief Migrates an agent to another location. + * + * This functions checks whether \a process and \a host are valid pointers + and change the value of the #m_host_t on which \a process is running. + */ +SIMIX_error_t SIMIX_process_change_host(smx_process_t process, smx_host_t host) +{ + simdata_process_t simdata = NULL; + + /* Sanity check */ + + xbt_assert0(((process) && (process->simdata) + && (host)), "Invalid parameters"); + simdata = process->simdata; + + xbt_swag_remove(process,simdata->host->simdata->process_list); + simdata->host = host; + xbt_swag_insert_at_head(process,host->simdata->process_list); + + return SIMIX_OK; +} + +/** \ingroup m_process_management + * \brief Return the user data of a #m_process_t. + * + * This functions checks whether \a process is a valid pointer or not + and return the user data associated to \a process if it is possible. + */ +void *SIMIX_process_get_data(smx_process_t process) +{ + xbt_assert0((process != NULL), "Invalid parameters"); + + return (process->data); +} + +/** \ingroup m_process_management + * \brief Set the user data of a #m_process_t. + * + * This functions checks whether \a process is a valid pointer or not + and set the user data associated to \a process if it is possible. + */ +SIMIX_error_t SIMIX_process_set_data(smx_process_t process,void *data) +{ + xbt_assert0((process != NULL), "Invalid parameters"); + xbt_assert0((process->data == NULL), "Data already set"); + + process->data = data; + + return SIMIX_OK; +} + +/** \ingroup m_process_management + * \brief Return the location on which an agent is running. + * + * This functions checks whether \a process is a valid pointer or not + and return the m_host_t corresponding to the location on which \a + process is running. + */ +smx_host_t SIMIX_process_get_host(smx_process_t process) +{ + xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters"); + + return (((simdata_process_t) process->simdata)->host); +} + +/** \ingroup m_process_management + * + * \brief Return a #m_process_t given its PID. + * + * This functions search in the list of all the created m_process_t for a m_process_t + whose PID is equal to \a PID. If no host is found, \c NULL is returned. + Note that the PID are uniq in the whole simulation, not only on a given host. + */ +/* +m_process_t MSG_process_from_PID(int PID) +{ + xbt_fifo_item_t i = NULL; + m_process_t process = NULL; + + xbt_fifo_foreach(msg_global->process_list,i,process,m_process_t) { + if(MSG_process_get_PID(process) == PID) return process; + } + return NULL; +} +*/ + +/** \ingroup m_process_management + * \brief Returns the process ID of \a process. + * + * This functions checks whether \a process is a valid pointer or not + and return its PID. + */ +/* +int MSG_process_get_PID(m_process_t process) +{ + xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters"); + + return (((simdata_process_t) process->simdata)->PID); +} +*/ +/** \ingroup m_process_management + * \brief Returns the process ID of the parent of \a process. + * + * This functions checks whether \a process is a valid pointer or not + and return its PID. Returns -1 if the agent has not been created by + another agent. + */ +/* +int MSG_process_get_PPID(m_process_t process) +{ + xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters"); + + return (((simdata_process_t) process->simdata)->PPID); +} +*/ +/** \ingroup m_process_management + * \brief Return the name of an agent. + * + * This functions checks whether \a process is a valid pointer or not + and return its name. + */ +const char *SIMIX_process_get_name(smx_process_t process) +{ + xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters"); + + return (process->name); +} + +/** \ingroup m_process_management + * \brief Return the PID of the current agent. + * + * This functions returns the PID of the currently running #m_process_t. + */ +/* +int MSG_process_self_PID(void) +{ + return (MSG_process_get_PID(MSG_process_self())); +} +*/ +/** \ingroup m_process_management + * \brief Return the PPID of the current agent. + * + * This functions returns the PID of the parent of the currently + * running #m_process_t. + */ +/* +int MSG_process_self_PPID(void) +{ + return (MSG_process_get_PPID(MSG_process_self())); +} +*/ +/** \ingroup m_process_management + * \brief Return the current agent. + * + * This functions returns the currently running #m_process_t. + */ +smx_process_t SIMIX_process_self(void) +{ + return simix_global ? simix_global->current_process : NULL; +} + +/** \ingroup m_process_management + * \brief Suspend the process. + * + * This functions suspend the process by suspending the task on which + * it was waiting for the completion. + */ +SIMIX_error_t SIMIX_process_suspend(smx_process_t process) +{ +/* + simdata_process_t simdata = NULL; + simdata_task_t simdata_task = NULL; + + XBT_IN2("(%p(%s))", process, process->name); + + xbt_assert0(((process) && (process->simdata)), "Invalid parameters"); + + PAJE_PROCESS_PUSH_STATE(process,"S",NULL); + + if(process!=SIMIX_process_self()) { + simdata = process->simdata; + + xbt_assert0(simdata->waiting_task,"Process not waiting for anything else. Weird !"); + + simdata_task = simdata->waiting_task->simdata; + + simdata->suspended = 1; + if(simdata->blocked) { + XBT_OUT; + return SIMIX_OK; + } + + xbt_assert0(((simdata_task->compute)||(simdata_task->comm))&& + !((simdata_task->compute)&&(simdata_task->comm)), + "Got a problem in deciding which action to choose !"); + simdata->suspended = 1; + if(simdata_task->compute) + surf_workstation_resource->common_public->suspend(simdata_task->compute); + else + surf_workstation_resource->common_public->suspend(simdata_task->comm); + } else { + m_task_t dummy = MSG_TASK_UNINITIALIZED; + dummy = MSG_task_create("suspended", 0.0, 0, NULL); + + simdata = process->simdata; + simdata->suspended = 1; + __MSG_task_execute(process,dummy); + surf_workstation_resource->common_public->suspend(dummy->simdata->compute); + __MSG_wait_for_computation(process,dummy); + simdata->suspended = 0; + + MSG_task_destroy(dummy); + } + XBT_OUT; + */ + return SIMIX_OK; +} + +/** \ingroup m_process_management + * \brief Resume a suspended process. + * + * This functions resume a suspended process by resuming the task on + * which it was waiting for the completion. + */ +SIMIX_error_t SIMIX_process_resume(smx_process_t process) +{ +/* + simdata_process_t simdata = NULL; + simdata_task_t simdata_task = NULL; + + xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters"); + CHECK_HOST(); + + XBT_IN2("(%p(%s))", process, process->name); + + if(process == SIMIX_process_self()) { + XBT_OUT; + SIMIX_RETURN(SIMIX_OK); + } + + simdata = process->simdata; + + if(simdata->blocked) { + PAJE_PROCESS_POP_STATE(process); + + simdata->suspended = 0; *//* He'll wake up by itself */ + /*XBT_OUT; + SIMIX_RETURN(SIMIX_OK); + } + + if(!(simdata->waiting_task)) { + xbt_assert0(0,"Process not waiting for anything else. Weird !"); + XBT_OUT; + return SIMIX_WARNING; + } + simdata_task = simdata->waiting_task->simdata; + + + if(simdata_task->compute) { + surf_workstation_resource->common_public->resume(simdata_task->compute); + PAJE_PROCESS_POP_STATE(process); + } + else { + PAJE_PROCESS_POP_STATE(process); + surf_workstation_resource->common_public->resume(simdata_task->comm); + } + + XBT_OUT; + */ + SIMIX_RETURN(SIMIX_OK); +} + +/** \ingroup m_process_management + * \brief Returns true if the process is suspended . + * + * This checks whether a process is suspended or not by inspecting the + * task on which it was waiting for the completion. + */ +int SIMIX_process_is_suspended(smx_process_t process) +{ + xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters"); + + return (process->simdata->suspended); +} + +int __SIMIX_process_block(double max_duration, const char *info) +{ +/* + smx_process_t process = SIMIX_process_self(); + m_task_t dummy = SIMIX_TASK_UNINITIALIZED; + char blocked_name[512]; + snprintf(blocked_name,512,"blocked [%s] (%s:%s)", + info, process->name, process->simdata->host->name); + + XBT_IN1(": max_duration=%g",max_duration); + + dummy = MSG_task_create(blocked_name, 0.0, 0, NULL); + + PAJE_PROCESS_PUSH_STATE(process,"B",NULL); + + process->simdata->blocked=1; + __MSG_task_execute(process,dummy); + surf_workstation_resource->common_public->suspend(dummy->simdata->compute); + if(max_duration>=0) + surf_workstation_resource->common_public->set_max_duration(dummy->simdata->compute, + max_duration); + __MSG_wait_for_computation(process,dummy); + MSG_task_destroy(dummy); + process->simdata->blocked=0; + + if(process->simdata->suspended) { + DEBUG0("I've been suspended in the meantime"); + SIMIX_process_suspend(process); + DEBUG0("I've been resumed, let's keep going"); + } + + PAJE_PROCESS_POP_STATE(process); + + XBT_OUT; + */ + return 1; +} + +SIMIX_error_t __SIMIX_process_unblock(smx_process_t process) +{ +/* + simdata_process_t simdata = NULL; + simdata_task_t simdata_task = NULL; + + xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters"); + CHECK_HOST(); + + XBT_IN2(": %s unblocking %s", SIMIX_process_self()->name,process->name); + + simdata = process->simdata; + if(!(simdata->waiting_task)) { + xbt_assert0(0,"Process not waiting for anything else. Weird !"); + XBT_OUT; + return SIMIX_WARNING; + } + simdata_task = simdata->waiting_task->simdata; + + xbt_assert0(simdata->blocked,"Process not blocked"); + + surf_workstation_resource->common_public->resume(simdata_task->compute); + + XBT_OUT; +*/ + SIMIX_RETURN(SIMIX_OK); +} + +int __SIMIX_process_isBlocked(smx_process_t process) +{ + xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters"); + + return (process->simdata->blocked); +} diff --git a/src/simix/smx_synchro.c b/src/simix/smx_synchro.c new file mode 100644 index 0000000000..14a2e3afc6 --- /dev/null +++ b/src/simix/smx_synchro.c @@ -0,0 +1,74 @@ +/* $Id$ */ + +/* Copyright (c) 2007 Arnaud Legrand, Bruno Donnassolo. + All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "private.h" +#include "xbt/log.h" + + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_synchro, simix, + "Logging specific to SIMIX (synchronization)"); + + +/****************************** Synchronization *******************************/ + +/*********************************** Mutex ************************************/ +smx_mutex_t SIMIX_mutex_init() +{ + return xbt_new0(s_smx_mutex_t,1); +} + +void SIMIX_mutex_lock(smx_mutex_t mutex) +{ + return; +} + +void SIMIX_mutex_trylock(smx_mutex_t mutex) +{ + return; +} + +void SIMIX_mutex_unlock(smx_mutex_t mutex) +{ + return; +} + +void SIMIX_mutex_destroy(smx_mutex_t mutex) +{ + return; +} + +/******************************** Conditional *********************************/ +smx_cond_t SIMIX_cond_init() +{ + return xbt_new0(s_smx_cond_t,1); +} + +void SIMIX_cond_signal(smx_cond_t cond) +{ + return; +} + +void SIMIX_cond_wait(smx_cond_t cond,smx_mutex_t mutex) +{ + return; +} + +void SIMIX_cond_wait_timeout(smx_cond_t cond,smx_mutex_t mutex, double max_duration) +{ + return; +} + +void SIMIX_cond_broadcast(smx_cond_t cond) +{ + return; +} + +void SIMIX_cond_destroy(smx_cond_t cond) +{ + return; +} -- 2.20.1