FRONTPANEL: Fix logic detecting sim_panel_exec_... API command completion
Command initiating response can be coalesced with subsequent data by TCP. Gracefully handle when that happens.
This commit is contained in:
parent
7bb02e7530
commit
649ddc63da
2 changed files with 44 additions and 16 deletions
|
@ -85,7 +85,7 @@ if (!update_display)
|
||||||
return;
|
return;
|
||||||
update_display = 0;
|
update_display = 0;
|
||||||
buf1[sizeof(buf1)-1] = buf2[sizeof(buf2)-1] = buf3[sizeof(buf3)-1] = 0;
|
buf1[sizeof(buf1)-1] = buf2[sizeof(buf2)-1] = buf3[sizeof(buf3)-1] = 0;
|
||||||
sprintf (buf1, "%s PC: %08X SP: %08X AP: %08X FP: %08X @PC: %08X\r\n", states[sim_panel_get_state (panel)], PC, SP, AP, FP, atPC);
|
sprintf (buf1, "%4s PC: %08X SP: %08X AP: %08X FP: %08X @PC: %08X\r\n", states[sim_panel_get_state (panel)], PC, SP, AP, FP, atPC);
|
||||||
sprintf (buf2, "PSL: %08X %s\r\n", PSL, "");
|
sprintf (buf2, "PSL: %08X %s\r\n", PSL, "");
|
||||||
sprintf (buf3, "R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X\r\n", R0, R1, R2, R3, R4, R5);
|
sprintf (buf3, "R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X\r\n", R0, R1, R2, R3, R4, R5);
|
||||||
sprintf (buf4, "R6:%08X R7:%08X R8:%08X R9:%08X R10:%08X R11:%08X\r\n", R6, R7, R8, R9, R10, R11);
|
sprintf (buf4, "R6:%08X R7:%08X R8:%08X R9:%08X R10:%08X R11:%08X\r\n", R6, R7, R8, R9, R10, R11);
|
||||||
|
@ -439,7 +439,7 @@ if (sim_panel_add_register_bits (panel, "PCQ[3]", NULL, 32, PCQ_3_bits)) {
|
||||||
}
|
}
|
||||||
if (1) {
|
if (1) {
|
||||||
unsigned int noop_noop_noop_halt = 0x00010101, brb_self = 0x0000FE11, addr400 = 0x00000400, pc_value;
|
unsigned int noop_noop_noop_halt = 0x00010101, brb_self = 0x0000FE11, addr400 = 0x00000400, pc_value;
|
||||||
int mstime = 0;
|
int mstime;
|
||||||
|
|
||||||
if (sim_panel_mem_deposit (panel, sizeof(addr400), &addr400, sizeof(noop_noop_noop_halt), &noop_noop_noop_halt)) {
|
if (sim_panel_mem_deposit (panel, sizeof(addr400), &addr400, sizeof(noop_noop_noop_halt), &noop_noop_noop_halt)) {
|
||||||
printf ("Error setting %08X to %08X: %s\n", addr400, noop_noop_noop_halt, sim_panel_get_error());
|
printf ("Error setting %08X to %08X: %s\n", addr400, noop_noop_noop_halt, sim_panel_get_error());
|
||||||
|
@ -453,6 +453,7 @@ if (1) {
|
||||||
printf ("Error starting simulator execution: %s\n", sim_panel_get_error());
|
printf ("Error starting simulator execution: %s\n", sim_panel_get_error());
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
mstime = 0;
|
||||||
while ((sim_panel_get_state (panel) == Run) &&
|
while ((sim_panel_get_state (panel) == Run) &&
|
||||||
(mstime < 1000)) {
|
(mstime < 1000)) {
|
||||||
usleep (100000);
|
usleep (100000);
|
||||||
|
@ -500,6 +501,7 @@ if (1) {
|
||||||
printf ("Error starting simulator execution: %s\n", sim_panel_get_error());
|
printf ("Error starting simulator execution: %s\n", sim_panel_get_error());
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
mstime = 0;
|
||||||
while ((sim_panel_get_state (panel) == Run) &&
|
while ((sim_panel_get_state (panel) == Run) &&
|
||||||
(mstime < 1000)) {
|
(mstime < 1000)) {
|
||||||
usleep (100000);
|
usleep (100000);
|
||||||
|
|
|
@ -144,7 +144,7 @@ struct PANEL {
|
||||||
int new_register;
|
int new_register;
|
||||||
size_t reg_query_size;
|
size_t reg_query_size;
|
||||||
unsigned long long array_element_data;
|
unsigned long long array_element_data;
|
||||||
OperationalState State;
|
volatile OperationalState State;
|
||||||
unsigned long long simulation_time;
|
unsigned long long simulation_time;
|
||||||
unsigned long long simulation_time_base;
|
unsigned long long simulation_time_base;
|
||||||
pthread_t io_thread;
|
pthread_t io_thread;
|
||||||
|
@ -2031,6 +2031,7 @@ struct sched_param sched_priority;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
int buf_data = 0;
|
int buf_data = 0;
|
||||||
int processing_register_output = 0;
|
int processing_register_output = 0;
|
||||||
|
int io_wait_done;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Boost Priority for this response processing thread to quickly digest
|
Boost Priority for this response processing thread to quickly digest
|
||||||
|
@ -2271,6 +2272,12 @@ while ((p->sock != INVALID_SOCKET) &&
|
||||||
p->io_response_data += strlen(s);
|
p->io_response_data += strlen(s);
|
||||||
strcpy (p->io_response + p->io_response_data, "\r\n");
|
strcpy (p->io_response + p->io_response_data, "\r\n");
|
||||||
p->io_response_data += 2;
|
p->io_response_data += 2;
|
||||||
|
if ((!p->parent) &&
|
||||||
|
(p->completion_string) &&
|
||||||
|
(!memcmp (s, p->completion_string, strlen (p->completion_string)))) {
|
||||||
|
_panel_debug (p, DBG_RCV, "Match with potentially coalesced additional data: '%s'", NULL, 0, p->completion_string);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_panel_debug (p, DBG_RCV, "Receive Data Discarded: '%s'", NULL, 0, s);
|
_panel_debug (p, DBG_RCV, "Receive Data Discarded: '%s'", NULL, 0, s);
|
||||||
|
@ -2279,7 +2286,7 @@ Start_Next_Line:
|
||||||
while (isspace(0xFF & (*s)))
|
while (isspace(0xFF & (*s)))
|
||||||
++s;
|
++s;
|
||||||
}
|
}
|
||||||
memmove (buf, s, strlen (s)+1);
|
memmove (buf, s, strlen (s) + 1);
|
||||||
buf_data = strlen (buf);
|
buf_data = strlen (buf);
|
||||||
if (buf_data)
|
if (buf_data)
|
||||||
_panel_debug (p, DBG_RSP, "Remnant Buffer Contents: '%s'", NULL, 0, buf);
|
_panel_debug (p, DBG_RSP, "Remnant Buffer Contents: '%s'", NULL, 0, buf);
|
||||||
|
@ -2287,27 +2294,42 @@ Start_Next_Line:
|
||||||
(p->completion_string) &&
|
(p->completion_string) &&
|
||||||
(!memcmp (buf, p->completion_string, strlen (p->completion_string)))) {
|
(!memcmp (buf, p->completion_string, strlen (p->completion_string)))) {
|
||||||
_panel_debug (p, DBG_RCV, "*Received Command Complete - Match: '%s'", NULL, 0, p->completion_string);
|
_panel_debug (p, DBG_RCV, "*Received Command Complete - Match: '%s'", NULL, 0, p->completion_string);
|
||||||
p->io_waiting = 0;
|
io_wait_done = 1;
|
||||||
pthread_cond_signal (&p->io_done);
|
|
||||||
}
|
}
|
||||||
if (!memcmp ("Simulator Running...", buf, 20)) {
|
if (!memcmp ("Simulator Running...", buf, 20)) {
|
||||||
_panel_debug (p, DBG_RSP, "State transitioning to Run", NULL, 0);
|
_panel_debug (p, DBG_RSP, "State transitioning to Run", NULL, 0);
|
||||||
p->State = Run;
|
p->State = Run;
|
||||||
buf_data -= 20;
|
buf_data -= 20;
|
||||||
if (buf_data) {
|
|
||||||
memmove (buf, buf + 20, buf_data + 1);
|
|
||||||
/* Since there is more to look at, we need to let the state
|
|
||||||
transition to Run propagate before examining that.*/
|
|
||||||
pthread_mutex_unlock (&p->io_lock);
|
|
||||||
msleep (100);
|
|
||||||
pthread_mutex_lock (&p->io_lock);
|
|
||||||
}
|
|
||||||
buf[buf_data] = '\0';
|
buf[buf_data] = '\0';
|
||||||
|
if (buf_data) {
|
||||||
|
memmove (buf, buf + 20, strlen (buf + 20) + 1);
|
||||||
|
buf_data = strlen (buf);
|
||||||
|
_panel_debug (p, DBG_RSP, "Remnant Buffer Contents: '%s'", NULL, 0, buf);
|
||||||
|
if (io_wait_done) { /* someone waiting for this? */
|
||||||
|
_panel_debug (p, DBG_RCV, "*Match Command Complete - Match signaling waiting thread", NULL, 0);
|
||||||
|
io_wait_done = 0;
|
||||||
|
p->io_waiting = 0;
|
||||||
|
p->completion_string = NULL;
|
||||||
|
pthread_cond_signal (&p->io_done);
|
||||||
|
/* Let this state transition propagate to the interested thread(s) */
|
||||||
|
/* before processing remaining buffered data */
|
||||||
|
pthread_mutex_unlock (&p->io_lock);
|
||||||
|
msleep (100);
|
||||||
|
pthread_mutex_lock (&p->io_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((p->State == Run) && (!strcmp (buf, sim_prompt))) {
|
if ((p->State == Run) && (!strcmp (buf, sim_prompt))) {
|
||||||
_panel_debug (p, DBG_RSP, "State transitioning to Halt", NULL, 0);
|
_panel_debug (p, DBG_RSP, "State transitioning to Halt", NULL, 0);
|
||||||
p->State = Halt;
|
p->State = Halt;
|
||||||
}
|
}
|
||||||
|
if (io_wait_done) {
|
||||||
|
_panel_debug (p, DBG_RCV, "*Match Command Complete - Match signaling waiting thread", NULL, 0);
|
||||||
|
io_wait_done = 0;
|
||||||
|
p->io_waiting = 0;
|
||||||
|
p->completion_string = NULL;
|
||||||
|
pthread_cond_signal (&p->io_done);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (p->io_waiting) {
|
if (p->io_waiting) {
|
||||||
_panel_debug (p, DBG_THR, "Receive: restarting waiting thread while exiting", NULL, 0);
|
_panel_debug (p, DBG_THR, "Receive: restarting waiting thread while exiting", NULL, 0);
|
||||||
|
@ -2550,16 +2572,20 @@ if (completion_status || completion_string) {
|
||||||
pthread_mutex_lock (&p->io_lock);
|
pthread_mutex_lock (&p->io_lock);
|
||||||
p->completion_string = completion_string;
|
p->completion_string = completion_string;
|
||||||
p->io_response_data = 0;
|
p->io_response_data = 0;
|
||||||
|
p->io_waiting = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_panel_debug (p, DBG_REQ, "Command %d Request%s: %*.*s", NULL, 0, p->command_count, completion_status ? " (with response)" : "", len, len, buf);
|
_panel_debug (p, DBG_REQ, "Command %d Request%s: %*.*s", NULL, 0, p->command_count, completion_status ? " (with response)" : "", len, len, buf);
|
||||||
ret = ((len + status_echo_len) == (sent_len = _panel_send (p, buf, len + status_echo_len))) ? 0 : -1;
|
ret = ((len + status_echo_len) == (sent_len = _panel_send (p, buf, len + status_echo_len))) ? 0 : -1;
|
||||||
|
|
||||||
if (completion_status || completion_string) {
|
if (completion_status || completion_string) {
|
||||||
if (!ret) { /* Sent OK? */
|
if (ret) { /* Send failed? */
|
||||||
|
p->completion_string = NULL;
|
||||||
|
p->io_waiting = 0;
|
||||||
|
}
|
||||||
|
else { /* Sent OK? */
|
||||||
char *tresponse = NULL;
|
char *tresponse = NULL;
|
||||||
|
|
||||||
p->io_waiting = 1;
|
|
||||||
while (p->io_waiting)
|
while (p->io_waiting)
|
||||||
pthread_cond_wait (&p->io_done, &p->io_lock); /* Wait for completion */
|
pthread_cond_wait (&p->io_done, &p->io_lock); /* Wait for completion */
|
||||||
tresponse = (char *)_panel_malloc (p->io_response_data + 1);
|
tresponse = (char *)_panel_malloc (p->io_response_data + 1);
|
||||||
|
|
Loading…
Add table
Reference in a new issue