From 7d4f1f16c26d7905e50ba97385040de0e37851ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Mon, 17 Jun 2013 20:28:15 +0200 Subject: [PATCH 01/24] Add header for simple atomic operations --- include/ucore/atomic.h | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 include/ucore/atomic.h diff --git a/include/ucore/atomic.h b/include/ucore/atomic.h new file mode 100644 index 0000000..c5bbe1d --- /dev/null +++ b/include/ucore/atomic.h @@ -0,0 +1,44 @@ +#ifndef UC_ATOMIC_H_ +#define UC_ATOMIC_H_ + +#ifdef __GNUC__ + + +/** + * Atomically add val to *ptr + * @return *ptr before the addition + */ +#define UC_ATOMIC_ADD(ptr, val) __sync_fetch_and_add((ptr), (val)) + +/** + * Atomically subtract val to *ptr + * @return *ptr before the subtraction + */ +#define UC_ATOMIC_SUB(ptr, val) __sync_fetch_and_add((ptr), -(val)) + +/** + * Atomically decrement *ptr + * @return *ptr before the decrement + */ +#define UC_ATOMIC_DEC(ptr) UC_ATOMIC_ADD((ptr), -1) + +/** + * Atomically increment *ptr + * @return *ptr before the increment + */ +#define UC_ATOMIC_INC(ptr) UC_ATOMIC_SUB((ptr), 1) + + +/** + * UC_ATOMIC_CAS(p, 12, + * Compare-And-Swap. If *ptr is oldval, write newwal to *ptr. + * @return *ptr that was before the operation. + */ +#define UC_ATOMIC_CAS(ptr, oldval, newval) __sync_val_compare_and_swap((ptr), (oldval), (newval)) + +#else +#error "No atomic operations implemented for this compiler" +#endif + + +#endif From b219136d6e8e471812ec902dc88fc4dd7ee9195b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Mon, 17 Jun 2013 20:32:15 +0200 Subject: [PATCH 02/24] fix UC_ATOMIC_DEC --- include/ucore/atomic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ucore/atomic.h b/include/ucore/atomic.h index c5bbe1d..1d7184d 100644 --- a/include/ucore/atomic.h +++ b/include/ucore/atomic.h @@ -20,7 +20,7 @@ * Atomically decrement *ptr * @return *ptr before the decrement */ -#define UC_ATOMIC_DEC(ptr) UC_ATOMIC_ADD((ptr), -1) +#define UC_ATOMIC_DEC(ptr) UC_ATOMIC_SUB((ptr), 1) /** * Atomically increment *ptr From e03b9a9f809d25f974407a7731b54206e9f64df0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 19 Jun 2013 18:47:45 +0200 Subject: [PATCH 03/24] Update docs --- include/ucore/atomic.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/ucore/atomic.h b/include/ucore/atomic.h index 1d7184d..5311352 100644 --- a/include/ucore/atomic.h +++ b/include/ucore/atomic.h @@ -1,8 +1,12 @@ #ifndef UC_ATOMIC_H_ #define UC_ATOMIC_H_ -#ifdef __GNUC__ +/** Atomic functions (macros). The ptr argument must be a pointer to + * an integer type. + * For gcc, see http://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/_005f_005fsync-Builtins.html + */ +#ifdef __GNUC__ /** * Atomically add val to *ptr @@ -11,7 +15,7 @@ #define UC_ATOMIC_ADD(ptr, val) __sync_fetch_and_add((ptr), (val)) /** - * Atomically subtract val to *ptr + * Atomically subtract val from *ptr * @return *ptr before the subtraction */ #define UC_ATOMIC_SUB(ptr, val) __sync_fetch_and_add((ptr), -(val)) @@ -30,8 +34,7 @@ /** - * UC_ATOMIC_CAS(p, 12, - * Compare-And-Swap. If *ptr is oldval, write newwal to *ptr. + * Atomic Compare-And-Swap. If *ptr is oldval, write newwal to *ptr. * @return *ptr that was before the operation. */ #define UC_ATOMIC_CAS(ptr, oldval, newval) __sync_val_compare_and_swap((ptr), (oldval), (newval)) From 6268e6ac8ee08a0b17ebb6ac4ed03fcaa4dbdaa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 19 Jun 2013 18:48:27 +0200 Subject: [PATCH 04/24] update comments --- include/ucore/bitvec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ucore/bitvec.h b/include/ucore/bitvec.h index af11d67..acbedaa 100644 --- a/include/ucore/bitvec.h +++ b/include/ucore/bitvec.h @@ -8,7 +8,7 @@ extern "C" { struct UCBitVec { //storage for the bits unsigned long *vec; - //length of the above vec. (Not the number of bits !) + //length in bytes of the above vec. size_t vec_len; }; From b4f9ecafe25a52f2e38f269f267c75de3d4c0189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 19 Jun 2013 18:48:45 +0200 Subject: [PATCH 05/24] add C++ guards --- include/ucore/backtrace.h | 11 +++++++++-- include/ucore/clock.h | 7 +++++++ include/ucore/iomux.h | 9 +++++++++ include/ucore/mersenne_twister.h | 7 +++++++ include/ucore/read_file.h | 8 ++++++++ include/ucore/timers.h | 7 +++++++ include/ucore/version.h | 8 ++++++++ 7 files changed, 55 insertions(+), 2 deletions(-) diff --git a/include/ucore/backtrace.h b/include/ucore/backtrace.h index 0110165..d1c43d5 100644 --- a/include/ucore/backtrace.h +++ b/include/ucore/backtrace.h @@ -1,9 +1,12 @@ #ifndef UC_BACKTRACE_H_ #define UC_BACKTRACE_H_ - -#define UC_BACTRACE_STDERR uc_backtrace_fd(2) #include +#ifdef __cplusplus +extern "C" { +#endif + +#define UC_BACTRACE_STDERR uc_backtrace_fd(2) /** * Print a stacktrace to the given file descriptor. * @@ -21,4 +24,8 @@ void uc_backtrace_fd(int fd); */ void uc_backtrace_buf(char *buf, size_t len); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/ucore/clock.h b/include/ucore/clock.h index fce2c82..b64c4a9 100644 --- a/include/ucore/clock.h +++ b/include/ucore/clock.h @@ -4,6 +4,9 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif /** * An abstract clock. @@ -110,5 +113,9 @@ void uc_settable_clock_set_tv(struct UCoreSettableClock *uclock, void uc_settable_clock_set(struct UCoreSettableClock *uclock, time_t secs, suseconds_t usecs); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/ucore/iomux.h b/include/ucore/iomux.h index 774b6d2..7f8c2f7 100644 --- a/include/ucore/iomux.h +++ b/include/ucore/iomux.h @@ -3,6 +3,11 @@ #include "timers.h" +#ifdef __cplusplus +extern "C" { +#endif + + #define MUX_EV_READ (1U << 0x00) #define MUX_EV_WRITE (1U << 0x01) //#define MUX_EV_EXCEPT (1 << 0x02) @@ -100,5 +105,9 @@ int iomux_update_events(struct IOMux *mux, struct IOMuxFD *fd); */ struct UCTimers *iomux_get_timers(struct IOMux *mux); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/ucore/mersenne_twister.h b/include/ucore/mersenne_twister.h index 1ff4e6f..f3fb166 100644 --- a/include/ucore/mersenne_twister.h +++ b/include/ucore/mersenne_twister.h @@ -1,6 +1,9 @@ #ifndef UCORE_MERSENNE_TWISTER_H #define UCORE_MERSENNE_TWISTER_H +#ifdef __cplusplus +extern "C" { +#endif /** Context used for the PRNG*/ #define MT_RAND_N 624 @@ -23,5 +26,9 @@ void mtsrand(int seed, MTRand *r); */ unsigned int mtrand(MTRand *r); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/ucore/read_file.h b/include/ucore/read_file.h index e86cc9e..173adc8 100644 --- a/include/ucore/read_file.h +++ b/include/ucore/read_file.h @@ -3,6 +3,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /** Read the content of a file. * The returned char* is malloced memory and must be freed by the caller. * The content is terminated by a nul byte, regardless of whether the content @@ -17,4 +21,8 @@ char * uc_read_file(const char *file_name, size_t *length, size_t max); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/ucore/timers.h b/include/ucore/timers.h index 19c9744..f4769e3 100644 --- a/include/ucore/timers.h +++ b/include/ucore/timers.h @@ -6,6 +6,9 @@ #include #include "rbtree.h" +#ifdef __cplusplus +extern "C" { +#endif struct UCTimer; struct UCTimers; @@ -140,4 +143,8 @@ int uc_timers_run(struct UCTimers *timers); //uc_timers_destroy(struct UCTimers *timers) is currently missing.. +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/ucore/version.h b/include/ucore/version.h index e33a37f..9f9d0b2 100644 --- a/include/ucore/version.h +++ b/include/ucore/version.h @@ -30,6 +30,9 @@ * * @endhtmlonly */ +#ifdef __cplusplus +extern "C" { +#endif /* Major version of the ucore library*/ extern const int ucore_version_major; @@ -46,5 +49,10 @@ extern const char ucore_version_str[]; /** Hostname where the library was built */ extern const char ucore_build_host[]; + +#ifdef __cplusplus +} +#endif + #endif From 012a5b1377cac9a68444cfca65b49871b75f68b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 19 Jun 2013 18:51:12 +0200 Subject: [PATCH 06/24] move iomux_impl.h to src/ dir, it's an implementation detail --- src/iomux_epoll.c | 2 +- src/iomux_impl.c | 2 +- {include/ucore => src}/iomux_impl.h | 4 ++-- src/iomux_select.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename {include/ucore => src}/iomux_impl.h (96%) diff --git a/src/iomux_epoll.c b/src/iomux_epoll.c index 21c8898..22f964b 100644 --- a/src/iomux_epoll.c +++ b/src/iomux_epoll.c @@ -4,7 +4,7 @@ #include #include #include -#include "ucore/iomux_impl.h" +#include "iomux_impl.h" //epoll (linux specific) IO mux. //We stuff the struct IOMuxFD pointer in the event.data.ptr slot diff --git a/src/iomux_impl.c b/src/iomux_impl.c index 2e47b31..f94e0c9 100644 --- a/src/iomux_impl.c +++ b/src/iomux_impl.c @@ -2,8 +2,8 @@ #include #include #include -#include #include "ucore/clock.h" +#include "iomux_impl.h" //dispatchers for the IOMux implementations */ diff --git a/include/ucore/iomux_impl.h b/src/iomux_impl.h similarity index 96% rename from include/ucore/iomux_impl.h rename to src/iomux_impl.h index 4770810..6c5484a 100644 --- a/include/ucore/iomux_impl.h +++ b/src/iomux_impl.h @@ -1,8 +1,8 @@ #ifndef IO_MUX_IMPL_H_ #define IO_MUX_IMPL_H_ -#include "iomux.h" -#include "timers.h" +#include "ucore/iomux.h" +#include "ucore/timers.h" /** struct for IOMux implementations */ struct IOMux { diff --git a/src/iomux_select.c b/src/iomux_select.c index ebad214..8b67414 100644 --- a/src/iomux_select.c +++ b/src/iomux_select.c @@ -5,8 +5,8 @@ #include #include #include -#include "ucore/iomux_impl.h" #include "ucore/utils.h" +#include "iomux_impl.h" #define IOMUX_GROW_CHUNK (32) From 84153e90dbb39414f527dc46e25b027450c199a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 20 Jun 2013 19:55:09 +0200 Subject: [PATCH 07/24] Make UC_LL_NONE work --- include/ucore/logging.h | 6 ++++-- src/logging.c | 9 ++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/ucore/logging.h b/include/ucore/logging.h index f36e1b3..9efa2d6 100644 --- a/include/ucore/logging.h +++ b/include/ucore/logging.h @@ -71,13 +71,15 @@ extern "C" { #endif -/** The log levels defined by ucore logging*/ +/** The log levels defined by ucore logging + * UC_LL_NONE must not be used in logging statements - but + * can be used to suppress all logging for a destination or module*/ enum UC_LOG_LEVEL { - UC_LL_NONE = 0, UC_LL_DEBUG = 1, UC_LL_INFO = 3, UC_LL_WARNING = 5, UC_LL_ERROR = 7, + UC_LL_NONE = 9, }; /** A destination for the logging messages*/ diff --git a/src/logging.c b/src/logging.c index 0784165..662278b 100644 --- a/src/logging.c +++ b/src/logging.c @@ -68,14 +68,15 @@ static SLIST_HEAD(, uc_log_destination) g_destinations; static int uc_log_reopen_file(struct uc_log_destination *dest); //Uses enum UC_LOG_LEVEL as index static const char *const g_log_levels[] = { - "NONE", + "UNKNOWN_0", "DEBUG", "UNKNOWN_2", "INFO", "UNKNOWN_4", "WARNING", "UNKNOWN_6", - "ERROR" + "ERROR", + "NONE" }; inline const char *uc_ll_2_str(enum UC_LOG_LEVEL l) @@ -104,7 +105,6 @@ static int uc_str_2_ll(const char *str, size_t len) static inline int uc_ll_2_syslog(enum UC_LOG_LEVEL l) { switch(l) { - case UC_LL_NONE: case UC_LL_DEBUG: return LOG_DEBUG; case UC_LL_INFO: @@ -113,6 +113,9 @@ static inline int uc_ll_2_syslog(enum UC_LOG_LEVEL l) return LOG_WARNING; case UC_LL_ERROR: return LOG_ERR; + case UC_LL_NONE: + return LOG_CRIT; //Fishy, but this should never happen + } return LOG_INFO; From 4aadb0ab2d6383187b352eb9aa047ac075127949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 20 Jun 2013 20:11:07 +0200 Subject: [PATCH 08/24] Clean up main logging function --- src/logging.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/logging.c b/src/logging.c index 662278b..cdf086a 100644 --- a/src/logging.c +++ b/src/logging.c @@ -547,22 +547,14 @@ void uc_logf(int log_level, int module, int raw, { va_list ap; struct uc_log_destination *dest; - const struct uc_log_module *log_module; va_start(ap, fmt); pthread_mutex_lock(&g_log_lock); - - //Find the module doign the logging, or use the unknown module - - //the latter would indicate a bug somewhere in the application as it should - //always specify a known module - if (module >= 0 && module < g_modules.cnt) - log_module = &g_modules.mods[module]; - else - log_module = &g_unknown_module; //do logging for each destination SLIST_FOREACH(dest, &g_destinations, entry) { + const struct uc_log_module *log_module; va_list apc; int module_log_level; @@ -571,11 +563,16 @@ void uc_logf(int log_level, int module, int raw, if (log_level < dest->log_level) continue; - //individual module level - if (module >= 0 && module < g_modules.cnt) + //Find the module doing the logging, or use the unknown module - + //the latter would indicate a bug somewhere in the application as it should + //always specify a known module + if (module >= 0 && module < g_modules.cnt) { module_log_level = dest->module_settings[module].log_level; - else //application bug. use global/unknown module + log_module = &g_modules.mods[module]; + } else { + log_module = &g_unknown_module; module_log_level = log_module->log_level; + } if (log_level < module_log_level) continue; From bcf0d66e4ea39e464bd7ad1e2c3e4cf4cdfbfdb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 20 Jun 2013 20:15:19 +0200 Subject: [PATCH 09/24] Add LL_NONE test --- test/test_logging.c | 61 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/test/test_logging.c b/test/test_logging.c index d0ad57f..76d1919 100644 --- a/test/test_logging.c +++ b/test/test_logging.c @@ -410,6 +410,64 @@ START_TEST (test_logfile_dest_mask) fail_if(st.st_size != 14*2, "was %ld\n", (long)st.st_size); END_TEST +START_TEST (test_loglevel_module_none) + + struct uc_log_module m = { + .id = 0, + .short_name = "MOD1", + .long_name = "Module 1", + .log_level = UC_LL_NONE, + }; + struct uc_log_modules mods = { + .mods = &m, + .cnt = 1, + }; + struct stat st; + struct uc_log_destination *dest; + int rc; + + uc_log_init(&mods); + + dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 1); + fail_if(dest == NULL); + uc_log_add_destination(dest); + + UC_LOGFR(UC_LL_ERROR, 0, "Lorum ipson %d\n", 1); + + rc = stat(FILE_NAME, &st); + fail_if(rc != 0, "stat failed: %s\n", strerror(errno)); + fail_if(st.st_size != 0, "was %ld\n", (long)st.st_size); +END_TEST + +START_TEST (test_loglevel_dest_none) + + struct uc_log_module m = { + .id = 0, + .short_name = "MOD1", + .long_name = "Module 1", + .log_level = UC_LL_DEBUG, + }; + struct uc_log_modules mods = { + .mods = &m, + .cnt = 1, + }; + struct stat st; + struct uc_log_destination *dest; + int rc; + + uc_log_init(&mods); + + dest = uc_log_new_file(FILE_NAME, UC_LL_NONE, 1); + fail_if(dest == NULL); + uc_log_add_destination(dest); + + UC_LOGFR(UC_LL_WARNING, 0, "Lorum ipson %d\n", 1); + + rc = stat(FILE_NAME, &st); + fail_if(rc != 0, "stat failed: %s\n", strerror(errno)); + fail_if(st.st_size != 0, "was %ld\n", (long)st.st_size); +END_TEST + Suite *logging_suite(void) { @@ -435,6 +493,9 @@ Suite *logging_suite(void) tcase_add_test(tc2, test_logfile_invalid_file_after_reopen); tcase_add_test(tc1, test_logfile_raw); + tcase_add_test(tc1, test_loglevel_module_none); + tcase_add_test(tc1, test_loglevel_dest_none); + tcase_add_checked_fixture(tc1, logging_rm_files, logging_rm_files); tcase_add_checked_fixture(tc2, logging_setup_subdir, logging_rm_subdir); From 9b7db5440e4b5fdcc0efb1372563db88191a7c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 27 Jun 2013 20:58:07 +0200 Subject: [PATCH 10/24] Allow CC shell environment to override compiler --- SConstruct | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SConstruct b/SConstruct index 695afbe..d32cd4d 100644 --- a/SConstruct +++ b/SConstruct @@ -59,6 +59,11 @@ def InstallPerm(env, dest, files, perm): env = Environment(tools = ['default', 'textfile']) + +#allow shell environment to override compiler +if os.environ.has_key('CC'): + env['CC'] = os.environ['CC'] + env.AddMethod(InstallPerm) Export('env', 'build_type', 'prefix', 'version_info', 'test_xml') From a8dcf6edff957af8db4a5c4dd203618cd34cec50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 27 Jun 2013 20:58:23 +0200 Subject: [PATCH 11/24] Get rid of inline warning from clang --- src/logging.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging.c b/src/logging.c index cdf086a..85146e8 100644 --- a/src/logging.c +++ b/src/logging.c @@ -79,7 +79,7 @@ static const char *const g_log_levels[] = { "NONE" }; -inline const char *uc_ll_2_str(enum UC_LOG_LEVEL l) +const char *uc_ll_2_str(enum UC_LOG_LEVEL l) { if (l < ARRAY_SIZE(g_log_levels)) { return g_log_levels[l]; From 1e0e840ee5ddd92f6e8ec3fb9bb5a4e995043649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 27 Jun 2013 20:58:43 +0200 Subject: [PATCH 12/24] Get rid of aligment warning on CONTAINER_OF in clang --- include/ucore/utils.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/ucore/utils.h b/include/ucore/utils.h index 9d1e86c..aad8379 100644 --- a/include/ucore/utils.h +++ b/include/ucore/utils.h @@ -48,12 +48,14 @@ //struct foo *f = CONTAINER_OF(p, struct foo, zap); #define CONTAINER_OF(ptr, type, member) ({ \ typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (unsigned char *)__mptr - offsetof(type, member) ); }) + (type *)((void *)(unsigned char *)__mptr - offsetof(type, member) ); }) + +//the void* cast is to suppress alignment warnings //Same as CONTAINER_OF, but for a const pointer to avoid gcc warnings.. #define CONST_CONTAINER_OF(ptr, type, member) ({ \ const typeof( ((const type *)0)->member ) *__mptr = (ptr); \ - (const type *)( (const unsigned char *)__mptr - offsetof(const type, member) ); }) + (const type *)((const void *)(const unsigned char *)__mptr - offsetof(const type, member) ); }) /** Align a value. * @param val value to align From 89232426e05e8593a7402b7d3eba6ed472c8e198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sun, 30 Jun 2013 14:34:19 +0200 Subject: [PATCH 13/24] Properly use return value of select to count the number of events --- src/iomux_epoll.c | 2 +- src/iomux_select.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/iomux_epoll.c b/src/iomux_epoll.c index 22f964b..65a9eaf 100644 --- a/src/iomux_epoll.c +++ b/src/iomux_epoll.c @@ -183,7 +183,7 @@ again: fd->callback(mux_, fd, events); //be sure not to use fd after the callback, it might been removed. - mux->pending_events[i].data.ptr = NULL; + mux->pending_events[i].data.ptr = NULL; //clear from pending list event_cnt++; } diff --git a/src/iomux_select.c b/src/iomux_select.c index 8b67414..ad39cf9 100644 --- a/src/iomux_select.c +++ b/src/iomux_select.c @@ -168,17 +168,18 @@ again: } if (FD_ISSET(mux->descriptors[i]->fd, &read_set)) { + rc--; events |= MUX_EV_READ; } if (FD_ISSET(mux->descriptors[i]->fd, &write_set)) { + rc--; events |= MUX_EV_WRITE; } if (events) { assert(mux->descriptors[i]->callback != NULL); mux->descriptors[i]->callback(mux_, mux->descriptors[i], events); - rc--; event_cnt++; } } From bf9802e565140943e246d833931cc9cf6010c18d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sun, 30 Jun 2013 21:42:02 +0200 Subject: [PATCH 14/24] First iteration of mbuf, message buffer api --- include/ucore/mbuf.h | 78 +++++++++++++++++ src/mbuf.c | 101 ++++++++++++++++++++++ test/test_mbuf.c | 197 +++++++++++++++++++++++++++++++++++++++++++ test/test_runner.c | 4 +- 4 files changed, 379 insertions(+), 1 deletion(-) create mode 100644 include/ucore/mbuf.h create mode 100644 src/mbuf.c create mode 100644 test/test_mbuf.c diff --git a/include/ucore/mbuf.h b/include/ucore/mbuf.h new file mode 100644 index 0000000..ebfc8aa --- /dev/null +++ b/include/ucore/mbuf.h @@ -0,0 +1,78 @@ +#ifndef UC_MBUF_H_ +#define UC_MBUF_H_ +#include +#include + +#ifdef __GNUC__ +# define UC_INLINE inline __attribute__((always_inline)) +#else +# define UC_INLINE inline +#endif + +enum UC_MBUF_FLAGS { + UC_MBUF_FL_MALLOC = 0x0001, //MBuf and MBuf->bufstart are seperatly malloc'd + UC_MBUF_FL_MALLOC_BUF = 0x0001, //MBuf is not malloc'd. MBuf->bufstart is malloc'd + UC_MBUF_FL_MALLOC_INLINE = 0x0002, //MBuf is one big malloc. Can't be resized + UC_MBUF_FL_STATIC = 0x0004, //MBuf and MBuf->bustart is user controlled. Can't be resized +}; + +struct MBuf { + struct MBuf *next; + uint8_t *p1; + uint8_t *p2; + uint8_t *p3; + uint8_t *p4; + void *cookie; + uint32_t flags; + uint32_t allocated; + uint8_t *bufstart; + uint8_t *head; + uint8_t *tail; + uint8_t inline_data[0]; +}; + +/* Conventions: + * push - prepend data to the buffer (in the head room part) + * pull - remove data from the beginning of the message. + * put - Add data to the buffer. + */ +struct MBuf *uc_mbuf_new_hr(uint32_t len, uint32_t headroom); +#define uc_mbuf_new(len) uc_mbuf_new_hr((len), 0) + +struct MBuf *uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom); +#define uc_mbuf_new_inline(len) uc_mbuf_new_inline_hr((len), 0) + +void uc_mbuf_free(struct MBuf *mbuf); +struct MBuf *uc_mbuf_copy(struct MBuf *mbuf); + +void uc_mbuf_init(struct MBuf *mbuf, uint8_t *buf, uint32_t len, uint32_t headroom, uint32_t flags); +void uc_mbuf_zero(struct MBuf *mbuf); +void uc_mbuf_reset(struct MBuf *mbuf); + +static UC_INLINE uint32_t uc_mbuf_len(struct MBuf *mbuf) +{ + return (uint32_t)(mbuf->tail - mbuf->head); +} + +static UC_INLINE uint32_t uc_mbuf_tailroom(struct MBuf *mbuf) +{ + return mbuf->allocated - (uint32_t)(mbuf->tail - mbuf->bufstart); +} + +static inline uint32_t uc_mbuf_headroom(struct MBuf *mbuf) +{ + return (uint32_t)(mbuf->head - mbuf->bufstart); +} + +uint8_t *uc_mbuf_put(struct MBuf *mbuf, uint32_t size); + +uint8_t *uc_mbuf_push(struct MBuf *mbuf, uint32_t size); + +uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size); + +struct MBuf *uc_uc_mbuf_new_hr(uint32_t len, uint32_t headroom); +struct MBuf *uc_uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom); + +#undef UC_INLINE + +#endif diff --git a/src/mbuf.c b/src/mbuf.c new file mode 100644 index 0000000..80a551e --- /dev/null +++ b/src/mbuf.c @@ -0,0 +1,101 @@ +#include +#include +#include "ucore/mbuf.h" + +uint8_t *uc_mbuf_put(struct MBuf *mbuf, uint32_t size) +{ + uint8_t *data = mbuf->tail; + if (uc_mbuf_tailroom(mbuf) < size) { + return NULL; + } + + mbuf->tail += size; + + return data; +} + +uint8_t *uc_mbuf_push(struct MBuf *mbuf, uint32_t size) +{ + if (uc_mbuf_headroom(mbuf) < size) { + return NULL; + } + + mbuf->head -= size; + + return mbuf->head; +} + +uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size) +{ + uint8_t *data = mbuf->head; + if (uc_mbuf_len(mbuf) < size) { + return NULL; + } + + mbuf->head += size; + + return data; +} + + +void uc_mbuf_init(struct MBuf *mbuf, uint8_t *buf, uint32_t len, uint32_t headroom, uint32_t flags) +{ + mbuf->bufstart = buf; + mbuf->next = NULL; + mbuf->p1 = mbuf->p2 = mbuf->p3 = mbuf->p4 = NULL; + mbuf->cookie = NULL; + mbuf->flags = flags; + mbuf->allocated = len + headroom; + mbuf->head = mbuf->bufstart + headroom; + mbuf->tail = mbuf->head; +} + +struct MBuf *uc_mbuf_new_hr(uint32_t len, uint32_t headroom) +{ + struct MBuf *mbuf; + uint8_t *buf; + + mbuf = malloc(sizeof *mbuf); + if (mbuf == NULL) + return mbuf; + + buf = malloc(len + headroom); + if (buf == NULL) { + free(mbuf); + return NULL; + } + + uc_mbuf_init(mbuf, buf, len, headroom, UC_MBUF_FL_MALLOC); + + return mbuf; +} + +struct MBuf *uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom) +{ + struct MBuf *mbuf; + + mbuf = malloc(sizeof *mbuf + len + headroom); + if (mbuf == NULL) + return mbuf; + + uc_mbuf_init(mbuf, mbuf->inline_data, len, headroom, UC_MBUF_FL_MALLOC_INLINE); + + return mbuf; +} + +void uc_mbuf_free(struct MBuf *mbuf) +{ + if (mbuf->flags & (UC_MBUF_FL_MALLOC | UC_MBUF_FL_MALLOC_BUF)) + free(mbuf->bufstart); + + if (mbuf->flags & (UC_MBUF_FL_MALLOC | UC_MBUF_FL_MALLOC_INLINE)) + free(mbuf); +} + +void uc_mbuf_zero(struct MBuf *mbuf) +{ + memset(mbuf->bufstart, 0, mbuf->allocated); +} + +#undef UC_INLINE + diff --git a/test/test_mbuf.c b/test/test_mbuf.c new file mode 100644 index 0000000..b465110 --- /dev/null +++ b/test/test_mbuf.c @@ -0,0 +1,197 @@ +#include +#include +#include + + +START_TEST (test_mbuf_new) + struct MBuf *mbuf; + + mbuf = uc_mbuf_new(110); + + fail_if(mbuf == NULL); + fail_if(uc_mbuf_len(mbuf) != 0); + fail_if(uc_mbuf_headroom(mbuf) != 0); + fail_if(uc_mbuf_tailroom(mbuf) != 110); + fail_if(mbuf->next != NULL); + fail_if(mbuf->p1 != NULL); + fail_if(mbuf->p2 != NULL); + fail_if(mbuf->p3 != NULL); + fail_if(mbuf->p4 != NULL); + fail_if(mbuf->cookie != NULL); + fail_if(mbuf->head != mbuf->tail); + + uc_mbuf_free(mbuf); + +END_TEST + +START_TEST (test_mbuf_new_inline) + struct MBuf *mbuf; + + mbuf = uc_mbuf_new_inline(110); + + fail_if(mbuf == NULL); + fail_if(uc_mbuf_len(mbuf) != 0); + fail_if(uc_mbuf_headroom(mbuf) != 0); + fail_if(uc_mbuf_tailroom(mbuf) != 110); + fail_if(mbuf->next != NULL); + fail_if(mbuf->p1 != NULL); + fail_if(mbuf->p2 != NULL); + fail_if(mbuf->p3 != NULL); + fail_if(mbuf->p4 != NULL); + fail_if(mbuf->cookie != NULL); + fail_if(mbuf->head != mbuf->tail); + + uc_mbuf_free(mbuf); + +END_TEST + +START_TEST (test_mbuf_new_headroom) + struct MBuf *mbuf; + + mbuf = uc_mbuf_new_hr(110,20); + + fail_if(mbuf == NULL); + fail_if(uc_mbuf_len(mbuf) != 0); + fail_if(uc_mbuf_headroom(mbuf) != 20); + fail_if(uc_mbuf_tailroom(mbuf) != 110); + fail_if(mbuf->next != NULL); + fail_if(mbuf->p1 != NULL); + fail_if(mbuf->p2 != NULL); + fail_if(mbuf->p3 != NULL); + fail_if(mbuf->p4 != NULL); + fail_if(mbuf->cookie != NULL); + fail_if(mbuf->head != mbuf->tail); + + uc_mbuf_free(mbuf); + +END_TEST + +START_TEST (test_mbuf_put) + struct MBuf *mbuf; + uint8_t *data; + + mbuf = uc_mbuf_new_inline(111); + fail_if(mbuf == NULL); + + data = uc_mbuf_put(mbuf, 111); + fail_if(data == NULL); + fail_if(uc_mbuf_len(mbuf) != 111); + fail_if(uc_mbuf_tailroom(mbuf) != 0); + + memset(data, 0, 111); + + uc_mbuf_free(mbuf); + +END_TEST + +START_TEST (test_mbuf_put_fail) + struct MBuf *mbuf; + uint8_t *data; + + mbuf = uc_mbuf_new_inline(10); + fail_if(mbuf == NULL); + + data = uc_mbuf_put(mbuf, 11); + fail_if(data != NULL); + + uc_mbuf_free(mbuf); + +END_TEST + +START_TEST (test_mbuf_push) + struct MBuf *mbuf; + uint8_t *data; + + mbuf = uc_mbuf_new_hr(10,1); + fail_if(mbuf == NULL); + + data = uc_mbuf_push(mbuf, 1); + fail_if(data == NULL); + fail_if(uc_mbuf_len(mbuf) != 1); + fail_if(uc_mbuf_headroom(mbuf) != 0); + + *data = 0; + + uc_mbuf_free(mbuf); + +END_TEST + + +START_TEST (test_mbuf_push_fail) + struct MBuf *mbuf; + uint8_t *data; + + mbuf = uc_mbuf_new_hr(1,2); + fail_if(mbuf == NULL); + + data = uc_mbuf_push(mbuf, 3); + fail_if(data != NULL); + + uc_mbuf_free(mbuf); + +END_TEST + +START_TEST (test_mbuf_pull) + struct MBuf *mbuf; + uint8_t *data1; + uint8_t *data2; + + mbuf = uc_mbuf_new_inline(10); + fail_if(mbuf == NULL); + + data1 = uc_mbuf_put(mbuf, 10); + fail_if(data1 == NULL); + fail_if(uc_mbuf_tailroom(mbuf) != 0); + fail_if(uc_mbuf_len(mbuf) != 10); + + data2 = uc_mbuf_pull(mbuf,10); + fail_if(data2 == NULL); + fail_if(data1 != data2); + fail_if(uc_mbuf_len(mbuf) != 0); + + uc_mbuf_free(mbuf); + +END_TEST + +START_TEST (test_mbuf_pull_fail) + struct MBuf *mbuf; + uint8_t *data1; + uint8_t *data2; + + mbuf = uc_mbuf_new_inline(10); + fail_if(mbuf == NULL); + + data1 = uc_mbuf_put(mbuf, 10); + fail_if(data1 == NULL); + fail_if(uc_mbuf_len(mbuf) != 10); + + data2 = uc_mbuf_pull(mbuf,11); + fail_if(data2 != NULL); + fail_if(uc_mbuf_len(mbuf) != 10); + + + uc_mbuf_free(mbuf); + +END_TEST + + + +Suite *mbuf_suite(void) +{ + Suite *s = suite_create("mbuf"); + TCase *tc = tcase_create("mbuf tests"); + tcase_add_test(tc, test_mbuf_new); + tcase_add_test(tc, test_mbuf_new_inline); + tcase_add_test(tc, test_mbuf_new_headroom); + tcase_add_test(tc, test_mbuf_put); + tcase_add_test(tc, test_mbuf_put_fail); + tcase_add_test(tc, test_mbuf_push); + tcase_add_test(tc, test_mbuf_push_fail); + tcase_add_test(tc, test_mbuf_pull); + tcase_add_test(tc, test_mbuf_pull_fail); + + suite_add_tcase(s, tc); + + return s; +} + diff --git a/test/test_runner.c b/test/test_runner.c index d85129a..d844221 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -19,6 +19,7 @@ extern Suite *clock_suite(void); extern Suite *seq_suite(void); extern Suite *sat_math_suite(void); extern Suite *timers_suite(void); +extern Suite *mbuf_suite(void); static suite_func suites[] = { bitvec_suite, @@ -33,7 +34,8 @@ static suite_func suites[] = { clock_suite, seq_suite, sat_math_suite, - timers_suite + timers_suite, + mbuf_suite }; int From 764dfc563c82f73b24ad6546860d92183e9cfa05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Mon, 1 Jul 2013 23:00:19 +0200 Subject: [PATCH 15/24] Don't trt yo be smart with the comma operator --- src/tval.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/tval.c b/src/tval.c index b2a2eea..4218742 100644 --- a/src/tval.c +++ b/src/tval.c @@ -6,8 +6,10 @@ uc_tvadd(struct timeval *dst, const struct timeval *a, const struct timeval *b) dst->tv_sec = a->tv_sec + b->tv_sec; dst->tv_usec = a->tv_usec + b->tv_usec; - if (dst->tv_usec >= 1000000) - dst->tv_sec++, dst->tv_usec -= 1000000; + if (dst->tv_usec >= 1000000) { + dst->tv_sec++; + dst->tv_usec -= 1000000; + } return dst; } @@ -18,8 +20,10 @@ uc_tvsub(struct timeval *dst, const struct timeval *a, const struct timeval *b) dst->tv_sec = a->tv_sec - b->tv_sec; dst->tv_usec = a->tv_usec - b->tv_usec; - if (dst->tv_usec < 0) - dst->tv_sec--, dst->tv_usec += 1000000; + if (dst->tv_usec < 0) { + dst->tv_sec--; + dst->tv_usec += 1000000; + } return dst; } From 6d77b78b41c3cfd5bd95e529e4aed2272aee5883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Mon, 1 Jul 2013 23:02:24 +0200 Subject: [PATCH 16/24] use unsigned long long for uc_ms2tv() --- src/tval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tval.c b/src/tval.c index 4218742..a2577e8 100644 --- a/src/tval.c +++ b/src/tval.c @@ -45,7 +45,7 @@ uc_tvcmp(const struct timeval *a, const struct timeval *b) } struct timeval * -uc_to2tv(struct timeval *dst, unsigned long ms) +uc_ms2tv(struct timeval *dst, unsigned long long ms) { dst->tv_sec = ms / 1000; dst->tv_usec = ms % 1000 * 1000; From d8376338faedc3a36bea3355c1c1d1f93bee2c46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 2 Jul 2013 21:21:27 +0200 Subject: [PATCH 17/24] Improve doxygen comments --- include/ucore/iomux.h | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/include/ucore/iomux.h b/include/ucore/iomux.h index 7f8c2f7..20a64cb 100644 --- a/include/ucore/iomux.h +++ b/include/ucore/iomux.h @@ -43,6 +43,9 @@ struct IOMuxFD { }; /** Creates a new IOMux. + * + * @param type the underlying implementation to use @see IOMUX_TYPE + * @return Newly allocated IOMux. NULL if memory allocation fails. */ struct IOMux *iomux_create(enum IOMUX_TYPE type); @@ -58,19 +61,27 @@ struct IOMux *iomux_create_ex(enum IOMUX_TYPE type, struct UCoreClock *uclock); void iomux_delete(struct IOMux *mux); /** Runs the event loop of the mux - * returns if the number of file descriptors and timers are 0 or + * + * @return if the number of file descriptors and timers are 0 or * an error occurs */ int iomux_run(struct IOMux *mux); -/* Adds a file descriptor to the watch set, - * returns 0 on success, an errno value on error */ +/* Adds a file descriptor to the watch set. + * The file descriptor integer value must reside in only + * one struct IOMuxFD. Adding e.g. the same file descriptor + * in 2 different struct IOMuxFD, one for read events and one for + * write events is not supported. + * + * @return 0 on success, an errno value on error + */ int iomux_register_fd(struct IOMux *mux, struct IOMuxFD *fd); /** Removes the file descriptor*/ int iomux_unregister_fd(struct IOMux *mux, struct IOMuxFD *fd); /** Updates the events to watch for in fd->what - * returns 0 on success, an errno value on error */ + * @return 0 on success, an errno value on error + */ int iomux_update_events(struct IOMux *mux, struct IOMuxFD *fd); @@ -100,7 +111,7 @@ int iomux_update_events(struct IOMux *mux, struct IOMuxFD *fd); iomux_update_events((mux), (fd));\ }) -/** Returns a UCTimer instance tied to this mux. +/** @return a UCTimer instance tied to this mux. * Used to schedule timers within this mux. */ struct UCTimers *iomux_get_timers(struct IOMux *mux); From bc65b3c421f9843fe9abec830b18ee46ca8aa74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 2 Jul 2013 21:22:03 +0200 Subject: [PATCH 18/24] Check for backtrace_fd returning NULL --- src/backtrace.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/backtrace.c b/src/backtrace.c index 58e1fb2..69885b5 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -35,16 +35,18 @@ void uc_backtrace_buf(char *buf, size_t len) buf[0] = 0; lines = backtrace_symbols(buffer, ptrs); - for (i = 1; i < ptrs; i++) { + if (lines != NULL) { + for (i = 1; i < ptrs; i++) { - int rc = snprintf(buf, remaining, "%s\n", lines[i]); - - if (rc <= 0 || (size_t)rc >= remaining) { - break; + int rc = snprintf(buf, remaining, "%s\n", lines[i]); + + if (rc <= 0 || (size_t)rc >= remaining) { + break; + } + + remaining -= rc; + buf += rc; } - - remaining -= rc; - buf += rc; } free(lines); From 65c32810cb7f46b63b0bfbc7ad38257f399e3360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 2 Jul 2013 21:22:38 +0200 Subject: [PATCH 19/24] Add test for uc_mbuf-copy_data --- include/ucore/mbuf.h | 5 +---- src/mbuf.c | 22 +++++++++++++++++++++- test/test_mbuf.c | 25 +++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/include/ucore/mbuf.h b/include/ucore/mbuf.h index ebfc8aa..406f951 100644 --- a/include/ucore/mbuf.h +++ b/include/ucore/mbuf.h @@ -43,7 +43,7 @@ struct MBuf *uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom); #define uc_mbuf_new_inline(len) uc_mbuf_new_inline_hr((len), 0) void uc_mbuf_free(struct MBuf *mbuf); -struct MBuf *uc_mbuf_copy(struct MBuf *mbuf); +struct MBuf *uc_mbuf_copy_data(struct MBuf *mbuf); void uc_mbuf_init(struct MBuf *mbuf, uint8_t *buf, uint32_t len, uint32_t headroom, uint32_t flags); void uc_mbuf_zero(struct MBuf *mbuf); @@ -70,9 +70,6 @@ uint8_t *uc_mbuf_push(struct MBuf *mbuf, uint32_t size); uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size); -struct MBuf *uc_uc_mbuf_new_hr(uint32_t len, uint32_t headroom); -struct MBuf *uc_uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom); - #undef UC_INLINE #endif diff --git a/src/mbuf.c b/src/mbuf.c index 80a551e..97c1c6e 100644 --- a/src/mbuf.c +++ b/src/mbuf.c @@ -5,6 +5,7 @@ uint8_t *uc_mbuf_put(struct MBuf *mbuf, uint32_t size) { uint8_t *data = mbuf->tail; + if (uc_mbuf_tailroom(mbuf) < size) { return NULL; } @@ -28,6 +29,7 @@ uint8_t *uc_mbuf_push(struct MBuf *mbuf, uint32_t size) uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size) { uint8_t *data = mbuf->head; + if (uc_mbuf_len(mbuf) < size) { return NULL; } @@ -37,7 +39,6 @@ uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size) return data; } - void uc_mbuf_init(struct MBuf *mbuf, uint8_t *buf, uint32_t len, uint32_t headroom, uint32_t flags) { mbuf->bufstart = buf; @@ -97,5 +98,24 @@ void uc_mbuf_zero(struct MBuf *mbuf) memset(mbuf->bufstart, 0, mbuf->allocated); } +struct MBuf *uc_mbuf_copy_data(struct MBuf *mbuf) +{ + uint32_t len; + struct MBuf *copy; + uint8_t *data; + + len = uc_mbuf_len(mbuf); + + copy = uc_mbuf_new_hr(len, uc_mbuf_headroom(mbuf)); + if (copy == NULL) { + return NULL; + } + + data = uc_mbuf_put(copy, len); + memcpy(data, mbuf->head, len); + + return copy; +} + #undef UC_INLINE diff --git a/test/test_mbuf.c b/test/test_mbuf.c index b465110..98b5bdd 100644 --- a/test/test_mbuf.c +++ b/test/test_mbuf.c @@ -174,6 +174,30 @@ START_TEST (test_mbuf_pull_fail) END_TEST +START_TEST (test_mbuf_copy) + struct MBuf *mbuf; + uint8_t *data1; + struct MBuf *copy; + + mbuf = uc_mbuf_new_inline_hr(10,5); + fail_if(mbuf == NULL); + + data1 = uc_mbuf_put(mbuf, 10); + fail_if(data1 == NULL); + + strcpy((char*)data1, "123456789"); + + copy = uc_mbuf_copy_data(mbuf); + fail_if(copy == NULL); + fail_if(uc_mbuf_len(copy) != 10); + fail_if(uc_mbuf_headroom(copy) != 5); + fail_if(memcmp(mbuf->head, copy->head, 10) != 0); + + uc_mbuf_free(mbuf); + uc_mbuf_free(copy); + +END_TEST + Suite *mbuf_suite(void) @@ -189,6 +213,7 @@ Suite *mbuf_suite(void) tcase_add_test(tc, test_mbuf_push_fail); tcase_add_test(tc, test_mbuf_pull); tcase_add_test(tc, test_mbuf_pull_fail); + tcase_add_test(tc, test_mbuf_copy); suite_add_tcase(s, tc); From 4304e013432eff6b643bb61299356a225c834410 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 6 Jul 2013 20:45:39 +0200 Subject: [PATCH 20/24] Add --coverage option to SConstruct file to build with gcov coverage support --- SConstruct | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/SConstruct b/SConstruct index d32cd4d..7b7f1c4 100644 --- a/SConstruct +++ b/SConstruct @@ -36,6 +36,12 @@ AddOption('--test_xml', help='Create a result.xml when running the testsuite' ) +AddOption('--coverage', + dest='coverage', + action='store_true', + help='Build with coverage (gcov) support' +) + AddOption('--stack-protection', dest = 'stack_protection', action='store_true', @@ -85,6 +91,9 @@ if GetOption('stack_protection'): env.Append(CFLAGS = ['-fstack-protector', '--param=ssp-buffer-size=4']) env.Append(CPPDEFINES = ['_FORTIFY_SOURCE=2']) +if GetOption('coverage'): + env.Append(CFLAGS = ['--coverage']) + env.Append(LINKFLAGS = ['--coverage']) #put all .sconsign files in one place env.SConsignFile() From c68ba458464f16334c033438411cfae0464f09b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 6 Jul 2013 20:47:37 +0200 Subject: [PATCH 21/24] Build doxygen docs from include/ dir instead of src/ --- Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doxyfile b/Doxyfile index dab44b8..2f3d864 100644 --- a/Doxyfile +++ b/Doxyfile @@ -655,7 +655,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = src +INPUT = include # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is From 8200aaab217cb2893ffd1cfab3a9c67807a25835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 6 Jul 2013 21:15:51 +0200 Subject: [PATCH 22/24] Add a test case for reading /dev/null --- test/test_read_file.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/test_read_file.c b/test/test_read_file.c index 0bb4990..0f93205 100644 --- a/test/test_read_file.c +++ b/test/test_read_file.c @@ -91,6 +91,17 @@ START_TEST (test_read_file_boundary) free(content); END_TEST +START_TEST (test_read_file_devnull) + char *content; + size_t len = 123; + + content = uc_read_file("/dev/null", &len, 1024); + fail_if(content == NULL); + fail_if(len != 0); + free(content); + +END_TEST + Suite *read_file_suite(void) { Suite *s = suite_create("read_file"); @@ -99,6 +110,8 @@ Suite *read_file_suite(void) tcase_add_test(tc, test_read_file_simple); tcase_add_test(tc, test_read_file_greater_than_max); tcase_add_test(tc, test_read_file_boundary); + tcase_add_test(tc, test_read_file_devnull); + suite_add_tcase(s, tc); From 42155cae39f5e127e998499c4b29bf739086fa50 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 6 Jul 2013 22:18:09 +0200 Subject: [PATCH 23/24] Add another test for mroe coverage --- test/test_read_file.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/test_read_file.c b/test/test_read_file.c index 0f93205..90e2ff8 100644 --- a/test/test_read_file.c +++ b/test/test_read_file.c @@ -102,6 +102,28 @@ START_TEST (test_read_file_devnull) END_TEST +START_TEST (test_read_file_too_big) + char *content; + const char *filename = "test_read_file_simple"; + size_t len; + ssize_t rc; + + int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664); + fail_if(fd == -1); + + rc = write(fd, "hello", 5); + fail_if(rc != 5, "rc was %ld", (long)rc); + + close(fd); + + content = uc_read_file(filename, &len, 4); + + fail_if(errno != EMSGSIZE); + fail_if(content != NULL); + + unlink(filename); +END_TEST + Suite *read_file_suite(void) { Suite *s = suite_create("read_file"); @@ -111,6 +133,7 @@ Suite *read_file_suite(void) tcase_add_test(tc, test_read_file_greater_than_max); tcase_add_test(tc, test_read_file_boundary); tcase_add_test(tc, test_read_file_devnull); + tcase_add_test(tc, test_read_file_too_big); suite_add_tcase(s, tc); From 24bf90b7e450ab6b256209177463980399af6c7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 6 Jul 2013 22:25:06 +0200 Subject: [PATCH 24/24] Another test for more coverage --- test/test_read_file.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/test/test_read_file.c b/test/test_read_file.c index 90e2ff8..5bef1f4 100644 --- a/test/test_read_file.c +++ b/test/test_read_file.c @@ -104,7 +104,7 @@ END_TEST START_TEST (test_read_file_too_big) char *content; - const char *filename = "test_read_file_simple"; + const char *filename = "test_read_file_too_big"; size_t len; ssize_t rc; @@ -124,6 +124,32 @@ START_TEST (test_read_file_too_big) unlink(filename); END_TEST +START_TEST (test_read_file_big) + char *content; + const char *filename = "test_read_file_big"; + char buf[4096 * 16]; + size_t len; + ssize_t rc; + + int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664); + fail_if(fd == -1); + memset(buf, 'a', sizeof buf); + + rc = write(fd, buf, sizeof buf); + fail_if(rc != sizeof buf, "rc was %ld", (long)rc); + + close(fd); + + content = uc_read_file(filename, &len, 4096*16); + fail_if(content == NULL); + fail_if(len != sizeof buf); + fail_if(memcmp(content, buf, sizeof buf) != 0); + + free(content); + + unlink(filename); +END_TEST + Suite *read_file_suite(void) { Suite *s = suite_create("read_file"); @@ -134,6 +160,7 @@ Suite *read_file_suite(void) tcase_add_test(tc, test_read_file_boundary); tcase_add_test(tc, test_read_file_devnull); tcase_add_test(tc, test_read_file_too_big); + tcase_add_test(tc, test_read_file_big); suite_add_tcase(s, tc);