mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-10-01 19:36:36 +00:00
netutils/ptpd: retain in-memory IPC for CONFIG_BUILD_FLAT in ptpd_status()
PR #3789 replaced the in-memory sigqueue + shared memory IPC in ptpd_status() with file-based IPC to support Protected and Kernel modes across address spaces. However, on microcontrollers running CONFIG_BUILD_FLAT, a filesystem or /tmp (TMPFS) is rarely mounted or available, causing ptpd_status() to fail with -ETIMEDOUT (errno 110) because the status file cannot be created. Retain the file-based IPC for !CONFIG_BUILD_FLAT (Protected and Kernel modes) while restoring the zero-overhead in-memory sigqueue + semaphore IPC for CONFIG_BUILD_FLAT. Both modes share the status serialization logic via ptp_populate_status() and support all fields including P2P. Assisted-by: Gemini:gemini-3.8-flash-medium Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
This commit is contained in:
parent
585db4b657
commit
8940f6b0d4
1 changed files with 161 additions and 44 deletions
|
|
@ -42,6 +42,8 @@
|
|||
#include <sched.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
#include <pthread.h>
|
||||
#include <nuttx/debug.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
|
@ -67,6 +69,16 @@
|
|||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_BUILD_FLAT
|
||||
/* Carrier structure for querying PTPD status in flat build mode */
|
||||
|
||||
struct ptpd_statusreq_s
|
||||
{
|
||||
sem_t done;
|
||||
struct ptpd_status_s dest;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Main PTPD state storage */
|
||||
|
||||
struct ptp_state_s
|
||||
|
|
@ -74,7 +86,11 @@ struct ptp_state_s
|
|||
/* Request for PTPD task to stop or dump status */
|
||||
|
||||
bool stop;
|
||||
#ifdef CONFIG_BUILD_FLAT
|
||||
FAR struct ptpd_statusreq_s *status_req; /* Set by SIGUSR1 */
|
||||
#else
|
||||
bool dump; /* Set by SIGUSR1, checked in main loop */
|
||||
#endif
|
||||
|
||||
/* Address of network interface we are operating on */
|
||||
|
||||
|
|
@ -181,6 +197,25 @@ struct ptp_state_s
|
|||
FAR const struct ptpd_config_s *config;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_BUILD_FLAT
|
||||
/* The status request of ptpd_status(). The daemon keeps its address until it
|
||||
* answers, which can be after ptpd_status() gave up waiting and returned, so
|
||||
* it lives in static memory and never on the stack of the caller. The lock
|
||||
* lets only one caller use it at a time.
|
||||
*/
|
||||
|
||||
static struct ptpd_statusreq_s g_statusreq =
|
||||
{
|
||||
SEM_INITIALIZER(0)
|
||||
};
|
||||
|
||||
static pthread_mutex_t g_statusreq_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
|
@ -1968,7 +2003,11 @@ static void ptp_signal_handler(int signo, FAR siginfo_t *siginfo,
|
|||
}
|
||||
else if (signo == SIGUSR1)
|
||||
{
|
||||
#ifdef CONFIG_BUILD_FLAT
|
||||
state->status_req = siginfo->si_value.sival_ptr;
|
||||
#else
|
||||
state->dump = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1985,6 +2024,79 @@ static void ptp_setup_sighandlers(FAR struct ptp_state_s *state)
|
|||
sigaction(SIGUSR1, &act, NULL);
|
||||
}
|
||||
|
||||
/* Populate status information structure from current state */
|
||||
|
||||
static void ptp_populate_status(FAR struct ptp_state_s *state,
|
||||
FAR struct ptpd_status_s *status)
|
||||
{
|
||||
memset(status, 0, sizeof(*status));
|
||||
status->clock_source_valid = state->selected_source_valid;
|
||||
|
||||
if (status->clock_source_valid)
|
||||
{
|
||||
FAR struct ptp_announce_s *s = &state->selected_source;
|
||||
|
||||
memcpy(status->clock_source_info.id,
|
||||
s->header.sourceidentity,
|
||||
sizeof(status->clock_source_info.id));
|
||||
|
||||
status->clock_source_info.utcoffset =
|
||||
(int16_t)(((uint16_t)s->utcoffset[0] << 8) | s->utcoffset[1]);
|
||||
status->clock_source_info.priority1 = s->gm_priority1;
|
||||
status->clock_source_info.clockclass = s->gm_quality[0];
|
||||
status->clock_source_info.accuracy = s->gm_quality[1];
|
||||
status->clock_source_info.priority2 = s->gm_priority2;
|
||||
status->clock_source_info.variance =
|
||||
((uint16_t)s->gm_quality[2] << 8) | s->gm_quality[3];
|
||||
|
||||
memcpy(status->clock_source_info.gm_id,
|
||||
s->gm_identity,
|
||||
sizeof(status->clock_source_info.gm_id));
|
||||
|
||||
status->clock_source_info.stepsremoved =
|
||||
((uint16_t)s->stepsremoved[0] << 8) | s->stepsremoved[1];
|
||||
status->clock_source_info.timesource = s->timesource;
|
||||
}
|
||||
|
||||
status->last_clock_update = state->last_delta_timestamp;
|
||||
status->last_delta_ns = state->last_delta_ns;
|
||||
status->last_adjtime_ns = state->last_adjtime_ns;
|
||||
status->drift_ppb = state->drift_ppb;
|
||||
status->path_delay_ns = state->path_delay_ns;
|
||||
|
||||
status->last_received_multicast = state->last_received_multicast;
|
||||
status->last_received_announce = state->last_received_announce;
|
||||
status->last_received_sync = state->last_received_sync;
|
||||
status->last_transmitted_sync = state->last_transmitted_sync;
|
||||
status->last_transmitted_announce = state->last_transmitted_announce;
|
||||
status->last_transmitted_delayresp = state->last_transmitted_delayresp;
|
||||
status->last_transmitted_delayreq = state->last_transmitted_delayreq;
|
||||
status->last_transmitted_pdelayreq = state->last_transmitted_pdelayreq;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BUILD_FLAT
|
||||
/* Process status information request in flat build mode */
|
||||
|
||||
static void ptp_process_statusreq(FAR struct ptp_state_s *state)
|
||||
{
|
||||
FAR struct ptpd_statusreq_s *req = state->status_req;
|
||||
|
||||
if (req == NULL)
|
||||
{
|
||||
return; /* No active request */
|
||||
}
|
||||
|
||||
state->status_req = NULL;
|
||||
ptp_populate_status(state, &req->dest);
|
||||
|
||||
/* Post semaphore to inform that we are done. The request belongs to the
|
||||
* caller of ptpd_status() and must not be touched after this.
|
||||
*/
|
||||
|
||||
sem_post(&req->done);
|
||||
}
|
||||
#else
|
||||
|
||||
/* Dump status to file when requested via signal.
|
||||
* Write atomically: temp file + rename.
|
||||
*/
|
||||
|
|
@ -2003,50 +2115,7 @@ static void ptp_dump_status_file(FAR struct ptp_state_s *state)
|
|||
|
||||
state->dump = false;
|
||||
|
||||
memset(&status, 0, sizeof(status));
|
||||
status.clock_source_valid = state->selected_source_valid;
|
||||
|
||||
if (status.clock_source_valid)
|
||||
{
|
||||
FAR struct ptp_announce_s *s = &state->selected_source;
|
||||
|
||||
memcpy(status.clock_source_info.id,
|
||||
s->header.sourceidentity,
|
||||
sizeof(status.clock_source_info.id));
|
||||
|
||||
status.clock_source_info.utcoffset =
|
||||
(int16_t)(((uint16_t)s->utcoffset[0] << 8) | s->utcoffset[1]);
|
||||
status.clock_source_info.priority1 = s->gm_priority1;
|
||||
status.clock_source_info.clockclass = s->gm_quality[0];
|
||||
status.clock_source_info.accuracy = s->gm_quality[1];
|
||||
status.clock_source_info.priority2 = s->gm_priority2;
|
||||
status.clock_source_info.variance =
|
||||
((uint16_t)s->gm_quality[2] << 8) | s->gm_quality[3];
|
||||
|
||||
memcpy(status.clock_source_info.gm_id,
|
||||
s->gm_identity,
|
||||
sizeof(status.clock_source_info.gm_id));
|
||||
|
||||
status.clock_source_info.stepsremoved =
|
||||
((uint16_t)s->stepsremoved[0] << 8) | s->stepsremoved[1];
|
||||
status.clock_source_info.timesource = s->timesource;
|
||||
}
|
||||
|
||||
status.last_clock_update = state->last_delta_timestamp;
|
||||
status.last_delta_ns = state->last_delta_ns;
|
||||
status.last_adjtime_ns = state->last_adjtime_ns;
|
||||
status.drift_ppb = state->drift_ppb;
|
||||
status.path_delay_ns = state->path_delay_ns;
|
||||
|
||||
status.last_received_multicast = state->last_received_multicast;
|
||||
status.last_received_announce = state->last_received_announce;
|
||||
status.last_received_sync = state->last_received_sync;
|
||||
status.last_transmitted_sync = state->last_transmitted_sync;
|
||||
status.last_transmitted_announce = state->last_transmitted_announce;
|
||||
status.last_transmitted_delayresp = state->last_transmitted_delayresp;
|
||||
status.last_transmitted_delayreq = state->last_transmitted_delayreq;
|
||||
|
||||
status.last_transmitted_pdelayreq = state->last_transmitted_pdelayreq;
|
||||
ptp_populate_status(state, &status);
|
||||
|
||||
snprintf(tmppath, sizeof(tmppath), "%s.tmp",
|
||||
CONFIG_NETUTILS_PTPD_STATUSFILE);
|
||||
|
|
@ -2069,6 +2138,7 @@ static void ptp_dump_status_file(FAR struct ptp_state_s *state)
|
|||
unlink(tmppath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
|
|
@ -2191,7 +2261,11 @@ int ptpd_start(FAR const struct ptpd_config_s *config)
|
|||
ptp_periodic_send(state);
|
||||
|
||||
state->selected_source_valid = is_selected_source_valid(state);
|
||||
#ifdef CONFIG_BUILD_FLAT
|
||||
ptp_process_statusreq(state);
|
||||
#else
|
||||
ptp_dump_status_file(state);
|
||||
#endif
|
||||
}
|
||||
|
||||
errout:
|
||||
|
|
@ -2224,6 +2298,48 @@ errout:
|
|||
|
||||
int ptpd_status(int pid, FAR struct ptpd_status_s *status)
|
||||
{
|
||||
#ifdef CONFIG_BUILD_FLAT
|
||||
int ret = OK;
|
||||
union sigval val;
|
||||
struct timespec timeout;
|
||||
|
||||
memset(status, 0, sizeof(struct ptpd_status_s));
|
||||
|
||||
pthread_mutex_lock(&g_statusreq_lock);
|
||||
|
||||
/* Drop the late answer to a request that timed out earlier */
|
||||
|
||||
while (sem_trywait(&g_statusreq.done) == 0)
|
||||
{
|
||||
}
|
||||
|
||||
/* Send the status request */
|
||||
|
||||
val.sival_ptr = &g_statusreq;
|
||||
|
||||
if (sigqueue(pid, SIGUSR1, val) != OK)
|
||||
{
|
||||
ret = -errno;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Wait for status request to be handled */
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &timeout);
|
||||
timeout.tv_sec += 1;
|
||||
if (sem_clockwait(&g_statusreq.done, CLOCK_MONOTONIC, &timeout) != 0)
|
||||
{
|
||||
ret = -errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(status, &g_statusreq.dest, sizeof(struct ptpd_status_s));
|
||||
}
|
||||
|
||||
errout:
|
||||
pthread_mutex_unlock(&g_statusreq_lock);
|
||||
return ret;
|
||||
#else
|
||||
int fd;
|
||||
int ret;
|
||||
int elapsed;
|
||||
|
|
@ -2270,6 +2386,7 @@ int ptpd_status(int pid, FAR struct ptpd_status_s *status)
|
|||
}
|
||||
|
||||
return OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue