0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-25 23:14:13 +01:00

ircd::util: Move syscall() templates out of util; minor reorg includes.

ircd::sys: Add abstract sysfs tool and template from fs::dev.
This commit is contained in:
Jason Volk 2020-06-11 00:43:36 -07:00
parent d9bfdc9678
commit eb00134100
6 changed files with 236 additions and 42 deletions

View file

@ -56,11 +56,8 @@
#include "time.h"
#include "logger.h"
#include "info.h"
#include "nacl.h"
#include "rand.h"
#include "crh.h"
#include "ed25519.h"
#include "color.h"
#include "lex_cast.h"
#include "base.h"
#include "stringops.h"
@ -72,9 +69,12 @@
#include "iov.h"
#include "grammar.h"
#include "parse.h"
#include "color.h"
#include "rfc1459.h"
#include "json/json.h"
#include "cbor/cbor.h"
#include "nacl.h"
#include "ed25519.h"
#include "openssl.h"
#include "pbc.h"
#include "fmt.h"
@ -83,6 +83,7 @@
#include "conf.h"
#include "magic.h"
#include "stats.h"
#include "sys.h"
#include "prof/prof.h"
#include "fs/fs.h"
#include "ios.h"

168
include/ircd/sys.h Normal file
View file

@ -0,0 +1,168 @@
// The Construct
//
// Copyright (C) The Construct Developers, Authors & Contributors
// Copyright (C) 2016-2020 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#pragma once
#define HAVE_IRCD_SYS_H
namespace ircd::sys
{
enum call :uint;
template<enum call = (enum call)0,
class function,
class... args>
long call(function&&, args&&...);
template<long number,
enum call = (enum call)0,
class... args>
long call(args&&... a);
// sysfs read to buffer
string_view get(const mutable_buffer &out, const string_view &path);
// sysfs read cast to type or defaults
template<class R = size_t,
size_t bufmax = 32>
R get(const string_view &path, const R &def = 0);
extern log::log log;
}
/// System call template options; changes behaviors.
enum ircd::sys::call
:uint
{
NOTHROW = 0x01,
UNINTERRUPTIBLE = 0x02,
};
/// Return a lex_cast'able (an integer) from a sysfs target.
template<class T,
size_t bufmax>
inline T
ircd::sys::get(const string_view &path,
const T &def)
{
char buf[bufmax];
const string_view val
{
get(buf, path)
};
return lex_castable<T>(val)?
lex_cast<T>(val):
def;
}
/// This template requires a system call number in the parameters. The
/// arguments are only the actual arguments passed to the syscall because
/// the number is given in the template.
///
template<long number,
enum ircd::sys::call opts,
class... args>
inline long
ircd::sys::call(args&&... a)
{
return call<opts>(::syscall, number, std::forward<args>(a)...);
}
/// Posix system call template to check for returned error value and throw the
/// approps errno in the proper std::system_error exception. Note the usage
/// here, the libc wrapper function is the first argument i.e:
/// syscall(::foo, bar, baz) not syscall(::foo(bar, baz));
///
/// when uninterruptible posix system call template; the syscall is
/// restarted until it no longer returns with EINTR.
///
template<enum ircd::sys::call opts,
class function,
class... args>
inline long
ircd::sys::call(function&& f,
args&&... a)
{
constexpr auto uninterruptible
{
opts & call::UNINTERRUPTIBLE
};
long ret; do
{
ret = f(std::forward<args>(a)...);
}
while(unlikely(uninterruptible && ret == -1 && errno == EINTR));
constexpr auto nothrow
{
opts & call::NOTHROW
};
if(unlikely(!nothrow && ret == -1L))
throw std::system_error
{
errno, std::system_category()
};
return ret;
}
///////////////////////////////////////////////////////////////////////////////
//
// Legacy convenience forwarder interface
//
namespace ircd {
template<class function,
class... args>
inline auto
syscall(function&& f,
args&&... a)
{
return sys::call(std::forward<function>(f), std::forward<args>(a)...);
}
template<long number,
class... args>
inline auto
syscall(args&&... a)
{
return sys::call<number>(std::forward<args>(a)...);
}
template<class function,
class... args>
inline auto
syscall_nointr(function&& f,
args&&... a)
{
constexpr enum sys::call opts
{
sys::call::UNINTERRUPTIBLE
};
return sys::call<opts>(std::forward<function>(f), std::forward<args>(a)...);
}
template<long number,
class... args>
inline auto
syscall_nointr(args&&... a)
{
constexpr enum sys::call opts
{
sys::call::UNINTERRUPTIBLE
};
return sys::call<number, opts>(std::forward<args>(a)...);
}
} // namespace ircd

View file

@ -39,7 +39,6 @@ namespace ircd
#include "reentrance.h"
#include "enum.h"
#include "custom_ptr.h"
#include "syscall.h"
#include "env.h"
#include "va_rtti.h"
#include "unique_iterator.h"

View file

@ -169,6 +169,7 @@ endif
if IOU
libircd_la_SOURCES += fs_iou.cc
endif
libircd_la_SOURCES += sys.cc
libircd_la_SOURCES += mods.cc
if LINUX
libircd_la_SOURCES += mods_ldso.cc

View file

@ -60,51 +60,16 @@ ircd::string_view
ircd::fs::dev::sysfs(const mutable_buffer &out,
const ulong &id,
const string_view &relpath)
try
{
thread_local char path_buf[1024];
const string_view path{fmt::sprintf
{
path_scratch, "%s/%s/%s",
blk::BASE_PATH,
path_buf, "dev/block/%s/%s",
sysfs_id(name_scratch, id),
relpath
}};
fs::fd::opts fdopts;
fdopts.errlog = false;
const fs::fd fd
{
path, fdopts
};
fs::read_opts ropts;
ropts.aio = false;
string_view ret
{
fs::read(fd, out, ropts)
};
ret = rstrip(ret, '\n');
ret = rstrip(ret, ' ');
return ret;
}
catch(const ctx::interrupted &)
{
throw;
}
catch(const std::exception &e)
{
#if 0
log::derror
{
log, "sysfs query dev_id:%lu `%s' :%s",
id,
relpath,
e.what(),
};
#endif
return {};
return sys::get(out, path);
}
ircd::string_view

60
ircd/sys.cc Normal file
View file

@ -0,0 +1,60 @@
// The Construct
//
// Copyright (C) The Construct Developers, Authors & Contributors
// Copyright (C) 2016-2020 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
decltype(ircd::sys::log)
ircd::sys::log
{
"sys"
};
ircd::string_view
ircd::sys::get(const mutable_buffer &out,
const string_view &relpath)
try
{
thread_local char buf[1024];
string_view path(relpath);
path = lstrip(relpath, "/sys/"_sv); // tolerate any errant /sys/ prefix
path = strlcpy(buf, "/sys/"_sv);
path = strlcat(buf, relpath);
fs::fd::opts fdopts;
fdopts.errlog = false;
const fs::fd fd
{
path, fdopts
};
string_view ret
{
data(out), sys::call(::read, fd, data(out), size(out))
};
ret = rstrip(ret, '\n');
ret = rstrip(ret, ' ');
return ret;
}
catch(const ctx::interrupted &)
{
throw;
}
catch(const std::exception &e)
{
#if 0
log::derror
{
log, "sysfs query `%s' :%s",
relpath,
e.what(),
};
#endif
return {};
}