/* * RTEMS monitor server (handles requests for info from RTEMS monitors * running on other nodes) * * $Id$ */ #include #include #include #include #include #include /* * Various id's for the server */ rtems_id rtems_monitor_server_task_id; rtems_id rtems_monitor_server_request_queue_id; /* our server */ rtems_id *rtems_monitor_server_request_queue_ids; /* all servers */ rtems_id rtems_monitor_server_response_queue_id; /* our server */ /* * Send a request to a server task */ rtems_status_code rtems_monitor_server_request( unsigned32 server_node, rtems_monitor_server_request_t *request, rtems_monitor_server_response_t *response ) { rtems_id server_id; rtems_status_code status; unsigned32 size; /* * What is id of monitor on target node? * Look it up if we don't know it yet. */ server_id = rtems_monitor_server_request_queue_ids[server_node]; if (server_id == 0) { status = rtems_message_queue_ident(RTEMS_MONITOR_QUEUE_NAME, server_node, &server_id); if (status != RTEMS_SUCCESSFUL) { rtems_error(status, "ident of remote server failed"); goto done; } rtems_monitor_server_request_queue_ids[server_node] = server_id; } request->return_id = rtems_monitor_server_response_queue_id; status = rtems_message_queue_send(server_id, request, sizeof(*request)); if (status != RTEMS_SUCCESSFUL) { rtems_error(status, "monitor server request send failed"); goto done; } /* * Await response, if requested */ if (response) { status = rtems_message_queue_receive(rtems_monitor_server_response_queue_id, response, &size, RTEMS_WAIT, 100); if (status != RTEMS_SUCCESSFUL) { rtems_error(status, "server did not respond"); /* maybe server task was restarted; look it up again next time */ rtems_monitor_server_request_queue_ids[server_node] = 0; goto done; } if (response->command != RTEMS_MONITOR_SERVER_RESPONSE) { status = RTEMS_INCORRECT_STATE; goto done; } } done: return status; } /* * monitor server task */ void rtems_monitor_server_task( rtems_task_argument monitor_flags ) { rtems_monitor_server_request_t request; rtems_monitor_server_response_t response; rtems_status_code status; unsigned32 size; for (;;) { status = rtems_message_queue_receive( rtems_monitor_server_request_queue_id, &request, &size, RTEMS_WAIT, (rtems_interval) 0); if (status != RTEMS_SUCCESSFUL) { rtems_error(status, "monitor server msg queue receive error"); goto failed; } if (size != sizeof(request)) { rtems_error(0, "monitor server bad size on receive"); goto failed; } switch (request.command) { case RTEMS_MONITOR_SERVER_CANONICAL: { rtems_monitor_object_type_t object_type; rtems_id id; rtems_id next_id; object_type = (rtems_monitor_object_type_t) request.argument0; id = (rtems_id) request.argument1; next_id = rtems_monitor_object_canonical_get(object_type, id, &response.payload, &size); response.command = RTEMS_MONITOR_SERVER_RESPONSE; response.result0 = next_id; response.result1 = size; #define SERVER_OVERHEAD (RTEMS_offsetof(rtems_monitor_server_response_t, \ payload)) status = rtems_message_queue_send(request.return_id, &response, size + SERVER_OVERHEAD); if (status != RTEMS_SUCCESSFUL) { rtems_error(status, "response send failed"); goto failed; } break; } default: { rtems_error(0, "invalid command to monitor server: %d", request.command); goto failed; } } } failed: rtems_task_delete(RTEMS_SELF); } /* * Kill off any old server * Not sure if this is useful, but it doesn't help */ void rtems_monitor_server_kill(void) { if (rtems_monitor_server_task_id) rtems_task_delete(rtems_monitor_server_task_id); rtems_monitor_server_task_id = 0; if (rtems_monitor_server_request_queue_id) rtems_message_queue_delete(rtems_monitor_server_request_queue_id); rtems_monitor_server_request_queue_ids = 0; if (rtems_monitor_server_response_queue_id) rtems_message_queue_delete(rtems_monitor_server_response_queue_id); rtems_monitor_server_response_queue_id = 0; if (rtems_monitor_server_request_queue_ids) free(rtems_monitor_server_request_queue_ids); rtems_monitor_server_request_queue_ids = 0; } void rtems_monitor_server_init( unsigned32 monitor_flags ) { rtems_status_code status; if (_System_state_Is_multiprocessing && (_Configuration_MP_table->maximum_nodes > 1)) { unsigned32 maximum_nodes = _Configuration_MP_table->maximum_nodes; /* * create the msg que our server will listen * Since we only get msgs from other RTEMS monitors, we just * need reserve space for 1 msg from each node. */ status = rtems_message_queue_create( RTEMS_MONITOR_QUEUE_NAME, maximum_nodes, sizeof(rtems_monitor_server_request_t), RTEMS_GLOBAL, &rtems_monitor_server_request_queue_id); if (status != RTEMS_SUCCESSFUL) { rtems_error(status, "could not create monitor server message queue"); goto done; } /* * create the msg que our responses will come on * Since monitor just does one thing at a time, we only need 1 item * message queue. */ status = rtems_message_queue_create( RTEMS_MONITOR_RESPONSE_QUEUE_NAME, 1, /* depth */ sizeof(rtems_monitor_server_response_t), RTEMS_GLOBAL, &rtems_monitor_server_response_queue_id); if (status != RTEMS_SUCCESSFUL) { rtems_error(status, "could not create monitor response message queue"); goto done; } /* need an id for queue of each other server we might talk to */ /* indexed by node, so add 1 to maximum_nodes */ rtems_monitor_server_request_queue_ids = (rtems_id *) malloc((maximum_nodes + 1) * sizeof(rtems_id)); (void) memset(rtems_monitor_server_request_queue_ids, 0, (maximum_nodes + 1) * sizeof(rtems_id)); rtems_monitor_server_request_queue_ids[rtems_monitor_node] = rtems_monitor_server_request_queue_id; /* * create the server task */ status = rtems_task_create(RTEMS_MONITOR_SERVER_NAME, 1, 0 /* default stack */, RTEMS_INTERRUPT_LEVEL(0), RTEMS_DEFAULT_ATTRIBUTES, &rtems_monitor_server_task_id); if (status != RTEMS_SUCCESSFUL) { rtems_error(status, "could not create monitor server task"); goto done; } /* * Start the server task */ status = rtems_task_start(rtems_monitor_server_task_id, rtems_monitor_server_task, monitor_flags); if (status != RTEMS_SUCCESSFUL) { rtems_error(status, "could not start monitor server"); goto done; } } done: return; }