2013-02-06 21:15:23 +01:00
|
|
|
/***
|
|
|
|
This file is part of systemd.
|
|
|
|
|
|
|
|
Copyright 2010 Lennart Poettering
|
|
|
|
Copyright 2013 Thomas H.P. Andersen
|
|
|
|
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
|
|
|
under the terms of the GNU Lesser General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
systemd is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
***/
|
|
|
|
|
2015-09-30 21:50:22 +02:00
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
2014-08-16 14:19:09 +02:00
|
|
|
#include <sys/wait.h>
|
2015-09-30 21:50:22 +02:00
|
|
|
#include <unistd.h>
|
2013-02-06 21:15:23 +01:00
|
|
|
|
2014-01-26 05:35:28 +01:00
|
|
|
#include "def.h"
|
|
|
|
#include "fileio.h"
|
2015-10-26 21:16:26 +01:00
|
|
|
#include "fs-util.h"
|
2015-09-30 21:50:22 +02:00
|
|
|
#include "rm-rf.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "string-util.h"
|
2015-09-30 21:50:22 +02:00
|
|
|
#include "util.h"
|
2013-02-06 21:15:23 +01:00
|
|
|
|
2014-05-13 19:47:58 +02:00
|
|
|
static void test_align_power2(void) {
|
|
|
|
unsigned long i, p2;
|
|
|
|
|
|
|
|
assert_se(ALIGN_POWER2(0) == 0);
|
|
|
|
assert_se(ALIGN_POWER2(1) == 1);
|
|
|
|
assert_se(ALIGN_POWER2(2) == 2);
|
|
|
|
assert_se(ALIGN_POWER2(3) == 4);
|
|
|
|
assert_se(ALIGN_POWER2(12) == 16);
|
|
|
|
|
|
|
|
assert_se(ALIGN_POWER2(ULONG_MAX) == 0);
|
|
|
|
assert_se(ALIGN_POWER2(ULONG_MAX - 1) == 0);
|
|
|
|
assert_se(ALIGN_POWER2(ULONG_MAX - 1024) == 0);
|
|
|
|
assert_se(ALIGN_POWER2(ULONG_MAX / 2) == ULONG_MAX / 2 + 1);
|
|
|
|
assert_se(ALIGN_POWER2(ULONG_MAX + 1) == 0);
|
|
|
|
|
|
|
|
for (i = 1; i < 131071; ++i) {
|
|
|
|
for (p2 = 1; p2 < i; p2 <<= 1)
|
|
|
|
/* empty */ ;
|
|
|
|
|
|
|
|
assert_se(ALIGN_POWER2(i) == p2);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = ULONG_MAX - 1024; i < ULONG_MAX; ++i) {
|
|
|
|
for (p2 = 1; p2 && p2 < i; p2 <<= 1)
|
|
|
|
/* empty */ ;
|
|
|
|
|
|
|
|
assert_se(ALIGN_POWER2(i) == p2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-15 16:54:52 +02:00
|
|
|
static void test_max(void) {
|
|
|
|
static const struct {
|
|
|
|
int a;
|
|
|
|
int b[CONST_MAX(10, 100)];
|
|
|
|
} val1 = {
|
|
|
|
.a = CONST_MAX(10, 100),
|
|
|
|
};
|
|
|
|
int d = 0;
|
|
|
|
|
|
|
|
assert_cc(sizeof(val1.b) == sizeof(int) * 100);
|
|
|
|
|
|
|
|
/* CONST_MAX returns (void) instead of a value if the passed arguments
|
|
|
|
* are not of the same type or not constant expressions. */
|
|
|
|
assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 10)), int));
|
|
|
|
assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 1U)), void));
|
|
|
|
|
|
|
|
assert_se(val1.a == 100);
|
|
|
|
assert_se(MAX(++d, 0) == 1);
|
|
|
|
assert_se(d == 1);
|
2014-08-22 13:55:57 +02:00
|
|
|
|
|
|
|
assert_cc(MAXSIZE(char[3], uint16_t) == 3);
|
|
|
|
assert_cc(MAXSIZE(char[3], uint32_t) == 4);
|
|
|
|
assert_cc(MAXSIZE(char, long) == sizeof(long));
|
2014-08-28 14:45:38 +02:00
|
|
|
|
|
|
|
assert_se(MAX(-5, 5) == 5);
|
|
|
|
assert_se(MAX(5, 5) == 5);
|
|
|
|
assert_se(MAX(MAX(1, MAX(2, MAX(3, 4))), 5) == 5);
|
|
|
|
assert_se(MAX(MAX(1, MAX(2, MAX(3, 2))), 1) == 3);
|
|
|
|
assert_se(MAX(MIN(1, MIN(2, MIN(3, 4))), 5) == 5);
|
|
|
|
assert_se(MAX(MAX(1, MIN(2, MIN(3, 2))), 1) == 2);
|
|
|
|
assert_se(LESS_BY(8, 4) == 4);
|
|
|
|
assert_se(LESS_BY(8, 8) == 0);
|
|
|
|
assert_se(LESS_BY(4, 8) == 0);
|
|
|
|
assert_se(LESS_BY(16, LESS_BY(8, 4)) == 12);
|
|
|
|
assert_se(LESS_BY(4, LESS_BY(8, 4)) == 0);
|
|
|
|
assert_se(CLAMP(-5, 0, 1) == 0);
|
|
|
|
assert_se(CLAMP(5, 0, 1) == 1);
|
|
|
|
assert_se(CLAMP(5, -10, 1) == 1);
|
|
|
|
assert_se(CLAMP(5, -10, 10) == 5);
|
|
|
|
assert_se(CLAMP(CLAMP(0, -10, 10), CLAMP(-5, 10, 20), CLAMP(100, -5, 20)) == 10);
|
2014-08-15 16:54:52 +02:00
|
|
|
}
|
|
|
|
|
shared: make container_of() use unique variable names
If you stack container_of() macros, you will get warnings due to shadowing
variables of the parent context. To avoid this, use unique names for
variables.
Two new helpers are added:
UNIQ: This evaluates to a truly unique value never returned by any
evaluation of this macro. It's a shortcut for __COUNTER__.
UNIQ_T: Takes two arguments and concatenates them. It is a shortcut for
CONCATENATE, but meant to defined typed local variables.
As you usually want to use variables that you just defined, you need to
reference the same unique value at least two times. However, UNIQ returns
a new value on each evaluation, therefore, you have to pass the unique
values into the macro like this:
#define my_macro(a, b) __max_macro(UNIQ, UNIQ, (a), (b))
#define __my_macro(uniqa, uniqb, a, b) ({
typeof(a) UNIQ_T(A, uniqa) = (a);
typeof(b) UNIQ_T(B, uniqb) = (b);
MY_UNSAFE_MACRO(UNIQ_T(A, uniqa), UNIQ_T(B, uniqb));
})
This way, MY_UNSAFE_MACRO() can safely evaluate it's arguments multiple
times as they are local variables. But you can also stack invocations to
the macro my_macro() without clashing names.
This is the same as if you did:
#define my_macro(a, b) __max_macro(__COUNTER__, __COUNTER__, (a), (b))
#define __my_macro(prefixa, prefixb, a, b) ({
typeof(a) CONCATENATE(A, prefixa) = (a);
typeof(b) CONCATENATE(B, prefixb) = (b);
MY_UNSAFE_MACRO(CONCATENATE(A, prefixa), CONCATENATE(B, prefixb));
})
...but in my opinion, the first macro is easier to write and read.
This patch starts by converting container_of() to use this new helper.
Other macros may follow (like MIN, MAX, CLAMP, ...).
2014-08-22 14:41:37 +02:00
|
|
|
static void test_container_of(void) {
|
|
|
|
struct mytype {
|
|
|
|
uint8_t pad1[3];
|
|
|
|
uint64_t v1;
|
|
|
|
uint8_t pad2[2];
|
|
|
|
uint32_t v2;
|
|
|
|
} _packed_ myval = { };
|
|
|
|
|
|
|
|
assert_cc(sizeof(myval) == 17);
|
|
|
|
assert_se(container_of(&myval.v1, struct mytype, v1) == &myval);
|
|
|
|
assert_se(container_of(&myval.v2, struct mytype, v2) == &myval);
|
|
|
|
assert_se(container_of(&container_of(&myval.v2,
|
|
|
|
struct mytype,
|
|
|
|
v2)->v1,
|
|
|
|
struct mytype,
|
|
|
|
v1) == &myval);
|
|
|
|
}
|
|
|
|
|
2014-12-29 17:51:36 +01:00
|
|
|
static void test_div_round_up(void) {
|
|
|
|
int div;
|
|
|
|
|
|
|
|
/* basic tests */
|
|
|
|
assert_se(DIV_ROUND_UP(0, 8) == 0);
|
|
|
|
assert_se(DIV_ROUND_UP(1, 8) == 1);
|
|
|
|
assert_se(DIV_ROUND_UP(8, 8) == 1);
|
|
|
|
assert_se(DIV_ROUND_UP(12, 8) == 2);
|
|
|
|
assert_se(DIV_ROUND_UP(16, 8) == 2);
|
|
|
|
|
|
|
|
/* test multiple evaluation */
|
|
|
|
div = 0;
|
|
|
|
assert_se(DIV_ROUND_UP(div++, 8) == 0 && div == 1);
|
|
|
|
assert_se(DIV_ROUND_UP(++div, 8) == 1 && div == 2);
|
|
|
|
assert_se(DIV_ROUND_UP(8, div++) == 4 && div == 3);
|
|
|
|
assert_se(DIV_ROUND_UP(8, ++div) == 2 && div == 4);
|
|
|
|
|
|
|
|
/* overflow test with exact division */
|
|
|
|
assert_se(sizeof(0U) == 4);
|
|
|
|
assert_se(0xfffffffaU % 10U == 0U);
|
|
|
|
assert_se(0xfffffffaU / 10U == 429496729U);
|
|
|
|
assert_se(DIV_ROUND_UP(0xfffffffaU, 10U) == 429496729U);
|
|
|
|
assert_se((0xfffffffaU + 10U - 1U) / 10U == 0U);
|
|
|
|
assert_se(0xfffffffaU / 10U + !!(0xfffffffaU % 10U) == 429496729U);
|
|
|
|
|
|
|
|
/* overflow test with rounded division */
|
|
|
|
assert_se(0xfffffffdU % 10U == 3U);
|
|
|
|
assert_se(0xfffffffdU / 10U == 429496729U);
|
|
|
|
assert_se(DIV_ROUND_UP(0xfffffffdU, 10U) == 429496730U);
|
|
|
|
assert_se((0xfffffffdU + 10U - 1U) / 10U == 0U);
|
|
|
|
assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U);
|
|
|
|
}
|
|
|
|
|
2013-04-05 01:09:50 +02:00
|
|
|
static void test_u64log2(void) {
|
2014-10-04 23:51:45 +02:00
|
|
|
assert_se(u64log2(0) == 0);
|
|
|
|
assert_se(u64log2(8) == 3);
|
|
|
|
assert_se(u64log2(9) == 3);
|
|
|
|
assert_se(u64log2(15) == 3);
|
|
|
|
assert_se(u64log2(16) == 4);
|
|
|
|
assert_se(u64log2(1024*1024) == 20);
|
|
|
|
assert_se(u64log2(1024*1024+5) == 20);
|
2013-04-05 01:09:50 +02:00
|
|
|
}
|
|
|
|
|
2013-04-26 02:53:29 +02:00
|
|
|
static void test_protect_errno(void) {
|
|
|
|
errno = 12;
|
|
|
|
{
|
|
|
|
PROTECT_ERRNO;
|
|
|
|
errno = 11;
|
|
|
|
}
|
2014-10-04 23:51:45 +02:00
|
|
|
assert_se(errno == 12);
|
2013-04-26 02:53:29 +02:00
|
|
|
}
|
|
|
|
|
2013-12-02 23:08:25 +01:00
|
|
|
static void test_in_set(void) {
|
|
|
|
assert_se(IN_SET(1, 1));
|
|
|
|
assert_se(IN_SET(1, 1, 2, 3, 4));
|
|
|
|
assert_se(IN_SET(2, 1, 2, 3, 4));
|
|
|
|
assert_se(IN_SET(3, 1, 2, 3, 4));
|
|
|
|
assert_se(IN_SET(4, 1, 2, 3, 4));
|
|
|
|
assert_se(!IN_SET(0, 1));
|
|
|
|
assert_se(!IN_SET(0, 1, 2, 3, 4));
|
|
|
|
}
|
|
|
|
|
2014-03-15 02:43:56 +01:00
|
|
|
static void test_log2i(void) {
|
|
|
|
assert_se(log2i(1) == 0);
|
|
|
|
assert_se(log2i(2) == 1);
|
|
|
|
assert_se(log2i(3) == 1);
|
|
|
|
assert_se(log2i(4) == 2);
|
|
|
|
assert_se(log2i(32) == 5);
|
|
|
|
assert_se(log2i(33) == 5);
|
|
|
|
assert_se(log2i(63) == 5);
|
|
|
|
assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
|
|
|
|
}
|
|
|
|
|
2014-08-16 14:19:09 +02:00
|
|
|
static void test_execute_directory(void) {
|
2015-01-09 03:21:12 +01:00
|
|
|
char template_lo[] = "/tmp/test-readlink_and_make_absolute-lo.XXXXXXX";
|
|
|
|
char template_hi[] = "/tmp/test-readlink_and_make_absolute-hi.XXXXXXX";
|
2015-02-12 20:32:03 +01:00
|
|
|
const char * dirs[] = {template_hi, template_lo, NULL};
|
2015-01-09 03:21:12 +01:00
|
|
|
const char *name, *name2, *name3, *overridden, *override, *masked, *mask;
|
|
|
|
|
|
|
|
assert_se(mkdtemp(template_lo));
|
|
|
|
assert_se(mkdtemp(template_hi));
|
|
|
|
|
2015-02-03 02:05:59 +01:00
|
|
|
name = strjoina(template_lo, "/script");
|
|
|
|
name2 = strjoina(template_hi, "/script2");
|
|
|
|
name3 = strjoina(template_lo, "/useless");
|
|
|
|
overridden = strjoina(template_lo, "/overridden");
|
|
|
|
override = strjoina(template_hi, "/overridden");
|
|
|
|
masked = strjoina(template_lo, "/masked");
|
|
|
|
mask = strjoina(template_hi, "/masked");
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
|
2015-07-07 01:19:25 +02:00
|
|
|
assert_se(write_string_file(name, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works", WRITE_STRING_FILE_CREATE) == 0);
|
|
|
|
assert_se(write_string_file(name2, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2", WRITE_STRING_FILE_CREATE) == 0);
|
|
|
|
assert_se(write_string_file(overridden, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
|
|
|
|
assert_se(write_string_file(override, "#!/bin/sh\necho 'Executing '$0", WRITE_STRING_FILE_CREATE) == 0);
|
|
|
|
assert_se(write_string_file(masked, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
|
2015-01-09 03:21:12 +01:00
|
|
|
assert_se(symlink("/dev/null", mask) == 0);
|
2014-08-16 14:19:09 +02:00
|
|
|
assert_se(chmod(name, 0755) == 0);
|
|
|
|
assert_se(chmod(name2, 0755) == 0);
|
2015-01-09 03:21:12 +01:00
|
|
|
assert_se(chmod(overridden, 0755) == 0);
|
|
|
|
assert_se(chmod(override, 0755) == 0);
|
|
|
|
assert_se(chmod(masked, 0755) == 0);
|
2014-08-16 14:19:09 +02:00
|
|
|
assert_se(touch(name3) >= 0);
|
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL);
|
2015-01-09 03:21:12 +01:00
|
|
|
|
2015-01-22 22:53:42 +01:00
|
|
|
assert_se(chdir(template_lo) == 0);
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
assert_se(access("it_works", F_OK) >= 0);
|
2015-01-09 03:21:12 +01:00
|
|
|
assert_se(access("failed", F_OK) < 0);
|
|
|
|
|
2015-01-22 22:53:42 +01:00
|
|
|
assert_se(chdir(template_hi) == 0);
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
assert_se(access("it_works2", F_OK) >= 0);
|
2015-01-09 03:21:12 +01:00
|
|
|
assert_se(access("failed", F_OK) < 0);
|
2014-08-16 14:19:09 +02:00
|
|
|
|
2015-04-04 11:52:57 +02:00
|
|
|
(void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL);
|
|
|
|
(void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
|
2014-08-16 14:19:09 +02:00
|
|
|
}
|
|
|
|
|
2014-12-17 05:53:23 +01:00
|
|
|
static void test_raw_clone(void) {
|
|
|
|
pid_t parent, pid, pid2;
|
|
|
|
|
|
|
|
parent = getpid();
|
|
|
|
log_info("before clone: getpid()→"PID_FMT, parent);
|
|
|
|
assert_se(raw_getpid() == parent);
|
|
|
|
|
|
|
|
pid = raw_clone(0, NULL);
|
2014-12-23 19:14:46 +01:00
|
|
|
assert_se(pid >= 0);
|
2014-12-17 05:53:23 +01:00
|
|
|
|
|
|
|
pid2 = raw_getpid();
|
|
|
|
log_info("raw_clone: "PID_FMT" getpid()→"PID_FMT" raw_getpid()→"PID_FMT,
|
|
|
|
pid, getpid(), pid2);
|
2014-12-25 17:40:46 +01:00
|
|
|
if (pid == 0) {
|
2014-12-23 19:14:46 +01:00
|
|
|
assert_se(pid2 != parent);
|
2014-12-25 17:40:46 +01:00
|
|
|
_exit(EXIT_SUCCESS);
|
|
|
|
} else {
|
|
|
|
int status;
|
|
|
|
|
2014-12-23 19:14:46 +01:00
|
|
|
assert_se(pid2 == parent);
|
2014-12-25 17:40:46 +01:00
|
|
|
waitpid(pid, &status, __WCLONE);
|
|
|
|
assert_se(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
|
|
|
|
}
|
2014-12-17 05:53:23 +01:00
|
|
|
}
|
|
|
|
|
2013-02-06 21:15:23 +01:00
|
|
|
int main(int argc, char *argv[]) {
|
2014-03-02 06:05:16 +01:00
|
|
|
log_parse_environment();
|
|
|
|
log_open();
|
|
|
|
|
2014-05-13 19:47:58 +02:00
|
|
|
test_align_power2();
|
2014-08-15 16:54:52 +02:00
|
|
|
test_max();
|
shared: make container_of() use unique variable names
If you stack container_of() macros, you will get warnings due to shadowing
variables of the parent context. To avoid this, use unique names for
variables.
Two new helpers are added:
UNIQ: This evaluates to a truly unique value never returned by any
evaluation of this macro. It's a shortcut for __COUNTER__.
UNIQ_T: Takes two arguments and concatenates them. It is a shortcut for
CONCATENATE, but meant to defined typed local variables.
As you usually want to use variables that you just defined, you need to
reference the same unique value at least two times. However, UNIQ returns
a new value on each evaluation, therefore, you have to pass the unique
values into the macro like this:
#define my_macro(a, b) __max_macro(UNIQ, UNIQ, (a), (b))
#define __my_macro(uniqa, uniqb, a, b) ({
typeof(a) UNIQ_T(A, uniqa) = (a);
typeof(b) UNIQ_T(B, uniqb) = (b);
MY_UNSAFE_MACRO(UNIQ_T(A, uniqa), UNIQ_T(B, uniqb));
})
This way, MY_UNSAFE_MACRO() can safely evaluate it's arguments multiple
times as they are local variables. But you can also stack invocations to
the macro my_macro() without clashing names.
This is the same as if you did:
#define my_macro(a, b) __max_macro(__COUNTER__, __COUNTER__, (a), (b))
#define __my_macro(prefixa, prefixb, a, b) ({
typeof(a) CONCATENATE(A, prefixa) = (a);
typeof(b) CONCATENATE(B, prefixb) = (b);
MY_UNSAFE_MACRO(CONCATENATE(A, prefixa), CONCATENATE(B, prefixb));
})
...but in my opinion, the first macro is easier to write and read.
This patch starts by converting container_of() to use this new helper.
Other macros may follow (like MIN, MAX, CLAMP, ...).
2014-08-22 14:41:37 +02:00
|
|
|
test_container_of();
|
2014-12-29 17:51:36 +01:00
|
|
|
test_div_round_up();
|
2013-04-05 01:09:50 +02:00
|
|
|
test_u64log2();
|
2013-04-26 02:53:29 +02:00
|
|
|
test_protect_errno();
|
2013-12-02 23:08:25 +01:00
|
|
|
test_in_set();
|
2014-03-15 02:43:56 +01:00
|
|
|
test_log2i();
|
2014-08-16 14:19:09 +02:00
|
|
|
test_execute_directory();
|
2014-12-17 05:53:23 +01:00
|
|
|
test_raw_clone();
|
2013-02-06 21:15:23 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|