Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions devIocStats/devIocStatsAnalog.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,13 +283,28 @@ static validGetParms statsGetParms[] = {
{"cbHighQueueOverruns", statsCbHighQOverruns, QUEUE_TYPE},
{NULL, NULL, 0}};

aStats devAiStats = {6, NULL, ai_init, ai_init_record, ai_ioint_info,
ai_read, NULL};
/* DEVSUPFUN is a bare `long (*)()`; under C23 empty parens mean "no
* arguments" rather than "unspecified arguments" (the C17-and-earlier
* meaning these DSET tables were written against), so these need an
* explicit cast to avoid -Wincompatible-pointer-types. */
aStats devAiStats = {6,
NULL,
(DEVSUPFUN)ai_init,
(DEVSUPFUN)ai_init_record,
(DEVSUPFUN)ai_ioint_info,
(DEVSUPFUN)ai_read,
NULL};
epicsExportAddress(dset, devAiStats);
aStats devAoStats = {6, NULL, NULL, ao_init_record, NULL, ao_write, NULL};
aStats devAoStats = {6, NULL, NULL, (DEVSUPFUN)ao_init_record,
NULL, (DEVSUPFUN)ao_write, NULL};
epicsExportAddress(dset, devAoStats);
aStats devAiClusts = {
6, NULL, ai_clusts_init, ai_clusts_init_record, NULL, ai_clusts_read, NULL};
aStats devAiClusts = {6,
NULL,
(DEVSUPFUN)ai_clusts_init,
(DEVSUPFUN)ai_clusts_init_record,
NULL,
(DEVSUPFUN)ai_clusts_read,
NULL};
epicsExportAddress(dset, devAiClusts);

static memInfo meminfo = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
Expand Down
16 changes: 11 additions & 5 deletions devIocStats/devIocStatsString.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,17 @@ static validGetStrParms statsGetStrParms[] = {
{"pwd2", statsPwd2, STATIC_TYPE},
{NULL, NULL, 0}};

sStats devStringinStats = {
5, NULL, stringin_init, stringin_init_record, NULL, stringin_read};
sStats devStringinEnvVar = {5, NULL, NULL, envvar_init_record,
NULL, envvar_read};
sStats devStringinEpics = {5, NULL, NULL, epics_init_record, NULL, epics_read};
/* DEVSUPFUN is a bare `long (*)()`; under C23 empty parens mean "no
* arguments" rather than "unspecified arguments" (the C17-and-earlier
* meaning these DSET tables were written against), so these need an
* explicit cast to avoid -Wincompatible-pointer-types. */
sStats devStringinStats = {5, NULL, (DEVSUPFUN)stringin_init,
(DEVSUPFUN)stringin_init_record, NULL,
(DEVSUPFUN)stringin_read};
sStats devStringinEnvVar = {5, NULL, NULL, (DEVSUPFUN)envvar_init_record,
NULL, (DEVSUPFUN)envvar_read};
sStats devStringinEpics = {5, NULL, NULL, (DEVSUPFUN)epics_init_record, NULL,
(DEVSUPFUN)epics_read};
epicsExportAddress(dset, devStringinStats);
epicsExportAddress(dset, devStringinEnvVar);
epicsExportAddress(dset, devStringinEpics);
Expand Down
9 changes: 7 additions & 2 deletions devIocStats/devIocStatsWaveform.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,13 @@ static validGetWfmParms statsGetWfmParms[] = {
{"pwd", statsPwd, STATIC_TYPE},
{NULL, NULL, 0}};

wStats devWaveformStats = {
5, NULL, waveform_init, waveform_init_record, NULL, waveform_read};
/* DEVSUPFUN is a bare `long (*)()`; under C23 empty parens mean "no
* arguments" rather than "unspecified arguments" (the C17-and-earlier
* meaning this DSET table was written against), so these need an
* explicit cast to avoid -Wincompatible-pointer-types. */
wStats devWaveformStats = {5, NULL, (DEVSUPFUN)waveform_init,
(DEVSUPFUN)waveform_init_record, NULL,
(DEVSUPFUN)waveform_read};
epicsExportAddress(dset, devWaveformStats);

/* ---------------------------------------------------------------------- */
Expand Down
26 changes: 26 additions & 0 deletions devIocStats/os/RTEMS/devIocStatsOSD.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,26 @@
#include <net/if.h>
#include <net/if_var.h>

/* osdCpuUsage.c walks _Objects_Information_table[]/Objects_Information
* directly; older RTEMS pulled these in transitively via rtems.h, current
* RTEMS no longer does, so include the Score header explicitly. */
#include <rtems/score/objectimpl.h>

/* osdCpuUsage.c reads Thread_Control::cpu_time_used (a Timestamp_Control)
* via the portable _Timestamp_Get_*() accessors rather than assuming its
* representation (struct timespec vs. int64_t sbintime_t is a per-
* architecture/config choice -- that's the whole point of the wrapper). */
Comment on lines +62 to +65

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need these comments?

#include <rtems/score/timestampimpl.h>

/* osdWorkspaceUsage.c uses _Workspace_Area directly; same transitive-
* include story as objectimpl.h above. */
#include <rtems/score/wkspace.h>

/* osdSuspTasks.c walks _RTEMS_tasks_Information.Objects directly; this is
* the Classic API task object information, declared here rather than
* anywhere Score-level. */
#include <rtems/rtems/tasksdata.h>

#undef malloc
#undef free

Expand Down Expand Up @@ -88,6 +108,12 @@
void bsp_reset(); \
bsp_reset(); \
}
#elif RTEMS_VERSION_INT >= VERSION_INT(6, 0, 0, 0)
/* rtemsReboot() no longer exists; current RTEMS's bsp_reset() takes a
* (source, code) pair instead (see <bsp/bootcard.h>). */
#include <bsp/bootcard.h>
#include <rtems/score/interr.h>
#define reboot(x) bsp_reset(RTEMS_FATAL_SOURCE_APPLICATION, (x))
#else
#define reboot(x) rtemsReboot()
#endif
33 changes: 33 additions & 0 deletions devIocStats/os/RTEMS/osdClustInfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,37 @@

#include <devIocStats.h>

#if RTEMS_LIBBSD_STACK

/* The legacy network stack's global `struct mbstat mbstat` doesn't exist
* under libbsd. libbsd's portable memstat API (memstat_sysctl_all(), the
* same mechanism `netstat -m`/`vmstat -z` use) looked like the right
* replacement and is what epics-modules/iocStats#61's RTEMS 6 port does
* too -- but memstat_sysctl_all() crashes on real hardware here: it walks
* into UMA's per-CPU counter stats (uma_vm_zone_stats() ->
* _bsd_counter_u64_alloc(), freebsd/sys/kern/subr_counter.c), which faults
* with a data abort (confirmed via addr2line against the crash PC/LR).
* Whatever's missing/broken in this RTEMS-libbsd port's counter(9)
* support, #61 was apparently never actually run on hardware either (it
* also has a row-index bug independent of this). Until that's root-caused,
* report "not available" rather than crash the IOC. */

int devIocStatsInitClusterInfo(void) { return 0; }

int devIocStatsGetClusterInfo(int pool, clustInfo *pval) {
(void)pool;
(void)pval;
return -1;
}

int devIocStatsGetClusterUsage(int pool, int *pval) {
(void)pool;
(void)pval;
return -1;
}

#else /* RTEMS_LIBBSD_STACK */

/* This would otherwise need _KERNEL to be defined... */
extern struct mbstat mbstat;

Expand Down Expand Up @@ -86,3 +117,5 @@ int devIocStatsGetClusterUsage(int pool, int *pval) {

return 0;
}

#endif /* RTEMS_LIBBSD_STACK */
18 changes: 14 additions & 4 deletions devIocStats/os/RTEMS/osdCpuUsage.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,12 @@ typedef char *objName;

#if defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS) || \
(__RTEMS_MAJOR__ > 4) || (__RTEMS_MAJOR__ == 4 && __RTEMS_MINOR__ > 9)
/* cpu_time_used is a Timestamp_Control; its representation (struct
* timespec vs. int64_t) is a per-architecture/config choice, so go
* through the portable accessor rather than assume struct-timespec
* layout. */
#define CPU_ELAPSED_TIME(tc) \
((double)(tc)->cpu_time_used.tv_sec + \
((double)tc->cpu_time_used.tv_nsec / 1E9))
((double)_Timestamp_Get_as_nanoseconds(&(tc)->cpu_time_used) / 1E9)
#else
#define CPU_ELAPSED_TIME(tc) ((double)(tc)->ticks_executed)
#endif
Expand Down Expand Up @@ -99,8 +102,15 @@ static void cpu_ticks(double *total, double *idle) {

obj = _Objects_Information_table[x][1];
if (obj) {
for (y = 1; y <= obj->maximum; y++) {
tc = (Thread_Control *)obj->local_table[y];
/* obj->maximum_id is an encoded Objects_Id (API/class/node/index),
* not a plain count -- _Objects_Get_maximum_index() extracts the
* actual maximum index, matching what RTEMS's own internals use. */
for (y = 1; y <= (int)_Objects_Get_maximum_index(obj); y++) {
/* local_table is indexed from 0, but the object's index-within-
* class (y) is 1-based (RTEMS stores objects at
* id_index - OBJECTS_INDEX_MINIMUM). Indexing with y directly
* reads one entry past the end of the array on every pass. */
tc = (Thread_Control *)obj->local_table[y - OBJECTS_INDEX_MINIMUM];
if (tc) {
*total += CPU_ELAPSED_TIME(tc);
RTEMS_OBJ_GET_NAME(tc, name);
Expand Down
31 changes: 24 additions & 7 deletions devIocStats/os/RTEMS/osdIFErrors.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,37 @@

#include <devIocStats.h>

/* This would otherwise need _KERNEL to be defined... */
extern struct ifnet *ifnet;
/* The kernel-internal `struct ifnet` linked list (walked via if_next) is
* gone under libbsd -- ifnet is now a CK_STAILQ and if_ierrors/if_oerrors
* are behind the if_get_counter KPI, neither meant for use outside the
* kernel proper. getifaddrs()/struct if_data is the portable, userspace-
* visible way to get the same per-interface error counts: each interface
* contributes one AF_LINK entry whose ifa_data is its struct if_data. */
#include <ifaddrs.h>
#include <net/if.h>
#include <sys/socket.h>
Comment on lines +43 to +51

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, does this need some kind of version check?


int devIocStatsInitIFErrors(void) { return 0; }

int devIocStatsGetIFErrors(ifErrInfo *pval) {
struct ifnet *ifp;
struct ifaddrs *addrs, *ifa;

/* add all interfaces' errors */
pval->ierrors = 0;
pval->oerrors = 0;
for (ifp = ifnet; ifp != NULL; ifp = ifp->if_next) {
pval->ierrors += ifp->if_ierrors;
pval->oerrors += ifp->if_oerrors;

if (getifaddrs(&addrs) < 0) {
return -1;
}

for (ifa = addrs; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_LINK &&
ifa->ifa_data != NULL) {
struct if_data *ifd = (struct if_data *)ifa->ifa_data;
pval->ierrors += ifd->ifi_ierrors;
pval->oerrors += ifd->ifi_oerrors;
}
}

freeifaddrs(addrs);
return 0;
}
18 changes: 11 additions & 7 deletions devIocStats/os/RTEMS/osdSuspTasks.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,21 @@ int devIocStatsInitSuspTasks(void) { return 0; }
int devIocStatsGetSuspTasks(int *pval) {
Objects_Control *o;
Objects_Id id = OBJECTS_ID_INITIAL_INDEX;
Objects_Id nid;
int n = 0;
Objects_Locations l;

/* count all suspended (LOCAL -- cannot deal with remote ones ATM) tasks */
while ((o = _Objects_Get_next(&_RTEMS_tasks_Information, id, &l, &nid))) {
if ((RTEMS_ALREADY_SUSPENDED == rtems_task_is_suspended(nid))) {
/* count all suspended (LOCAL -- cannot deal with remote ones ATM) tasks.
* _Objects_Get_next()'s signature/semantics changed: no more separate
* Objects_Locations out-param (it now just returns NULL when nothing
* local is found), the object information comes first, and id doubles
* as both the search-from input and the next-id output. It locks the
* object allocator mutex when it finds something, which the caller must
* release -- see cpukit/libcsupport/src/resource_snapshot.c for the
* reference usage this follows. */
while ((o = _Objects_Get_next(id, &_RTEMS_tasks_Information.Objects, &id))) {
if ((RTEMS_ALREADY_SUSPENDED == rtems_task_is_suspended(o->id))) {
Comment on lines +50 to +59

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this need a conditional on RTEMS version? Also, I think the comment is a bit overly verbose. Saying that the syntax is changed is relevant in the commit message but not in the code IMO.

n++;
}
_Thread_Enable_dispatch();
id = nid;
_Objects_Allocator_unlock();
}
*pval = n;
return 0;
Expand Down
13 changes: 12 additions & 1 deletion devIocStats/os/RTEMS/osdWorkspaceUsage.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,18 @@ int devIocStatsGetWorkspaceUsage(memInfo *pval) {
_RTEMS_Unlock_allocator();
#endif /* RTEMS_PROTECTED_HEAP */
#if (__RTEMS_MAJOR__ > 4) || (__RTEMS_MAJOR__ == 4 && __RTEMS_MINOR__ > 9)
pval->numBytesTotal = Configuration.work_space_size;
/* rtems_configuration_get_work_space_size() (the public accessor for
* the global `Configuration` object, which a support library can't
* reach directly -- it's only declared when the application itself
* includes <rtems/confdefs.h>) reports the compile-time *configured*
* workspace size. Hardware-verified on a real BBB (RTEMS_INIT=new)
* that this does NOT match the actual runtime-negotiated workspace
* region: Free.total+Used.total came back ~227MB while this reported
* ~624KB. Derive the total from the same heap-info call that already
* produced Free/Used instead -- it's the only value guaranteed
* self-consistent with them, regardless of how this port sizes the
* workspace at boot. */
pval->numBytesTotal = info.Free.total + info.Used.total;
#else
pval->numBytesTotal = _Configuration_Table->work_space_size;
#endif
Expand Down