Skip to content

Commit

Permalink
Avoid C preprocessor trick where macro has the same name as a function.
Browse files Browse the repository at this point in the history
In C, one can do preprocessor tricks by making a macro expansion include
the macro's own name.  We actually used this in the tree to automatically
provide function arguments, e.g.:

    int f(int x, const char *file, int line);
    #define f(x) f(x, __FILE__, __LINE__)

...

    f(1);    /* Expands to a call like f(1, __FILE__, __LINE__); */

However it's somewhat confusing, so this commit stops using that trick.

Reported-by: Ed Maste <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
Acked-by: Ed Maste <[email protected]>
  • Loading branch information
blp committed Jul 29, 2013
1 parent 74cc396 commit 5453ae2
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 56 deletions.
2 changes: 1 addition & 1 deletion lib/jsonrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ void
jsonrpc_recv_wait(struct jsonrpc *rpc)
{
if (rpc->status || rpc->received || !byteq_is_empty(&rpc->input)) {
(poll_immediate_wake)(rpc->name);
poll_immediate_wake_at(rpc->name);
} else {
stream_recv_wait(rpc->stream);
}
Expand Down
10 changes: 7 additions & 3 deletions lib/latch.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,13 @@ latch_is_set(const struct latch *latch)
return pfd.revents & POLLIN;
}

/* Causes the next poll_block() to wake up when 'latch' is set. */
/* Causes the next poll_block() to wake up when 'latch' is set.
*
* ('where' is used in debug logging. Commonly one would use latch_wait() to
* automatically provide the caller's source file and line number for
* 'where'.) */
void
(latch_wait)(const struct latch *latch, const char *where)
latch_wait_at(const struct latch *latch, const char *where)
{
(poll_fd_wait)(latch->fds[0], POLLIN, where);
poll_fd_wait_at(latch->fds[0], POLLIN, where);
}
4 changes: 2 additions & 2 deletions lib/latch.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ bool latch_poll(struct latch *);
void latch_set(struct latch *);

bool latch_is_set(const struct latch *);
void latch_wait(const struct latch *, const char *where);
#define latch_wait(latch) latch_wait(latch, SOURCE_LOCATOR)
void latch_wait_at(const struct latch *, const char *where);
#define latch_wait(latch) latch_wait_at(latch, SOURCE_LOCATOR)

#endif /* latch.h */
16 changes: 12 additions & 4 deletions lib/ovs-thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,13 @@ ovsthread_once_done(struct ovsthread_once *once)
}

/* Asserts that the process has not yet created any threads (beyond the initial
* thread). */
* thread).
*
* ('where' is used in logging. Commonly one would use
* assert_single_threaded() to automatically provide the caller's source file
* and line number for 'where'.) */
void
(assert_single_threaded)(const char *where)
assert_single_threaded_at(const char *where)
{
if (multithreaded) {
VLOG_FATAL("%s: attempted operation not allowed when multithreaded",
Expand All @@ -148,9 +152,13 @@ void

/* Forks the current process (checking that this is allowed). Aborts with
* VLOG_FATAL if fork() returns an error, and otherwise returns the value
* returned by fork(). */
* returned by fork().
*
* ('where' is used in logging. Commonly one would use xfork() to
* automatically provide the caller's source file and line number for
* 'where'.) */
pid_t
(xfork)(const char *where)
xfork_at(const char *where)
{
pid_t pid;

Expand Down
8 changes: 4 additions & 4 deletions lib/ovs-thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,11 +377,11 @@ ovsthread_once_start(struct ovsthread_once *once)
((ONCE)->done ? false : ({ OVS_ACQUIRE(ONCE); true; }))
#endif

void assert_single_threaded(const char *where);
#define assert_single_threaded() assert_single_threaded(SOURCE_LOCATOR)
void assert_single_threaded_at(const char *where);
#define assert_single_threaded() assert_single_threaded_at(SOURCE_LOCATOR)

pid_t xfork(const char *where);
#define xfork() xfork(SOURCE_LOCATOR)
pid_t xfork_at(const char *where);
#define xfork() xfork_at(SOURCE_LOCATOR)

void forbid_forking(const char *reason);
bool may_fork(void);
Expand Down
37 changes: 18 additions & 19 deletions lib/poll-loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@
#include "timeval.h"
#include "vlog.h"

#undef poll_fd_wait
#undef poll_timer_wait
#undef poll_timer_wait_until
#undef poll_immediate_wake

VLOG_DEFINE_THIS_MODULE(poll_loop);

COVERAGE_DEFINE(poll_fd_wait);
Expand Down Expand Up @@ -63,10 +58,11 @@ static struct poll_loop *poll_loop(void);
* is affected. The event will need to be re-registered after poll_block() is
* called if it is to persist.
*
* Ordinarily the 'where' argument is supplied automatically; see poll-loop.h
* for more information. */
* ('where' is used in debug logging. Commonly one would use poll_fd_wait() to
* automatically provide the caller's source file and line number for
* 'where'.) */
void
poll_fd_wait(int fd, short int events, const char *where)
poll_fd_wait_at(int fd, short int events, const char *where)
{
struct poll_loop *loop = poll_loop();

Expand All @@ -93,10 +89,11 @@ poll_fd_wait(int fd, short int events, const char *where)
* is affected. The timer will need to be re-registered after poll_block() is
* called if it is to persist.
*
* Ordinarily the 'where' argument is supplied automatically; see poll-loop.h
* for more information. */
* ('where' is used in debug logging. Commonly one would use poll_timer_wait()
* to automatically provide the caller's source file and line number for
* 'where'.) */
void
poll_timer_wait(long long int msec, const char *where)
poll_timer_wait_at(long long int msec, const char *where)
{
long long int now = time_msec();
long long int when;
Expand All @@ -112,7 +109,7 @@ poll_timer_wait(long long int msec, const char *where)
when = LLONG_MAX;
}

poll_timer_wait_until(when, where);
poll_timer_wait_until_at(when, where);
}

/* Causes the following call to poll_block() to wake up when the current time,
Expand All @@ -124,10 +121,11 @@ poll_timer_wait(long long int msec, const char *where)
* is affected. The timer will need to be re-registered after poll_block() is
* called if it is to persist.
*
* Ordinarily the 'where' argument is supplied automatically; see poll-loop.h
* for more information. */
* ('where' is used in debug logging. Commonly one would use
* poll_timer_wait_until() to automatically provide the caller's source file
* and line number for 'where'.) */
void
poll_timer_wait_until(long long int when, const char *where)
poll_timer_wait_until_at(long long int when, const char *where)
{
struct poll_loop *loop = poll_loop();
if (when < loop->timeout_when) {
Expand All @@ -139,12 +137,13 @@ poll_timer_wait_until(long long int when, const char *where)
/* Causes the following call to poll_block() to wake up immediately, without
* blocking.
*
* Ordinarily the 'where' argument is supplied automatically; see poll-loop.h
* for more information. */
* ('where' is used in debug logging. Commonly one would use
* poll_immediate_wake() to automatically provide the caller's source file and
* line number for 'where'.) */
void
poll_immediate_wake(const char *where)
poll_immediate_wake_at(const char *where)
{
poll_timer_wait(0, where);
poll_timer_wait_at(0, where);
}

/* Logs, if appropriate, that the poll loop was awakened by an event
Expand Down
31 changes: 15 additions & 16 deletions lib/poll-loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,24 @@ extern "C" {
/* Schedule events to wake up the following poll_block().
*
* The poll_loop logs the 'where' argument to each function at "debug" level
* when an event causes a wakeup. Ordinarily, it is automatically filled in
* with the location in the source of the call, and the caller should therefore
* omit it. But, if the function you are implementing is very generic, so that
* its location in the source would not be very helpful for debugging, you can
* avoid the macro expansion and pass a different argument, e.g.:
* (poll_fd_wait)(fd, events, where);
* See timer_wait() for an example.
*/
void poll_fd_wait(int fd, short int events, const char *where);
#define poll_fd_wait(fd, events) poll_fd_wait(fd, events, SOURCE_LOCATOR)
* when an event causes a wakeup. Each of these ways to schedule an event has
* a function and a macro wrapper. The macro version automatically supplies
* the source code location of the caller. The function version allows the
* caller to supply a location explicitly, which is useful if the caller's own
* caller would be more useful in log output. See timer_wait_at() for an
* example. */
void poll_fd_wait_at(int fd, short int events, const char *where);
#define poll_fd_wait(fd, events) poll_fd_wait_at(fd, events, SOURCE_LOCATOR)

void poll_timer_wait(long long int msec, const char *where);
#define poll_timer_wait(msec) poll_timer_wait(msec, SOURCE_LOCATOR)
void poll_timer_wait_at(long long int msec, const char *where);
#define poll_timer_wait(msec) poll_timer_wait_at(msec, SOURCE_LOCATOR)

void poll_timer_wait_until(long long int msec, const char *where);
#define poll_timer_wait_until(msec) poll_timer_wait_until(msec, SOURCE_LOCATOR)
void poll_timer_wait_until_at(long long int msec, const char *where);
#define poll_timer_wait_until(msec) \
poll_timer_wait_until_at(msec, SOURCE_LOCATOR)

void poll_immediate_wake(const char *where);
#define poll_immediate_wake() poll_immediate_wake(SOURCE_LOCATOR)
void poll_immediate_wake_at(const char *where);
#define poll_immediate_wake() poll_immediate_wake_at(SOURCE_LOCATOR)

/* Wait until an event occurs. */
void poll_block(void);
Expand Down
12 changes: 8 additions & 4 deletions lib/timer.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011 Nicira, Inc.
* Copyright (c) 2011, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -32,11 +32,15 @@ timer_msecs_until_expired(const struct timer *timer)
}
}

/* Causes poll_block() to wake when 'timer' expires. */
/* Causes poll_block() to wake when 'timer' expires.
*
* ('where' is used in debug logging. Commonly one would use timer_wait() to
* automatically provide the caller's source file and line number for
* 'where'.) */
void
(timer_wait)(const struct timer *timer, const char *where)
timer_wait_at(const struct timer *timer, const char *where)
{
if (timer->t < LLONG_MAX) {
(poll_timer_wait_until)(timer->t, where);
poll_timer_wait_until_at(timer->t, where);
}
}
6 changes: 3 additions & 3 deletions lib/timer.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011 Nicira, Inc.
* Copyright (c) 2011, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -27,8 +27,8 @@ struct timer {
};

long long int timer_msecs_until_expired(const struct timer *);
void timer_wait(const struct timer *, const char *where);
#define timer_wait(timer) timer_wait(timer, SOURCE_LOCATOR)
void timer_wait_at(const struct timer *, const char *where);
#define timer_wait(timer) timer_wait_at(timer, SOURCE_LOCATOR)

/* Causes 'timer' to expire when 'duration' milliseconds have passed.
*
Expand Down

0 comments on commit 5453ae2

Please sign in to comment.