From 5125afc819f831bd8a77ea144b2bba49a9528a97 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sat, 28 Apr 2012 23:29:56 +0200 Subject: [PATCH] Conf: Made the default context static This involves some bits of magic with constructor priorities and a hack, which forces linking of conf-context.c. --- ucw/conf-context.c | 34 ++++++++++++++++++---------------- ucw/conf-input.c | 2 +- ucw/conf-internal.h | 9 ++++++++- ucw/conf.h | 15 ++++----------- ucw/lib.h | 1 + ucw/threads-conf.c | 2 +- ucw/threads.c | 4 ++-- 7 files changed, 35 insertions(+), 32 deletions(-) diff --git a/ucw/conf-context.c b/ucw/conf-context.c index 1584143c..8a7b4a6b 100644 --- a/ucw/conf-context.c +++ b/ucw/conf-context.c @@ -12,20 +12,20 @@ #include #include -#ifndef CONFIG_UCW_DEFAULT_CONFIG -#define CONFIG_UCW_DEFAULT_CONFIG NULL -#endif +static struct cf_context cf_default_context; -#ifndef CONFIG_UCW_ENV_VAR_CONFIG -#define CONFIG_UCW_ENV_VAR_CONFIG NULL -#endif +static void +cf_init_context(struct cf_context *cc) +{ + cc->need_journal = 1; + clist_init(&cc->conf_entries); +} struct cf_context * cf_new_context(void) { struct cf_context *cc = xmalloc_zero(sizeof(*cc)); - cc->need_journal = 1; - clist_init(&cc->conf_entries); + cf_init_context(cc); return cc; } @@ -33,6 +33,7 @@ void cf_free_context(struct cf_context *cc) { ASSERT(!cc->is_active); + ASSERT(cc != &cf_default_context); xfree(cc->parser); xfree(cc); } @@ -53,15 +54,16 @@ cf_switch_context(struct cf_context *cc) return prev; } +static void CONSTRUCTOR_WITH_PRIORITY(10100) +cf_init_default_context(void) +{ + cf_init_context(&cf_default_context); + ucwlib_thread_context()->cf_context = &cf_default_context; + cf_default_context.is_active = 1; +} + struct cf_context * cf_obtain_context(void) { - struct ucwlib_context *uc = ucwlib_thread_context(); - if (unlikely(!uc->cf_context)) - { - struct cf_context *cc = cf_new_context(); - uc->cf_context = cc; - cc->is_active = 1; - } - return uc->cf_context; + return cf_get_context(); } diff --git a/ucw/conf-input.c b/ucw/conf-input.c index 92acb35d..f8ed1ff0 100644 --- a/ucw/conf-input.c +++ b/ucw/conf-input.c @@ -475,7 +475,7 @@ final_commit(struct cf_context *cc) int cf_getopt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index) { - struct cf_context *cc = cf_obtain_context(); + struct cf_context *cc = cf_get_context(); cc->postpone_commit = 1; while (1) { diff --git a/ucw/conf-internal.h b/ucw/conf-internal.h index 7f10a85f..a47ab466 100644 --- a/ucw/conf-internal.h +++ b/ucw/conf-internal.h @@ -63,9 +63,16 @@ struct cf_context { static inline struct cf_context * cf_get_context(void) { - return ucwlib_thread_context()->cf_context; + struct cf_context *cc = ucwlib_thread_context()->cf_context; + ASSERT(cc->is_active); + return cc; } +// In fact, this is equivalent to cf_get_context(), but it is not inlined, +// because we want to force the linker to include conf-context.c, which contains +// a constructor of the whole context mechanism. +struct cf_context *cf_obtain_context(void); + /* conf-intr.c */ #define OP_MASK 0xff // only get the operation #define OP_OPEN 0x100 // here we only get an opening brace instead of parameters diff --git a/ucw/conf.h b/ucw/conf.h index a15d0da2..82bc852f 100644 --- a/ucw/conf.h +++ b/ucw/conf.h @@ -21,10 +21,10 @@ struct mempool; * ~~~~~~~~~~~~~~~~~~~~~~ * * The state of the configuration parser is stored within a configuration context. - * If you do not create contexts explicitly, the library will create one for you - * and you need not care, as long as you use a single configuration file. + * One such context is automatically created during initialization of the library + * and you need not care about more, as long as you use a single configuration file. * - * In whole generality, you can define as many context as you wish and switch + * In full generality, you can define as many context as you wish and switch * between them. Each thread has its own pointer to the current context, which * must not be shared with other threads. ***/ @@ -34,7 +34,7 @@ struct cf_context *cf_new_context(void); /** * Free a configuration context. The context must not be set as current - * for any thread. + * for any thread, nor can it be the default context. * * All configuration settings made within the context are rolled back * (except when journalling is turned off). All memory allocated on behalf @@ -49,12 +49,6 @@ void cf_free_context(struct cf_context *cc); **/ struct cf_context *cf_switch_context(struct cf_context *cc); -/** - * Return a pointer to the current context, or create the default context - * if there is no context active. - **/ -struct cf_context *cf_obtain_context(void); - /*** === Data types [[conf_types]] ***/ enum cf_class { /** Class of the configuration item. **/ @@ -423,4 +417,3 @@ char *cf_parse_double(const char *str, double *ptr); /** Parser for doubles. **/ char *cf_parse_ip(const char *p, u32 *varp); /** Parser for IP addresses. **/ #endif - diff --git a/ucw/lib.h b/ucw/lib.h index f894d2c4..e7518def 100644 --- a/ucw/lib.h +++ b/ucw/lib.h @@ -59,6 +59,7 @@ #define NONRET __attribute__((noreturn)) /** Function does not return **/ #define UNUSED __attribute__((unused)) /** Variable/parameter is knowingly unused **/ #define CONSTRUCTOR __attribute__((constructor)) /** Call function upon start of program **/ +#define CONSTRUCTOR_WITH_PRIORITY(p) __attribute__((constructor(p))) /** Define constructor with a given priority **/ #define PACKED __attribute__((packed)) /** Structure should be packed **/ #define CONST __attribute__((const)) /** Function depends only on arguments **/ #define PURE __attribute__((pure)) /** Function depends only on arguments and global vars **/ diff --git a/ucw/threads-conf.c b/ucw/threads-conf.c index b96f867f..68abbdae 100644 --- a/ucw/threads-conf.c +++ b/ucw/threads-conf.c @@ -20,7 +20,7 @@ static struct cf_section threads_config = { } }; -static void CONSTRUCTOR +static void CONSTRUCTOR_WITH_PRIORITY(19999) ucwlib_threads_conf_init(void) { cf_declare_section("Threads", &threads_config, 0); diff --git a/ucw/threads.c b/ucw/threads.c index bd242310..1377733b 100644 --- a/ucw/threads.c +++ b/ucw/threads.c @@ -67,7 +67,7 @@ ucwlib_tid(void) /*** Thread context ***/ -static void CONSTRUCTOR +static void CONSTRUCTOR_WITH_PRIORITY(10000) ucwlib_threads_init_master(void) { pthread_mutex_init(&ucwlib_master_mutex, NULL); @@ -95,7 +95,7 @@ ucwlib_free_thread_context(void *p) xfree(p); } -static void CONSTRUCTOR +static void CONSTRUCTOR_WITH_PRIORITY(10000) ucwlib_threads_init(void) { if (pthread_key_create(&ucwlib_context_key, ucwlib_free_thread_context) < 0) -- 2.39.5