1
0
Fork 0

Compare commits

..

No commits in common. "45f455831ceb4899ab9e4053b18b10475f40c910" and "7fd6727a6e00762a1c618b4ec9f89d0d5b739ea4" have entirely different histories.

18 changed files with 888 additions and 826 deletions

View file

@ -1,2 +0,0 @@
_release
_debug

View file

@ -9,14 +9,6 @@ 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:
@ -24,35 +16,29 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: {fetch-depth: 0}
- run: sudo apt-get install -y build-essential
- run: make VERBOSE=1 CFG=${{ matrix.cfg}} -j$(nproc)
- run: |
_${{ matrix.cfg }}/inotify-info --version
_${{ matrix.cfg }}/inotify-info
- run: make CFG=${{ matrix.cfg}} -j$(nproc)
- run: _${{ matrix.cfg }}/inotify-info
build-with-zig:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: {fetch-depth: 0}
- uses: actions/cache@v4
with:
key: zig-sdk-and-cache-${{ hashFiles('.github/workflows/ci.yaml') }}
path: ~/.cache/zig
- run: |
wget --progress=dot:mega \
https://ziglang.org/download/0.13.0/zig-linux-$(uname -m)-0.13.0.tar.xz
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-sdk
- run: |
make VERBOSE=1 -j$(nproc) \
make -j$(nproc) \
CC="zig-sdk/zig cc -target $(uname -m)-linux-musl" \
CXX="zig-sdk/zig c++ -target $(uname -m)-linux-musl"
- run: |
_release/inotify-info --version
_release/inotify-info
- run: _release/inotify-info
build-with-docker:
runs-on: ubuntu-latest

View file

@ -8,10 +8,15 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Archive
run: make inotify-info-${{ github.ref_name }}.tar.gz
- name: Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/v')
with:
files: inotify-info-${{ github.ref_name }}.tar.gz
generate_release_notes: true
draft: true
prerelease: true

2
.gitignore vendored
View file

@ -1,4 +1,4 @@
_debug/
_release/
/inotify-info-*.tar.gz
/inotify-info-v*.tar.gz

View file

@ -1,14 +1,23 @@
FROM alpine:edge
FROM alpine
RUN apk add make zig git
# 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
WORKDIR inotify-info
COPY . .
RUN CC="zig cc -target $(uname -m)-linux-musl" \
CXX="zig c++ -target $(uname -m)-linux-musl" \
make VERBOSE=1
RUN CC="/zig/zig cc -target $(uname -m)-linux-musl" \
CXX="/zig/zig c++ -target $(uname -m)-linux-musl" \
make
FROM scratch
COPY --from=0 /inotify-info/_release/inotify-info /inotify-info

View file

@ -20,16 +20,11 @@ ifeq ($(CFG), debug)
ASAN ?= 1
endif
PREFIX ?= /usr/local
BINDIR := $(PREFIX)/bin
LD = $(CC)
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
@ -38,15 +33,10 @@ ifneq ($(COMPILER),clang)
WARNINGS += -Wsuggest-attribute=format -Wall
endif
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
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
LIBS = -Wl,--no-as-needed -lm -ldl -lpthread -lstdc++
CFILES = \
@ -69,7 +59,6 @@ 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
@ -83,6 +72,7 @@ else
endif
PROJ = $(ODIR)/$(NAME)
$(info Building $(ODIR)/$(NAME)...)
ifeq ($(VERBOSE), 1)
VERBOSE_PREFIX=
@ -104,16 +94,12 @@ $(ODIR)/$(NAME): $(OBJS)
$(ODIR)/%.o: %.c Makefile
$(VERBOSE_PREFIX)echo "---- $< ----";
@$(MKDIR) $(dir $@)
$(VERBOSE_PREFIX)$(CC) -MMD -MP $(CFLAGS) -o $@ -c $<
$(VERBOSE_PREFIX)$(CC) -MMD -MP -std=gnu99 $(CFLAGS) -o $@ -c $<
$(ODIR)/%.o: %.cpp Makefile
$(VERBOSE_PREFIX)echo "---- $< ----";
@$(MKDIR) $(dir $@)
$(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
$(VERBOSE_PREFIX)$(CXX) -MMD -MP -std=c++11 $(CFLAGS) $(CXXFLAGS) -o $@ -c $<
.PHONY: clean
@ -124,18 +110,8 @@ clean:
$(VERBOSE_PREFIX)$(RM) $(OBJS:.o=.d)
$(VERBOSE_PREFIX)$(RM) $(OBJS:.o=.dwo)
.PHONY: install
install: all
install -D $(PROJ) $(BINDIR)/$(NAME)
.PHONY: uninstall
uninstall:
$(RM) $(BINDIR)/$(NAME)
define RELEASE_RULES
inotify-info-$(TAG).tar.gz:
git archive --prefix=inotify-info-$(TAG)/ v$(TAG) | gzip -n > $$@
git archive --prefix=inotify-info-$(TAG)/ $(TAG) | gzip -n > $$@
endef
$(foreach TAG,$(shell git tag 2>/dev/null | sed -n '/^v/ s/^v//p'),$(eval $(RELEASE_RULES)))
$(foreach TAG,$(shell git tag 2>/dev/null),$(eval $(RELEASE_RULES)))

View file

@ -22,11 +22,17 @@ Building _debug/inotify-info...
Linking _debug/inotify-info...
```
## Install
Or you can build Docker image.
The resulting executable will be at `_release/inotify-info`. You are free to
copy the resulting executable to any suitable location in your `$PATH` or run
`make install` to install to `/usr/local/bin`.
```sh
docker build . -t inotify-info
```
## Install
You are free to copy the resulting executable to any suitable location in your `$PATH`.
```
cp _release/inotify-info /usr/local/bin/
```
## Run (Prints Summary)
```
@ -154,16 +160,12 @@ Searching '/' for listed inodes... (8 threads)
94111468 [10304h] /home/mikesart/.cache/xfce4/xfce4-appfinder/
```
## Run on Docker/podman
## Run on Docker
```sh
docker build . -t inotify-info
docker run --rm --privileged -v /proc:/proc inotify-info
```
When running under [podman][podman] non-root mode, append `--ulimit
nofile=65535:65535` to the `podman build` command.
## Run on Nix(OS)
```
@ -179,4 +181,3 @@ nix run nixpkgs#inotify-info
[problem2]: https://unix.stackexchange.com/questions/15509/whos-consuming-my-inotify-resources
[lfqueue]: https://github.com/Taymindis/lfqueue
[bsd]: https://github.com/Taymindis/lfqueue/blob/master/LICENSE
[podman]: https://podman.io/

20
debian/changelog vendored
View file

@ -1,23 +1,3 @@
inotify-info (0.0.3-1) sid; urgency=medium
* Uploading to sid.
* Merging upstream version 0.0.3.
* Removing manual debhelper install file, not needed anymore with new
upstream version.
* Enabling non-silent output during build.
-- Daniel Baumann <daniel.baumann@progress-linux.org> Sat, 13 Jul 2024 13:02:30 +0200
inotify-info (0.0.2-1) sid; urgency=medium
* Uploading to sid.
* Merging upstream version 0.0.2.
* Removing march.patch, not needed anymore.
* Removing dwz.patch, not needed anymore.
* Setting INOTIFYINFO_VERSION to debian package version.
-- Daniel Baumann <daniel.baumann@progress-linux.org> Mon, 03 Jun 2024 22:01:31 +0200
inotify-info (0.0.1-2) sid; urgency=medium
* Uploading to sid.

2
debian/copyright vendored
View file

@ -1,7 +1,7 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: inotify-info
Upstream-Contact: https://github.com/mikesart/inotify-info/issues
Source: https://github.com/mikesart/inotify-info/tags
Source: https://github.com/mikesart/inotify-info/releases
Files: *
Copyright: 2021 Michael Sartain <mikesart@fastmail.com>

1
debian/inotify-info.install vendored Normal file
View file

@ -0,0 +1 @@
_release/inotify-info /usr/bin

19
debian/patches/debian/0001-march.patch vendored Normal file
View file

@ -0,0 +1,19 @@
Author: Daniel Baumann <daniel.baumann@progress-linux.org>
Description: Building without -march=native (Closes: #1071076).
diff -Naurp inotify-info.orig/Makefile inotify-info/Makefile
--- inotify-info.orig/Makefile
+++ inotify-info/Makefile
@@ -33,10 +33,10 @@ ifneq ($(COMPILER),clang)
WARNINGS += -Wsuggest-attribute=format -Wall
endif
-CFLAGS = $(WARNINGS) -march=native -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames -gsplit-dwarf
+CFLAGS = $(WARNINGS) -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
+LDFLAGS = -gdwarf-4 -g2 -Wl,--build-id=sha1
LIBS = -Wl,--no-as-needed -lm -ldl -lpthread -lstdc++
CFILES = \

15
debian/patches/debian/0002-dwz.patch vendored Normal file
View file

@ -0,0 +1,15 @@
Author: Daniel Baumann <daniel.baumann@progress-linux.org>
Description: Building without -gsplit-dwarf to workaround bug in dwz causing FTBFS (#1016936).
diff -Naurp inotify-info.orig/Makefile inotify-info/Makefile
--- inotify-info.orig/Makefile
+++ inotify-info/Makefile
@@ -33,7 +33,7 @@ ifneq ($(COMPILER),clang)
WARNINGS += -Wsuggest-attribute=format -Wall
endif
-CFLAGS = $(WARNINGS) -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames -gsplit-dwarf
+CFLAGS = $(WARNINGS) -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames
CFLAGS += -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64
CXXFLAGS = -fno-rtti -Woverloaded-virtual
LDFLAGS = -gdwarf-4 -g2 -Wl,--build-id=sha1

2
debian/patches/series vendored Normal file
View file

@ -0,0 +1,2 @@
debian/0001-march.patch
debian/0002-dwz.patch

8
debian/rules vendored
View file

@ -1,15 +1,7 @@
#!/usr/bin/make -f
export INOTIFYINFO_VERSION = $(shell dpkg-parsechangelog -SVersion)
%:
dh ${@}
execute_after_dh_auto_clean:
rm -rf _release
override_dh_auto_build:
dh_auto_build -- VERBOSE=1
override_dh_auto_install:
dh_auto_install -- PREFIX=$(CURDIR)/debian/inotify-info/usr

View file

@ -24,38 +24,34 @@
#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 <unordered_map>
#include <unordered_set>
#include <vector>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>
#include "inotify-info.h"
#include "lfqueue/lfqueue.h"
#ifndef INOTIFYINFO_VERSION
#error INOTIFYINFO_VERSION must be set
#endif
/*
* TODO
* - Comments
@ -81,7 +77,8 @@ static std::vector<std::string> ignore_dirs;
/*
* filename info
*/
struct filename_info_t {
struct filename_info_t
{
ino64_t inode; // Inode number
dev_t dev; // Device ID containing file
std::string filename;
@ -90,7 +87,8 @@ struct filename_info_t {
/*
* inotify process info
*/
struct procinfo_t {
struct procinfo_t
{
pid_t pid = 0;
// uid
@ -116,7 +114,8 @@ struct procinfo_t {
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 ); }
@ -127,7 +126,8 @@ public:
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,7 +136,8 @@ 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 );
@ -150,12 +151,10 @@ public:
/*
* thread info
*/
class thread_info_t {
public:
thread_info_t(thread_shared_data_t& tdata_in)
: tdata(tdata_in)
class thread_info_t
{
}
public:
thread_info_t( thread_shared_data_t &tdata_in ) : tdata( tdata_in ) {}
~thread_info_t() {}
void queue_directory( char *path );
@ -182,7 +181,8 @@ public:
* getdents64 syscall
*/
GCC_DIAG_PUSH_OFF( pedantic )
struct linux_dirent64 {
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
@ -209,11 +209,13 @@ std::string string_formatv(const char* fmt, va_list ap)
std::string str;
int size = 512;
for (;;) {
for ( ;; )
{
str.resize( size );
int n = vsnprintf( ( char * )str.c_str(), size, fmt, ap );
if ((n > -1) && (n < size)) {
if ( ( n > -1 ) && ( n < size ) )
{
str.resize( n );
return str;
}
@ -240,7 +242,8 @@ static std::string get_link_name(const char* pathname)
char filename[ PATH_MAX + 1 ];
ssize_t ret = readlink( pathname, filename, sizeof( filename ) );
if ((ret > 0) && (ret < (ssize_t)sizeof(filename))) {
if ( ( ret > 0 ) && ( ret < ( ssize_t )sizeof( filename ) ) )
{
filename[ ret ] = 0;
Result = filename;
}
@ -251,7 +254,8 @@ static uid_t get_uid(const char* pathname)
{
int fd = open( pathname, O_RDONLY, 0 );
if (fd >= 0) {
if ( fd >= 0 )
{
char buf[ 16 * 1024 ];
ssize_t len = read( fd, buf, sizeof( buf ) );
@ -259,11 +263,13 @@ static uid_t get_uid(const char* pathname)
close( fd );
fd = -1;
if (len > 0) {
if ( len > 0 )
{
buf[ len - 1 ] = 0;
const char *uidstr = strstr( buf, "\nUid:" );
if (uidstr) {
if ( uidstr )
{
return atoll( uidstr + 5 );
}
}
@ -284,12 +290,14 @@ static uint32_t inotify_parse_fdinfo_file(procinfo_t& procinfo, const char* fdse
uint32_t watch_count = 0;
FILE *fp = fopen( fdset_name, "r" );
if (fp) {
if ( fp )
{
char line_buf[ 256 ];
procinfo.fdset_filenames.push_back( fdset_name );
for (;;) {
for ( ;; )
{
if ( !fgets( line_buf, sizeof( line_buf ), fp ) )
break;
@ -301,13 +309,15 @@ static uint32_t inotify_parse_fdinfo_file(procinfo_t& procinfo, const char* fdse
* 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:" );
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
@ -335,16 +345,19 @@ static void inotify_parse_fddir(procinfo_t& procinfo)
if ( !dir_fd )
return;
for (;;) {
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])) {
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") {
if ( filename == "anon_inode:inotify" || filename == "inotify" )
{
filename = string_format( "/proc/%d/fdinfo/%s", procinfo.pid, dp_fd->d_name );
procinfo.instances++;
@ -368,9 +381,11 @@ char* thread_info_t::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 )
break;
@ -388,8 +403,9 @@ 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 (%s)\n", filename, errno, strerror(errno));
if ( statx( 0, filename, flags, mask, &statxbuf ) == -1 )
{
printf( "ERROR: statx-ino( %s ) failed. Errno: %d\n", filename, errno );
memset( &statxbuf, 0, sizeof( statxbuf ) );
}
@ -417,8 +433,9 @@ 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 (%s)\n", filename, errno, strerror(errno));
if ( ret == -1 )
{
printf( "ERROR: stat-dev_t( %s ) failed. Errno: %d\n", filename, errno );
return 0;
}
return statbuf.st_dev;
@ -429,8 +446,9 @@ 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 (%s)\n", filename, errno, strerror(errno));
if ( ret == -1 )
{
printf( "ERROR: stat-ino( %s ) failed. Errno: %d\n", filename, errno );
return 0;
}
@ -443,14 +461,16 @@ void thread_info_t::add_filename(ino64_t inode, const char* path, const char* d_
{
auto it = tdata.inode_set.find( inode );
if (it != tdata.inode_set.end()) {
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() );
// 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;
@ -464,7 +484,8 @@ void thread_info_t::add_filename(ino64_t inode, const char* path, const char* d_
static bool is_dot_dir( const char *dname )
{
if (dname[0] == '.') {
if ( dname[ 0 ] == '.' )
{
if ( !dname[ 1 ] )
return true;
@ -490,8 +511,10 @@ static bool is_proc_dir(const char* path, const char* d_name)
struct statfs s;
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;
@ -507,13 +530,17 @@ int thread_info_t::parse_dirqueue_entry()
char __attribute__( ( aligned( 16 ) ) ) buf[ 1024 ];
char *path = dequeue_directory();
if (!path) {
if ( !path )
{
return -1;
}
for (std::string& dname : ignore_dirs) {
if (dname == path) {
if (g_verbose > 1) {
for ( std::string &dname : ignore_dirs )
{
if ( dname == path )
{
if ( g_verbose > 1 )
{
printf( "Ignoring '%s'\n", path );
}
return 0;
@ -521,7 +548,8 @@ int thread_info_t::parse_dirqueue_entry()
}
int fd = open( path, O_RDONLY | O_DIRECTORY, 0 );
if (fd < 0) {
if ( fd < 0 )
{
free( path );
return 0;
}
@ -530,27 +558,32 @@ int thread_info_t::parse_dirqueue_entry()
size_t pathlen = strlen( path );
for (;;) {
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 (%s)\n", path, ret, errno, strerror(errno));
if ( spew_error )
{
printf( "ERROR: sys_getdents64 failed on '%s': %d errno:%d\n", path, ret, errno );
}
break;
}
if ( ret == 0 )
break;
for (int bpos = 0; bpos < ret;) {
for ( int bpos = 0; bpos < ret; )
{
struct linux_dirent64 *dirp = ( struct linux_dirent64 * )( buf + bpos );
const char *d_name = dirp->d_name;
@ -562,18 +595,22 @@ 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) {
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)) {
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) {
if ( newpath )
{
strcpy( newpath, path );
strcpy( newpath + pathlen, d_name );
newpath[ pathlen + len ] = '/';
@ -597,7 +634,8 @@ static void* parse_dirqueue_threadproc(void* 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 )
break;
@ -608,7 +646,8 @@ static void* parse_dirqueue_threadproc(void* arg)
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() ) )
return true;
@ -626,21 +665,25 @@ static bool watch_count_is_greater(procinfo_t elem1, procinfo_t elem2)
return elem1.watches > elem2.watches;
}
static bool init_inotify_proclist( std::vector< procinfo_t > &inotify_proclist )
{
DIR *dir_proc = opendir( "/proc" );
if (!dir_proc) {
printf("ERROR: opendir /proc failed: %d (%s)\n", errno, strerror(errno));
if ( !dir_proc )
{
printf( "ERROR: opendir /proc failed: %d\n", errno );
return false;
}
for (;;) {
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 );
@ -649,12 +692,14 @@ static bool init_inotify_proclist(std::vector<procinfo_t>& inotify_proclist)
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()) {
if ( !procinfo.executable.empty() )
{
procinfo.appname = basename( (char*)procinfo.executable.c_str() );
inotify_parse_fddir( procinfo );
if (procinfo.instances) {
if ( procinfo.instances )
{
inotify_proclist.push_back( procinfo );
}
}
@ -670,7 +715,8 @@ static bool init_inotify_proclist(std::vector<procinfo_t>& inotify_proclist)
// 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 )
{
if (thousands_sep) {
if ( thousands_sep )
{
char src[16];
char *p_src = src;
char *p_dst = dst;
@ -678,7 +724,8 @@ size_t str_format_uint32(char dst[16], uint32_t num)
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 +786,9 @@ static void print_inotify_proclist(std::vector<procinfo_t>& inotify_proclist)
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);
@ -758,18 +807,23 @@ static void print_inotify_proclist(std::vector<procinfo_t>& inotify_proclist)
BYELLOW, lenApp, procinfo.appname.c_str(), RESET,
lenInstances, procinfo.instances );
if (g_verbose > 1) {
for (std::string& fname : procinfo.fdset_filenames) {
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) {
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 );
@ -782,20 +836,24 @@ static void print_inotify_proclist(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) {
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) {
for ( const auto &inode : it1.second )
{
inode_set[ inode ].insert( dev );
}
}
}
if (!inode_set.empty()) {
if ( !inode_set.empty() )
{
dirqueues.resize( numthreads );
}
@ -817,18 +875,22 @@ static uint32_t find_files_in_inode_set(const std::vector<procinfo_t>& inotify_p
// Initialize thread_info_t array
std::vector< class thread_info_t > thread_array( g_numthreads, thread_info_t( tdata ) );
for (uint32_t idx = 0; idx < thread_array.size(); 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 );
// Add and parse root
thread_info.queue_directory( strdup( "/" ) );
thread_info.parse_dirqueue_entry();
} else if (pthread_create(&thread_info.pthread_id, NULL, &parse_dirqueue_threadproc, &thread_info)) {
}
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;
}
@ -838,16 +900,20 @@ static uint32_t find_files_in_inode_set(const std::vector<procinfo_t>& inotify_p
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) {
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 );
if (g_verbose > 1) {
if ( g_verbose > 1 )
{
printf( "Thread #%zu rc=%d status=%d\n", thread_info.pthread_id, rc, ( int )( intptr_t )status );
}
}
@ -858,7 +924,8 @@ static uint32_t find_files_in_inode_set(const std::vector<procinfo_t>& inotify_p
all_found_files.insert( all_found_files.end(),
thread_info.found_files.begin(), thread_info.found_files.end() );
if (g_verbose > 1) {
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() );
}
@ -886,8 +953,10 @@ static uint32_t get_inotify_procfs_value(const std::string& fname)
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) {
if ( fd >= 0 )
{
if ( read( fd, buf, sizeof( buf ) ) > 0 )
{
val = strtoul( buf, nullptr, 10 );
}
@ -899,14 +968,16 @@ 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) {
for ( const std::string &fname : filenames )
{
char str[16];
uint32_t val = get_inotify_procfs_value( fname );
@ -921,30 +992,42 @@ static uint32_t parse_config_file(const char* config_file)
uint32_t dir_count = 0;
FILE *fp = fopen( config_file, "r" );
if (fp) {
if ( fp )
{
char line_buf[ 8192 ];
bool in_ignore_dirs_section = false;
for (;;) {
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) {
}
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] == '/')) {
}
else if ( in_ignore_dirs_section && ( line_buf[ 0 ] == '/' ) )
{
size_t len = strcspn( line_buf, "\r\n" );
if (len > 1) {
if ( len > 1 )
{
line_buf[ len ] = 0;
if (line_buf[len - 1] != '/') {
if ( line_buf[ len - 1 ] != '/' )
{
line_buf[ len ] = '/';
line_buf[ len + 1 ] = '\0';
}
@ -966,7 +1049,8 @@ 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) {
if ( xdg_config_dir )
{
std::string config_file = std::string( xdg_config_dir ) + "/" + filename;
if ( parse_config_file( config_file.c_str() ) )
return true;
@ -977,7 +1061,8 @@ static bool parse_ignore_dirs_file()
}
const char *home_dir = getenv( "HOME" );
if (home_dir) {
if ( home_dir )
{
std::string config_file = std::string( home_dir ) + "/" + filename;
if ( parse_config_file( config_file.c_str() ) )
return true;
@ -990,27 +1075,22 @@ static bool parse_ignore_dirs_file()
return false;
}
static void print_version()
{
printf("%s\n", INOTIFYINFO_VERSION);
}
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" );
exit( -1 );
}
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 }
};
@ -1019,24 +1099,20 @@ static void parse_cmdline(int argc, char** argv, std::vector<std::string>& cmdli
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("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( "ignoredir", long_opts[ opt_ind ].name ) )
{
std::string dirname = optarg;
if (dirname.size() > 1) {
if ( dirname.size() > 1 )
{
if ( optarg[ dirname.size() - 1 ] != '/' )
dirname += "/";
ignore_dirs.push_back( dirname );
@ -1048,25 +1124,25 @@ static void parse_cmdline(int argc, char** argv, std::vector<std::string>& cmdli
break;
case 'h':
case '?':
print_usage(argv[0]);
exit(0);
default:
print_usage( argv[ 0 ] );
exit(-1);
break;
}
}
for (; optind < argc; optind++) {
for ( ; optind < argc; optind++ )
{
cmdline_applist.push_back( argv[ optind ] );
}
parse_ignore_dirs_file();
if (g_verbose > 1) {
if ( g_verbose > 1 )
{
printf( "%lu ignore_dirs:\n", ignore_dirs.size() );
for (std::string& dname : ignore_dirs) {
for ( std::string &dname : ignore_dirs )
{
printf( " '%s'\n", dname.c_str() );
}
}
@ -1083,7 +1159,8 @@ int main(int argc, char* argv[])
std::vector< procinfo_t > inotify_proclist;
struct lconv *env = localeconv();
if (env && env->thousands_sep && env->thousands_sep[0]) {
if (env && env->thousands_sep && env->thousands_sep[0])
{
thousands_sep = env->thousands_sep[0];
}
@ -1093,12 +1170,14 @@ int main(int argc, char* argv[])
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;
for (procinfo_t& procinfo : inotify_proclist) {
for ( procinfo_t &procinfo : inotify_proclist )
{
procinfo.in_cmd_line = is_proc_in_cmdline_applist( procinfo, cmdline_applist );
total_watches += procinfo.watches;
@ -1117,10 +1196,12 @@ int main(int argc, char* argv[])
double search_time = gettime();
uint32_t total_scanned_dirs = find_files_in_inode_set( inotify_proclist, all_found_files );
if (total_scanned_dirs) {
if ( total_scanned_dirs )
{
search_time = gettime() - search_time;
for (const filename_info_t& fname_info : all_found_files) {
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() );

View file

@ -57,3 +57,4 @@
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);

View file

@ -27,14 +27,14 @@
* 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,8 +48,7 @@
#include <Windows.h>
#include <time.h>
#ifdef _WIN64
inline BOOL __SYNC_BOOL_CAS(LONG64 volatile* dest, LONG64 input, LONG64 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) \
@ -64,8 +63,7 @@ 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)
{
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) \
@ -109,18 +107,15 @@ 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)
{
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)
{
static inline void _lfqueue_free(__attribute__ ((unused)) void* pl, void* ptr) {
free(ptr);
}
static void *
_dequeue(lfqueue_t* lfqueue)
{
_dequeue(lfqueue_t *lfqueue) {
lfqueue_cas_node_t *head, *next;
void *val;
@ -133,7 +128,8 @@ _dequeue(lfqueue_t* lfqueue)
val = NULL;
goto _done;
}
} else {
}
else {
if (next) {
val = next->value;
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) {
@ -156,8 +152,7 @@ _done:
}
static void *
_single_dequeue(lfqueue_t* lfqueue)
{
_single_dequeue(lfqueue_t *lfqueue) {
lfqueue_cas_node_t *head, *next;
void *val;
@ -169,7 +164,8 @@ _single_dequeue(lfqueue_t* lfqueue)
if (next == NULL) {
return NULL;
}
} else {
}
else {
if (next) {
val = next->value;
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) {
@ -186,8 +182,7 @@ _single_dequeue(lfqueue_t* lfqueue)
}
static int
_enqueue(lfqueue_t* lfqueue, void* value)
{
_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) {
@ -213,8 +208,7 @@ _enqueue(lfqueue_t* lfqueue, void* value)
}
static void
__lfq_recycle_free(lfqueue_t* lfqueue, lfqueue_cas_node_t* freenode)
{
__lfq_recycle_free(lfqueue_t *lfqueue, lfqueue_cas_node_t* freenode) {
lfqueue_cas_node_t *freed;
do {
freed = lfqueue->move_free;
@ -226,8 +220,7 @@ __lfq_recycle_free(lfqueue_t* lfqueue, lfqueue_cas_node_t* freenode)
}
static void
__lfq_check_free(lfqueue_t* lfqueue)
{
__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);
@ -248,13 +241,13 @@ __lfq_check_free(lfqueue_t* lfqueue)
__LFQ_SYNC_MEMORY();
}
int lfqueue_init(lfqueue_t* lfqueue)
{
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)
{
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;
@ -283,8 +276,8 @@ int lfqueue_init_mf(lfqueue_t* lfqueue, void* pl, lfqueue_malloc_fn lfqueue_mall
return 0;
}
void lfqueue_destroy(lfqueue_t* lfqueue)
{
void
lfqueue_destroy(lfqueue_t *lfqueue) {
void* p;
while ((p = lfqueue_deq(lfqueue))) {
lfqueue->_free(lfqueue->pl, p);
@ -305,8 +298,8 @@ void lfqueue_destroy(lfqueue_t* lfqueue)
lfqueue->size = 0;
}
int lfqueue_enq(lfqueue_t* lfqueue, void* value)
{
int
lfqueue_enq(lfqueue_t *lfqueue, void *value) {
if (_enqueue(lfqueue, value)) {
return -1;
}
@ -314,11 +307,12 @@ int lfqueue_enq(lfqueue_t* lfqueue, void* value)
return 0;
}
void* lfqueue_deq(lfqueue_t* lfqueue)
{
void*
lfqueue_deq(lfqueue_t *lfqueue) {
void *v;
if (//__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) &&
(v = _dequeue(lfqueue))) {
(v = _dequeue(lfqueue))
) {
__LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
return v;
@ -326,8 +320,8 @@ void* lfqueue_deq(lfqueue_t* lfqueue)
return NULL;
}
void* lfqueue_deq_must(lfqueue_t* lfqueue)
{
void*
lfqueue_deq_must(lfqueue_t *lfqueue) {
void *v;
while ( !(v = _dequeue(lfqueue)) ) {
// Rest the thread for other thread, to avoid keep looping force
@ -338,11 +332,12 @@ void* lfqueue_deq_must(lfqueue_t* lfqueue)
}
/**This is only applicable when only single thread consume only**/
void* lfqueue_single_deq(lfqueue_t* lfqueue)
{
void*
lfqueue_single_deq(lfqueue_t *lfqueue) {
void *v;
if (//__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) &&
(v = _single_dequeue(lfqueue))) {
(v = _single_dequeue(lfqueue))
) {
__LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
return v;
@ -351,8 +346,8 @@ void* lfqueue_single_deq(lfqueue_t* lfqueue)
}
/**This is only applicable when only single thread consume only**/
void* lfqueue_single_deq_must(lfqueue_t* lfqueue)
{
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
@ -363,13 +358,12 @@ void* lfqueue_single_deq_must(lfqueue_t* lfqueue)
}
size_t
lfqueue_size(lfqueue_t* lfqueue)
{
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"

View file

@ -31,8 +31,8 @@
#ifndef LFQUEUE_H
#define LFQUEUE_H
#include <stdint.h>
#include <stdlib.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
@ -75,8 +75,10 @@ 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