mirror of https://github.com/OpenIPC/firmware.git
				
				
				
			
		
			
				
	
	
		
			101 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Diff
		
	
	
			
		
		
	
	
			101 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Diff
		
	
	
| --- linux-4.9.37/drivers/tty/vt/selection.c	2017-07-12 16:42:41.000000000 +0300
 | |
| +++ linux-4.9.y/drivers/tty/vt/selection.c	2021-06-07 13:01:34.000000000 +0300
 | |
| @@ -13,6 +13,7 @@
 | |
|  #include <linux/tty.h>
 | |
|  #include <linux/sched.h>
 | |
|  #include <linux/mm.h>
 | |
| +#include <linux/mutex.h>
 | |
|  #include <linux/slab.h>
 | |
|  #include <linux/types.h>
 | |
|  
 | |
| @@ -40,6 +41,7 @@
 | |
|  static int sel_end;
 | |
|  static int sel_buffer_lth;
 | |
|  static char *sel_buffer;
 | |
| +static DEFINE_MUTEX(sel_lock);
 | |
|  
 | |
|  /* clear_selection, highlight and highlight_pointer can be called
 | |
|     from interrupt (via scrollback/front) */
 | |
| @@ -163,7 +165,7 @@
 | |
|  	char *bp, *obp;
 | |
|  	int i, ps, pe, multiplier;
 | |
|  	u16 c;
 | |
| -	int mode;
 | |
| +	int mode, ret = 0;
 | |
|  
 | |
|  	poke_blanked_console();
 | |
|  
 | |
| @@ -203,6 +205,7 @@
 | |
|  		pe = tmp;
 | |
|  	}
 | |
|  
 | |
| +	mutex_lock(&sel_lock);
 | |
|  	if (sel_cons != vc_cons[fg_console].d) {
 | |
|  		clear_selection();
 | |
|  		sel_cons = vc_cons[fg_console].d;
 | |
| @@ -248,9 +251,10 @@
 | |
|  			break;
 | |
|  		case TIOCL_SELPOINTER:
 | |
|  			highlight_pointer(pe);
 | |
| -			return 0;
 | |
| +			goto unlock;
 | |
|  		default:
 | |
| -			return -EINVAL;
 | |
| +			ret = -EINVAL;
 | |
| +			goto unlock;
 | |
|  	}
 | |
|  
 | |
|  	/* remove the pointer */
 | |
| @@ -272,7 +276,7 @@
 | |
|  	else if (new_sel_start == sel_start)
 | |
|  	{
 | |
|  		if (new_sel_end == sel_end)	/* no action required */
 | |
| -			return 0;
 | |
| +			goto unlock;
 | |
|  		else if (new_sel_end > sel_end)	/* extend to right */
 | |
|  			highlight(sel_end + 2, new_sel_end);
 | |
|  		else				/* contract from right */
 | |
| @@ -299,7 +303,8 @@
 | |
|  	if (!bp) {
 | |
|  		printk(KERN_WARNING "selection: kmalloc() failed\n");
 | |
|  		clear_selection();
 | |
| -		return -ENOMEM;
 | |
| +		ret = -ENOMEM;
 | |
| +		goto unlock;
 | |
|  	}
 | |
|  	kfree(sel_buffer);
 | |
|  	sel_buffer = bp;
 | |
| @@ -324,7 +329,9 @@
 | |
|  		}
 | |
|  	}
 | |
|  	sel_buffer_lth = bp - sel_buffer;
 | |
| -	return 0;
 | |
| +unlock:
 | |
| +	mutex_unlock(&sel_lock);
 | |
| +	return ret;
 | |
|  }
 | |
|  
 | |
|  /* Insert the contents of the selection buffer into the
 | |
| @@ -352,10 +359,13 @@
 | |
|  	tty_buffer_lock_exclusive(&vc->port);
 | |
|  
 | |
|  	add_wait_queue(&vc->paste_wait, &wait);
 | |
| +	mutex_lock(&sel_lock);
 | |
|  	while (sel_buffer && sel_buffer_lth > pasted) {
 | |
|  		set_current_state(TASK_INTERRUPTIBLE);
 | |
|  		if (tty_throttled(tty)) {
 | |
| +			mutex_unlock(&sel_lock);
 | |
|  			schedule();
 | |
| +			mutex_lock(&sel_lock);
 | |
|  			continue;
 | |
|  		}
 | |
|  		__set_current_state(TASK_RUNNING);
 | |
| @@ -364,6 +374,7 @@
 | |
|  					      count);
 | |
|  		pasted += count;
 | |
|  	}
 | |
| +	mutex_unlock(&sel_lock);
 | |
|  	remove_wait_queue(&vc->paste_wait, &wait);
 | |
|  	__set_current_state(TASK_RUNNING);
 | |
|  
 |