From 606ed52568f3b9edfe5098987cae70c775226dc5 Mon Sep 17 00:00:00 2001 From: Ralf Kirchner Date: Fri, 23 May 2014 17:09:22 +0200 Subject: libblock: Use pthread_once() for initialization Enabling and disabling preemption as done for single core will not work for SMP. In the bdbuf initialization preemption handling can be avoided in general by using pthread_once(). --- cpukit/libblock/src/bdbuf.c | 54 +++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 29 deletions(-) (limited to 'cpukit/libblock') diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c index 07f479f036..a1d9cf736d 100644 --- a/cpukit/libblock/src/bdbuf.c +++ b/cpukit/libblock/src/bdbuf.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -137,8 +138,7 @@ typedef struct rtems_bdbuf_cache rtems_id read_ahead_task; /**< Read-ahead task */ rtems_chain_control read_ahead_chain; /**< Read-ahead request chain */ bool read_ahead_enabled; /**< Read-ahead enabled */ - - bool initialised; /**< Initialised state. */ + rtems_status_code init_status; /**< The initialization status */ } rtems_bdbuf_cache; typedef enum { @@ -168,7 +168,8 @@ typedef enum { RTEMS_BDBUF_FATAL_SYNC_UNLOCK, RTEMS_BDBUF_FATAL_TREE_RM, RTEMS_BDBUF_FATAL_WAIT_EVNT, - RTEMS_BDBUF_FATAL_WAIT_TRANS_EVNT + RTEMS_BDBUF_FATAL_WAIT_TRANS_EVNT, + RTEMS_BDBUF_FATAL_ONCE } rtems_bdbuf_fatal_code; /** @@ -218,6 +219,8 @@ static rtems_task rtems_bdbuf_read_ahead_task(rtems_task_argument arg); */ static rtems_bdbuf_cache bdbuf_cache; +static pthread_once_t rtems_bdbuf_once_state = PTHREAD_ONCE_INIT; + #if RTEMS_BDBUF_TRACE /** * If true output the trace message. @@ -1385,13 +1388,8 @@ rtems_bdbuf_read_request_size (uint32_t transfer_count) + sizeof (rtems_blkdev_sg_buffer) * transfer_count; } -/** - * Initialise the cache. - * - * @return rtems_status_code The initialisation status. - */ -rtems_status_code -rtems_bdbuf_init (void) +static rtems_status_code +rtems_bdbuf_do_init (void) { rtems_bdbuf_group* group; rtems_bdbuf_buffer* bd; @@ -1399,7 +1397,6 @@ rtems_bdbuf_init (void) size_t b; size_t cache_aligment; rtems_status_code sc; - rtems_mode prev_mode; if (rtems_bdbuf_tracer) printf ("bdbuf:init\n"); @@ -1418,22 +1415,6 @@ rtems_bdbuf_init (void) > RTEMS_MINIMUM_STACK_SIZE / 8U) return RTEMS_INVALID_NUMBER; - /* - * We use a special variable to manage the initialisation incase we have - * completing threads doing this. You may get errors if the another thread - * makes a call and we have not finished initialisation. - */ - prev_mode = rtems_bdbuf_disable_preemption (); - if (bdbuf_cache.initialised) - { - rtems_bdbuf_restore_preemption (prev_mode); - return RTEMS_RESOURCE_IN_USE; - } - - memset(&bdbuf_cache, 0, sizeof(bdbuf_cache)); - bdbuf_cache.initialised = true; - rtems_bdbuf_restore_preemption (prev_mode); - /* * For unspecified cache alignments we use the CPU alignment. */ @@ -1650,11 +1631,26 @@ error: rtems_semaphore_delete (bdbuf_cache.lock); } - bdbuf_cache.initialised = false; - return RTEMS_UNSATISFIED; } +static void +rtems_bdbuf_init_once (void) +{ + bdbuf_cache.init_status = rtems_bdbuf_do_init(); +} + +rtems_status_code +rtems_bdbuf_init (void) +{ + int eno = pthread_once (&rtems_bdbuf_once_state, rtems_bdbuf_init_once); + + if (eno != 0) + rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_ONCE); + + return bdbuf_cache.init_status; +} + static void rtems_bdbuf_wait_for_event (rtems_event_set event) { -- cgit v1.2.3