[FIX] deadlock during __switch_to() instrumentation 34/43834/1
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Tue, 14 Jul 2015 10:12:33 +0000 (13:12 +0300)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Tue, 14 Jul 2015 10:12:33 +0000 (13:12 +0300)
during __switch_to() handler execution we have 'rq->lock' locked by
__schedule(). So we can not call schedule_work() (which also uses 'rq->lock')

Change-Id: If8f0b0302d27ef21c80be7433e7ad3b5b0400668
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
buffer/buffer_queue.c
buffer/buffer_queue.h
buffer/swap_buffer_module.c
buffer/swap_buffer_module.h
buffer/swap_buffer_to_buffer_queue.h
driver/driver_to_buffer.c
driver/driver_to_buffer.h
ks_features/ksf_msg.c
writer/swap_msg.c
writer/swap_msg.h

index 2a7c39e..803e930 100644 (file)
@@ -425,19 +425,14 @@ void add_to_read_list(struct swap_subbuffer *subbuffer)
        sync_unlock(&read_queue.queue_sync);
 }
 
-/**
- * @brief Call add to read list and callback function from driver module.
- *
- * @param subbuffer Pointer to the subbuffer to add.
- * @return swap_buffer_callback result.
- */
-int add_to_read_list_with_callback(struct swap_subbuffer *subbuffer)
+static int add_to_read_list_with_callback(struct swap_subbuffer *subbuffer,
+                                  bool wakeup)
 {
        int result = 0;
 
        add_to_read_list(subbuffer);
        /* TODO Handle ret value */
-       result = swap_buffer_callback(subbuffer);
+       result = swap_buffer_callback(subbuffer, wakeup);
 
        return result;
 }
@@ -461,7 +456,8 @@ unsigned int get_readable_buf_cnt(void)
  * beginning of memory for writing should be stored.
  * @return Found swap_subbuffer.
  */
-struct swap_subbuffer *get_from_write_list(size_t size, void **ptr_to_write)
+struct swap_subbuffer *get_from_write_list(size_t size, void **ptr_to_write,
+                                          bool wakeup)
 {
        struct swap_subbuffer *result = NULL;
 
@@ -532,7 +528,7 @@ struct swap_subbuffer *get_from_write_list(size_t size, void **ptr_to_write)
                callback_queue.start_ptr =
                        callback_queue.start_ptr->next_in_queue;
 
-               add_to_read_list_with_callback(tmp_buffer);
+               add_to_read_list_with_callback(tmp_buffer, wakeup);
        }
 
        return result;
index f89ee99..9b3291e 100644 (file)
@@ -32,6 +32,7 @@
 #ifndef __BUFFER_QUEUE_H__
 #define __BUFFER_QUEUE_H__
 
+#include <linux/types.h>
 #include "buffer_description.h"
 
 int buffer_queue_allocation(size_t subbuffer_size,
@@ -39,7 +40,8 @@ int buffer_queue_allocation(size_t subbuffer_size,
 void buffer_queue_free(void);
 int buffer_queue_reset(void);
 void buffer_queue_flush(void);
-struct swap_subbuffer *get_from_write_list(size_t size, void **ptr_to_write);
+struct swap_subbuffer *get_from_write_list(size_t size, void **ptr_to_write,
+                                          bool wakeup);
 struct swap_subbuffer *get_from_read_list(void);
 void add_to_write_list(struct swap_subbuffer *subbuffer);
 void add_to_read_list(struct swap_subbuffer *subbuffer);
index 1f4a0f8..551f940 100644 (file)
@@ -49,7 +49,7 @@ static unsigned char swap_buffer_status = BUFFER_FREE;
 /**
  * @brief Subbuffer callback type.
  */
-typedef int(*subbuffer_callback_type)(void);
+typedef int(*subbuffer_callback_type)(bool wakeup);
 
 /* Callback that is called when full subbuffer appears */
 static subbuffer_callback_type subbuffer_callback;
@@ -188,7 +188,7 @@ EXPORT_SYMBOL_GPL(swap_buffer_uninit);
  * @param size Size of a data for writing.
  * @return Size of written data on success, negative error code otherwise.
  */
-ssize_t swap_buffer_write(void *data, size_t size)
+ssize_t swap_buffer_write(void *data, size_t size, bool wakeup)
 {
        int result = E_SB_SUCCESS;
        struct swap_subbuffer *buffer_to_write = NULL;
@@ -207,7 +207,7 @@ ssize_t swap_buffer_write(void *data, size_t size)
        swap_irq_disable(&flags);
 
        /* Get next write buffer and occupying semaphore */
-       buffer_to_write = get_from_write_list(size, &ptr_to_write);
+       buffer_to_write = get_from_write_list(size, &ptr_to_write, wakeup);
        if (!buffer_to_write) {
                swap_irq_enable(&flags);
                return -E_SB_NO_WRITABLE_BUFFERS;
@@ -329,14 +329,14 @@ EXPORT_SYMBOL_GPL(swap_buffer_flush);
  * @return -E_SB_NO_CALLBACK if no callback is registered or callbacks ret
  * value otherwise.
  */
-int swap_buffer_callback(void *buffer)
+int swap_buffer_callback(void *buffer, bool wakeup)
 {
        int result;
 
        if (!subbuffer_callback)
                return -E_SB_NO_CALLBACK;
 
-       result = subbuffer_callback();
+       result = subbuffer_callback(wakeup);
        if (result < 0)
                print_err("Callback error! Error code: %d\n", result);
 
index 4a4a8db..95b31fa 100644 (file)
@@ -60,7 +60,7 @@ struct swap_subbuffer;
 struct buffer_init_t {
        size_t subbuffer_size;
        unsigned int nr_subbuffers;
-       int (*subbuffer_full_cb)(void);
+       int (*subbuffer_full_cb)(bool wakeup);
 
        unsigned char lower_threshold;
        int (*low_mem_cb)(void);
@@ -82,7 +82,7 @@ int swap_buffer_uninit(void);
 /* SWAP Buffer write function. Pass it size of the data and pointer to the data.
  * On success returns number of bytes written (>=0) or error code (<0)
  * otherwise */
-ssize_t swap_buffer_write(void *data, size_t size);
+ssize_t swap_buffer_write(void *data, size_t size, bool wakeup);
 
 /* SWAP Buffer get. Put subbuffer pointer to the variable *subbuffer.
  * Return pages count in subbuffer. */
index 4d1da3a..076549d 100644 (file)
@@ -29,6 +29,8 @@
 #ifndef __SWAP_BUFFER_TO_BUFFER_QUEUE_H__
 #define __SWAP_BUFFER_TO_BUFFER_QUEUE_H__
 
-int swap_buffer_callback(void *buffer);
+#include <linux/types.h>
+
+int swap_buffer_callback(void *buffer, bool wakeup);
 
 #endif /* __SWAP_BUFFER_TO_BUFFER_QUEUE_H__ */
index 2d8e94b..909b3b1 100644 (file)
@@ -140,16 +140,12 @@ static int driver_to_buffer_release(void)
        return E_SD_SUCCESS;
 }
 
-/**
- * @brief Buffers callback function
- *
- * @return 0
- */
-int driver_to_buffer_callback(void)
+static int driver_to_buffer_callback(bool wakeup)
 {
        /* Increment buffers_to_read counter */
        inc_buffers_to_read();
-       swap_device_wake_up_process();
+       if (wakeup)
+               swap_device_wake_up_process();
 
        return E_SD_SUCCESS;
 }
index 200c6bb..e133ee1 100644 (file)
@@ -33,7 +33,6 @@
 int driver_to_buffer_initialize(size_t size, unsigned int count);
 int driver_to_buffer_uninitialize(void);
 ssize_t driver_to_buffer_read(char __user *buf, size_t count);
-void driver_to_buffer_callback(void);
 int driver_to_buffer_fill_spd(struct splice_pipe_desc *spd);
 int driver_to_buffer_buffer_to_read(void);
 int driver_to_buffer_next_buffer_to_read(void);
index 100fe85..94d2151 100644 (file)
@@ -360,7 +360,7 @@ static void context_switch(struct pt_regs *regs, enum swap_msg_id id)
        mcs->tid = task->pid;
        mcs->cpu_num = smp_processor_id();
 
-       swap_msg_flush(m, sizeof(*mcs));
+       swap_msg_flush_wakeupoff(m, sizeof(*mcs));
        swap_msg_put(m);
 }
 
index 7f496ba..abfd992 100644 (file)
@@ -119,14 +119,14 @@ struct swap_msg *swap_msg_get(enum swap_msg_id id)
 }
 EXPORT_SYMBOL_GPL(swap_msg_get);
 
-int swap_msg_flush(struct swap_msg *m, size_t size)
+static int __swap_msg_flush(struct swap_msg *m, size_t size, bool wakeup)
 {
        if (unlikely(size >= SWAP_MSG_PAYLOAD_SIZE))
                return -ENOMEM;
 
        m->len = size;
 
-       if (swap_buffer_write(m, SWAP_MSG_PRIV_DATA + size) !=
+       if (swap_buffer_write(m, SWAP_MSG_PRIV_DATA + size, wakeup) !=
            (SWAP_MSG_PRIV_DATA + size)) {
                atomic_inc(&discarded);
                return -EINVAL;
@@ -134,8 +134,19 @@ int swap_msg_flush(struct swap_msg *m, size_t size)
 
        return 0;
 }
+
+int swap_msg_flush(struct swap_msg *m, size_t size)
+{
+       return __swap_msg_flush(m, size, true);
+}
 EXPORT_SYMBOL_GPL(swap_msg_flush);
 
+int swap_msg_flush_wakeupoff(struct swap_msg *m, size_t size)
+{
+       return __swap_msg_flush(m, size, false);
+}
+EXPORT_SYMBOL_GPL(swap_msg_flush_wakeupoff);
+
 void swap_msg_put(struct swap_msg *m)
 {
        put_cpu();
@@ -350,7 +361,7 @@ int swap_msg_raw(void *data, size_t size)
        m->seq_num = atomic_inc_return(&seq_num);
 
        /* TODO: What should be returned?! When message was discarded. */
-       if (swap_buffer_write(m, size) != size)
+       if (swap_buffer_write(m, size, true) != size)
                atomic_inc(&discarded);
 
        return size;
index afa6dbd..068885d 100644 (file)
@@ -76,6 +76,7 @@ static inline u64 swap_msg_current_time(void)
 
 struct swap_msg *swap_msg_get(enum swap_msg_id id);
 int swap_msg_flush(struct swap_msg *m, size_t size);
+int swap_msg_flush_wakeupoff(struct swap_msg *m, size_t size);
 void swap_msg_put(struct swap_msg *m);
 
 static inline void *swap_msg_payload(struct swap_msg *m)