Commit b4d60d63 authored by yoogx's avatar yoogx

* Add support for multi-core systems: assignment of thread

          affinity for GNU/Linux and RTEMS platforms
parent 5ce7aff6
......@@ -5,14 +5,14 @@
*
* For more informations, please visit http://taste.tuxfamily.org/wiki
*
* Copyright (C) 2010-2014 ESA & ISAE.
* Copyright (C) 2010-2015 ESA & ISAE.
*/
#ifndef __PO_HI_TASK_H__
#define __PO_HI_TASK_H__
/*
* Define some values that are dependant of the
* Define some values that are dependant of the
* underlying executive.
*/
#if defined(POSIX) || defined (XENO_POSIX)
......@@ -30,7 +30,7 @@
#include <stdio.h>
#define __PO_HI_MAIN_NAME _tmain
#define __PO_HI_MAIN_TYPE int
#define __PO_HI_MAIN_ARGS
#define __PO_HI_MAIN_ARGS
#define __PO_HI_MAIN_RETURN EXIT_SUCCESS
#define __ERRORMSG(s, args...) fprintf(stderr, s, ##args)
#elif defined (XENO_NATIVE)
......@@ -50,7 +50,7 @@
#elif defined(RTEMS_POSIX)
#define __PO_HI_MAIN_NAME POSIX_Init
#define __PO_HI_MAIN_TYPE int
#define __PO_HI_MAIN_ARGS
#define __PO_HI_MAIN_ARGS
#define __PO_HI_MAIN_RETURN 0
#define __ERRORMSG(s, args...) fprintf(stderr, s, ##args)
#endif
......@@ -100,38 +100,40 @@ typedef size_t __po_hi_stack_t;
int __po_hi_initialize_tasking(void);
/*
* Create a periodic task.
*
* Create a periodic task.
*
* The task created have the identifier given by the first
* parameter. It is created according to the period created
* with __po_hi_* functions (like __po_hi_milliseconds())
* and priority parameters (use the OS priority). The task execute
* periodically start_routine.
*
* This function returns SUCCESS if there is no error. Else,
* This function returns SUCCESS if there is no error. Else,
* it returns the negative value ERROR_CREATE_TASK.
*/
int __po_hi_create_periodic_task (const __po_hi_task_id id,
const __po_hi_time_t* period,
const __po_hi_priority_t priority,
int __po_hi_create_periodic_task (const __po_hi_task_id id,
const __po_hi_time_t* period,
const __po_hi_priority_t priority,
const __po_hi_stack_t stack_size,
const __po_hi_int8_t core_id,
void* (*start_routine)(void));
/*
* Create a sporadic task.
* Create a sporadic task.
*
* The identifier of the task is the first parameter. The period and
* the priority of the task are stored in the second and third
* parameter. The code executed by the task is stored in the
* start_routine pointer.
*
*
* Returns SUCCESS value if there is no error. Else, returns the negative
* value ERROR_CREATE_TASK
*/
int __po_hi_create_sporadic_task (const __po_hi_task_id id,
const __po_hi_time_t* period,
const __po_hi_priority_t priority,
const __po_hi_time_t* period,
const __po_hi_priority_t priority,
const __po_hi_stack_t stack_size,
const __po_hi_int8_t core_id,
void* (*start_routine)(void));
/*
......@@ -141,14 +143,15 @@ int __po_hi_create_sporadic_task (const __po_hi_task_id id,
* the priority of the task are stored in the second and third
* parameter. The code executed by the task is stored in the
* start_routine pointer.
*
*
* Returns SUCCESS value if there is no error. Else, returns the negative
* value ERROR_CREATE_TASK
*/
int __po_hi_create_generic_task (const __po_hi_task_id id,
const __po_hi_time_t* period,
const __po_hi_priority_t priority,
int __po_hi_create_generic_task (const __po_hi_task_id id,
const __po_hi_time_t* period,
const __po_hi_priority_t priority,
const __po_hi_stack_t stack_size,
const __po_hi_int8_t core_id,
void* (*start_routine)(void),
void* arg);
......@@ -193,4 +196,4 @@ void __po_hi_tasks_killall (void);
void __po_hi_task_wait_offset (const __po_hi_time_t* time);
#endif /* __PO_HI_TASK_H__ */
#endif /* __PO_HI_TASK_H__ */
......@@ -5,7 +5,7 @@
*
* For more informations, please visit http://taste.tuxfamily.org/wiki
*
* Copyright (C) 2011-2014 ESA & ISAE.
* Copyright (C) 2011-2015 ESA & ISAE.
*/
#include <deployment.h>
......@@ -97,7 +97,7 @@ static struct rtems_bsdnet_ifconfig netdriver_config = {
#ifdef RTEMS48
loopback_config,
#else
0,
0,
#endif
*/
"255.255.255.255", /* IP address */
......@@ -144,7 +144,7 @@ void __po_hi_c_driver_eth_leon_poller (const __po_hi_device_id dev_id)
struct sockaddr_in sa;
__po_hi_device_id dev;
__po_hi_node_t dev_init;
int established = 0;
int established = 0;
__po_hi_protocol_conf_t* protocol_conf;
unsigned long* swap_pointer;
......@@ -207,7 +207,7 @@ void __po_hi_c_driver_eth_leon_poller (const __po_hi_device_id dev_id)
if (sock > max_socket )
{
max_socket = sock;
}
}
}
}
__DEBUGMSG ("[DRIVER ETH] Poller initialization finished, waiting for other tasks\n");
......@@ -233,7 +233,7 @@ void __po_hi_c_driver_eth_leon_poller (const __po_hi_device_id dev_id)
{
#ifdef __PO_HI_DEBUG
__DEBUGMSG ("[DRIVER ETH] Error on select for node %d\n", __po_hi_mynode);
#endif
#endif
}
#ifdef __PO_HI_DEBUG
__DEBUGMSG ("[DRIVER ETH] Receive message\n");
......@@ -293,7 +293,7 @@ void __po_hi_c_driver_eth_leon_poller (const __po_hi_device_id dev_id)
__po_hi_main_deliver (& __po_hi_c_driver_eth_leon_poller_received_request);
}
}
}
}
}
#endif
......@@ -382,7 +382,7 @@ void __po_hi_c_driver_eth_leon_init (__po_hi_device_id id)
__DEBUGMSG ("[DRIVER ETH] Receiving socket for device %d created, value=%d\n", id, nodes[id].socket);
sa.sin_addr.s_addr = htonl (INADDR_ANY); /* We listen on all adresses */
sa.sin_family = AF_INET;
sa.sin_family = AF_INET;
sa.sin_port = htons (ip_port); /* Port provided by the generated code */
if( bind (nodes[id].socket , (struct sockaddr *) &sa , sizeof (struct sockaddr_in) ) == -1 )
......@@ -397,7 +397,7 @@ void __po_hi_c_driver_eth_leon_init (__po_hi_device_id id)
__DEBUGMSG ("[DRIVER ETH] Receiving socket listen on any address on port %d\n", sa.sin_port);
/*
/*
* Create the thread which receive all data from other
* nodes. This thread will execute the function
* __po_hi_receiver_task
......@@ -405,8 +405,9 @@ void __po_hi_c_driver_eth_leon_init (__po_hi_device_id id)
__po_hi_initialize_add_task ();
__po_hi_create_generic_task
(-1, 0,__PO_HI_MAX_PRIORITY, 0, (void* (*)(void)) __po_hi_c_driver_eth_leon_poller, NULL);
__po_hi_create_generic_task
(-1, 0,__PO_HI_MAX_PRIORITY, 0, 0, (void* (*)(void)) __po_hi_c_driver_eth_leon_poller, NULL);
// XXX Why forcing core id to 0 ?
}
/*
......@@ -484,7 +485,7 @@ void __po_hi_c_driver_eth_leon_init (__po_hi_device_id id)
* second to connect on.
*/
ret = connect (nodes[dev].socket,
ret = connect (nodes[dev].socket,
(struct sockaddr*) &sa ,
sizeof (struct sockaddr_in));
......@@ -543,7 +544,7 @@ void __po_hi_c_driver_eth_leon_init (__po_hi_device_id id)
#endif
#if defined (__PO_HI_NEED_DRIVER_ETH_LEON)
#if defined (__PO_HI_NEED_DRIVER_ETH_LEON)
__po_hi_msg_t __po_hi_c_driver_eth_leon_sender_msg;
......@@ -585,7 +586,7 @@ int __po_hi_c_driver_eth_leon_sender (__po_hi_task_id task, __po_hi_port_t port
#ifdef __PO_HI_DEBUG
__DEBUGMSG (" [DRIVER SOCKETS] Invalid socket for port-id %d, device-id %d\n", destination_port, associated_device);
#endif
return __PO_HI_ERROR_TRANSPORT_SEND;
return __PO_HI_ERROR_TRANSPORT_SEND;
}
/*
......@@ -600,7 +601,7 @@ int __po_hi_c_driver_eth_leon_sender (__po_hi_task_id task, __po_hi_port_t port
__DEBUGMSG (" [error getsockopt() in file %s, line%d ]\n", __FILE__, __LINE__);
close (nodes[associated_device].socket);
nodes[associated_device].socket = -1;
return __PO_HI_ERROR_TRANSPORT_SEND;
return __PO_HI_ERROR_TRANSPORT_SEND;
}
if (optval != 0)
......@@ -608,7 +609,7 @@ int __po_hi_c_driver_eth_leon_sender (__po_hi_task_id task, __po_hi_port_t port
__DEBUGMSG (" [error getsockopt() return code in file %s, line%d ]\n", __FILE__, __LINE__);
close (nodes[associated_device].socket);
nodes[associated_device].socket = -1;
return __PO_HI_ERROR_TRANSPORT_SEND;
return __PO_HI_ERROR_TRANSPORT_SEND;
}
/* Ignore SIGPIPE to be able to recover from errors instead of crashing the node */
......@@ -636,12 +637,12 @@ int __po_hi_c_driver_eth_leon_sender (__po_hi_task_id task, __po_hi_port_t port
__DEBUGMSG (" [error write() length in file %s, line%d ]\n", __FILE__, __LINE__);
close (nodes[associated_device].socket);
nodes[associated_device].socket = -1;
return __PO_HI_ERROR_TRANSPORT_SEND;
return __PO_HI_ERROR_TRANSPORT_SEND;
}
break;
}
#endif
default:
default:
{
request->port = destination_port;
__po_hi_msg_reallocate (&__po_hi_c_driver_eth_leon_sender_msg);
......@@ -661,7 +662,7 @@ int __po_hi_c_driver_eth_leon_sender (__po_hi_task_id task, __po_hi_port_t port
__DEBUGMSG (" [error write() length in file %s, line%d ]\n", __FILE__, __LINE__);
close (nodes[associated_device].socket);
nodes[associated_device].socket = -1;
return __PO_HI_ERROR_TRANSPORT_SEND;
return __PO_HI_ERROR_TRANSPORT_SEND;
}
request->port = __PO_HI_GQUEUE_INVALID_PORT;
......
......@@ -5,7 +5,7 @@
*
* For more informations, please visit http://taste.tuxfamily.org/wiki
*
* Copyright (C) 2010-2014 ESA & ISAE.
* Copyright (C) 2010-2015 ESA & ISAE.
*/
#include <deployment.h>
......@@ -528,7 +528,8 @@ void __po_hi_driver_sockets_init (__po_hi_device_id dev_id)
__po_hi_initialize_add_task ();
__po_hi_create_generic_task
(-1, 0,__PO_HI_MAX_PRIORITY, 0, (void* (*)(void))__po_hi_sockets_poller, &dev_id);
(-1, 0,__PO_HI_MAX_PRIORITY, 0, 0, (void* (*)(void))__po_hi_sockets_poller, &dev_id);
// XXX Why forcing core id to 0 ?
}
......
......@@ -5,9 +5,22 @@
*
* For more informations, please visit http://taste.tuxfamily.org/wiki
*
* Copyright (C) 2007-2009 Telecom ParisTech, 2010-2014 ESA & ISAE.
* Copyright (C) 2007-2009 Telecom ParisTech, 2010-2015 ESA & ISAE.
*/
#ifdef POSIX
#ifdef __linux__
/* We need GNU extensions to support thread affinify.
These are Linux specific
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include <sched.h>
#endif
#endif
#if defined (RTEMS_POSIX) || defined (POSIX) || defined (XENO_POSIX)
#if defined (__CYGWIN__) || defined (__MINGW32__)
#else
......@@ -171,6 +184,7 @@ int __po_hi_wait_for_next_period (__po_hi_task_id task)
__PO_HI_INSTRUMENTATION_VCD_WRITE("1t%d\n", task);
return (__PO_HI_SUCCESS);
#elif defined (_WIN32)
int ret;
__po_hi_task_delay_until (&(tasks[task].timer), task);
......@@ -180,6 +194,7 @@ int __po_hi_wait_for_next_period (__po_hi_task_id task)
}
return (__PO_HI_SUCCESS);
#elif defined (RTEMS_PURE)
rtems_status_code ret;
ret = rtems_rate_monotonic_period (tasks[task].ratemon_period, (rtems_interval)__PO_HI_TIME_TO_US(tasks[task].period) / rtems_configuration_get_microseconds_per_tick());
......@@ -203,6 +218,7 @@ int __po_hi_wait_for_next_period (__po_hi_task_id task)
}
return (__PO_HI_UNAVAILABLE);
#elif defined (XENO_NATIVE)
unsigned long overrun;
int ret;
......@@ -250,7 +266,8 @@ int __po_hi_initialize_tasking( )
#if defined (POSIX) || defined (RTEMS_POSIX) || defined (XENO_POSIX)
pthread_t __po_hi_posix_create_thread (__po_hi_priority_t priority,
__po_hi_stack_t stack_size,
void* (*start_routine)(void),
const __po_hi_int8_t core_id,
void* (*start_routine)(void),
void* arg)
{
int policy;
......@@ -258,11 +275,27 @@ pthread_t __po_hi_posix_create_thread (__po_hi_priority_t priority,
pthread_attr_t attr;
struct sched_param param;
/* Create attributes to store all configuration parameters */
if (pthread_attr_init (&attr) != 0)
{
return ((pthread_t)__PO_HI_ERROR_PTHREAD_ATTR);
}
#if defined (POSIX) && defined (__linux__)
/* Thread affinity */
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(core_id, &cpuset);
if (pthread_attr_setaffinity_np(&attr, sizeof(cpuset), &cpuset) != 0)
{
__DEBUGMSG("CANNOT SET AFFINTY\n");
return ((pthread_t)__PO_HI_ERROR_PTHREAD_ATTR);
}
#endif
#if defined (POSIX) || defined (XENO_POSIX)
if (pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM) != 0)
{
......@@ -273,7 +306,7 @@ pthread_t __po_hi_posix_create_thread (__po_hi_priority_t priority,
if (pthread_attr_setstacksize (&attr, stack_size) != 0)
{
return ((pthread_t)__PO_HI_ERROR_PTHREAD_ATTR);
}
}
}
#elif defined (RTEMS_POSIX)
if (pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS) != 0)
......@@ -353,27 +386,46 @@ DWORD __po_hi_win32_create_thread (__po_hi_task_id id,
}
#endif
#ifdef RTEMS_PURE
rtems_id __po_hi_rtems_create_thread (__po_hi_priority_t priority,
__po_hi_stack_t stack_size,
__po_hi_int8_t core_id,
void* (*start_routine)(void),
void* arg)
{
rtems_id rid;
if (rtems_task_create (rtems_build_name( 'T', 'A', nb_tasks, ' ' ), 1, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &rid) != RTEMS_SUCCESSFUL)
{
if (rtems_task_create (rtems_build_name( 'T', 'A', nb_tasks, ' ' ),
1,
RTEMS_MINIMUM_STACK_SIZE,
RTEMS_DEFAULT_MODES,
RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &rid)
!= RTEMS_SUCCESSFUL)
{
__DEBUGMSG ("ERROR when creating the task\n");
return __PO_HI_ERROR_CREATE_TASK;
}
}
#ifdef RTEMS411
/* Thread affinity API for SMP systems appeared in RTEMS 4.11,
section 25 of RTEMS Applications C User’s Guide */
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(processor_index, &cpuset);
if (rtems_task_set_affinity(task_id, sizeof(cpuset), &cpuset) != RTEMS_SUCCESSFUL)
{
__DEBUGMSG ("ERROR setting thread affinity\n");
return __PO_HI_ERROR_CREATE_TASK;
}
#endif
if (rtems_task_start (rid, (rtems_task_entry)start_routine, 0 ) != RTEMS_SUCCESSFUL)
{
{
__DEBUGMSG ("ERROR when starting the task\n");
return __PO_HI_ERROR_CREATE_TASK;
}
}
return rid;
}
......@@ -405,6 +457,7 @@ int __po_hi_create_generic_task (const __po_hi_task_id id,
const __po_hi_time_t* period,
const __po_hi_priority_t priority,
const __po_hi_stack_t stack_size,
const __po_hi_int8_t core_id,
void* (*start_routine)(void),
void* arg)
{
......@@ -412,7 +465,7 @@ int __po_hi_create_generic_task (const __po_hi_task_id id,
if (id == -1)
{
#if defined (POSIX) || defined (RTEMS_POSIX) || defined (XENO_POSIX)
__po_hi_posix_create_thread (priority, stack_size, start_routine, arg);
__po_hi_posix_create_thread (priority, stack_size, core_id, start_routine, arg);
return (__PO_HI_SUCCESS);
#elif defined (_WIN32)
__po_hi_win32_create_thread (id, priority, stack_size, start_routine, arg);
......@@ -428,7 +481,7 @@ int __po_hi_create_generic_task (const __po_hi_task_id id,
return (__PO_HI_SUCCESS);
#elif defined (RTEMS_PURE)
(void) arg;
__po_hi_rtems_create_thread (priority, stack_size, start_routine, arg);
__po_hi_rtems_create_thread (priority, stack_size, core_id, start_routine, arg);
return (__PO_HI_SUCCESS);
#else
return (__PO_HI_UNAVAILABLE);
......@@ -441,10 +494,10 @@ int __po_hi_create_generic_task (const __po_hi_task_id id,
my_task->id = id;
#if defined (POSIX) || defined (RTEMS_POSIX) || defined (XENO_POSIX)
my_task->tid = __po_hi_posix_create_thread (priority, stack_size, start_routine, arg);
my_task->tid = __po_hi_posix_create_thread (priority, stack_size, core_id, start_routine, arg);
__po_hi_posix_initialize_task (my_task);
#elif defined (RTEMS_PURE)
my_task->rtems_id = __po_hi_rtems_create_thread (priority, stack_size, start_routine, arg);
my_task->rtems_id = __po_hi_rtems_create_thread (priority, stack_size, core_id, start_routine, arg);
#elif defined (_WIN32)
my_task->tid = __po_hi_win32_create_thread (id, priority, stack_size, start_routine, arg);
#elif defined (XENO_NATIVE)
......@@ -462,9 +515,10 @@ int __po_hi_create_periodic_task (const __po_hi_task_id id,
const __po_hi_time_t* period,
const __po_hi_priority_t priority,
const __po_hi_stack_t stack_size,
const __po_hi_int8_t core_id,
void* (*start_routine)(void))
{
if (__po_hi_create_generic_task( id, period , priority , stack_size, start_routine, NULL) != 1)
if (__po_hi_create_generic_task( id, period , priority , stack_size, core_id, start_routine, NULL) != 1)
{
__DEBUGMSG ("ERROR when creating generic task (task id=%d)\n", id);
return (__PO_HI_ERROR_CREATE_TASK);
......@@ -508,6 +562,7 @@ int __po_hi_create_sporadic_task (const __po_hi_task_id id,
const __po_hi_time_t* period,
const __po_hi_priority_t priority,
const __po_hi_stack_t stack_size,
const __po_hi_int8_t core_id,
void* (*start_routine)(void) )
{
/*
......@@ -515,7 +570,7 @@ int __po_hi_create_sporadic_task (const __po_hi_task_id id,
* last parameter. Typically, a sporadic thread will wait on a
* mutex.
*/
if (__po_hi_create_generic_task( id, period , priority , stack_size, start_routine, NULL) != 1)
if (__po_hi_create_generic_task( id, period , priority , stack_size, core_id, start_routine, NULL) != 1)
{
return (__PO_HI_ERROR_CREATE_TASK);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment