net: Make check_next_chunk() mutually exclusive 05/316905/1
authorDongwoo Lee <dwoo08.lee@samsung.com>
Thu, 19 Dec 2024 06:23:47 +0000 (15:23 +0900)
committerDongwoo Lee <dwoo08.lee@samsung.com>
Thu, 19 Dec 2024 06:58:59 +0000 (15:58 +0900)
Since 4004285311 ("Fix the race in data_finished() and resp_finished()"),
Although the possibility of a race between two threads executing
data_finished() and resp_finished() is reduced, it is still possible
to enter the check_next_chunk() function at the same time in certain
circumstances as below:

Thread A  | Thread B
-------------------------------------------------+--------------------------------------------------------------
 | chunk->resp_finished = 1;
chunk->data_finished = 1;  |
if (chunk->resp_finished)      |
check_next_chunk(chunk, transfer);  |
chunk->chunk_number = transfer->chunk_number++;  |
 | if (chunk->data_finished)
 | check_next_chunk(chunk, transfer);
 |      >> chunk->chunk_number = transfer->chunk_number++;
                                                 | <chunk_number becomes unmatched>
chunk->data_finished = chunk->resp_finished = 0; |


To address this, this makes the functions completely mutually exclusive.

Change-Id: I94df217ec82dadc322050693e86763f9c8213d05
Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com>
libthor/thor_net.c

index 9da314cde7e3bd63327a703548b9c42330326438..55a63062ec647c10d74af1caaa5bc4271f4793cf 100644 (file)
@@ -6,6 +6,7 @@
 #include <sys/socket.h>
 #include <aio.h>
 #include <signal.h>
+#include <pthread.h>
 
 #include "thor.h"
 #include "thor_internal.h"
@@ -149,6 +150,7 @@ struct t_thor_net_chunk {
        int chunk_number;
        int data_finished;
        int resp_finished;
+       pthread_mutex_t lock;
 };
 
 struct t_thor_net_transfer {
@@ -258,9 +260,14 @@ static void data_finished(sigval_t sigval)
                return;
        }
 
+       pthread_mutex_lock(&chunk->lock);
        chunk->data_finished = 1;
-       if (chunk->resp_finished)
+       pthread_mutex_unlock(&chunk->lock);
+
+       pthread_mutex_lock(&chunk->lock);
+       if (chunk->data_finished && chunk->resp_finished)
                check_next_chunk(chunk, transfer);
+       pthread_mutex_unlock(&chunk->lock);
 }
 
 static void resp_finished(sigval_t sigval)
@@ -307,9 +314,14 @@ static void resp_finished(sigval_t sigval)
                                          chunk->chunk_number,
                                          transfer->user_data);
 
+       pthread_mutex_lock(&chunk->lock);
        chunk->resp_finished = 1;
-       if (chunk->data_finished)
+       pthread_mutex_unlock(&chunk->lock);
+
+       pthread_mutex_lock(&chunk->lock);
+       if (chunk->data_finished && chunk->resp_finished)
                check_next_chunk(chunk, transfer);
+       pthread_mutex_unlock(&chunk->lock);
 }
 
 static int thor_net_send_raw_data(thor_device_handle *th,
@@ -348,6 +360,8 @@ static int thor_net_send_raw_data(thor_device_handle *th,
        if (!chunk.buf)
                return -ENOMEM;
 
+       pthread_mutex_init(&chunk.lock, NULL);
+
        chunk.data_transfer.aio_fildes = nh->sock_fd;
        chunk.data_transfer.aio_buf = chunk.buf;
        chunk.data_transfer.aio_nbytes = chunk.trans_unit_size;