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
44 changes: 44 additions & 0 deletions fs/procfs/fs_procfsiobinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <nuttx/mm/iob.h>
#include <nuttx/fs/fs.h>
#include <nuttx/fs/procfs.h>
#include <nuttx/spinlock.h>

#include "fs_heap.h"

Expand Down Expand Up @@ -111,6 +112,11 @@ const struct procfs_operations g_iobinfo_operations =
iobinfo_stat /* stat */
};

#ifdef CONFIG_IOB_OWNER_TRACKING
extern volatile spinlock_t g_iob_lock;
extern FAR struct iob_s *g_iob_committed;
#endif

/****************************************************************************
* Private Functions
****************************************************************************/
Expand Down Expand Up @@ -223,6 +229,44 @@ static ssize_t iobinfo_read(FAR struct file *filep, FAR char *buffer,
&offset);
totalsize += copysize;

#ifdef CONFIG_IOB_OWNER_TRACKING
buffer += copysize;
buflen -= copysize;

irqstate_t flags = spin_lock_irqsave(&g_iob_lock);

for (unsigned int i = 0; i < CONFIG_IOB_NBUFFERS; i++)
{
FAR struct iob_s *iob = iob_get_iob_by_index(i);

/* Print: PID (or -1 for ISR) and flags in hex */

if (iob->io_owner_flags != 0)
{
linesize = procfs_snprintf(iobfile->line, IOBINFO_LINELEN,
"%02d %p -> %p pid=%d flags=0x%02x\n", i,
iob, iob->io_flink,
(int)iob->io_owner_pid,
(unsigned)iob->io_owner_flags);
}
else
{
linesize = procfs_snprintf(iobfile->line, IOBINFO_LINELEN,
"%02d %p -> %p Free\n", i,
iob, iob->io_flink);
}

copysize = procfs_memcpy(iobfile->line, linesize,
buffer, buflen, &offset);
totalsize += copysize;

buffer += copysize;
buflen -= copysize;
}

spin_unlock_irqrestore(&g_iob_lock, flags);
#endif

/* Update the file offset */

filep->f_pos += totalsize;
Expand Down
10 changes: 10 additions & 0 deletions include/nuttx/mm/iob.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ struct iob_s
#endif
unsigned int io_pktlen; /* Total length of the packet */

#ifdef CONFIG_IOB_OWNER_TRACKING
int16_t io_owner_pid;
uint8_t io_owner_cpu; /* CPU index (SMP), 0 on UP */
uint8_t io_owner_flags; /* bit0: ISR; bit1: committed; future use */
#endif

#ifdef CONFIG_IOB_ALLOC
iob_free_cb_t io_free; /* Custom free callback */
FAR uint8_t *io_data;
Expand Down Expand Up @@ -183,6 +189,10 @@ struct iob_stats_s

void iob_initialize(void);

#ifdef CONFIG_IOB_OWNER_TRACKING
struct iob_s *iob_get_iob_by_index(unsigned int index);
#endif

/****************************************************************************
* Name: iob_timedalloc
*
Expand Down
9 changes: 9 additions & 0 deletions mm/iob/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,14 @@ config IOB_DEBUG
NOTE that this selection is not available if IOBs are being used
to syslog buffering logic (CONFIG_SYSLOG_BUFFER=y)!

config IOB_OWNER_TRACKING
bool "Track task/ISR owner of each IOB (for debugging)"
default n
help
When enabled, each IOB carries small metadata indicating the
allocating context (task PID or ISR). This helps debug leaks,
starvation and ownership bugs without changing the IOB API.
Disabled by default to avoid extra RAM on small targets.

endif # MM_IOB
endmenu # Common I/O buffer support
30 changes: 30 additions & 0 deletions mm/iob/iob_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,34 @@
#include <nuttx/nuttx.h>
#include <nuttx/mm/iob.h>

#ifdef CONFIG_IOB_OWNER_TRACKING
#include <nuttx/irq.h> /* up_interrupt_context() */
#include <nuttx/sched.h> /* getpid(), this_cpu() if available */
#endif

#include "iob.h"

/****************************************************************************
* Private Functions
****************************************************************************/

/* Small helper to stamp owner information */
#ifdef CONFIG_IOB_OWNER_TRACKING
static inline void iob_set_owner(FAR struct iob_s *iob, bool is_committed)
{
bool isr = up_interrupt_context();
int pid = isr ? -1 : getpid(); /* Kernel-space getpid is OK */
#ifdef CONFIG_SMP
iob->io_owner_cpu = (uint8_t)this_cpu(); /* otherwise 0 on UP */
#else
iob->io_owner_cpu = 0;
#endif
iob->io_owner_pid = (int16_t)pid;
iob->io_owner_flags = 0x1 |
(isr ? 0x02 : 0x00) | (is_committed ? 0x04 : 0x00);
}
#endif

static clock_t iob_allocwait_gettimeout(clock_t start, unsigned int timeout)
{
sclock_t tick;
Expand Down Expand Up @@ -96,6 +118,9 @@ static FAR struct iob_s *iob_alloc_committed(void)
iob->io_len = 0; /* Length of the data in the entry */
iob->io_offset = 0; /* Offset to the beginning of data */
iob->io_pktlen = 0; /* Total length of the packet */
#ifdef CONFIG_IOB_OWNER_TRACKING
iob_set_owner(iob, true);
#endif
}

spin_unlock_irqrestore(&g_iob_lock, flags);
Expand Down Expand Up @@ -135,6 +160,11 @@ static FAR struct iob_s *iob_tryalloc_internal(bool throttled)
iob->io_len = 0; /* Length of the data in the entry */
iob->io_offset = 0; /* Offset to the beginning of data */
iob->io_pktlen = 0; /* Total length of the packet */

#ifdef CONFIG_IOB_OWNER_TRACKING
iob_set_owner(iob, false);
#endif

return iob;
}
}
Expand Down
15 changes: 15 additions & 0 deletions mm/iob/iob_free.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob)
kmm_free(iob);
}

#ifdef CONFIG_IOB_OWNER_TRACKING
/* Clear owner metadata when returning to free list */

iob->io_owner_pid = 0;
iob->io_owner_cpu = 0;
iob->io_owner_flags = 0;
#endif
return next;
}
#endif
Expand Down Expand Up @@ -196,6 +203,14 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob)
}
#endif

#ifdef CONFIG_IOB_OWNER_TRACKING
/* Clear owner metadata when returning to free list */

iob->io_owner_pid = 0;
iob->io_owner_cpu = 0;
iob->io_owner_flags = 0;
#endif

/* And return the I/O buffer after the one that was freed */

return next;
Expand Down
Loading
Loading