|
|
Some intelligent drivers can check to see if they need to call the tty line discipline. This is useful because driver writers can sometimes write a more efficient line discipline than the discipline supplied for their particular hardware. In the code below (extracted from an write(D2oddi) routine), the driver checks to see if it needs to call the tty line discipline. If it does not, there is a call to a user-written function: xx_alternate_line_discipline( ).
if (need_to_call_line_discipline) run_ld(tp, DIST_LINESW_WRITE,a, b, c, d, e); else xx_alternate_line_discipline();The multithreaded alternate line discipline routine would look like this:
1 xx_alternate_line_discipline() 2 { 3 s = tc_tlock(tp); 4 ... 5 while (....) { 6 ..... 7 lockb(&xx_board [board]);A lock is acquired at line 3; this lock protects the tp structure. The code then goes into a loop in which an indefinite activity such as copying characters into dual-ported memory takes place. Within the loop, the board itself is locked (line 7); this is necessary to prevent different processes manipulating queues on the same dual ported memory.
It is important to allow for error conditions. The next fragment of code illustrates the point that you must check for error conditions, and if such a condition occurs, you must be sure to release the locks in the correct order: that is, the most recently acquired lock must be the first to be released. This code is a continuation of the code above:
10 ... 11 if (error) 12 unlockb(&xx_board[board], -1); 13 tc_tunlock(tp,s); 14 15 u.u_error = EFAULT; 16 return; 17 } 18 ... 19 } 20 unlockb(&xx_board[board], -1); 21 tc_tunlock(tp,s); 22 }When an error occurs, both locks are released in the correct order. The first call passes -1 as the oldspl value because the original spl level will be set by the second unlockb.