When creating a thread, waiting for the thread function to start 57/176157/3
authorGilbok Lee <gilbok.lee@samsung.com>
Tue, 17 Apr 2018 06:37:27 +0000 (15:37 +0900)
committerGilbok Lee <gilbok.lee@samsung.com>
Tue, 24 Apr 2018 08:14:11 +0000 (17:14 +0900)
[Version] 0.2.38
[Profile] Mobile, Wearable
[Issue Type] Fix bugs

Change-Id: I5f8cc010267a0b95882996e981fbf65bd33f6385

packaging/libmm-radio.spec
src/include/mm_radio_priv.h
src/include/mm_radio_priv_hal.h
src/include/mm_radio_utils.h
src/mm_radio_priv_emulator.c
src/mm_radio_priv_hal.c

index 66a472d..3833445 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       libmm-radio
 Summary:    Multimedia Framework Radio Library
-Version:    0.2.37
+Version:    0.2.38
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index 1c7d6df..a806c12 100644 (file)
@@ -151,6 +151,13 @@ typedef struct {
        int data;
 } mm_radio_msg_t;
 
+typedef enum {
+       MM_RADIO_THREAD_MSG = 0,
+       MM_RADIO_THREAD_SEEK,
+       MM_RADIO_THREAD_SCAN,
+       MM_RADIO_THREAD_NUM
+} MMRadioThreadTypes;
+
 /*---------------------------------------------------------------------------
     GLOBAL DATA TYPE DEFINITIONS:
 ---------------------------------------------------------------------------*/
@@ -182,9 +189,10 @@ typedef struct {
        /* radio attributes */
        MMHandleType* attrs;
 
+       MMRadioThread_t thread[MM_RADIO_THREAD_NUM];
+
        /* message callback */
        GAsyncQueue *msg_queue;
-       MMRadioThread_t msg;
        MMMessageCallback msg_cb;
        void* msg_cb_param;
 
@@ -200,11 +208,7 @@ typedef struct {
        /* hw debug */
        struct v4l2_dbg_register reg;
 
-       /* scan */
-       MMRadioThread_t scan;
-
        /* seek */
-       MMRadioThread_t seek;
        int prev_seek_freq;
        MMRadioSeekDirectionType seek_direction;
 
index ed80aee..31fb1ce 100644 (file)
@@ -155,6 +155,13 @@ typedef struct {
        int data;
 } mm_radio_msg_t;
 
+typedef enum {
+       MM_RADIO_THREAD_MSG = 0,
+       MM_RADIO_THREAD_SEEK,
+       MM_RADIO_THREAD_SCAN,
+       MM_RADIO_THREAD_NUM
+} MMRadioThreadTypes;
+
 /*---------------------------------------------------------------------------
     GLOBAL DATA TYPE DEFINITIONS:
 ---------------------------------------------------------------------------*/
@@ -173,17 +180,14 @@ typedef struct {
        /* radio attributes */
        MMHandleType *attrs;
 
+       MMRadioThread_t thread[MM_RADIO_THREAD_NUM];
+
        /* message callback */
        GAsyncQueue *msg_queue;
-       MMRadioThread_t msg;
        MMMessageCallback msg_cb;
        void *msg_cb_param;
 
-       /* scan */
-       MMRadioThread_t scan;
-
        /* seek */
-       MMRadioThread_t seek;
        int prev_seek_freq;
        bool is_muted;
        bool seek_unmute;
index b538b6d..c72da4a 100644 (file)
@@ -63,6 +63,14 @@ do {                                         \
        }                                               \
 } while (0)
 
+#define MMRADIO_GFREEIF(x)     \
+do {                                           \
+       if (x) {                                \
+               g_free(x);                      \
+               x = NULL;                       \
+       }                                               \
+} while (0)
+
 #define MMRADIO_CHECK_INSTANCE(x_radio)                                \
 do {                                                                                           \
        if (!x_radio) {                                                                 \
@@ -88,6 +96,14 @@ do {                                                                                         \
        }                                                                                               \
 } while (0)
 
+#define MMRADIO_CHECK_ARG_RETURN_VOID(x_radio)                                 \
+do {                                                                                           \
+       if (!x_radio) {                                                                 \
+               MMRADIO_LOG_ERROR("argument is NULL\n");                        \
+               return; \
+       }                                                                                               \
+} while (0)
+
 #define MMRADIO_CHECK_DEVICE_STATE(x_radio)                            \
 do {                                                                                                   \
        if (x_radio->radio_fd < 0) {                                            \
@@ -112,17 +128,11 @@ do {                                                                                                              \
 #define MMRADIO_VOLUME_LOCK(x_radio)           pthread_mutex_lock(&((mm_radio_t *)x_radio)->volume_lock)
 #define MMRADIO_VOLUME_UNLOCK(x_radio)         pthread_mutex_unlock(&((mm_radio_t *)x_radio)->volume_lock)
 
-/* seek thread */
-#define MMRADIO_SEEK_THREAD_LOCK(x_radio)      pthread_mutex_lock(&((mm_radio_t *)x_radio)->seek.mutex)
-#define MMRADIO_SEEK_THREAD_UNLOCK(x_radio)    pthread_mutex_unlock(&((mm_radio_t *)x_radio)->seek.mutex)
-#define MMRADIO_SEEK_THREAD_WAIT(x_radio)      pthread_cond_wait(&((mm_radio_t *)x_radio)->seek.cond, &((mm_radio_t *)x_radio)->seek.mutex)
-#define MMRADIO_SEEK_THREAD_SIGNAL(x_radio)    pthread_cond_signal(&((mm_radio_t *)x_radio)->seek.cond)
-
-/* scan thread */
-#define MMRADIO_SCAN_THREAD_LOCK(x_radio)      pthread_mutex_lock(&((mm_radio_t *)x_radio)->scan.mutex)
-#define MMRADIO_SCAN_THREAD_UNLOCK(x_radio)    pthread_mutex_unlock(&((mm_radio_t *)x_radio)->scan.mutex)
-#define MMRADIO_SCAN_THREAD_WAIT(x_radio)      pthread_cond_wait(&((mm_radio_t *)x_radio)->scan.cond, &((mm_radio_t *)x_radio)->scan.mutex)
-#define MMRADIO_SCAN_THREAD_SIGNAL(x_radio)    pthread_cond_signal(&((mm_radio_t *)x_radio)->scan.cond)
+/* msg/seek/scan thread */
+#define MMRADIO_THREAD_LOCK(x_thread_t)                pthread_mutex_lock(&x_thread_t->mutex)
+#define MMRADIO_THREAD_UNLOCK(x_thread_t)      pthread_mutex_unlock(&x_thread_t->mutex)
+#define MMRADIO_THREAD_WAIT(x_thread_t)                pthread_cond_wait(&x_thread_t->cond, &x_thread_t->mutex)
+#define MMRADIO_THREAD_SIGNAL(x_thread_t)      pthread_cond_signal(&x_thread_t->cond)
 
 /* hal seek thread */
 #define MMRADIO_HAL_SEEK_THREAD_LOCK(x_radio)  pthread_mutex_lock(&((mm_radio_t *)x_radio)->hal_seek_mutex)
index 21f0f11..6234fda 100644 (file)
@@ -126,8 +126,10 @@ static bool __mmradio_set_state(mm_radio_t * radio, int new_state);
 static void __mmradio_seek_thread(mm_radio_t * radio);
 static void __mmradio_scan_thread(mm_radio_t * radio);
 static bool __is_tunable_frequency(mm_radio_t * radio, int freq);
-static int __mmradio_create_thread(mm_radio_t *radio);
-static void __mmradio_destroy_thread(mm_radio_t *radio);
+static int __mmradio_create_threads(mm_radio_t *radio);
+static void __mmradio_destroy_threads(mm_radio_t *radio);
+static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type);
+static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type);
 static int __mmradio_set_deemphasis(mm_radio_t * radio);
 static int __mmradio_set_band_range(mm_radio_t * radio);
 static int __mmradio_get_wave_num(mm_radio_t * radio);
@@ -135,6 +137,14 @@ static int __resource_release_cb(mm_resource_manager_h rm,
        mm_resource_manager_res_h res, void *user_data);
 static void __mmradio_msg_thread(mm_radio_t *radio);
 static void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data);
+
+typedef void (*thread_function)(mm_radio_t *);
+thread_function __mmradio_thread_function[] = {
+       &__mmradio_msg_thread,
+       &__mmradio_seek_thread,
+       &__mmradio_scan_thread
+};
+
 /*===========================================================================
   FUNCTION DEFINITIONS
 ========================================================================== */
@@ -228,7 +238,7 @@ int _mmradio_create_radio(mm_radio_t * radio)
        }
 
        /* create mutex and thread */
-       ret = __mmradio_create_thread(radio);
+       ret = __mmradio_create_threads(radio);
        if (ret) {
                MMRADIO_LOG_ERROR("failed to create threads");
                goto ERROR_THREAD;
@@ -250,7 +260,7 @@ int _mmradio_create_radio(mm_radio_t * radio)
        return MM_ERROR_NONE;
 
 ERROR_RESOURCE:
-       __mmradio_destroy_thread(radio);
+       __mmradio_destroy_threads(radio);
 ERROR_THREAD:
        if (radio->msg_queue)
                g_async_queue_unref(radio->msg_queue);
@@ -350,7 +360,7 @@ int _mmradio_destroy(mm_radio_t * radio)
 
        _mmradio_unrealize(radio);
        /* destroy mutex and thread */
-       __mmradio_destroy_thread(radio);
+       __mmradio_destroy_threads(radio);
 
        if (radio->msg_queue)
                g_async_queue_unref(radio->msg_queue);
@@ -708,16 +718,12 @@ int _mmradio_start_pipeline(mm_radio_t * radio)
 
        if (gst_element_set_state(radio->pGstreamer_s->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
                MMRADIO_LOG_ERROR("failed to change pipeline state");
-               gst_object_unref(radio->pGstreamer_s->pipeline);
-               g_free(radio->pGstreamer_s);
                return MM_ERROR_RADIO_INVALID_STATE;
        }
 
        ret_state = gst_element_get_state(radio->pGstreamer_s->pipeline, NULL, NULL, RADIO_GST_STATE_CHANGE_TIMEOUT);
        if (ret_state == GST_STATE_CHANGE_FAILURE) {
                MMRADIO_LOG_ERROR("GST_STATE_CHANGE_FAILURE");
-               gst_object_unref(radio->pGstreamer_s->pipeline);
-               g_free(radio->pGstreamer_s);
                return MM_ERROR_RADIO_INVALID_STATE;
        } else {
                MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
@@ -734,17 +740,13 @@ int _mmradio_stop_pipeline(mm_radio_t * radio)
 
        MMRADIO_LOG_FENTER();
        if (gst_element_set_state(radio->pGstreamer_s->pipeline, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) {
-               MMRADIO_LOG_DEBUG("Fail to change pipeline state");
-               gst_object_unref(radio->pGstreamer_s->pipeline);
-               g_free(radio->pGstreamer_s);
+               MMRADIO_LOG_ERROR("Fail to change pipeline state");
                return MM_ERROR_RADIO_INVALID_STATE;
        }
 
        ret_state = gst_element_get_state(radio->pGstreamer_s->pipeline, NULL, NULL, RADIO_GST_STATE_CHANGE_TIMEOUT);
        if (ret_state == GST_STATE_CHANGE_FAILURE) {
-               MMRADIO_LOG_DEBUG("GST_STATE_CHANGE_FAILURE");
-               gst_object_unref(radio->pGstreamer_s->pipeline);
-               g_free(radio->pGstreamer_s);
+               MMRADIO_LOG_ERROR("GST_STATE_CHANGE_FAILURE");
                return MM_ERROR_RADIO_INVALID_STATE;
        } else {
                MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
@@ -759,10 +761,12 @@ int _mmradio_destroy_pipeline(mm_radio_t * radio)
        GstStateChangeReturn ret_state;
        MMRADIO_LOG_FENTER();
 
+       MMRADIO_CHECK_ARG(radio->pGstreamer_s);
+
        if (gst_element_set_state(radio->pGstreamer_s->pipeline, GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE) {
                MMRADIO_LOG_DEBUG("failed to change pipeline state");
                gst_object_unref(radio->pGstreamer_s->pipeline);
-               g_free(radio->pGstreamer_s);
+               MMRADIO_GFREEIF(radio->pGstreamer_s);
                return MM_ERROR_RADIO_INVALID_STATE;
        }
 
@@ -770,14 +774,14 @@ int _mmradio_destroy_pipeline(mm_radio_t * radio)
        if (ret_state == GST_STATE_CHANGE_FAILURE) {
                MMRADIO_LOG_DEBUG("GST_STATE_CHANGE_FAILURE");
                gst_object_unref(radio->pGstreamer_s->pipeline);
-               g_free(radio->pGstreamer_s);
+               MMRADIO_GFREEIF(radio->pGstreamer_s);
                return MM_ERROR_RADIO_INVALID_STATE;
        } else {
                MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
        }
 
        gst_object_unref(radio->pGstreamer_s->pipeline);
-       g_free(radio->pGstreamer_s);
+       MMRADIO_GFREEIF(radio->pGstreamer_s);
        MMRADIO_LOG_FLEAVE();
        return ret;
 }
@@ -785,21 +789,26 @@ int _mmradio_destroy_pipeline(mm_radio_t * radio)
 
 int _mmradio_seek(mm_radio_t * radio, MMRadioSeekDirectionType direction)
 {
+       MMRadioThread_t *p_thread = NULL;
+
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
 
-       if (radio->seek.is_running) {
+       p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
+       MMRADIO_CHECK_ARG(p_thread);
+
+       if (p_thread->is_running) {
                MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
                return MM_ERROR_RADIO_INTERNAL;
        }
 
        MMRADIO_SLOG_DEBUG("trying to seek. direction[0:UP/1:DOWN) %d", direction);
        radio->seek_direction = direction;
-       radio->seek.is_running = true;
-       radio->seek.stop = false;
-       MMRADIO_SEEK_THREAD_SIGNAL(radio);
+       p_thread->is_running = true;
+       p_thread->stop = false;
+       MMRADIO_THREAD_SIGNAL(p_thread);
 
        MMRADIO_LOG_FLEAVE();
 
@@ -808,15 +817,20 @@ int _mmradio_seek(mm_radio_t * radio, MMRadioSeekDirectionType direction)
 
 int _mmradio_start_scan(mm_radio_t * radio)
 {
+       MMRadioThread_t *p_thread = NULL;
+
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
 
-       radio->scan.stop = false;
-       radio->scan.is_running = true;
+       p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
+       MMRADIO_CHECK_ARG(p_thread);
+
+       p_thread->stop = false;
+       p_thread->is_running = true;
 
-       MMRADIO_SCAN_THREAD_SIGNAL(radio);
+       MMRADIO_THREAD_SIGNAL(p_thread);
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
 
@@ -832,7 +846,7 @@ int _mmradio_stop_scan(mm_radio_t * radio)
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
 
-       radio->scan.stop = true;
+       radio->thread[MM_RADIO_THREAD_SCAN].stop = true;
 
        MMRADIO_LOG_FLEAVE();
 
@@ -865,22 +879,31 @@ void __mmradio_scan_thread(mm_radio_t * radio)
        int prev_freq = 0;
        int emulatoridx = 0;
        int freq = 0;
+       MMRadioThread_t *p_thread = NULL;
 
        MMRADIO_LOG_FENTER();
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       MMRADIO_SCAN_THREAD_LOCK(radio);
+       p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
+
+       MMRADIO_THREAD_LOCK(p_thread);
+       MMRADIO_THREAD_SIGNAL(p_thread);
+       MMRADIO_THREAD_UNLOCK(p_thread);
+
+       MMRADIO_THREAD_LOCK(p_thread);
 
-       while (!radio->scan.thread_exit) {
+       while (!p_thread->thread_exit) {
                MMRADIO_LOG_DEBUG("scan thread started. waiting for signal.");
-               MMRADIO_SCAN_THREAD_WAIT(radio);
+               MMRADIO_THREAD_WAIT(p_thread);
+               MMRADIO_LOG_DEBUG("scan thread started. got signal.");
 
-               if (radio->scan.thread_exit) {
+               if (p_thread->thread_exit) {
                        MMRADIO_LOG_DEBUG("exiting scan thread");
                        goto EXIT;
                }
 
-               if (radio->scan.stop) {
+               if (p_thread->stop) {
                        MMRADIO_LOG_INFO("scan was stopped");
                        goto FINISHED;
                }
@@ -897,19 +920,19 @@ void __mmradio_scan_thread(mm_radio_t * radio)
                prev_freq = 0;
                emulatoridx = 0;
 
-               while (!radio->scan.stop) {
+               while (!p_thread->stop) {
 
                        freq = 0;
 
                        MMRADIO_LOG_DEBUG("scanning....");
 
                        /* now we can get new frequency from radio device */
-                       if (radio->scan.thread_exit) {
+                       if (p_thread->thread_exit) {
                                MMRADIO_LOG_DEBUG("exiting scan thread");
                                goto EXIT;
                        }
 
-                       if (radio->scan.stop)
+                       if (p_thread->stop)
                                break;
 
                        usleep(1000 * 1000);
@@ -921,12 +944,12 @@ void __mmradio_scan_thread(mm_radio_t * radio)
                                break;
                        }
 
-                       if (radio->scan.thread_exit) {
+                       if (p_thread->thread_exit) {
                                MMRADIO_LOG_DEBUG("exiting scan thread");
                                goto EXIT;
                        }
 
-                       if (radio->scan.stop)
+                       if (p_thread->stop)
                                break;
 
                        if (freq == prev_freq)
@@ -935,14 +958,14 @@ void __mmradio_scan_thread(mm_radio_t * radio)
                        prev_freq = freq;
                        MMRADIO_LOG_INFO("scanning : new frequency : [%d]", freq);
 
-                       /* drop if max freq is scanned */
+                       /* drop if out of range freq is scanned */
                        if (freq >= radio->region_setting.band_max
                            || freq < radio->region_setting.band_min) {
                                MMRADIO_LOG_DEBUG("%d freq is dropping...and stopping scan", freq);
                                break;
                        }
 
-                       if (radio->scan.stop)
+                       if (p_thread->stop)
                                break;                  /* doesn't need to post */
 
                        __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_INFO, freq);
@@ -965,17 +988,17 @@ FINISHED:
                        }
                }
 
-               if (!radio->scan.stop)
+               if (!p_thread->stop)
                        __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_FINISHED, 0);
                else
                        __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_STOPPED, 0);
 
-               radio->scan.is_running = false;
-               radio->scan.stop = false;
+               p_thread->is_running = false;
+               p_thread->stop = false;
        }
 
 EXIT:
-       MMRADIO_SCAN_THREAD_UNLOCK(radio);
+       MMRADIO_THREAD_UNLOCK(p_thread);
        MMRADIO_LOG_FLEAVE();
        pthread_exit(NULL);
        return;
@@ -1000,17 +1023,25 @@ void __mmradio_seek_thread(mm_radio_t * radio)
        int freq = 0;
        int i = 0;
        int emulatoridx = 0;
+       MMRadioThread_t *p_thread = NULL;
 
        MMRADIO_LOG_FENTER();
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       MMRADIO_SEEK_THREAD_LOCK(radio);
+       p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
 
-       while (!radio->seek.thread_exit) {
+       MMRADIO_THREAD_LOCK(p_thread);
+       MMRADIO_THREAD_SIGNAL(p_thread);
+       MMRADIO_THREAD_UNLOCK(p_thread);
+
+       MMRADIO_THREAD_LOCK(p_thread);
+
+       while (!p_thread->thread_exit) {
                MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.\n");
-               MMRADIO_SEEK_THREAD_WAIT(radio);
+               MMRADIO_THREAD_WAIT(p_thread);
 
-               if (radio->seek.thread_exit) {
+               if (p_thread->thread_exit) {
                        MMRADIO_LOG_DEBUG("exiting seek thread");
                        break;
                }
@@ -1018,7 +1049,7 @@ void __mmradio_seek_thread(mm_radio_t * radio)
                MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
                MMRADIO_LOG_DEBUG("seeking....");
 
-               if (radio->seek.stop) {
+               if (p_thread->stop) {
                        MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
                        goto SEEK_FAILED;
                }
@@ -1076,18 +1107,18 @@ void __mmradio_seek_thread(mm_radio_t * radio)
                radio->prev_seek_freq = freq;
                MMRADIO_LOG_INFO("seeking : new frequency : [%d]", (int) freq);
                __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, freq);
-               radio->seek.stop = true;
-               radio->seek.is_running = false;
+               p_thread->stop = true;
+               p_thread->is_running = false;
                continue;
 
 SEEK_FAILED:
                /* freq -1 means it's failed to seek */
                __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, -1);
-               radio->seek.stop = true;
-               radio->seek.is_running = false;
+               p_thread->stop = true;
+               p_thread->is_running = false;
        }
 
-       MMRADIO_SEEK_THREAD_UNLOCK(radio);
+       MMRADIO_THREAD_UNLOCK(p_thread);
        MMRADIO_LOG_FLEAVE();
        pthread_exit(NULL);
        return;
@@ -1451,125 +1482,146 @@ int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
        return MM_ERROR_NONE;
 }
 
-static int __mmradio_create_thread(mm_radio_t *radio)
+static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
 {
-       int ret = MM_ERROR_NONE;
+       MMRadioThread_t *p_thread = NULL;
 
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE(radio);
 
-       MMRADIO_INIT_MUTEX(radio->cmd_lock);
-
-       radio->msg.thread_id = pthread_create(&radio->msg.thread, NULL,
-               (void *)__mmradio_msg_thread, (void *)radio);
-       if (radio->msg.thread_id) {
-               /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
-               MMRADIO_LOG_ERROR("failed to create thread : msg");
-               goto ERROR;
+       if (type >= MM_RADIO_THREAD_NUM) {
+               MMRADIO_LOG_WARNING("wrong argument thread type");
+               return MM_ERROR_RADIO_INTERNAL;
        }
 
-       MMRADIO_INIT_MUTEX(radio->seek.mutex);
-       MMRADIO_INIT_COND(radio->seek.cond);
+       p_thread = &radio->thread[type];
+       MMRADIO_CHECK_ARG(p_thread);
+
+       MMRADIO_INIT_MUTEX(p_thread->mutex);
+       MMRADIO_INIT_COND(p_thread->cond);
 
-       radio->seek.thread_id = pthread_create(&radio->seek.thread, NULL,
-               (void *)__mmradio_seek_thread, (void *)radio);
-       if (radio->seek.thread_id) {
-               MMRADIO_LOG_DEBUG("failed to create thread : seek");
-               goto ERROR;
+       MMRADIO_THREAD_LOCK(p_thread);
+       p_thread->thread_id = pthread_create(&p_thread->thread, NULL,
+               (void *)__mmradio_thread_function[type], (void *)radio);
+       if (p_thread->thread_id) {
+               MMRADIO_LOG_DEBUG("failed to create thread : [%d]", type);
+               MMRADIO_THREAD_UNLOCK(p_thread);
+               return MM_ERROR_RADIO_INTERNAL;
        }
 
-       MMRADIO_INIT_MUTEX(radio->scan.mutex);
-       MMRADIO_INIT_COND(radio->scan.cond);
+       MMRADIO_LOG_DEBUG("wait for [%d] thread", type);
+       MMRADIO_THREAD_WAIT(p_thread);
+       MMRADIO_LOG_DEBUG("[%d] thread started", type);
+       MMRADIO_THREAD_UNLOCK(p_thread);
 
-       radio->scan.thread_id = pthread_create(&radio->scan.thread, NULL,
-               (void *)__mmradio_scan_thread, (void *)radio);
+       return MM_ERROR_NONE;
 
-       if (radio->scan.thread_id) {
-               MMRADIO_LOG_ERROR("failed to create thread : scan");
-               goto ERROR;
-       }
+ERROR:
+       pthread_mutex_destroy(&p_thread->mutex);
+       pthread_cond_destroy(&p_thread->cond);
+       return MM_ERROR_RADIO_INTERNAL;
 
-       MMRADIO_LOG_FLEAVE();
-       return ret;
+}
 
-ERROR:
-       if (radio->seek.thread) {
-               MMRADIO_SEEK_THREAD_LOCK(radio);
-               radio->seek.thread_exit = true;
-               MMRADIO_SEEK_THREAD_SIGNAL(radio);
-               MMRADIO_SEEK_THREAD_UNLOCK(radio);
-               pthread_join(radio->seek.thread, NULL);
-               radio->seek.thread = 0;
-       }
+static int __mmradio_create_threads(mm_radio_t *radio)
+{
+       int ret = MM_ERROR_NONE;
+       int type = 0;
 
-       if (radio->msg.thread) {
-               mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
-               if (!msg) {
-                       MMRADIO_LOG_ERROR("failed to get mm_radio_msg_t");
-               } else {
-                       msg->msg_type = MM_RADIO_MSG_DESTROY;
-                       g_async_queue_push_front(radio->msg_queue, msg);
-                       pthread_join(radio->msg.thread, NULL);
-                       radio->msg.thread = 0;
+       MMRADIO_LOG_FENTER();
+
+       MMRADIO_CHECK_INSTANCE(radio);
+
+       MMRADIO_INIT_MUTEX(radio->cmd_lock);
+
+       for (type = (int)MM_RADIO_THREAD_MSG; type < (int)MM_RADIO_THREAD_NUM; type++) {
+               ret = __mmradio_create_thread_type(radio, (MMRadioThreadTypes)type);
+               if (ret) {
+                       MMRADIO_LOG_ERROR("failed to create thread(%d)", type);
+                       while (--type >= (int)MM_RADIO_THREAD_MSG)
+                               __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
+                       goto ERROR;
                }
        }
 
-       pthread_mutex_destroy(&radio->cmd_lock);
-       pthread_mutex_destroy(&radio->seek.mutex);
-       pthread_cond_destroy(&radio->seek.cond);
-       pthread_mutex_destroy(&radio->scan.mutex);
-       pthread_cond_destroy(&radio->scan.cond);
+       MMRADIO_LOG_FLEAVE();
+       return ret;
 
+ERROR:
+       pthread_mutex_destroy(&radio->cmd_lock);
+       MMRADIO_LOG_FLEAVE();
        return MM_ERROR_RADIO_INTERNAL;
 }
 
-static void __mmradio_destroy_thread(mm_radio_t *radio)
+static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
 {
+       MMRadioThread_t *p_thread = NULL;
+       mm_radio_msg_t *msg = NULL;
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       if (radio->seek.thread) {
-               MMRADIO_SEEK_THREAD_LOCK(radio);
-               radio->seek.thread_exit = true;
-               MMRADIO_SEEK_THREAD_SIGNAL(radio);
-               MMRADIO_SEEK_THREAD_UNLOCK(radio);
-               pthread_join(radio->seek.thread, NULL);
-               radio->seek.thread = 0;
-       }
-
-       if (radio->scan.thread) {
-               MMRADIO_SCAN_THREAD_LOCK(radio);
-               radio->scan.thread_exit = true;
-               MMRADIO_SCAN_THREAD_SIGNAL(radio);
-               MMRADIO_SCAN_THREAD_UNLOCK(radio);
-               pthread_join(radio->scan.thread, NULL);
-               radio->scan.thread = 0;
+       if (type >= MM_RADIO_THREAD_NUM) {
+               MMRADIO_LOG_WARNING("wrong argument thread type");
+               return;
        }
 
-       if (radio->msg.thread) {
-               mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
-               if (!msg) {
-                       MMRADIO_LOG_ERROR("failed to get mm_radio_msg_t");
-               } else {
-                       msg->msg_type = MM_RADIO_MSG_DESTROY;
-                       g_async_queue_push_front(radio->msg_queue, msg);
-                       pthread_join(radio->msg.thread, NULL);
-                       radio->msg.thread = 0;
+       p_thread = &radio->thread[type];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
+
+       if (p_thread->thread) {
+               switch (type) {
+               case MM_RADIO_THREAD_MSG:
+                       msg = g_slice_new0(mm_radio_msg_t);
+                       if (!msg) {
+                               MMRADIO_LOG_ERROR("failed to get mm_radio_msg_t");
+                       } else {
+                               msg->msg_type = MM_RADIO_MSG_DESTROY;
+                               g_async_queue_push_front(radio->msg_queue, msg);
+                               pthread_join(p_thread->thread, NULL);
+                               p_thread->thread = 0;
+                       }
+                       break;
+               case MM_RADIO_THREAD_SEEK:
+               case MM_RADIO_THREAD_SCAN:
+                       MMRADIO_THREAD_LOCK(p_thread);
+                       p_thread->thread_exit = true;
+                       MMRADIO_THREAD_SIGNAL(p_thread);
+                       MMRADIO_THREAD_UNLOCK(p_thread);
+                       pthread_join(p_thread->thread, NULL);
+                       p_thread->thread = 0;
+                       break;
+               default:
+                       MMRADIO_LOG_WARNING("(%d)type isn't handled", type);
+                       break;
                }
+       } else {
+               MMRADIO_LOG_WARNING("(%d)thread is zero", type);
        }
 
-       pthread_mutex_destroy(&radio->cmd_lock);
+       pthread_mutex_destroy(&p_thread->mutex);
+       pthread_cond_destroy(&p_thread->cond);
 
-       pthread_mutex_destroy(&radio->seek.mutex);
-       pthread_cond_destroy(&radio->seek.cond);
-       pthread_mutex_destroy(&radio->scan.mutex);
-       pthread_cond_destroy(&radio->scan.cond);
+       MMRADIO_LOG_FLEAVE();
+}
+
+static void __mmradio_destroy_threads(mm_radio_t *radio)
+{
+       int type = (int)MM_RADIO_THREAD_NUM;
+       MMRADIO_LOG_FENTER();
+
+       MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
+
+       while (--type >= 0)
+               __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
+
+       pthread_mutex_destroy(&radio->cmd_lock);
 
        MMRADIO_LOG_FLEAVE();
 }
 
+
 void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data)
 {
        mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
@@ -1587,18 +1639,31 @@ void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_dat
 
 void __mmradio_msg_thread(mm_radio_t *radio)
 {
-       MMMessageParamType param = {0,};
        mm_radio_msg_t *msg = NULL;
-       int exit_msg_thread = 0;
+       MMRadioThread_t *p_thread = NULL;
+
+       MMRADIO_LOG_FENTER();
+       MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
+
+       p_thread = &radio->thread[MM_RADIO_THREAD_MSG];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
+
+       p_thread->thread_exit = false;
+
+       MMRADIO_THREAD_LOCK(p_thread);
+       MMRADIO_THREAD_SIGNAL(p_thread);
+       MMRADIO_THREAD_UNLOCK(p_thread);
 
        /*we run a while one loop*/
-       while (exit_msg_thread == 0) {
+       while (!p_thread->thread_exit) {
                msg = (mm_radio_msg_t *)g_async_queue_pop(radio->msg_queue);
                if (!msg) {
                        MMRADIO_LOG_ERROR("poped message is NULL!");
                        break;
                }
 
+               MMMessageParamType param = {0,};
+
                switch (msg->msg_type) {
                case MM_RADIO_MSG_DESTROY:
                        MMRADIO_LOG_INFO("get destroy msg. pop all event to finish this thread");
@@ -1609,7 +1674,7 @@ void __mmradio_msg_thread(mm_radio_t *radio)
                                        g_slice_free(mm_radio_msg_t, msg_pop);
                                }
                        }
-                       exit_msg_thread = 1;
+                       p_thread->thread_exit = true;
                        break;
                case MM_RADIO_MSG_SCAN_INFO:
                        MMRADIO_LOG_INFO("get scan info frequency: %d", msg->data);
@@ -1647,4 +1712,6 @@ void __mmradio_msg_thread(mm_radio_t *radio)
        }
 
        MMRADIO_LOG_INFO("msg thread is finished");
+       MMRADIO_LOG_FLEAVE();
+       pthread_exit(NULL);
 }
index 5dab31b..3d1f8d6 100644 (file)
@@ -123,8 +123,10 @@ void _mmradio_seek_cancel(mm_radio_t *radio);
 static void __mmradio_seek_thread(mm_radio_t *radio);
 static void __mmradio_scan_thread(mm_radio_t *radio);
 static bool __is_tunable_frequency(mm_radio_t *radio, int freq);
-static int __mmradio_create_thread(mm_radio_t *radio);
-static void __mmradio_destroy_thread(mm_radio_t *radio);
+static int __mmradio_create_threads(mm_radio_t *radio);
+static void __mmradio_destroy_threads(mm_radio_t *radio);
+static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type);
+static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type);
 
 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data);
 static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level);
@@ -133,6 +135,13 @@ static int __resource_release_cb(mm_resource_manager_h rm,
 static void __mmradio_msg_thread(mm_radio_t *radio);
 static void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data);
 
+typedef void (*thread_function)(mm_radio_t *);
+thread_function __mmradio_thread_function[] = {
+       &__mmradio_msg_thread,
+       &__mmradio_seek_thread,
+       &__mmradio_scan_thread
+};
+
 int _mmradio_apply_region(mm_radio_t *radio, MMRadioRegionType region, bool update)
 {
        int ret = MM_ERROR_NONE;
@@ -196,7 +205,7 @@ int _mmradio_create_radio(mm_radio_t *radio)
        }
 
        /* create mutex and thread */
-       ret = __mmradio_create_thread(radio);
+       ret = __mmradio_create_threads(radio);
        if (ret) {
                MMRADIO_LOG_ERROR("failed to create threads");
                goto ERROR_THREAD;
@@ -226,7 +235,7 @@ int _mmradio_create_radio(mm_radio_t *radio)
 ERROR_HAL_INIT:
        mm_resource_manager_destroy(radio->resource_manager);
 ERROR_RESOURCE:
-       __mmradio_destroy_thread(radio);
+       __mmradio_destroy_threads(radio);
 ERROR_THREAD:
        if (radio->msg_queue)
                g_async_queue_unref(radio->msg_queue);
@@ -342,7 +351,7 @@ int _mmradio_destroy(mm_radio_t *radio)
        _mmradio_unrealize(radio);
 
        /* destroy mutex and thread */
-       __mmradio_destroy_thread(radio);
+       __mmradio_destroy_threads(radio);
 
        if (radio->msg_queue)
                g_async_queue_unref(radio->msg_queue);
@@ -673,13 +682,17 @@ int _mmradio_stop(mm_radio_t *radio)
 int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
 {
        int ret = MM_ERROR_NONE;
+       MMRadioThread_t *p_thread = NULL;
 
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
 
-       if (radio->seek.is_running) {
+       p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
+       MMRADIO_CHECK_ARG(p_thread);
+
+       if (p_thread->is_running) {
                MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
                return MM_ERROR_RADIO_INTERNAL;
        }
@@ -699,10 +712,10 @@ int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
 
        MMRADIO_LOG_INFO("trying to seek. direction[0:UP/1:DOWN) %d", direction);
        radio->seek_direction = direction;
-       radio->seek.is_running = true;
-       radio->seek.stop = false;
+       p_thread->is_running = true;
+       p_thread->stop = false;
 
-       MMRADIO_SEEK_THREAD_SIGNAL(radio);
+       MMRADIO_THREAD_SIGNAL(p_thread);
 
        MMRADIO_LOG_FLEAVE();
 
@@ -716,7 +729,7 @@ void _mmradio_seek_cancel(mm_radio_t *radio)
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
        /* cancel any outstanding seek request */
-       radio->seek.stop = true;
+       radio->thread[MM_RADIO_THREAD_SEEK].stop = true;
 
        MMRADIO_LOG_FLEAVE();
 }
@@ -724,13 +737,17 @@ void _mmradio_seek_cancel(mm_radio_t *radio)
 int _mmradio_start_scan(mm_radio_t *radio)
 {
        int ret = MM_ERROR_NONE;
+       MMRadioThread_t *p_thread = NULL;;
 
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
 
-       radio->scan.stop = false;
+       p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
+       MMRADIO_CHECK_ARG(p_thread);
+
+       p_thread->stop = false;
 
        if (!radio->is_ready) {
                ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
@@ -772,9 +789,9 @@ int _mmradio_start_scan(mm_radio_t *radio)
                MMRADIO_LOG_DEBUG("radio prepared and opened");
        }
 
-       radio->scan.is_running = true;
+       p_thread->is_running = true;
 
-       MMRADIO_SCAN_THREAD_SIGNAL(radio);
+       MMRADIO_THREAD_SIGNAL(p_thread);
 
        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
 
@@ -790,7 +807,7 @@ int _mmradio_stop_scan(mm_radio_t *radio)
        MMRADIO_CHECK_INSTANCE(radio);
        MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
 
-       radio->scan.stop = true;
+       radio->thread[MM_RADIO_THREAD_SCAN].stop = true;
 
        MMRADIO_LOG_FLEAVE();
 
@@ -826,26 +843,37 @@ void __mmradio_scan_thread(mm_radio_t *radio)
        int ret = MM_ERROR_NONE;
        int prev_freq = 0;
 
+       MMRadioThread_t *p_thread = NULL;
+
        MMRADIO_LOG_FENTER();
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       MMRADIO_SCAN_THREAD_LOCK(radio);
+       p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
+
+       MMRADIO_THREAD_LOCK(p_thread);
+       MMRADIO_THREAD_SIGNAL(p_thread);
+       MMRADIO_THREAD_UNLOCK(p_thread);
 
-       while (!radio->scan.thread_exit) {
+       MMRADIO_THREAD_LOCK(p_thread);
+
+       while (!p_thread->thread_exit) {
                MMRADIO_LOG_DEBUG("scan thread started. waiting for signal.");
-               MMRADIO_SCAN_THREAD_WAIT(radio);
+               MMRADIO_THREAD_WAIT(p_thread);
 
-               if (radio->scan.thread_exit) {
+               if (p_thread->thread_exit) {
                        MMRADIO_LOG_DEBUG("exiting scan thread");
                        goto EXIT;
                }
 
-               ret = radio_hal_mute(radio->hal_inf);
-               if (ret == MM_ERROR_NOT_SUPPORT_API) {
-                       MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
-               } else if (ret != MM_ERROR_NONE) {
-                       MMRADIO_LOG_ERROR("faied to set radio hal mute");
-                       goto FINISHED;
+               if (radio->old_state == MM_RADIO_STATE_PLAYING) {
+                       ret = radio_hal_mute(radio->hal_inf);
+                       if (ret == MM_ERROR_NOT_SUPPORT_API) {
+                               MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
+                       } else if (ret != MM_ERROR_NONE) {
+                               MMRADIO_LOG_ERROR("faied to set radio hal mute");
+                               goto FINISHED;
+                       }
                }
 
                ret = radio_hal_set_frequency(radio->hal_inf, radio->region_setting.band_min);
@@ -856,17 +884,17 @@ void __mmradio_scan_thread(mm_radio_t *radio)
                MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
 
                prev_freq = 0;
-               while (!radio->scan.stop) {
+               while (!p_thread->stop) {
                        uint32_t freq = 0;
 
                        MMRADIO_LOG_DEBUG("scanning....");
 
-                       if (radio->scan.thread_exit) {
+                       if (p_thread->thread_exit) {
                                MMRADIO_LOG_DEBUG("exiting scan thread");
                                goto EXIT;
                        }
 
-                       if (radio->scan.stop) {
+                       if (p_thread->stop) {
                                MMRADIO_LOG_INFO("scan was canceled");
                                goto FINISHED;
                        }
@@ -879,12 +907,12 @@ void __mmradio_scan_thread(mm_radio_t *radio)
                                break;
                        }
 
-                       if (radio->scan.thread_exit) {
+                       if (p_thread->thread_exit) {
                                MMRADIO_LOG_DEBUG("exiting scan thread");
                                goto EXIT;
                        }
 
-                       if (radio->scan.stop) {
+                       if (p_thread->stop) {
                                MMRADIO_LOG_INFO("scan was canceled");
                                goto FINISHED;
                        }
@@ -908,7 +936,7 @@ void __mmradio_scan_thread(mm_radio_t *radio)
                                        break;
                                }
 
-                               if (radio->scan.stop) {
+                               if (p_thread->stop) {
                                        /* doesn't need to post */
                                        break;
                                }
@@ -973,19 +1001,19 @@ FINISHED_ERR:
                        MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
                }
 
-               if (!radio->scan.stop)
+               if (!p_thread->stop)
                        __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_FINISHED, 0);
                else
                        __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_STOPPED, 0);
 
-               radio->scan.is_running = false;
+               p_thread->is_running = false;
 
        }
 
 EXIT:
-       radio->scan.is_running = false;
+       p_thread->is_running = false;
 
-       MMRADIO_SCAN_THREAD_UNLOCK(radio);
+       MMRADIO_THREAD_UNLOCK(p_thread);
 
        MMRADIO_LOG_FLEAVE();
 
@@ -1012,17 +1040,25 @@ void __mmradio_seek_thread(mm_radio_t *radio)
 {
        int ret = MM_ERROR_NONE;
        uint32_t freq = 0;
+       MMRadioThread_t *p_thread = NULL;
 
        MMRADIO_LOG_FENTER();
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       MMRADIO_SEEK_THREAD_LOCK(radio);
+       p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
+
+       MMRADIO_THREAD_LOCK(p_thread);
+       MMRADIO_THREAD_SIGNAL(p_thread);
+       MMRADIO_THREAD_UNLOCK(p_thread);
 
-       while (!radio->seek.thread_exit) {
+       MMRADIO_THREAD_LOCK(p_thread);
+
+       while (!p_thread->thread_exit) {
                MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.");
-               MMRADIO_SEEK_THREAD_WAIT(radio);
+               MMRADIO_THREAD_WAIT(p_thread);
 
-               if (radio->seek.thread_exit) {
+               if (p_thread->thread_exit) {
                        MMRADIO_LOG_DEBUG("exiting seek thread");
                        goto EXIT;
                }
@@ -1030,7 +1066,7 @@ void __mmradio_seek_thread(mm_radio_t *radio)
                MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
                MMRADIO_LOG_DEBUG("seeking....");
 
-               if (radio->seek.stop) {
+               if (p_thread->stop) {
                        MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
                        goto SEEK_FAILED;
                }
@@ -1045,12 +1081,12 @@ void __mmradio_seek_thread(mm_radio_t *radio)
                        goto SEEK_FAILED;
                }
 
-               if (radio->seek.thread_exit) {
+               if (p_thread->thread_exit) {
                        MMRADIO_LOG_DEBUG("exiting seek thread");
                        goto EXIT;
                }
 
-               if (radio->seek.stop) {
+               if (p_thread->stop) {
                        MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
                        goto SEEK_FAILED;
                }
@@ -1098,7 +1134,7 @@ void __mmradio_seek_thread(mm_radio_t *radio)
                radio->prev_seek_freq = (int)freq;
                MMRADIO_LOG_INFO("seeking : new frequency : [%d]", (int) freq);
                __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, freq);
-               radio->seek.is_running = false;
+               p_thread->is_running = false;
                continue;
 
 SEEK_FAILED:
@@ -1114,12 +1150,12 @@ SEEK_FAILED:
                }
                /* freq -1 means it's failed to seek */
                __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, -1);
-               radio->seek.is_running = false;
+               p_thread->is_running = false;
        }
 
 EXIT:
-       radio->seek.is_running = false;
-       MMRADIO_SEEK_THREAD_UNLOCK(radio);
+       p_thread->is_running = false;
+       MMRADIO_THREAD_UNLOCK(p_thread);
        MMRADIO_LOG_FLEAVE();
        pthread_exit(NULL);
 }
@@ -1488,128 +1524,149 @@ static int __resource_release_cb(mm_resource_manager_h rm,
        return FALSE;
 }
 
-static int __mmradio_create_thread(mm_radio_t *radio)
+static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
 {
-       int ret = MM_ERROR_NONE;
+       MMRadioThread_t *p_thread = NULL;
 
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE(radio);
 
-       MMRADIO_INIT_MUTEX(radio->cmd_lock);
-       MMRADIO_INIT_MUTEX(radio->volume_lock);
-       MMRADIO_INIT_MUTEX(radio->hal_seek_mutex);
-
-       radio->msg.thread_id = pthread_create(&radio->msg.thread, NULL,
-               (void *)__mmradio_msg_thread, (void *)radio);
-       if (radio->msg.thread_id) {
-               /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
-               MMRADIO_LOG_ERROR("failed to create thread : msg");
-               goto ERROR;
+       if (type >= MM_RADIO_THREAD_NUM) {
+               MMRADIO_LOG_WARNING("wrong argument thread type");
+               return MM_ERROR_RADIO_INTERNAL;
        }
 
-       MMRADIO_INIT_MUTEX(radio->seek.mutex);
-       MMRADIO_INIT_COND(radio->seek.cond);
-
-       radio->seek.thread_id = pthread_create(&radio->seek.thread, NULL,
-               (void *)__mmradio_seek_thread, (void *)radio);
-       if (radio->seek.thread_id) {
-               MMRADIO_LOG_DEBUG("failed to create thread : seek");
-               goto ERROR;
-       }
+       p_thread = &radio->thread[type];
+       MMRADIO_CHECK_ARG(p_thread);
 
-       MMRADIO_INIT_MUTEX(radio->scan.mutex);
-       MMRADIO_INIT_COND(radio->scan.cond);
+       MMRADIO_INIT_MUTEX(p_thread->mutex);
+       MMRADIO_INIT_COND(p_thread->cond);
 
-       radio->scan.thread_id = pthread_create(&radio->scan.thread, NULL,
-               (void *)__mmradio_scan_thread, (void *)radio);
-       if (radio->scan.thread_id) {
-               MMRADIO_LOG_ERROR("failed to create thread : scan");
-               goto ERROR;
+       MMRADIO_THREAD_LOCK(p_thread);
+       p_thread->thread_id = pthread_create(&p_thread->thread, NULL,
+               (void *)__mmradio_thread_function[type], (void *)radio);
+       if (p_thread->thread_id) {
+               MMRADIO_LOG_DEBUG("failed to create thread : [%d]", type);
+               MMRADIO_THREAD_UNLOCK(p_thread);
+               return MM_ERROR_RADIO_INTERNAL;
        }
 
-       MMRADIO_LOG_FLEAVE();
-       return ret;
+       MMRADIO_LOG_DEBUG("wait for [%d] thread", type);
+       MMRADIO_THREAD_WAIT(p_thread);
+       MMRADIO_LOG_DEBUG("[%d] thread started", type);
+       MMRADIO_THREAD_UNLOCK(p_thread);
+
+       return MM_ERROR_NONE;
 
 ERROR:
-       if (radio->seek.thread) {
-               MMRADIO_SEEK_THREAD_LOCK(radio);
-               radio->seek.thread_exit = true;
-               MMRADIO_SEEK_THREAD_SIGNAL(radio);
-               MMRADIO_SEEK_THREAD_UNLOCK(radio);
-               pthread_join(radio->seek.thread, NULL);
-               radio->seek.thread = 0;
-       }
+       pthread_mutex_destroy(&p_thread->mutex);
+       pthread_cond_destroy(&p_thread->cond);
+       return MM_ERROR_RADIO_INTERNAL;
 
-       if (radio->msg.thread) {
-               mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
-               if (!msg) {
-                       MMRADIO_LOG_ERROR("failed to get mm_radio_msg_t");
-               } else {
-                       msg->msg_type = MM_RADIO_MSG_DESTROY;
-                       g_async_queue_push_front(radio->msg_queue, msg);
-                       pthread_join(radio->msg.thread, NULL);
-                       radio->msg.thread = 0;
+}
+
+static int __mmradio_create_threads(mm_radio_t *radio)
+{
+       int ret = MM_ERROR_NONE;
+       int type = 0;
+
+       MMRADIO_LOG_FENTER();
+
+       MMRADIO_CHECK_INSTANCE(radio);
+
+       MMRADIO_INIT_MUTEX(radio->cmd_lock);
+       MMRADIO_INIT_MUTEX(radio->volume_lock);
+       MMRADIO_INIT_MUTEX(radio->hal_seek_mutex);
+
+       for (type = (int)MM_RADIO_THREAD_MSG; type < (int)MM_RADIO_THREAD_NUM; type++) {
+               ret = __mmradio_create_thread_type(radio, (MMRadioThreadTypes)type);
+               if (ret) {
+                       MMRADIO_LOG_ERROR("failed to create thread(%d)", type);
+                       while (--type >= (int)MM_RADIO_THREAD_MSG)
+                               __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
+                       goto ERROR;
                }
        }
 
+       MMRADIO_LOG_FLEAVE();
+       return ret;
+
+ERROR:
        pthread_mutex_destroy(&radio->cmd_lock);
        pthread_mutex_destroy(&radio->volume_lock);
        pthread_mutex_destroy(&radio->hal_seek_mutex);
-       pthread_mutex_destroy(&radio->seek.mutex);
-       pthread_cond_destroy(&radio->seek.cond);
-       pthread_mutex_destroy(&radio->scan.mutex);
-       pthread_cond_destroy(&radio->scan.cond);
 
+       MMRADIO_LOG_FLEAVE();
        return MM_ERROR_RADIO_INTERNAL;
 }
 
-static void __mmradio_destroy_thread(mm_radio_t *radio)
+static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
 {
+       MMRadioThread_t *p_thread = NULL;
+       mm_radio_msg_t *msg = NULL;
        MMRADIO_LOG_FENTER();
 
        MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
 
-       if (radio->seek.thread) {
-               MMRADIO_SEEK_THREAD_LOCK(radio);
-               radio->seek.thread_exit = true;
-               MMRADIO_SEEK_THREAD_SIGNAL(radio);
-               MMRADIO_SEEK_THREAD_UNLOCK(radio);
-               pthread_join(radio->seek.thread, NULL);
-               radio->seek.thread = 0;
+       if (type >= MM_RADIO_THREAD_NUM) {
+               MMRADIO_LOG_WARNING("wrong argument thread type");
+               return;
        }
 
-       if (radio->scan.thread) {
-               MMRADIO_SCAN_THREAD_LOCK(radio);
-               radio->scan.thread_exit = true;
-               MMRADIO_SCAN_THREAD_SIGNAL(radio);
-               MMRADIO_SCAN_THREAD_UNLOCK(radio);
-               pthread_join(radio->scan.thread, NULL);
-               radio->scan.thread = 0;
-       }
+       p_thread = &radio->thread[type];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
 
-       if (radio->msg.thread) {
-               mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
-               if (!msg) {
-                       MMRADIO_LOG_ERROR("failed to get mm_radio_msg_t");
-               } else {
-                       msg->msg_type = MM_RADIO_MSG_DESTROY;
-                       g_async_queue_push_front(radio->msg_queue, msg);
-                       pthread_join(radio->msg.thread, NULL);
-                       radio->msg.thread = 0;
+       if (p_thread->thread) {
+               switch (type) {
+               case MM_RADIO_THREAD_MSG:
+                       msg = g_slice_new0(mm_radio_msg_t);
+                       if (!msg) {
+                               MMRADIO_LOG_ERROR("failed to get mm_radio_msg_t");
+                       } else {
+                               msg->msg_type = MM_RADIO_MSG_DESTROY;
+                               g_async_queue_push_front(radio->msg_queue, msg);
+                               pthread_join(p_thread->thread, NULL);
+                               p_thread->thread = 0;
+                       }
+                       break;
+               case MM_RADIO_THREAD_SEEK:
+               case MM_RADIO_THREAD_SCAN:
+                       MMRADIO_THREAD_LOCK(p_thread);
+                       p_thread->thread_exit = true;
+                       MMRADIO_THREAD_SIGNAL(p_thread);
+                       MMRADIO_THREAD_UNLOCK(p_thread);
+                       pthread_join(p_thread->thread, NULL);
+                       p_thread->thread = 0;
+                       break;
+               default:
+                       MMRADIO_LOG_WARNING("(%d)type isn't handled", type);
+                       break;
                }
+       } else {
+               MMRADIO_LOG_WARNING("(%d)thread is zero", type);
        }
 
+       pthread_mutex_destroy(&p_thread->mutex);
+       pthread_cond_destroy(&p_thread->cond);
+
+       MMRADIO_LOG_FLEAVE();
+}
+
+static void __mmradio_destroy_threads(mm_radio_t *radio)
+{
+       int type = (int)MM_RADIO_THREAD_NUM;
+       MMRADIO_LOG_FENTER();
+
+       MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
+
+       while (--type >= 0)
+               __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
+
        pthread_mutex_destroy(&radio->cmd_lock);
        pthread_mutex_destroy(&radio->volume_lock);
        pthread_mutex_destroy(&radio->hal_seek_mutex);
 
-       pthread_mutex_destroy(&radio->seek.mutex);
-       pthread_cond_destroy(&radio->seek.cond);
-
-       pthread_mutex_destroy(&radio->scan.mutex);
-       pthread_cond_destroy(&radio->scan.cond);
-
        MMRADIO_LOG_FLEAVE();
 }
 
@@ -1630,18 +1687,33 @@ void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_dat
 
 void __mmradio_msg_thread(mm_radio_t *radio)
 {
-       MMMessageParamType param = {0,};
+
        mm_radio_msg_t *msg = NULL;
-       int exit_msg_thread = 0;
+       MMRadioThread_t *p_thread = NULL;
+
+       MMRADIO_LOG_FENTER();
+       MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
+
+       p_thread = &radio->thread[MM_RADIO_THREAD_MSG];
+       MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
+
+       p_thread->thread_exit = false;
 
-       /*we run a while one loop*/
-       while (exit_msg_thread == 0) {
+
+       MMRADIO_THREAD_LOCK(p_thread);
+       MMRADIO_THREAD_SIGNAL(p_thread);
+       MMRADIO_THREAD_UNLOCK(p_thread);
+
+       /* we run a while one loop*/
+       while (!p_thread->thread_exit) {
                msg = (mm_radio_msg_t *)g_async_queue_pop(radio->msg_queue);
                if (!msg) {
                        MMRADIO_LOG_ERROR("poped message is NULL!");
                        break;
                }
 
+               MMMessageParamType param = {0,};
+
                switch (msg->msg_type) {
                case MM_RADIO_MSG_DESTROY:
                        MMRADIO_LOG_INFO("get destroy msg. pop all event to finish this thread");
@@ -1652,7 +1724,7 @@ void __mmradio_msg_thread(mm_radio_t *radio)
                                        g_slice_free(mm_radio_msg_t, msg_pop);
                                }
                        }
-                       exit_msg_thread = 1;
+                       p_thread->thread_exit = true;
                        break;
                case MM_RADIO_MSG_SCAN_INFO:
                        MMRADIO_LOG_INFO("get scan info frequency: %d", msg->data);
@@ -1691,4 +1763,6 @@ void __mmradio_msg_thread(mm_radio_t *radio)
        }
 
        MMRADIO_LOG_INFO("msg thread is finished");
+       MMRADIO_LOG_FLEAVE();
+       pthread_exit(NULL);
 }