summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yaml10
-rw-r--r--.gitignore2
-rw-r--r--Dockerfile17
-rw-r--r--Makefile29
-rw-r--r--README.md7
-rw-r--r--inotify-info.cpp867
-rw-r--r--inotify-info.h59
-rw-r--r--lfqueue/lfqueue.c544
-rw-r--r--lfqueue/lfqueue.h90
9 files changed, 776 insertions, 849 deletions
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 83eb40c..319f4cc 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -9,6 +9,14 @@ concurrency:
cancel-in-progress: true
jobs:
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - run: sudo apt-get install -y make clang-format
+ - run: make lint
+ - run: git diff --exit-code
+
build-with-gcc:
strategy:
matrix:
@@ -30,7 +38,7 @@ jobs:
path: ~/.cache/zig
- run: |
wget --progress=dot:mega \
- https://ziglang.org/download/0.11.0/zig-linux-$(uname -m)-0.11.0.tar.xz
+ https://ziglang.org/download/0.12.0/zig-linux-$(uname -m)-0.12.0.tar.xz
tar -xJf zig-linux-*.tar.xz
rm zig-linux-*.xz
mv zig-linux-* zig-sdk
diff --git a/.gitignore b/.gitignore
index d8a5a7d..ad40b15 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
_debug/
_release/
-/inotify-info-v*.tar.gz
+/inotify-info-*.tar.gz
diff --git a/Dockerfile b/Dockerfile
index 8acb222..aa19614 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,22 +1,13 @@
-FROM alpine
+FROM alpine:edge
-# zig is installed from the upstream tarball, because:
-# - as of writing, alpine has zig only in testing (which is cumbersome to use)
-# - apk get zig pulls in libllvm, which is huge.
-#
-# Upstream tarball is statically linked, making it small and convenient to use.
-RUN apk add make \
- && wget https://ziglang.org/download/0.11.0/zig-linux-$(uname -m)-0.11.0.tar.xz \
- && tar -xJf zig-linux-*.tar.xz \
- && rm zig-linux-*.xz \
- && mv zig-linux-* zig
+RUN apk add make zig git
WORKDIR inotify-info
COPY . .
-RUN CC="/zig/zig cc -target $(uname -m)-linux-musl" \
- CXX="/zig/zig c++ -target $(uname -m)-linux-musl" \
+RUN CC="zig cc -target $(uname -m)-linux-musl" \
+ CXX="zig c++ -target $(uname -m)-linux-musl" \
make
FROM scratch
diff --git a/Makefile b/Makefile
index 6bf0e0a..cb95bb4 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,8 @@ RM = rm -f
MKDIR = mkdir -p
VERBOSE ?= 0
+INOTIFYINFO_VERSION ?= $(shell git describe --tags --dirty 2>/dev/null || echo unknown)
+
COMPILER = $(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc)
WARNINGS = -Wall -Wextra -Wpedantic -Wmissing-include-dirs -Wformat=2 -Wshadow
@@ -33,10 +35,15 @@ ifneq ($(COMPILER),clang)
WARNINGS += -Wsuggest-attribute=format -Wall
endif
-CFLAGS = $(WARNINGS) -march=native -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames -gsplit-dwarf
-CFLAGS += -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64
-CXXFLAGS = -fno-rtti -Woverloaded-virtual
-LDFLAGS = -march=native -gdwarf-4 -g2 -Wl,--build-id=sha1
+DEFINES = -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64
+DEFINES += -DINOTIFYINFO_VERSION=\"$(INOTIFYINFO_VERSION)\"
+
+CFLAGS += $(WARNINGS) $(DEFINES)
+CFLAGS += -std=gnu99 -fno-exceptions
+
+CXXFLAGS += $(WARNINGS) $(DEFINES)
+CXXFLAGS += -std=c++11 -fno-exceptions -fno-rtti -Woverloaded-virtual
+
LIBS = -Wl,--no-as-needed -lm -ldl -lpthread -lstdc++
CFILES = \
@@ -59,6 +66,7 @@ ifeq ($(ASAN), 1)
ASAN_FLAGS += -fsanitize=object-size # enable object size checking, detect various out-of-bounds accesses.
ASAN_FLAGS += -fsanitize=alignment # enable alignment checking, detect various misaligned objects;
CFLAGS += $(ASAN_FLAGS)
+ CXXFLAGS += $(ASAN_FLAGS)
LDFLAGS += $(ASAN_FLAGS)
endif
@@ -72,7 +80,6 @@ else
endif
PROJ = $(ODIR)/$(NAME)
-$(info Building $(ODIR)/$(NAME)...)
ifeq ($(VERBOSE), 1)
VERBOSE_PREFIX=
@@ -94,12 +101,16 @@ $(ODIR)/$(NAME): $(OBJS)
$(ODIR)/%.o: %.c Makefile
$(VERBOSE_PREFIX)echo "---- $< ----";
@$(MKDIR) $(dir $@)
- $(VERBOSE_PREFIX)$(CC) -MMD -MP -std=gnu99 $(CFLAGS) -o $@ -c $<
+ $(VERBOSE_PREFIX)$(CC) -MMD -MP $(CFLAGS) -o $@ -c $<
$(ODIR)/%.o: %.cpp Makefile
$(VERBOSE_PREFIX)echo "---- $< ----";
@$(MKDIR) $(dir $@)
- $(VERBOSE_PREFIX)$(CXX) -MMD -MP -std=c++11 $(CFLAGS) $(CXXFLAGS) -o $@ -c $<
+ $(VERBOSE_PREFIX)$(CXX) -MMD -MP $(CXXFLAGS) -o $@ -c $<
+
+.PHONY: lint
+lint:
+ find . -name '*.h' -o -name '*.c' -o -name '*.cpp' | xargs clang-format -i --style=webkit
.PHONY: clean
@@ -112,6 +123,6 @@ clean:
define RELEASE_RULES
inotify-info-$(TAG).tar.gz:
- git archive --prefix=inotify-info-$(TAG)/ $(TAG) | gzip -n > $$@
+ git archive --prefix=inotify-info-$(TAG)/ v$(TAG) | gzip -n > $$@
endef
-$(foreach TAG,$(shell git tag 2>/dev/null),$(eval $(RELEASE_RULES)))
+$(foreach TAG,$(shell git tag 2>/dev/null | sed -n '/^v/ s/^v//p'),$(eval $(RELEASE_RULES)))
diff --git a/README.md b/README.md
index a652a65..3c64833 100644
--- a/README.md
+++ b/README.md
@@ -22,12 +22,6 @@ Building _debug/inotify-info...
Linking _debug/inotify-info...
```
-Or you can build Docker image.
-
-```sh
-docker build . -t inotify-info
-```
-
## Install
You are free to copy the resulting executable to any suitable location in your `$PATH`.
```
@@ -163,6 +157,7 @@ Searching '/' for listed inodes... (8 threads)
## Run on Docker
```sh
+docker build . -t inotify-info
docker run --rm --privileged -v /proc:/proc inotify-info
```
diff --git a/inotify-info.cpp b/inotify-info.cpp
index 71ed3a1..ae5e61e 100644
--- a/inotify-info.cpp
+++ b/inotify-info.cpp
@@ -24,34 +24,38 @@
#define _GNU_SOURCE 1
-#include <limits.h>
#include <dirent.h>
#include <fcntl.h>
#include <getopt.h>
+#include <libgen.h>
+#include <limits.h>
+#include <locale.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <libgen.h>
-#include <locale.h>
#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#include <syscall.h>
#include <unistd.h>
-#include <sys/sysmacros.h>
-#include <sys/statfs.h>
+#include <algorithm>
#include <cstdint>
#include <string>
-#include <vector>
-#include <algorithm>
-#include <unordered_set>
#include <unordered_map>
+#include <unordered_set>
+#include <vector>
#include "inotify-info.h"
#include "lfqueue/lfqueue.h"
+#ifndef INOTIFYINFO_VERSION
+#error INOTIFYINFO_VERSION must be set
+#endif
+
/*
* TODO
* - Comments
@@ -72,23 +76,21 @@ static int g_kernel_provides_watches_info = 0;
static char thousands_sep = ',';
-static std::vector< std::string > ignore_dirs;
+static std::vector<std::string> ignore_dirs;
/*
* filename info
*/
-struct filename_info_t
-{
- ino64_t inode; // Inode number
- dev_t dev; // Device ID containing file
+struct filename_info_t {
+ ino64_t inode; // Inode number
+ dev_t dev; // Device ID containing file
std::string filename;
};
/*
* inotify process info
*/
-struct procinfo_t
-{
+struct procinfo_t {
pid_t pid = 0;
// uid
@@ -108,26 +110,24 @@ struct procinfo_t
std::string appname;
// Inotify fdset filenames
- std::vector< std::string > fdset_filenames;
+ std::vector<std::string> fdset_filenames;
// Device id map -> set of inodes for that device id
- std::unordered_map< dev_t, std::unordered_set< ino64_t > > dev_map;
+ std::unordered_map<dev_t, std::unordered_set<ino64_t>> dev_map;
};
-class lfqueue_wrapper_t
-{
+class lfqueue_wrapper_t {
public:
- lfqueue_wrapper_t() { lfqueue_init( &queue ); }
- ~lfqueue_wrapper_t() { lfqueue_destroy( &queue ); }
+ lfqueue_wrapper_t() { lfqueue_init(&queue); }
+ ~lfqueue_wrapper_t() { lfqueue_destroy(&queue); }
- void queue_directory( char *path ) { lfqueue_enq( &queue, path ); }
- char *dequeue_directory() { return ( char * )lfqueue_deq( &queue ); }
+ void queue_directory(char* path) { lfqueue_enq(&queue, path); }
+ char* dequeue_directory() { return (char*)lfqueue_deq(&queue); }
public:
typedef long long my_m256i __attribute__((__vector_size__(32), __aligned__(32)));
- union
- {
+ union {
lfqueue_t queue;
my_m256i align_buf[4]; // Align to 128 bytes
};
@@ -136,141 +136,135 @@ public:
/*
* shared thread data
*/
-class thread_shared_data_t
-{
+class thread_shared_data_t {
public:
- bool init( uint32_t numthreads, const std::vector< procinfo_t > &inotify_proclist );
+ bool init(uint32_t numthreads, const std::vector<procinfo_t>& inotify_proclist);
public:
// Array of queues - one per thread
- std::vector< lfqueue_wrapper_t > dirqueues;
+ std::vector<lfqueue_wrapper_t> dirqueues;
// Map of all inotify inodes watched to the set of devices they are on
- std::unordered_map< ino64_t, std::unordered_set< dev_t > > inode_set;
+ std::unordered_map<ino64_t, std::unordered_set<dev_t>> inode_set;
};
/*
* thread info
*/
-class thread_info_t
-{
+class thread_info_t {
public:
- thread_info_t( thread_shared_data_t &tdata_in ) : tdata( tdata_in ) {}
- ~thread_info_t() {}
+ thread_info_t(thread_shared_data_t& tdata_in)
+ : tdata(tdata_in)
+ {
+ }
+ ~thread_info_t() { }
- void queue_directory( char *path );
- char *dequeue_directory();
+ void queue_directory(char* path);
+ char* dequeue_directory();
// Returns -1: queue empty, 0: open error, > 0 success
int parse_dirqueue_entry();
- void add_filename( ino64_t inode, const char *path, const char *d_name, bool is_dir );
+ void add_filename(ino64_t inode, const char* path, const char* d_name, bool is_dir);
public:
uint32_t idx = 0;
pthread_t pthread_id = 0;
- thread_shared_data_t &tdata;
+ thread_shared_data_t& tdata;
// Total dirs scanned by this thread
uint32_t scanned_dirs = 0;
// Files found by this thread
- std::vector< filename_info_t > found_files;
+ std::vector<filename_info_t> found_files;
};
/*
* getdents64 syscall
*/
-GCC_DIAG_PUSH_OFF( pedantic )
-struct linux_dirent64
-{
- uint64_t d_ino; // Inode number
- int64_t d_off; // Offset to next linux_dirent
+GCC_DIAG_PUSH_OFF(pedantic)
+struct linux_dirent64 {
+ uint64_t d_ino; // Inode number
+ int64_t d_off; // Offset to next linux_dirent
unsigned short d_reclen; // Length of this linux_dirent
- unsigned char d_type; // File type
- char d_name[]; // Filename (null-terminated)
+ unsigned char d_type; // File type
+ char d_name[]; // Filename (null-terminated)
};
GCC_DIAG_POP()
-int sys_getdents64( int fd, char *dirp, int count )
+int sys_getdents64(int fd, char* dirp, int count)
{
- return syscall( SYS_getdents64, fd, dirp, count );
+ return syscall(SYS_getdents64, fd, dirp, count);
}
static double gettime()
{
struct timespec ts;
- clock_gettime( CLOCK_MONOTONIC, &ts );
- return ( double )ts.tv_sec + ( double )ts.tv_nsec / 1e9;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (double)ts.tv_sec + (double)ts.tv_nsec / 1e9;
}
-std::string string_formatv( const char *fmt, va_list ap )
+std::string string_formatv(const char* fmt, va_list ap)
{
std::string str;
int size = 512;
- for ( ;; )
- {
- str.resize( size );
- int n = vsnprintf( ( char * )str.c_str(), size, fmt, ap );
+ for (;;) {
+ str.resize(size);
+ int n = vsnprintf((char*)str.c_str(), size, fmt, ap);
- if ( ( n > -1 ) && ( n < size ) )
- {
- str.resize( n );
+ if ((n > -1) && (n < size)) {
+ str.resize(n);
return str;
}
- size = ( n > -1 ) ? ( n + 1 ) : ( size * 2 );
+ size = (n > -1) ? (n + 1) : (size * 2);
}
}
-std::string string_format( const char *fmt, ... )
+std::string string_format(const char* fmt, ...)
{
va_list ap;
std::string str;
- va_start( ap, fmt );
- str = string_formatv( fmt, ap );
- va_end( ap );
+ va_start(ap, fmt);
+ str = string_formatv(fmt, ap);
+ va_end(ap);
return str;
}
-static std::string get_link_name( const char *pathname )
+static std::string get_link_name(const char* pathname)
{
std::string Result;
- char filename[ PATH_MAX + 1 ];
+ char filename[PATH_MAX + 1];
- ssize_t ret = readlink( pathname, filename, sizeof( filename ) );
- if ( ( ret > 0 ) && ( ret < ( ssize_t )sizeof( filename ) ) )
- {
- filename[ ret ] = 0;
+ ssize_t ret = readlink(pathname, filename, sizeof(filename));
+ if ((ret > 0) && (ret < (ssize_t)sizeof(filename))) {
+ filename[ret] = 0;
Result = filename;
}
return Result;
}
-static uid_t get_uid(const char *pathname)
+static uid_t get_uid(const char* pathname)
{
- int fd = open( pathname, O_RDONLY, 0 );
+ int fd = open(pathname, O_RDONLY, 0);
- if ( fd >= 0 )
- {
- char buf[ 16 * 1024 ];
+ if (fd >= 0) {
+ char buf[16 * 1024];
- ssize_t len = read( fd, buf, sizeof( buf ) );
+ ssize_t len = read(fd, buf, sizeof(buf));
- close( fd );
+ close(fd);
fd = -1;
- if ( len > 0 )
- {
- buf[ len - 1 ] = 0;
+ if (len > 0) {
+ buf[len - 1] = 0;
- const char *uidstr = strstr( buf, "\nUid:" );
- if ( uidstr )
- {
- return atoll( uidstr + 5 );
+ const char* uidstr = strstr(buf, "\nUid:");
+ if (uidstr) {
+ return atoll(uidstr + 5);
}
}
}
@@ -278,27 +272,25 @@ static uid_t get_uid(const char *pathname)
return -1;
}
-static uint64_t get_token_val( const char *line, const char *token )
+static uint64_t get_token_val(const char* line, const char* token)
{
- const char *str = strstr( line, token );
+ const char* str = strstr(line, token);
- return str ? strtoull( str + strlen( token ), nullptr, 16 ) : 0;
+ return str ? strtoull(str + strlen(token), nullptr, 16) : 0;
}
-static uint32_t inotify_parse_fdinfo_file( procinfo_t &procinfo, const char *fdset_name )
+static uint32_t inotify_parse_fdinfo_file(procinfo_t& procinfo, const char* fdset_name)
{
uint32_t watch_count = 0;
- FILE *fp = fopen( fdset_name, "r" );
- if ( fp )
- {
- char line_buf[ 256 ];
+ FILE* fp = fopen(fdset_name, "r");
+ if (fp) {
+ char line_buf[256];
- procinfo.fdset_filenames.push_back( fdset_name );
+ procinfo.fdset_filenames.push_back(fdset_name);
- for ( ;; )
- {
- if ( !fgets( line_buf, sizeof( line_buf ), fp ) )
+ for (;;) {
+ if (!fgets(line_buf, sizeof(line_buf), fp))
break;
/* sample fdinfo; inotify line added in linux 3.8, available if
@@ -309,15 +301,13 @@ static uint32_t inotify_parse_fdinfo_file( procinfo_t &procinfo, const char *fds
* ino: 5865
* inotify wd:1 ino:80001 sdev:800011 mask:100 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:01000800bc1b8c7c
*/
- if ( !strncmp( line_buf, "inotify ", 8 ) )
- {
+ if (!strncmp(line_buf, "inotify ", 8)) {
watch_count++;
- uint64_t inode_val = get_token_val( line_buf, "ino:" );
- uint64_t sdev_val = get_token_val( line_buf, "sdev:" );
+ uint64_t inode_val = get_token_val(line_buf, "ino:");
+ uint64_t sdev_val = get_token_val(line_buf, "sdev:");
- if ( inode_val )
- {
+ if (inode_val) {
// https://unix.stackexchange.com/questions/645937/listing-the-files-that-are-being-watched-by-inotify-instances
// Assuming that the sdev field is encoded according to Linux's so-called "huge
// encoding", which uses 20 bits (instead of 8) for minor numbers, in bitwise
@@ -326,42 +316,39 @@ static uint32_t inotify_parse_fdinfo_file( procinfo_t &procinfo, const char *fds
unsigned int minor = sdev_val & 0xfffff;
// Add inode to this device map
- procinfo.dev_map[ makedev( major, minor ) ].insert( inode_val );
+ procinfo.dev_map[makedev(major, minor)].insert(inode_val);
}
}
}
- fclose( fp );
+ fclose(fp);
}
return watch_count;
}
-static void inotify_parse_fddir( procinfo_t &procinfo )
+static void inotify_parse_fddir(procinfo_t& procinfo)
{
- std::string filename = string_format( "/proc/%d/fd", procinfo.pid );
+ std::string filename = string_format("/proc/%d/fd", procinfo.pid);
- DIR *dir_fd = opendir( filename.c_str() );
- if ( !dir_fd )
+ DIR* dir_fd = opendir(filename.c_str());
+ if (!dir_fd)
return;
- for ( ;; )
- {
- struct dirent *dp_fd = readdir( dir_fd );
- if ( !dp_fd )
+ for (;;) {
+ struct dirent* dp_fd = readdir(dir_fd);
+ if (!dp_fd)
break;
- if ( ( dp_fd->d_type == DT_LNK ) && isdigit( dp_fd->d_name[ 0 ] ) )
- {
- filename = string_format( "/proc/%d/fd/%s", procinfo.pid, dp_fd->d_name );
- filename = get_link_name( filename.c_str() );
+ if ((dp_fd->d_type == DT_LNK) && isdigit(dp_fd->d_name[0])) {
+ filename = string_format("/proc/%d/fd/%s", procinfo.pid, dp_fd->d_name);
+ filename = get_link_name(filename.c_str());
- if ( filename == "anon_inode:inotify" || filename == "inotify" )
- {
- filename = string_format( "/proc/%d/fdinfo/%s", procinfo.pid, dp_fd->d_name );
+ if (filename == "anon_inode:inotify" || filename == "inotify") {
+ filename = string_format("/proc/%d/fdinfo/%s", procinfo.pid, dp_fd->d_name);
procinfo.instances++;
- procinfo.watches += inotify_parse_fdinfo_file( procinfo, filename.c_str() );
+ procinfo.watches += inotify_parse_fdinfo_file(procinfo, filename.c_str());
/* If any watches have been found, enable the stats display */
g_kernel_provides_watches_info |= !!procinfo.watches;
@@ -369,25 +356,23 @@ static void inotify_parse_fddir( procinfo_t &procinfo )
}
}
- closedir( dir_fd );
+ closedir(dir_fd);
}
-void thread_info_t::queue_directory( char *path )
+void thread_info_t::queue_directory(char* path)
{
- tdata.dirqueues[ idx ].queue_directory( path );
+ tdata.dirqueues[idx].queue_directory(path);
}
-char *thread_info_t::dequeue_directory()
+char* thread_info_t::dequeue_directory()
{
- char *path = tdata.dirqueues[ idx ].dequeue_directory();
+ char* path = tdata.dirqueues[idx].dequeue_directory();
- if ( !path )
- {
+ if (!path) {
// Nothing on our queue, check queues on other threads
- for ( lfqueue_wrapper_t &dirq : tdata.dirqueues )
- {
+ for (lfqueue_wrapper_t& dirq : tdata.dirqueues) {
path = dirq.dequeue_directory();
- if ( path )
+ if (path)
break;
}
}
@@ -396,59 +381,56 @@ char *thread_info_t::dequeue_directory()
}
// statx() was added to Linux in kernel 4.11; library support was added in glibc 2.28.
-#if defined( __linux__ ) && ( ( __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 28 ) || ( __GLIBC__ > 2 ) )
+#if defined(__linux__) && ((__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 28) || (__GLIBC__ > 2))
-struct statx mystatx( const char *filename, unsigned int mask = 0 )
+struct statx mystatx(const char* filename, unsigned int mask = 0)
{
struct statx statxbuf;
int flags = AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | AT_STATX_DONT_SYNC;
- if ( statx( 0, filename, flags, mask, &statxbuf ) == -1 )
- {
- printf( "ERROR: statx-ino( %s ) failed. Errno: %d\n", filename, errno );
- memset( &statxbuf, 0, sizeof( statxbuf ) );
+ if (statx(0, filename, flags, mask, &statxbuf) == -1) {
+ printf("ERROR: statx-ino( %s ) failed. Errno: %d\n", filename, errno);
+ memset(&statxbuf, 0, sizeof(statxbuf));
}
return statxbuf;
}
-static dev_t stat_get_dev_t( const char *filename )
+static dev_t stat_get_dev_t(const char* filename)
{
- struct statx statxbuf = mystatx( filename );
+ struct statx statxbuf = mystatx(filename);
- return makedev( statxbuf.stx_dev_major, statxbuf.stx_dev_minor );
+ return makedev(statxbuf.stx_dev_major, statxbuf.stx_dev_minor);
}
-static uint64_t stat_get_ino( const char *filename )
+static uint64_t stat_get_ino(const char* filename)
{
- return mystatx( filename, STATX_INO ).stx_ino;
+ return mystatx(filename, STATX_INO).stx_ino;
}
#else
// Fall back to using stat() functions. Should work but be slower than using statx().
-static dev_t stat_get_dev_t( const char *filename )
+static dev_t stat_get_dev_t(const char* filename)
{
struct stat statbuf;
- int ret = stat( filename, &statbuf );
- if ( ret == -1 )
- {
- printf( "ERROR: stat-dev_t( %s ) failed. Errno: %d\n", filename, errno );
+ int ret = stat(filename, &statbuf);
+ if (ret == -1) {
+ printf("ERROR: stat-dev_t( %s ) failed. Errno: %d\n", filename, errno);
return 0;
}
return statbuf.st_dev;
}
-static uint64_t stat_get_ino( const char *filename )
+static uint64_t stat_get_ino(const char* filename)
{
struct stat statbuf;
- int ret = stat( filename, &statbuf );
- if ( ret == -1 )
- {
- printf( "ERROR: stat-ino( %s ) failed. Errno: %d\n", filename, errno );
+ int ret = stat(filename, &statbuf);
+ if (ret == -1) {
+ printf("ERROR: stat-ino( %s ) failed. Errno: %d\n", filename, errno);
return 0;
}
@@ -457,39 +439,36 @@ static uint64_t stat_get_ino( const char *filename )
#endif
-void thread_info_t::add_filename( ino64_t inode, const char *path, const char *d_name, bool is_dir )
+void thread_info_t::add_filename(ino64_t inode, const char* path, const char* d_name, bool is_dir)
{
- auto it = tdata.inode_set.find( inode );
+ auto it = tdata.inode_set.find(inode);
- if ( it != tdata.inode_set.end() )
- {
- const std::unordered_set< dev_t > &dev_set = it->second;
+ if (it != tdata.inode_set.end()) {
+ const std::unordered_set<dev_t>& dev_set = it->second;
- std::string filename = std::string( path ) + d_name;
- dev_t dev = stat_get_dev_t( filename.c_str() );
+ std::string filename = std::string(path) + d_name;
+ dev_t dev = stat_get_dev_t(filename.c_str());
// Make sure the inode AND device ID match before adding.
- if ( dev_set.find( dev ) != dev_set.end() )
- {
+ if (dev_set.find(dev) != dev_set.end()) {
filename_info_t fname;
fname.filename = is_dir ? filename + "/" : filename;
fname.inode = inode;
fname.dev = dev;
- found_files.push_back( fname );
+ found_files.push_back(fname);
}
}
}
-static bool is_dot_dir( const char *dname )
+static bool is_dot_dir(const char* dname)
{
- if ( dname[ 0 ] == '.' )
- {
- if ( !dname[ 1 ] )
+ if (dname[0] == '.') {
+ if (!dname[1])
return true;
- if ( ( dname[ 1 ] == '.' ) && !dname[ 2 ] )
+ if ((dname[1] == '.') && !dname[2])
return true;
}
@@ -497,24 +476,22 @@ static bool is_dot_dir( const char *dname )
}
// From "linux/magic.h"
-#define PROC_SUPER_MAGIC 0x9fa0
-#define SMB_SUPER_MAGIC 0x517B
-#define CIFS_SUPER_MAGIC 0xFF534D42 /* the first four bytes of SMB PDUs */
-#define SMB2_SUPER_MAGIC 0xFE534D42
-#define FUSE_SUPER_MAGIC 0x65735546
+#define PROC_SUPER_MAGIC 0x9fa0
+#define SMB_SUPER_MAGIC 0x517B
+#define CIFS_SUPER_MAGIC 0xFF534D42 /* the first four bytes of SMB PDUs */
+#define SMB2_SUPER_MAGIC 0xFE534D42
+#define FUSE_SUPER_MAGIC 0x65735546
// Detect proc and fuse directories and skip them.
// https://github.com/mikesart/inotify-info/issues/6
// Could use setmntent("/proc/mounts", "r") + getmntent if speed is an issue?
-static bool is_proc_dir( const char *path, const char *d_name )
+static bool is_proc_dir(const char* path, const char* d_name)
{
struct statfs s;
- std::string filename = std::string( path ) + d_name;
+ std::string filename = std::string(path) + d_name;
- if ( statfs(filename.c_str(), &s ) == 0 )
- {
- switch ( s.f_type )
- {
+ if (statfs(filename.c_str(), &s) == 0) {
+ switch (s.f_type) {
case PROC_SUPER_MAGIC:
case FUSE_SUPER_MAGIC:
return true;
@@ -527,65 +504,55 @@ static bool is_proc_dir( const char *path, const char *d_name )
// Returns -1: queue empty, 0: open error, > 0 success
int thread_info_t::parse_dirqueue_entry()
{
- char __attribute__( ( aligned( 16 ) ) ) buf[ 1024 ];
+ char __attribute__((aligned(16))) buf[1024];
- char *path = dequeue_directory();
- if ( !path )
- {
+ char* path = dequeue_directory();
+ if (!path) {
return -1;
}
- for ( std::string &dname : ignore_dirs )
- {
- if ( dname == path )
- {
- if ( g_verbose > 1 )
- {
- printf( "Ignoring '%s'\n", path );
+ for (std::string& dname : ignore_dirs) {
+ if (dname == path) {
+ if (g_verbose > 1) {
+ printf("Ignoring '%s'\n", path);
}
return 0;
}
}
- int fd = open( path, O_RDONLY | O_DIRECTORY, 0 );
- if ( fd < 0 )
- {
- free( path );
+ int fd = open(path, O_RDONLY | O_DIRECTORY, 0);
+ if (fd < 0) {
+ free(path);
return 0;
}
scanned_dirs++;
- size_t pathlen = strlen( path );
+ size_t pathlen = strlen(path);
- for ( ;; )
- {
- int ret = sys_getdents64( fd, buf, sizeof( buf ) );
+ for (;;) {
+ int ret = sys_getdents64(fd, buf, sizeof(buf));
- if ( ret < 0 )
- {
+ if (ret < 0) {
bool spew_error = true;
- if ( ( errno == 5 ) && !strncmp( path, "/sys/kernel/", 12 ) )
- {
+ if ((errno == 5) && !strncmp(path, "/sys/kernel/", 12)) {
// In docker container we can get permission denied errors in /sys/kernel. Ignore them.
// https://github.com/mikesart/inotify-info/issues/16
spew_error = false;
}
- if ( spew_error )
- {
- printf( "ERROR: sys_getdents64 failed on '%s': %d errno:%d\n", path, ret, errno );
+ if (spew_error) {
+ printf("ERROR: sys_getdents64 failed on '%s': %d errno:%d\n", path, ret, errno);
}
break;
}
- if ( ret == 0 )
+ if (ret == 0)
break;
- for ( int bpos = 0; bpos < ret; )
- {
- struct linux_dirent64 *dirp = ( struct linux_dirent64 * )( buf + bpos );
- const char *d_name = dirp->d_name;
+ for (int bpos = 0; bpos < ret;) {
+ struct linux_dirent64* dirp = (struct linux_dirent64*)(buf + bpos);
+ const char* d_name = dirp->d_name;
// DT_BLK This is a block device.
// DT_CHR This is a character device.
@@ -595,28 +562,24 @@ int thread_info_t::parse_dirqueue_entry()
// DT_REG This is a regular file.
// DT_LNK This is a symbolic link.
- if ( dirp->d_type == DT_REG || dirp->d_type == DT_LNK )
- {
- add_filename( dirp->d_ino, path, d_name, false );
+ if (dirp->d_type == DT_REG || dirp->d_type == DT_LNK) {
+ add_filename(dirp->d_ino, path, d_name, false);
}
// DT_DIR This is a directory.
- else if ( dirp->d_type == DT_DIR )
- {
- if ( !is_dot_dir( d_name ) && !is_proc_dir( path, d_name ) )
- {
- add_filename( dirp->d_ino, path, d_name, true );
-
- size_t len = strlen( d_name );
- char *newpath = ( char * )malloc( pathlen + len + 2 );
-
- if ( newpath )
- {
- strcpy( newpath, path );
- strcpy( newpath + pathlen, d_name );
- newpath[ pathlen + len ] = '/';
- newpath[ pathlen + len + 1 ] = 0;
-
- queue_directory( newpath );
+ else if (dirp->d_type == DT_DIR) {
+ if (!is_dot_dir(d_name) && !is_proc_dir(path, d_name)) {
+ add_filename(dirp->d_ino, path, d_name, true);
+
+ size_t len = strlen(d_name);
+ char* newpath = (char*)malloc(pathlen + len + 2);
+
+ if (newpath) {
+ strcpy(newpath, path);
+ strcpy(newpath + pathlen, d_name);
+ newpath[pathlen + len] = '/';
+ newpath[pathlen + len + 1] = 0;
+
+ queue_directory(newpath);
}
}
}
@@ -625,107 +588,97 @@ int thread_info_t::parse_dirqueue_entry()
}
}
- close( fd );
- free( path );
+ close(fd);
+ free(path);
return 1;
}
-static void *parse_dirqueue_threadproc( void *arg )
+static void* parse_dirqueue_threadproc(void* arg)
{
- thread_info_t *pthread_info = ( thread_info_t * )arg;
+ thread_info_t* pthread_info = (thread_info_t*)arg;
- for ( ;; )
- {
+ for (;;) {
// Loop until all the dequeue(s) fail
- if ( pthread_info->parse_dirqueue_entry() == -1 )
+ if (pthread_info->parse_dirqueue_entry() == -1)
break;
}
return nullptr;
}
-static bool is_proc_in_cmdline_applist( const procinfo_t &procinfo, std::vector< std::string > &cmdline_applist )
+static bool is_proc_in_cmdline_applist(const procinfo_t& procinfo, std::vector<std::string>& cmdline_applist)
{
- for ( const std::string &str : cmdline_applist )
- {
+ for (const std::string& str : cmdline_applist) {
// Check if our command line string is a subset of this appname
- if ( strstr( procinfo.appname.c_str(), str.c_str() ) )
+ if (strstr(procinfo.appname.c_str(), str.c_str()))
return true;
// Check if the PIDs match
- if ( atoll( str.c_str() ) == procinfo.pid )
+ if (atoll(str.c_str()) == procinfo.pid)
return true;
}
return false;
}
-static bool watch_count_is_greater ( procinfo_t elem1, procinfo_t elem2 )
+static bool watch_count_is_greater(procinfo_t elem1, procinfo_t elem2)
{
- return elem1.watches > elem2.watches;
+ return elem1.watches > elem2.watches;
}
-
-static bool init_inotify_proclist( std::vector< procinfo_t > &inotify_proclist )
+static bool init_inotify_proclist(std::vector<procinfo_t>& inotify_proclist)
{
- DIR *dir_proc = opendir( "/proc" );
+ DIR* dir_proc = opendir("/proc");
- if ( !dir_proc )
- {
- printf( "ERROR: opendir /proc failed: %d\n", errno );
+ if (!dir_proc) {
+ printf("ERROR: opendir /proc failed: %d\n", errno);
return false;
}
- for ( ;; )
- {
- struct dirent *dp_proc = readdir( dir_proc );
- if ( !dp_proc )
+ for (;;) {
+ struct dirent* dp_proc = readdir(dir_proc);
+ if (!dp_proc)
break;
- if ( ( dp_proc->d_type == DT_DIR ) && isdigit( dp_proc->d_name[ 0 ] ) )
- {
+ if ((dp_proc->d_type == DT_DIR) && isdigit(dp_proc->d_name[0])) {
procinfo_t procinfo;
- procinfo.pid = atoll( dp_proc->d_name );
+ procinfo.pid = atoll(dp_proc->d_name);
- std::string executable = string_format( "/proc/%d/exe", procinfo.pid );
- std::string status = string_format( "/proc/%d/status", procinfo.pid );
- procinfo.uid = get_uid( status.c_str() );
- procinfo.executable = get_link_name( executable.c_str() );
- if ( !procinfo.executable.empty() )
- {
- procinfo.appname = basename( (char*)procinfo.executable.c_str() );
+ std::string executable = string_format("/proc/%d/exe", procinfo.pid);
+ std::string status = string_format("/proc/%d/status", procinfo.pid);
+ procinfo.uid = get_uid(status.c_str());
+ procinfo.executable = get_link_name(executable.c_str());
+ if (!procinfo.executable.empty()) {
+ procinfo.appname = basename((char*)procinfo.executable.c_str());
- inotify_parse_fddir( procinfo );
+ inotify_parse_fddir(procinfo);
- if ( procinfo.instances )
- {
- inotify_proclist.push_back( procinfo );
+ if (procinfo.instances) {
+ inotify_proclist.push_back(procinfo);
}
}
}
}
std::sort(inotify_proclist.begin(), inotify_proclist.end(), watch_count_is_greater);
- closedir( dir_proc );
+ closedir(dir_proc);
return true;
}
// From:
// https://stackoverflow.com/questions/1449805/how-to-format-a-number-using-comma-as-thousands-separator-in-c
-size_t str_format_uint32( char dst[16], uint32_t num )
+size_t str_format_uint32(char dst[16], uint32_t num)
{
- if ( thousands_sep )
- {
+ if (thousands_sep) {
char src[16];
- char *p_src = src;
- char *p_dst = dst;
+ char* p_src = src;
+ char* p_dst = dst;
int num_len, commas;
num_len = sprintf(src, "%u", num);
- for (commas = 2 - num_len % 3; *p_src; commas = (commas + 1) % 3)
- {
+ for (commas = 2 - num_len % 3; *p_src; commas = (commas + 1) % 3) {
*p_dst++ = *p_src++;
if (commas == 1) {
*p_dst++ = thousands_sep;
@@ -739,7 +692,7 @@ size_t str_format_uint32( char dst[16], uint32_t num )
return sprintf(dst, "%u", num);
}
-static void print_inotify_proclist( std::vector< procinfo_t > &inotify_proclist )
+static void print_inotify_proclist(std::vector<procinfo_t>& inotify_proclist)
{
#if 0
// test data
@@ -775,192 +728,170 @@ static void print_inotify_proclist( std::vector< procinfo_t > &inotify_proclist
int lenWatches = 8;
int lenInstances = 10;
- for ( procinfo_t &procinfo : inotify_proclist )
- lenApp = std::max<int>( procinfo.appname.length(), lenApp );
+ for (procinfo_t& procinfo : inotify_proclist)
+ lenApp = std::max<int>(procinfo.appname.length(), lenApp);
/* If the number of watches is negative, the kernel doesn't support this info. omit the header*/
if (g_kernel_provides_watches_info)
- printf( "%s%*s %-*s %-*s %*s %*s%s\n",
+ printf("%s%*s %-*s %-*s %*s %*s%s\n",
BCYAN, lenPid, "Pid", lenUid, "Uid", lenApp, "App", lenWatches, "Watches", lenInstances, "Instances", RESET);
else
- printf( "%s%*s %-*s %*s %*s%s\n",
+ printf("%s%*s %-*s %*s %*s%s\n",
BCYAN, lenPid, "Pid", lenUid, "Uid", lenApp, "App", lenInstances, "Instances", RESET);
-
- for ( procinfo_t &procinfo : inotify_proclist )
- {
+ for (procinfo_t& procinfo : inotify_proclist) {
char watches_str[16];
str_format_uint32(watches_str, procinfo.watches);
if (g_kernel_provides_watches_info)
- printf( "%*d %-*d %s%-*s%s %*s %*u\n",
+ printf("%*d %-*d %s%-*s%s %*s %*u\n",
lenPid, procinfo.pid,
lenUid, procinfo.uid,
BYELLOW, lenApp, procinfo.appname.c_str(), RESET,
lenWatches, watches_str,
- lenInstances, procinfo.instances );
+ lenInstances, procinfo.instances);
else
- printf( "%*d %-*d %s%-*s%s %*u\n",
+ printf("%*d %-*d %s%-*s%s %*u\n",
lenPid, procinfo.pid,
lenUid, procinfo.uid,
BYELLOW, lenApp, procinfo.appname.c_str(), RESET,
- lenInstances, procinfo.instances );
+ lenInstances, procinfo.instances);
- if ( g_verbose > 1 )
- {
- for ( std::string &fname : procinfo.fdset_filenames )
- {
- printf( " %s%s%s\n", CYAN, fname.c_str(), RESET );
+ if (g_verbose > 1) {
+ for (std::string& fname : procinfo.fdset_filenames) {
+ printf(" %s%s%s\n", CYAN, fname.c_str(), RESET);
}
}
- if ( procinfo.in_cmd_line )
- {
- for ( const auto &it1 : procinfo.dev_map )
- {
+ if (procinfo.in_cmd_line) {
+ for (const auto& it1 : procinfo.dev_map) {
dev_t dev = it1.first;
- printf( "%s[%u.%u]:%s", BGRAY, major( dev ), minor( dev ), RESET );
- for ( const auto &it2 : it1.second )
- {
- std::string inode_device_str = string_format( "%lu", it2 );
+ printf("%s[%u.%u]:%s", BGRAY, major(dev), minor(dev), RESET);
+ for (const auto& it2 : it1.second) {
+ std::string inode_device_str = string_format("%lu", it2);
- printf( " %s%s%s", BGRAY, inode_device_str.c_str(), RESET );
+ printf(" %s%s%s", BGRAY, inode_device_str.c_str(), RESET);
}
- printf( "\n" );
+ printf("\n");
}
}
}
}
-bool thread_shared_data_t::init( uint32_t numthreads, const std::vector< procinfo_t > &inotify_proclist )
+bool thread_shared_data_t::init(uint32_t numthreads, const std::vector<procinfo_t>& inotify_proclist)
{
- for ( const procinfo_t &procinfo : inotify_proclist )
- {
- if ( !procinfo.in_cmd_line )
+ for (const procinfo_t& procinfo : inotify_proclist) {
+ if (!procinfo.in_cmd_line)
continue;
- for ( const auto &it1 : procinfo.dev_map )
- {
+ for (const auto& it1 : procinfo.dev_map) {
dev_t dev = it1.first;
- for ( const auto &inode : it1.second )
- {
- inode_set[ inode ].insert( dev );
+ for (const auto& inode : it1.second) {
+ inode_set[inode].insert(dev);
}
}
}
- if ( !inode_set.empty() )
- {
- dirqueues.resize( numthreads );
+ if (!inode_set.empty()) {
+ dirqueues.resize(numthreads);
}
return !inode_set.empty();
}
-static uint32_t find_files_in_inode_set( const std::vector< procinfo_t > &inotify_proclist,
- std::vector< filename_info_t > &all_found_files )
+static uint32_t find_files_in_inode_set(const std::vector<procinfo_t>& inotify_proclist,
+ std::vector<filename_info_t>& all_found_files)
{
thread_shared_data_t tdata;
- g_numthreads = std::max< size_t >( 1, g_numthreads );
+ g_numthreads = std::max<size_t>(1, g_numthreads);
- if ( !tdata.init( g_numthreads, inotify_proclist ) )
+ if (!tdata.init(g_numthreads, inotify_proclist))
return 0;
- printf( "\n%sSearching '/' for listed inodes...%s (%lu threads)\n", BCYAN, RESET, g_numthreads );
+ printf("\n%sSearching '/' for listed inodes...%s (%lu threads)\n", BCYAN, RESET, g_numthreads);
// Initialize thread_info_t array
- std::vector< class thread_info_t > thread_array( g_numthreads, thread_info_t( tdata ) );
+ std::vector<class thread_info_t> thread_array(g_numthreads, thread_info_t(tdata));
- for ( uint32_t idx = 0; idx < thread_array.size(); idx++ )
- {
- thread_info_t &thread_info = thread_array[ idx ];
+ for (uint32_t idx = 0; idx < thread_array.size(); idx++) {
+ thread_info_t& thread_info = thread_array[idx];
thread_info.idx = idx;
- if ( idx == 0 )
- {
+ if (idx == 0) {
// Add root dir in case someone is watching it
- thread_info.add_filename( stat_get_ino( "/" ), "/", "", false );
+ thread_info.add_filename(stat_get_ino("/"), "/", "", false);
// Add and parse root
- thread_info.queue_directory( strdup( "/" ) );
+ thread_info.queue_directory(strdup("/"));
thread_info.parse_dirqueue_entry();
- }
- else if ( pthread_create( &thread_info.pthread_id, NULL, &parse_dirqueue_threadproc, &thread_info ) )
- {
- printf( "Warning: pthread_create failed. errno: %d\n", errno );
+ } else if (pthread_create(&thread_info.pthread_id, NULL, &parse_dirqueue_threadproc, &thread_info)) {
+ printf("Warning: pthread_create failed. errno: %d\n", errno);
thread_info.pthread_id = 0;
}
}
// Put main thread to work
- parse_dirqueue_threadproc( &thread_array[ 0 ] );
+ parse_dirqueue_threadproc(&thread_array[0]);
uint32_t total_scanned_dirs = 0;
- for ( const thread_info_t &thread_info : thread_array )
- {
- if ( thread_info.pthread_id )
- {
- if ( g_verbose > 1 )
- {
- printf( "Waiting for thread #%zu\n", thread_info.pthread_id );
+ for (const thread_info_t& thread_info : thread_array) {
+ if (thread_info.pthread_id) {
+ if (g_verbose > 1) {
+ printf("Waiting for thread #%zu\n", thread_info.pthread_id);
}
- void *status = NULL;
- int rc = pthread_join( thread_info.pthread_id, &status );
+ void* status = NULL;
+ int rc = pthread_join(thread_info.pthread_id, &status);
- if ( g_verbose > 1 )
- {
- printf( "Thread #%zu rc=%d status=%d\n", thread_info.pthread_id, rc, ( int )( intptr_t )status );
+ if (g_verbose > 1) {
+ printf("Thread #%zu rc=%d status=%d\n", thread_info.pthread_id, rc, (int)(intptr_t)status);
}
}
// Snag data from this thread
total_scanned_dirs += thread_info.scanned_dirs;
- all_found_files.insert( all_found_files.end(),
- thread_info.found_files.begin(), thread_info.found_files.end() );
+ all_found_files.insert(all_found_files.end(),
+ thread_info.found_files.begin(), thread_info.found_files.end());
- if ( g_verbose > 1 )
- {
- printf( "Thread #%zu: %u dirs, %zu files found\n",
- thread_info.pthread_id, thread_info.scanned_dirs, thread_info.found_files.size() );
+ if (g_verbose > 1) {
+ printf("Thread #%zu: %u dirs, %zu files found\n",
+ thread_info.pthread_id, thread_info.scanned_dirs, thread_info.found_files.size());
}
}
struct
{
- bool operator()( const filename_info_t &a, const filename_info_t &b ) const
+ bool operator()(const filename_info_t& a, const filename_info_t& b) const
{
- if ( a.dev == b.dev )
+ if (a.dev == b.dev)
return a.inode < b.inode;
return a.dev < b.dev;
}
} filename_info_less_func;
- std::sort( all_found_files.begin(), all_found_files.end(), filename_info_less_func );
+ std::sort(all_found_files.begin(), all_found_files.end(), filename_info_less_func);
return total_scanned_dirs;
}
-static uint32_t get_inotify_procfs_value( const std::string &fname )
+static uint32_t get_inotify_procfs_value(const std::string& fname)
{
- char buf[ 64 ];
+ char buf[64];
uint32_t val = 0;
std::string filename = "/proc/sys/fs/inotify/" + fname;
- int fd = open( filename.c_str(), O_RDONLY );
- if ( fd >= 0 )
- {
- if ( read( fd, buf, sizeof( buf ) ) > 0 )
- {
- val = strtoul( buf, nullptr, 10 );
+ int fd = open(filename.c_str(), O_RDONLY);
+ if (fd >= 0) {
+ if (read(fd, buf, sizeof(buf)) > 0) {
+ val = strtoul(buf, nullptr, 10);
}
- close( fd );
+ close(fd);
}
return val;
@@ -968,77 +899,63 @@ static uint32_t get_inotify_procfs_value( const std::string &fname )
static void print_inotify_limits()
{
- const std::vector< std::string > filenames =
- {
+ const std::vector<std::string> filenames = {
"max_queued_events",
"max_user_instances",
"max_user_watches"
};
- printf( "%sINotify Limits:%s\n", BCYAN, RESET );
- for ( const std::string &fname : filenames )
- {
+ printf("%sINotify Limits:%s\n", BCYAN, RESET);
+ for (const std::string& fname : filenames) {
char str[16];
- uint32_t val = get_inotify_procfs_value( fname );
+ uint32_t val = get_inotify_procfs_value(fname);
str_format_uint32(str, val);
- printf( " %-20s %s%s%s\n", fname.c_str(), BGREEN, str, RESET );
+ printf(" %-20s %s%s%s\n", fname.c_str(), BGREEN, str, RESET);
}
}
-static uint32_t parse_config_file( const char *config_file )
+static uint32_t parse_config_file(const char* config_file)
{
uint32_t dir_count = 0;
- FILE *fp = fopen( config_file, "r" );
- if ( fp )
- {
- char line_buf[ 8192 ];
+ FILE* fp = fopen(config_file, "r");
+ if (fp) {
+ char line_buf[8192];
bool in_ignore_dirs_section = false;
- for ( ;; )
- {
- if ( !fgets( line_buf, sizeof( line_buf ) - 1, fp ) )
+ for (;;) {
+ if (!fgets(line_buf, sizeof(line_buf) - 1, fp))
break;
- if ( line_buf[0] == '#' )
- {
+ if (line_buf[0] == '#') {
// comment
- }
- else if ( !in_ignore_dirs_section )
- {
- size_t len = strcspn( line_buf, "\r\n" );
+ } else if (!in_ignore_dirs_section) {
+ size_t len = strcspn(line_buf, "\r\n");
- if ( ( len == 12 ) && !strncmp( "[ignoredirs]", line_buf, 12 ) )
- {
+ if ((len == 12) && !strncmp("[ignoredirs]", line_buf, 12)) {
in_ignore_dirs_section = true;
}
- }
- else if ( line_buf[ 0 ] == '[' )
- {
+ } else if (line_buf[0] == '[') {
in_ignore_dirs_section = false;
- }
- else if ( in_ignore_dirs_section && ( line_buf[ 0 ] == '/' ) )
- {
- size_t len = strcspn( line_buf, "\r\n" );
-
- if ( len > 1 )
- {
- line_buf[ len ] = 0;
- if ( line_buf[ len - 1 ] != '/' )
- {
- line_buf[ len ] = '/';
- line_buf[ len + 1 ] = '\0';
+ } else if (in_ignore_dirs_section && (line_buf[0] == '/')) {
+ size_t len = strcspn(line_buf, "\r\n");
+
+ if (len > 1) {
+ line_buf[len] = 0;
+ if (line_buf[len - 1] != '/') {
+ line_buf[len] = '/';
+ line_buf[len + 1] = '\0';
}
- ignore_dirs.push_back( line_buf );
+ ignore_dirs.push_back(line_buf);
dir_count++;
}
}
}
- fclose( fp );
+ fclose(fp);
}
return dir_count;
@@ -1048,74 +965,81 @@ static bool parse_ignore_dirs_file()
{
const std::string filename = "inotify-info.config";
- const char *xdg_config_dir = getenv( "XDG_CONFIG_HOME" );
- if ( xdg_config_dir )
- {
- std::string config_file = std::string( xdg_config_dir ) + "/" + filename;
- if ( parse_config_file( config_file.c_str() ) )
+ const char* xdg_config_dir = getenv("XDG_CONFIG_HOME");
+ if (xdg_config_dir) {
+ std::string config_file = std::string(xdg_config_dir) + "/" + filename;
+ if (parse_config_file(config_file.c_str()))
return true;
- config_file = std::string( xdg_config_dir) + "/.config/" + filename;
- if ( parse_config_file( config_file.c_str() ) )
+ config_file = std::string(xdg_config_dir) + "/.config/" + filename;
+ if (parse_config_file(config_file.c_str()))
return true;
}
- const char *home_dir = getenv( "HOME" );
- if ( home_dir )
- {
- std::string config_file = std::string( home_dir ) + "/" + filename;
- if ( parse_config_file( config_file.c_str() ) )
+ const char* home_dir = getenv("HOME");
+ if (home_dir) {
+ std::string config_file = std::string(home_dir) + "/" + filename;
+ if (parse_config_file(config_file.c_str()))
return true;
}
std::string config_file = "/etc/" + filename;
- if ( parse_config_file( config_file.c_str() ) )
+ if (parse_config_file(config_file.c_str()))
return true;
return false;
}
-static void print_usage( const char *appname )
+static void print_version()
{
- printf( "Usage: %s [--threads=##] [appname | pid...]\n", appname );
- printf( " [-vv]\n" );
- printf( " [-?|-h|--help]\n" );
+ printf("%s\n", INOTIFYINFO_VERSION);
+}
- exit( -1 );
+static void print_usage(const char* appname)
+{
+ printf("Usage: %s [--threads=##] [appname | pid...]\n", appname);
+ printf(" [-vv]\n");
+ printf(" [--version]\n");
+ printf(" [-?|-h|--help]\n");
}
-static void parse_cmdline( int argc, char **argv, std::vector< std::string > &cmdline_applist )
+static void parse_cmdline(int argc, char** argv, std::vector<std::string>& cmdline_applist)
{
- static struct option long_opts[] =
- {
+ static struct option long_opts[] = {
{ "verbose", no_argument, 0, 0 },
{ "threads", required_argument, 0, 0 },
{ "ignoredir", required_argument, 0, 0 },
+ { "version", no_argument, 0, 0 },
+ { "help", no_argument, 0, 0 },
{ 0, 0, 0, 0 }
};
// Let's pick the number of processors online (with a max of 32) for a default.
- g_numthreads = std::min< uint32_t >( g_numthreads, sysconf( _SC_NPROCESSORS_ONLN ) );
+ g_numthreads = std::min<uint32_t>(g_numthreads, sysconf(_SC_NPROCESSORS_ONLN));
int c;
int opt_ind = 0;
- while ( ( c = getopt_long( argc, argv, "m:s:?hv", long_opts, &opt_ind ) ) != -1 )
- {
- switch ( c )
- {
+ while ((c = getopt_long(argc, argv, "m:s:?hv", long_opts, &opt_ind)) != -1) {
+ switch (c) {
case 0:
- if ( !strcasecmp( "verbose", long_opts[ opt_ind ].name ) )
+ if (!strcasecmp("help", long_opts[opt_ind].name)) {
+ print_usage(argv[0]);
+ exit(0);
+ };
+ if (!strcasecmp("version", long_opts[opt_ind].name)) {
+ print_version();
+ exit(0);
+ }
+ if (!strcasecmp("verbose", long_opts[opt_ind].name))
g_verbose++;
- else if ( !strcasecmp( "threads", long_opts[ opt_ind ].name ) )
- g_numthreads = atoi( optarg );
- else if ( !strcasecmp( "ignoredir", long_opts[ opt_ind ].name ) )
- {
+ else if (!strcasecmp("threads", long_opts[opt_ind].name))
+ g_numthreads = atoi(optarg);
+ else if (!strcasecmp("ignoredir", long_opts[opt_ind].name)) {
std::string dirname = optarg;
- if ( dirname.size() > 1 )
- {
- if ( optarg[ dirname.size() - 1 ] != '/' )
+ if (dirname.size() > 1) {
+ if (optarg[dirname.size() - 1] != '/')
dirname += "/";
- ignore_dirs.push_back( dirname );
+ ignore_dirs.push_back(dirname);
}
}
break;
@@ -1124,93 +1048,88 @@ static void parse_cmdline( int argc, char **argv, std::vector< std::string > &cm
break;
case 'h':
case '?':
+ print_usage(argv[0]);
+ exit(0);
default:
- print_usage( argv[ 0 ] );
+ print_usage(argv[0]);
+ exit(-1);
break;
}
}
- for ( ; optind < argc; optind++ )
- {
- cmdline_applist.push_back( argv[ optind ] );
+ for (; optind < argc; optind++) {
+ cmdline_applist.push_back(argv[optind]);
}
parse_ignore_dirs_file();
- if ( g_verbose > 1 )
- {
- printf( "%lu ignore_dirs:\n", ignore_dirs.size() );
+ if (g_verbose > 1) {
+ printf("%lu ignore_dirs:\n", ignore_dirs.size());
- for ( std::string &dname : ignore_dirs )
- {
- printf( " '%s'\n", dname.c_str() );
+ for (std::string& dname : ignore_dirs) {
+ printf(" '%s'\n", dname.c_str());
}
}
}
static void print_separator()
{
- printf( "%s%s%s\n", YELLOW, std::string( 78, '-' ).c_str(), RESET );
+ printf("%s%s%s\n", YELLOW, std::string(78, '-').c_str(), RESET);
}
-int main( int argc, char *argv[] )
+int main(int argc, char* argv[])
{
- std::vector< std::string > cmdline_applist;
- std::vector< procinfo_t > inotify_proclist;
+ std::vector<std::string> cmdline_applist;
+ std::vector<procinfo_t> inotify_proclist;
- struct lconv *env = localeconv();
- if (env && env->thousands_sep && env->thousands_sep[0])
- {
+ struct lconv* env = localeconv();
+ if (env && env->thousands_sep && env->thousands_sep[0]) {
thousands_sep = env->thousands_sep[0];
}
- parse_cmdline( argc, argv, cmdline_applist );
+ parse_cmdline(argc, argv, cmdline_applist);
print_separator();
print_inotify_limits();
print_separator();
- if ( init_inotify_proclist( inotify_proclist ) )
- {
+ if (init_inotify_proclist(inotify_proclist)) {
uint32_t total_watches = 0;
uint32_t total_instances = 0;
- std::vector< filename_info_t > all_found_files;
+ std::vector<filename_info_t> all_found_files;
- for ( procinfo_t &procinfo : inotify_proclist )
- {
- procinfo.in_cmd_line = is_proc_in_cmdline_applist( procinfo, cmdline_applist );
+ for (procinfo_t& procinfo : inotify_proclist) {
+ procinfo.in_cmd_line = is_proc_in_cmdline_applist(procinfo, cmdline_applist);
total_watches += procinfo.watches;
total_instances += procinfo.instances;
}
if (inotify_proclist.size()) {
- print_inotify_proclist( inotify_proclist );
+ print_inotify_proclist(inotify_proclist);
print_separator();
}
if (g_kernel_provides_watches_info)
- printf( "Total inotify Watches: %s%u%s\n", BGREEN, total_watches, RESET );
- printf( "Total inotify Instances: %s%u%s\n", BGREEN, total_instances, RESET );
+ printf("Total inotify Watches: %s%u%s\n", BGREEN, total_watches, RESET);
+ printf("Total inotify Instances: %s%u%s\n", BGREEN, total_instances, RESET);
print_separator();
double search_time = gettime();
- uint32_t total_scanned_dirs = find_files_in_inode_set( inotify_proclist, all_found_files );
- if ( total_scanned_dirs )
- {
+ uint32_t total_scanned_dirs = find_files_in_inode_set(inotify_proclist, all_found_files);
+ if (total_scanned_dirs) {
search_time = gettime() - search_time;
- for ( const filename_info_t &fname_info : all_found_files )
- {
- printf( "%s%9lu%s [%u:%u] %s\n", BGREEN, fname_info.inode, RESET,
- major( fname_info.dev ), minor( fname_info.dev ),
- fname_info.filename.c_str() );
+ for (const filename_info_t& fname_info : all_found_files) {
+ printf("%s%9lu%s [%u:%u] %s\n", BGREEN, fname_info.inode, RESET,
+ major(fname_info.dev), minor(fname_info.dev),
+ fname_info.filename.c_str());
}
- setlocale( LC_NUMERIC, "" );
-GCC_DIAG_PUSH_OFF( format )
- printf( "\n%'u dirs scanned (%.2f seconds)\n", total_scanned_dirs, search_time );
-GCC_DIAG_POP()
+ setlocale(LC_NUMERIC, "");
+ GCC_DIAG_PUSH_OFF(format)
+ printf("\n%'u dirs scanned (%.2f seconds)\n", total_scanned_dirs, search_time);
+ GCC_DIAG_POP()
}
}
diff --git a/inotify-info.h b/inotify-info.h
index fe42811..095da7a 100644
--- a/inotify-info.h
+++ b/inotify-info.h
@@ -22,39 +22,38 @@
* THE SOFTWARE.
*/
-#define RESET "\x1b[0m"
-#define GRAY "\x1b[0;30m"
-#define RED "\x1b[0;31m"
-#define GREEN "\x1b[0;32m"
-#define YELLOW "\x1b[0;33m"
-#define BLUE "\x1b[0;34m"
-#define MAGENTA "\x1b[0;35m"
-#define CYAN "\x1b[0;36m"
-#define WHITE "\x1b[0;37m"
-#define BGRAY "\x1b[1;30m"
-#define BRED "\x1b[1;31m"
-#define BGREEN "\x1b[1;32m"
-#define BYELLOW "\x1b[1;33m"
-#define BBLUE "\x1b[1;34m"
+#define RESET "\x1b[0m"
+#define GRAY "\x1b[0;30m"
+#define RED "\x1b[0;31m"
+#define GREEN "\x1b[0;32m"
+#define YELLOW "\x1b[0;33m"
+#define BLUE "\x1b[0;34m"
+#define MAGENTA "\x1b[0;35m"
+#define CYAN "\x1b[0;36m"
+#define WHITE "\x1b[0;37m"
+#define BGRAY "\x1b[1;30m"
+#define BRED "\x1b[1;31m"
+#define BGREEN "\x1b[1;32m"
+#define BYELLOW "\x1b[1;33m"
+#define BBLUE "\x1b[1;34m"
#define BMAGENTA "\x1b[1;35m"
-#define BCYAN "\x1b[1;36m"
-#define BWHITE "\x1b[1;37m"
+#define BCYAN "\x1b[1;36m"
+#define BWHITE "\x1b[1;37m"
-#define TO_STR( x ) #x
-#define TO_STR_VALUE( x ) TO_STR( x )
+#define TO_STR(x) #x
+#define TO_STR_VALUE(x) TO_STR(x)
-#define ATTRIBUTE_PRINTF( _x, _y ) __attribute__( ( __format__( __printf__, _x, _y ) ) )
+#define ATTRIBUTE_PRINTF(_x, _y) __attribute__((__format__(__printf__, _x, _y)))
-#define GCC_DIAG_STR( s ) #s
-#define GCC_DIAG_JOINSTR( x, y ) GCC_DIAG_STR( x##y )
-#define GCC_DIAG_DO_PRAGMA( x ) _Pragma( #x )
-#define GCC_DIAG_PRAGMA( x ) GCC_DIAG_DO_PRAGMA( GCC diagnostic x )
+#define GCC_DIAG_STR(s) #s
+#define GCC_DIAG_JOINSTR(x, y) GCC_DIAG_STR(x##y)
+#define GCC_DIAG_DO_PRAGMA(x) _Pragma(#x)
+#define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
-#define GCC_DIAG_PUSH_OFF( x ) \
- GCC_DIAG_PRAGMA( push ) \
- GCC_DIAG_PRAGMA( ignored GCC_DIAG_JOINSTR( -W, x ) )
-#define GCC_DIAG_POP() GCC_DIAG_PRAGMA( pop )
-
-std::string string_formatv(const char *fmt, va_list ap) ATTRIBUTE_PRINTF(1, 0);
-std::string string_format(const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2);
+#define GCC_DIAG_PUSH_OFF(x) \
+ GCC_DIAG_PRAGMA(push) \
+ GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W, x))
+#define GCC_DIAG_POP() GCC_DIAG_PRAGMA(pop)
+std::string string_formatv(const char* fmt, va_list ap) ATTRIBUTE_PRINTF(1, 0);
+std::string string_format(const char* fmt, ...) ATTRIBUTE_PRINTF(1, 2);
diff --git a/lfqueue/lfqueue.c b/lfqueue/lfqueue.c
index 17b8ae3..63a7aa8 100644
--- a/lfqueue/lfqueue.c
+++ b/lfqueue/lfqueue.c
@@ -1,40 +1,40 @@
/*
-*
-* BSD 2-Clause License
-*
-* Copyright (c) 2018, Taymindis Woon
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are met:
-*
-* * Redistributions of source code must retain the above copyright notice, this
-* list of conditions and the following disclaimer.
-*
-* * Redistributions in binary form must reproduce the above copyright notice,
-* this list of conditions and the following disclaimer in the documentation
-* and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
-*/
+ *
+ * BSD 2-Clause License
+ *
+ * Copyright (c) 2018, Taymindis Woon
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-#include <errno.h>
#if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
+#include <sched.h>
#include <sys/time.h>
#include <unistd.h> // for usleep
-#include <sched.h>
#define __LFQ_VAL_COMPARE_AND_SWAP __sync_val_compare_and_swap
#define __LFQ_BOOL_COMPARE_AND_SWAP __sync_bool_compare_and_swap
@@ -48,13 +48,14 @@
#include <Windows.h>
#include <time.h>
#ifdef _WIN64
-inline BOOL __SYNC_BOOL_CAS(LONG64 volatile *dest, LONG64 input, LONG64 comparand) {
- return InterlockedCompareExchangeNoFence64(dest, input, comparand) == comparand;
+inline BOOL __SYNC_BOOL_CAS(LONG64 volatile* dest, LONG64 input, LONG64 comparand)
+{
+ return InterlockedCompareExchangeNoFence64(dest, input, comparand) == comparand;
}
#define __LFQ_VAL_COMPARE_AND_SWAP(dest, comparand, input) \
- InterlockedCompareExchangeNoFence64((LONG64 volatile *)dest, (LONG64)input, (LONG64)comparand)
+ InterlockedCompareExchangeNoFence64((LONG64 volatile*)dest, (LONG64)input, (LONG64)comparand)
#define __LFQ_BOOL_COMPARE_AND_SWAP(dest, comparand, input) \
- __SYNC_BOOL_CAS((LONG64 volatile *)dest, (LONG64)input, (LONG64)comparand)
+ __SYNC_BOOL_CAS((LONG64 volatile*)dest, (LONG64)input, (LONG64)comparand)
#define __LFQ_FETCH_AND_ADD InterlockedExchangeAddNoFence64
#define __LFQ_ADD_AND_FETCH InterlockedAddNoFence64
#define __LFQ_SYNC_MEMORY MemoryBarrier
@@ -63,13 +64,14 @@ inline BOOL __SYNC_BOOL_CAS(LONG64 volatile *dest, LONG64 input, LONG64 comparan
#ifndef asm
#define asm __asm
#endif
-inline BOOL __SYNC_BOOL_CAS(LONG volatile *dest, LONG input, LONG comparand) {
- return InterlockedCompareExchangeNoFence(dest, input, comparand) == comparand;
+inline BOOL __SYNC_BOOL_CAS(LONG volatile* dest, LONG input, LONG comparand)
+{
+ return InterlockedCompareExchangeNoFence(dest, input, comparand) == comparand;
}
#define __LFQ_VAL_COMPARE_AND_SWAP(dest, comparand, input) \
- InterlockedCompareExchangeNoFence((LONG volatile *)dest, (LONG)input, (LONG)comparand)
+ InterlockedCompareExchangeNoFence((LONG volatile*)dest, (LONG)input, (LONG)comparand)
#define __LFQ_BOOL_COMPARE_AND_SWAP(dest, comparand, input) \
- __SYNC_BOOL_CAS((LONG volatile *)dest, (LONG)input, (LONG)comparand)
+ __SYNC_BOOL_CAS((LONG volatile*)dest, (LONG)input, (LONG)comparand)
#define __LFQ_FETCH_AND_ADD InterlockedExchangeAddNoFence
#define __LFQ_ADD_AND_FETCH InterlockedAddNoFence
#define __LFQ_SYNC_MEMORY() asm mfence
@@ -85,9 +87,9 @@ inline BOOL __SYNC_BOOL_CAS(LONG volatile *dest, LONG input, LONG comparand) {
#if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
#define lfq_time_t long
#define lfq_get_curr_time(_time_sec) \
-struct timeval _time_; \
-gettimeofday(&_time_, NULL); \
-*_time_sec = _time_.tv_sec
+ struct timeval _time_; \
+ gettimeofday(&_time_, NULL); \
+ *_time_sec = _time_.tv_sec
#define lfq_diff_time(_etime_, _stime_) _etime_ - _stime_
#else
#define lfq_time_t time_t
@@ -96,281 +98,285 @@ gettimeofday(&_time_, NULL); \
#endif
struct lfqueue_cas_node_s {
- void * value;
- struct lfqueue_cas_node_s *next, *nextfree;
- lfq_time_t _deactivate_tm;
+ void* value;
+ struct lfqueue_cas_node_s *next, *nextfree;
+ lfq_time_t _deactivate_tm;
};
-//static lfqueue_cas_node_t* __lfq_assigned(lfqueue_t *);
-static void __lfq_recycle_free(lfqueue_t *, lfqueue_cas_node_t*);
-static void __lfq_check_free(lfqueue_t *);
-static void *_dequeue(lfqueue_t *);
-static void *_single_dequeue(lfqueue_t *);
-static int _enqueue(lfqueue_t *, void* );
-static inline void* _lfqueue_malloc(__attribute__ ((unused)) void* pl, size_t sz) {
- return malloc(sz);
+// static lfqueue_cas_node_t* __lfq_assigned(lfqueue_t *);
+static void __lfq_recycle_free(lfqueue_t*, lfqueue_cas_node_t*);
+static void __lfq_check_free(lfqueue_t*);
+static void* _dequeue(lfqueue_t*);
+static void* _single_dequeue(lfqueue_t*);
+static int _enqueue(lfqueue_t*, void*);
+static inline void* _lfqueue_malloc(__attribute__((unused)) void* pl, size_t sz)
+{
+ return malloc(sz);
}
-static inline void _lfqueue_free(__attribute__ ((unused)) void* pl, void* ptr) {
- free(ptr);
+static inline void _lfqueue_free(__attribute__((unused)) void* pl, void* ptr)
+{
+ free(ptr);
}
-static void *
-_dequeue(lfqueue_t *lfqueue) {
- lfqueue_cas_node_t *head, *next;
- void *val;
-
- for (;;) {
- head = lfqueue->head;
- if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, head)) {
- next = head->next;
- if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->tail, head, head)) {
- if (next == NULL) {
- val = NULL;
- goto _done;
- }
- }
- else {
- if (next) {
- val = next->value;
- if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) {
- break;
- }
- } else {
- val = NULL;
- goto _done;
- }
- }
- }
- }
-
- __lfq_recycle_free(lfqueue, head);
+static void*
+_dequeue(lfqueue_t* lfqueue)
+{
+ lfqueue_cas_node_t *head, *next;
+ void* val;
+
+ for (;;) {
+ head = lfqueue->head;
+ if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, head)) {
+ next = head->next;
+ if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->tail, head, head)) {
+ if (next == NULL) {
+ val = NULL;
+ goto _done;
+ }
+ } else {
+ if (next) {
+ val = next->value;
+ if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) {
+ break;
+ }
+ } else {
+ val = NULL;
+ goto _done;
+ }
+ }
+ }
+ }
+
+ __lfq_recycle_free(lfqueue, head);
_done:
- // __asm volatile("" ::: "memory");
- __LFQ_SYNC_MEMORY();
- __lfq_check_free(lfqueue);
- return val;
+ // __asm volatile("" ::: "memory");
+ __LFQ_SYNC_MEMORY();
+ __lfq_check_free(lfqueue);
+ return val;
}
-static void *
-_single_dequeue(lfqueue_t *lfqueue) {
- lfqueue_cas_node_t *head, *next;
- void *val;
-
- for (;;) {
- head = lfqueue->head;
- if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, head)) {
- next = head->next;
- if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->tail, head, head)) {
- if (next == NULL) {
- return NULL;
- }
- }
- else {
- if (next) {
- val = next->value;
- if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) {
- lfqueue->_free(lfqueue->pl, head);
- break;
- }
- } else {
- return NULL;
- }
- }
- }
- }
- return val;
+static void*
+_single_dequeue(lfqueue_t* lfqueue)
+{
+ lfqueue_cas_node_t *head, *next;
+ void* val;
+
+ for (;;) {
+ head = lfqueue->head;
+ if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, head)) {
+ next = head->next;
+ if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->tail, head, head)) {
+ if (next == NULL) {
+ return NULL;
+ }
+ } else {
+ if (next) {
+ val = next->value;
+ if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) {
+ lfqueue->_free(lfqueue->pl, head);
+ break;
+ }
+ } else {
+ return NULL;
+ }
+ }
+ }
+ }
+ return val;
}
static int
-_enqueue(lfqueue_t *lfqueue, void* value) {
- lfqueue_cas_node_t *tail, *node;
- node = (lfqueue_cas_node_t*) lfqueue->_malloc(lfqueue->pl, sizeof(lfqueue_cas_node_t));
- if (node == NULL) {
- perror("malloc");
- return errno;
- }
- node->value = value;
- node->next = NULL;
- node->nextfree = NULL;
- for (;;) {
- __LFQ_SYNC_MEMORY();
- tail = lfqueue->tail;
- if (__LFQ_BOOL_COMPARE_AND_SWAP(&tail->next, NULL, node)) {
- // compulsory swap as tail->next is no NULL anymore, it has fenced on other thread
- __LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->tail, tail, node);
- __lfq_check_free(lfqueue);
- return 0;
- }
- }
-
- /*It never be here*/
- return -1;
+_enqueue(lfqueue_t* lfqueue, void* value)
+{
+ lfqueue_cas_node_t *tail, *node;
+ node = (lfqueue_cas_node_t*)lfqueue->_malloc(lfqueue->pl, sizeof(lfqueue_cas_node_t));
+ if (node == NULL) {
+ perror("malloc");
+ return errno;
+ }
+ node->value = value;
+ node->next = NULL;
+ node->nextfree = NULL;
+ for (;;) {
+ __LFQ_SYNC_MEMORY();
+ tail = lfqueue->tail;
+ if (__LFQ_BOOL_COMPARE_AND_SWAP(&tail->next, NULL, node)) {
+ // compulsory swap as tail->next is no NULL anymore, it has fenced on other thread
+ __LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->tail, tail, node);
+ __lfq_check_free(lfqueue);
+ return 0;
+ }
+ }
+
+ /*It never be here*/
+ return -1;
}
static void
-__lfq_recycle_free(lfqueue_t *lfqueue, lfqueue_cas_node_t* freenode) {
- lfqueue_cas_node_t *freed;
- do {
- freed = lfqueue->move_free;
- } while (!__LFQ_BOOL_COMPARE_AND_SWAP(&freed->nextfree, NULL, freenode) );
+__lfq_recycle_free(lfqueue_t* lfqueue, lfqueue_cas_node_t* freenode)
+{
+ lfqueue_cas_node_t* freed;
+ do {
+ freed = lfqueue->move_free;
+ } while (!__LFQ_BOOL_COMPARE_AND_SWAP(&freed->nextfree, NULL, freenode));
- lfq_get_curr_time(&freenode->_deactivate_tm);
+ lfq_get_curr_time(&freenode->_deactivate_tm);
- __LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->move_free, freed, freenode);
+ __LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->move_free, freed, freenode);
}
static void
-__lfq_check_free(lfqueue_t *lfqueue) {
- lfq_time_t curr_time;
- if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->in_free_mode, 0, 1)) {
- lfq_get_curr_time(&curr_time);
- lfqueue_cas_node_t *rtfree = lfqueue->root_free, *nextfree;
- while ( rtfree && (rtfree != lfqueue->move_free) ) {
- nextfree = rtfree->nextfree;
- if ( lfq_diff_time(curr_time, rtfree->_deactivate_tm) > 2) {
- // printf("%p\n", rtfree);
- lfqueue->_free(lfqueue->pl, rtfree);
- rtfree = nextfree;
- } else {
- break;
- }
- }
- lfqueue->root_free = rtfree;
- __LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->in_free_mode, 1, 0);
- }
- __LFQ_SYNC_MEMORY();
+__lfq_check_free(lfqueue_t* lfqueue)
+{
+ lfq_time_t curr_time;
+ if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->in_free_mode, 0, 1)) {
+ lfq_get_curr_time(&curr_time);
+ lfqueue_cas_node_t *rtfree = lfqueue->root_free, *nextfree;
+ while (rtfree && (rtfree != lfqueue->move_free)) {
+ nextfree = rtfree->nextfree;
+ if (lfq_diff_time(curr_time, rtfree->_deactivate_tm) > 2) {
+ // printf("%p\n", rtfree);
+ lfqueue->_free(lfqueue->pl, rtfree);
+ rtfree = nextfree;
+ } else {
+ break;
+ }
+ }
+ lfqueue->root_free = rtfree;
+ __LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->in_free_mode, 1, 0);
+ }
+ __LFQ_SYNC_MEMORY();
}
-int
-lfqueue_init(lfqueue_t *lfqueue) {
- return lfqueue_init_mf(lfqueue, NULL, _lfqueue_malloc, _lfqueue_free);
+int lfqueue_init(lfqueue_t* lfqueue)
+{
+ return lfqueue_init_mf(lfqueue, NULL, _lfqueue_malloc, _lfqueue_free);
}
-int
-lfqueue_init_mf(lfqueue_t *lfqueue, void* pl, lfqueue_malloc_fn lfqueue_malloc, lfqueue_free_fn lfqueue_free) {
- lfqueue->_malloc = lfqueue_malloc;
- lfqueue->_free = lfqueue_free;
- lfqueue->pl = pl;
-
- lfqueue_cas_node_t *base = lfqueue_malloc(pl, sizeof(lfqueue_cas_node_t));
- lfqueue_cas_node_t *freebase = lfqueue_malloc(pl, sizeof(lfqueue_cas_node_t));
- if (base == NULL || freebase == NULL) {
- perror("malloc");
- return errno;
- }
- base->value = NULL;
- base->next = NULL;
- base->nextfree = NULL;
- base->_deactivate_tm = 0;
-
- freebase->value = NULL;
- freebase->next = NULL;
- freebase->nextfree = NULL;
- freebase->_deactivate_tm = 0;
-
- lfqueue->head = lfqueue->tail = base; // Not yet to be free for first node only
- lfqueue->root_free = lfqueue->move_free = freebase; // Not yet to be free for first node only
- lfqueue->size = 0;
- lfqueue->in_free_mode = 0;
-
- return 0;
+int lfqueue_init_mf(lfqueue_t* lfqueue, void* pl, lfqueue_malloc_fn lfqueue_malloc, lfqueue_free_fn lfqueue_free)
+{
+ lfqueue->_malloc = lfqueue_malloc;
+ lfqueue->_free = lfqueue_free;
+ lfqueue->pl = pl;
+
+ lfqueue_cas_node_t* base = lfqueue_malloc(pl, sizeof(lfqueue_cas_node_t));
+ lfqueue_cas_node_t* freebase = lfqueue_malloc(pl, sizeof(lfqueue_cas_node_t));
+ if (base == NULL || freebase == NULL) {
+ perror("malloc");
+ return errno;
+ }
+ base->value = NULL;
+ base->next = NULL;
+ base->nextfree = NULL;
+ base->_deactivate_tm = 0;
+
+ freebase->value = NULL;
+ freebase->next = NULL;
+ freebase->nextfree = NULL;
+ freebase->_deactivate_tm = 0;
+
+ lfqueue->head = lfqueue->tail = base; // Not yet to be free for first node only
+ lfqueue->root_free = lfqueue->move_free = freebase; // Not yet to be free for first node only
+ lfqueue->size = 0;
+ lfqueue->in_free_mode = 0;
+
+ return 0;
}
-void
-lfqueue_destroy(lfqueue_t *lfqueue) {
- void* p;
- while ((p = lfqueue_deq(lfqueue))) {
- lfqueue->_free(lfqueue->pl, p);
- }
- // Clear the recycle chain nodes
- lfqueue_cas_node_t *rtfree = lfqueue->root_free, *nextfree;
- while (rtfree && (rtfree != lfqueue->move_free) ) {
- nextfree = rtfree->nextfree;
- lfqueue->_free(lfqueue->pl, rtfree);
- rtfree = nextfree;
- }
- if (rtfree) {
- lfqueue->_free(lfqueue->pl, rtfree);
- }
-
- lfqueue->_free(lfqueue->pl, lfqueue->tail); // Last free
-
- lfqueue->size = 0;
+void lfqueue_destroy(lfqueue_t* lfqueue)
+{
+ void* p;
+ while ((p = lfqueue_deq(lfqueue))) {
+ lfqueue->_free(lfqueue->pl, p);
+ }
+ // Clear the recycle chain nodes
+ lfqueue_cas_node_t *rtfree = lfqueue->root_free, *nextfree;
+ while (rtfree && (rtfree != lfqueue->move_free)) {
+ nextfree = rtfree->nextfree;
+ lfqueue->_free(lfqueue->pl, rtfree);
+ rtfree = nextfree;
+ }
+ if (rtfree) {
+ lfqueue->_free(lfqueue->pl, rtfree);
+ }
+
+ lfqueue->_free(lfqueue->pl, lfqueue->tail); // Last free
+
+ lfqueue->size = 0;
}
-int
-lfqueue_enq(lfqueue_t *lfqueue, void *value) {
- if (_enqueue(lfqueue, value)) {
- return -1;
- }
- __LFQ_ADD_AND_FETCH(&lfqueue->size, 1);
- return 0;
+int lfqueue_enq(lfqueue_t* lfqueue, void* value)
+{
+ if (_enqueue(lfqueue, value)) {
+ return -1;
+ }
+ __LFQ_ADD_AND_FETCH(&lfqueue->size, 1);
+ return 0;
}
-void*
-lfqueue_deq(lfqueue_t *lfqueue) {
- void *v;
- if (//__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) &&
- (v = _dequeue(lfqueue))
- ) {
-
- __LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
- return v;
- }
- return NULL;
+void* lfqueue_deq(lfqueue_t* lfqueue)
+{
+ void* v;
+ if ( //__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) &&
+ (v = _dequeue(lfqueue))) {
+
+ __LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
+ return v;
+ }
+ return NULL;
}
-void*
-lfqueue_deq_must(lfqueue_t *lfqueue) {
- void *v;
- while ( !(v = _dequeue(lfqueue)) ) {
- // Rest the thread for other thread, to avoid keep looping force
- lfqueue_sleep(1);
- }
- __LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
- return v;
+void* lfqueue_deq_must(lfqueue_t* lfqueue)
+{
+ void* v;
+ while (!(v = _dequeue(lfqueue))) {
+ // Rest the thread for other thread, to avoid keep looping force
+ lfqueue_sleep(1);
+ }
+ __LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
+ return v;
}
/**This is only applicable when only single thread consume only**/
-void*
-lfqueue_single_deq(lfqueue_t *lfqueue) {
- void *v;
- if (//__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) &&
- (v = _single_dequeue(lfqueue))
- ) {
-
- __LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
- return v;
- }
- return NULL;
+void* lfqueue_single_deq(lfqueue_t* lfqueue)
+{
+ void* v;
+ if ( //__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) &&
+ (v = _single_dequeue(lfqueue))) {
+
+ __LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
+ return v;
+ }
+ return NULL;
}
/**This is only applicable when only single thread consume only**/
-void*
-lfqueue_single_deq_must(lfqueue_t *lfqueue) {
- void *v;
- while ( !(v = _single_dequeue(lfqueue)) ) {
- // Rest the thread for other thread, to avoid keep looping force
- lfqueue_sleep(1);
- }
- __LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
- return v;
+void* lfqueue_single_deq_must(lfqueue_t* lfqueue)
+{
+ void* v;
+ while (!(v = _single_dequeue(lfqueue))) {
+ // Rest the thread for other thread, to avoid keep looping force
+ lfqueue_sleep(1);
+ }
+ __LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
+ return v;
}
size_t
-lfqueue_size(lfqueue_t *lfqueue) {
- return __LFQ_ADD_AND_FETCH(&lfqueue->size, 0);
+lfqueue_size(lfqueue_t* lfqueue)
+{
+ return __LFQ_ADD_AND_FETCH(&lfqueue->size, 0);
}
-void
-lfqueue_sleep(unsigned int milisec) {
+void lfqueue_sleep(unsigned int milisec)
+{
#if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
- usleep(milisec * 1000);
+ usleep(milisec * 1000);
#pragma GCC diagnostic pop
#else
- Sleep(milisec);
+ Sleep(milisec);
#endif
}
diff --git a/lfqueue/lfqueue.h b/lfqueue/lfqueue.h
index 1eafc7b..a99147a 100644
--- a/lfqueue/lfqueue.h
+++ b/lfqueue/lfqueue.h
@@ -1,38 +1,38 @@
/*
-*
-* BSD 2-Clause License
-*
-* Copyright (c) 2018, Taymindis Woon
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are met:
-*
-* * Redistributions of source code must retain the above copyright notice, this
-* list of conditions and the following disclaimer.
-*
-* * Redistributions in binary form must reproduce the above copyright notice,
-* this list of conditions and the following disclaimer in the documentation
-* and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
-*/
+ *
+ * BSD 2-Clause License
+ *
+ * Copyright (c) 2018, Taymindis Woon
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
#ifndef LFQUEUE_H
#define LFQUEUE_H
-#include <stdlib.h>
#include <stdint.h>
+#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
@@ -53,32 +53,30 @@ typedef void (*lfqueue_free_fn)(void*, void*);
#endif
typedef struct {
- lfqueue_cas_node_t *head, *tail, *root_free, *move_free;
- volatile size_t size;
- volatile lfq_bool_t in_free_mode;
- lfqueue_malloc_fn _malloc;
- lfqueue_free_fn _free;
- void *pl;
+ lfqueue_cas_node_t *head, *tail, *root_free, *move_free;
+ volatile size_t size;
+ volatile lfq_bool_t in_free_mode;
+ lfqueue_malloc_fn _malloc;
+ lfqueue_free_fn _free;
+ void* pl;
} lfqueue_t;
-extern int lfqueue_init(lfqueue_t *lfqueue);
-extern int lfqueue_init_mf(lfqueue_t *lfqueue, void* pl, lfqueue_malloc_fn lfqueue_malloc, lfqueue_free_fn lfqueue_free);
-extern int lfqueue_enq(lfqueue_t *lfqueue, void *value);
-extern void* lfqueue_deq(lfqueue_t *lfqueue);
-extern void* lfqueue_single_deq(lfqueue_t *lfqueue);
+extern int lfqueue_init(lfqueue_t* lfqueue);
+extern int lfqueue_init_mf(lfqueue_t* lfqueue, void* pl, lfqueue_malloc_fn lfqueue_malloc, lfqueue_free_fn lfqueue_free);
+extern int lfqueue_enq(lfqueue_t* lfqueue, void* value);
+extern void* lfqueue_deq(lfqueue_t* lfqueue);
+extern void* lfqueue_single_deq(lfqueue_t* lfqueue);
/** loop until value been dequeue, it sleeps 1ms if not found to reduce cpu high usage **/
-extern void* lfqueue_deq_must(lfqueue_t *lfqueue);
-extern void* lfqueue_single_deq_must(lfqueue_t *lfqueue);
+extern void* lfqueue_deq_must(lfqueue_t* lfqueue);
+extern void* lfqueue_single_deq_must(lfqueue_t* lfqueue);
-extern void lfqueue_destroy(lfqueue_t *lfqueue);
-extern size_t lfqueue_size(lfqueue_t *lfqueue);
+extern void lfqueue_destroy(lfqueue_t* lfqueue);
+extern size_t lfqueue_size(lfqueue_t* lfqueue);
extern void lfqueue_sleep(unsigned int milisec);
-
#ifdef __cplusplus
}
#endif
#endif
-