Need pseudo code for producer consumer problem stated below - multithreading

Need algorithm/pseudo-code for a producer-consumer problem in which we have one
producer and two consumers sharing a bounded buffer (capacity N). Any of the two
consumers can consume an item from the buffer if buffer is not empty; however, the
consumers have to wait if the buffer is empty. Moreover, the producer has to wait if the buffer is full. Implement the buffer is FIFO circular queue.
Also can someone answer below questions?
Can all the N slots may be full in the buffer simultaneously?
If yes how? and if not why not?

The buffer can be full if the producer adds values to the buffer faster than the consumers extract values from the buffer. If the consumers extract the values as fast or faster than the producer adds values the buffer will never fill.
Instead of pseudo-code I will present a general solution using the Ada programming language. This solution works for one or more producers and one or more consumers.
The Ada solution consists of three files. The first file is a package specification which defines the API for a producer-consumer problem.
-----------------------------------------------------------------------
-- Producer-consumer with bounded buffer
-----------------------------------------------------------------------
generic
Capacity : Positive;
package Bounded_PC is
task type Producer is
entry set_id(Id : in Positive);
entry Stop;
end Producer;
task type Consumer is
entry set_id(Id : in Positive);
entry Stop;
end Consumer;
end Bounded_PC;
This solution requires the size of the shared buffer to be specified as a generic parameter when instantiating the package Bounded_PC.
The package defines two task types (tasks are Ada's name for threads). The first task type is named Producer. The Producer task type defines two entries. The entry Set_Id establishes the programmer-chosen Id for a particular instance of the task type. The entry Stop is used to stop the execution of an instance of the task type.
The task type Consumer has an identical interface, with an entry to set the task Id and an entry to stop the task.
This is the entire API for the producer and consumer tasks in this example.
The implementation of the tasks and their shared buffer is contained in the package body for the Bounded_PC package.
with Ada.Text_IO; use Ada.Text_IO;
package body Bounded_PC is
subtype Index_T is Positive range 1..Capacity;
type Buf_Array is array (Index_T) of Integer;
------------
-- Buffer --
------------
protected Buffer is
Entry Write(Item : in Integer);
Entry Read(Item : out Integer);
private
Buf : Buf_Array;
Write_Index : Index_T := 1;
Read_Index : Index_T := 1;
Count : Natural := 0;
end Buffer;
protected body Buffer is
entry Write(Item : in Integer) when Count < Capacity is
begin
Buf(Write_Index) := Item;
Write_Index := (Write_Index mod Capacity) + 1;
Count := Count + 1;
end Write;
entry Read(Item : out Integer) when Count > 0 is
begin
Item := Buf(Read_Index);
Read_Index := (Read_Index mod Capacity) + 1;
Count := Count - 1;
end Read;
end Buffer;
--------------
-- Producer --
--------------
task body Producer is
Value : Integer := 0;
Me : Positive;
begin
accept Set_Id(Id : in Positive) do
Me := Id;
end Set_Id;
loop
select
accept Stop;
exit;
else
select
Buffer.Write(Value);
Put_Line("Producer" & Me'Image & " wrote" & Value'Image);
Value := Value + 1;
or
delay 0.001;
end select;
end select;
end loop;
end Producer;
--------------
-- Consumer --
--------------
task body Consumer is
Value : Integer;
Me : Positive;
begin
accept Set_Id(Id : in Positive) do
Me := Id;
end Set_Id;
loop
select
accept Stop;
exit;
else
select
Buffer.Read(Value);
Put_Line("Consumer" & Me'Image & " read" & Value'Image);
or
delay 0.001;
end select;
end select;
end loop;
end Consumer;
end Bounded_PC;
Ada allows the programmer to specify the range of values for an array index. The subtype Index_T is a subtype of Integer with a minimum value of 1 and a maximum value of Capacity, which is the generic parameter used to make an instance of this package.
The array type used as the bounded shared buffer in this example is named Buf_Array. Buff_Array is indexed by Index_T and each element is an Integer.
The buffer itself is an Ada protected object. Ada protected objects are implicitly protected from race conditions. The protected object named Buffer has two entries. The Write entry will be called by instances of the Producer task type. The Read entry will be called by instances of the Consumer task type. The Write entry passes an Integer in to the buffer and the Read entry passes an Integer out of the buffer.
The private part of the protected Buffer specification contains the internal data elements of Buffer. Those elements are an instance of Buf_Array named Buf, and instance of Index_T named Write_Index, an instance of Intex_T named Read_Index and an instance of the subtype Natural, which is an Integer with a minimum value of 0. This instance is named Count.
The protected body of Buffer implements the two entries Write and Read.
The Write entry has a boundary condition allowing the Write entry to execute only when the buffer is not full, or as the logic states, when Count is less than Capacity. When the Write entry does execute it assigns the value in the parameter Item to the array element at Write_Index. It then increments the Write_Index accounting for modular wrap around logic. Finally it increments Count.
If the boundary condition is false, in this case Count is not less than Capacity, the calling task is suspended in a queue automatically managed by the language. The next task in the queue, if any, is then handled and its value is written to the buffer.
The logic for the Read entry is very similar. The boundary condition differs from the Write boundary condition. Instead the Read entry only executes when the buffer is not empty, or as stated in the logic, when Count > 0. When the Read entry executes it copies the value in the Buf array at index Read_Index to the parameter Item, increments Read_Index using modular arithmetic and decrements count. The Read entry has its own entry buffer where instance of Consumer will be queued until a value is written to Buffer.
The Producer task type is implemented by first declaring two local variables. Each instance of the task type will have its own instances of these two variables. The first variable, named Value, is an Integer initialized to 0. The second variable is a subtype of Integer named Positive, which is an integer with a minimum value of 1. The name of this variable is Me. Me will hold the task Id assigned to this instance of the task.
After the "begin" reserved word there is an accept statement which accepts the Set_Id task entry. The value passed to this instance of producer will be assigned to its local Me variable. The task will wait at the accept call until another task calls its entry and passed its ID.
The real work of this task is to write numbers to Buffer until another task calls its Stop entry. All this is done within the loop statement. The "select" statement forms the beginning of a conditional branch in the response. Either the task will accept a call from another task on the Stop entry, in which case it will exit the loop, or it will write a value to the Buffer protected object. Upon successfully writing to Buffer the producer instance outputs a message identifying the task ID and the value written to Buffer. The number contained in the variable Value is incremented. If the Write entry does not execute within 0.001 seconds (1 millisecond) the loop repeats.
The Consumer task type is very similar to the producer. It declares two local variables Value and Me. It waits to accept is Set_Id entry and assigns the number passed to it to its local variable named Me. The consumer then executes a loop similar to the producer loop. The only difference is that it reads value from Buffer and prints that value.
The Bounded_PC package must be used within an actual program. The following procedure named main provides the program structure to test this package.
with Bounded_PC;
procedure Main is
package Int_Pck is new Bounded_Pc(10);
use Int_Pck;
P1 : Producer;
P2 : Producer;
C1 : Consumer;
C2 : Consumer;
begin
P1.Set_Id(1);
P2.Set_Id(2);
C1.Set_Id(1);
C2.Set_Id(2);
delay 0.01;
P1.Stop;
P2.Stop;
delay 0.01;
C1.Stop;
C2.Stop;
end Main;
The a concrete instance of the generic Bounded_Pc package is declared passing the number 10 as the capacity of the Buffer array.
Two producers named P1 and P1 are created. Two consumers named C1 and C2 are created.
following the "begin" reserved word in the main procedure the Set_Id entries for tasks P1, P2, C1, C2 are called, passing ID values for each task.
The main procedure then delays (sleeps) for 0.01 seconds, or 10 milliseconds. The Stop entries for P1 and P2 are called, the main procedure delays for another 10 milliseconds and then calls the stop procedures for C1 and C2.
The output of this program is:
Producer 2 wrote 0
Producer 2 wrote 1
Producer 2 wrote 2
Producer 2 wrote 3
Producer 2 wrote 4
Producer 2 wrote 5
Producer 2 wrote 6
Producer 2 wrote 7
Producer 2 wrote 8
Producer 2 wrote 9
Producer 2 wrote 10
Consumer 1 read 0
Consumer 1 read 1
Consumer 1 read 2
Consumer 1 read 3
Consumer 1 read 4
Consumer 1 read 5
Consumer 1 read 6
Consumer 1 read 7
Consumer 1 read 8
Consumer 1 read 9
Consumer 1 read 10
Consumer 1 read 11
Producer 2 wrote 11
Consumer 2 read 0
Consumer 1 read 12
Producer 2 wrote 12
Producer 1 wrote 0
Producer 2 wrote 13
Consumer 2 read 13
Producer 2 wrote 14
Producer 1 wrote 1
Producer 1 wrote 2
Producer 1 wrote 3
Producer 2 wrote 15
Producer 1 wrote 4
Producer 1 wrote 5
Producer 2 wrote 16
Producer 2 wrote 17
Producer 2 wrote 18
Producer 1 wrote 6
Producer 2 wrote 19
Consumer 2 read 14
Consumer 1 read 1
Consumer 2 read 15
Consumer 1 read 2
Producer 1 wrote 7
Producer 2 wrote 20
Producer 1 wrote 8
Producer 2 wrote 21
Consumer 2 read 3
Consumer 1 read 4
Consumer 2 read 16
Consumer 1 read 5
Consumer 2 read 17
Consumer 1 read 18
Consumer 2 read 6
Consumer 1 read 19
Consumer 1 read 20
Consumer 1 read 8
Consumer 1 read 21
Consumer 1 read 9
Consumer 2 read 7
Consumer 1 read 22
Producer 1 wrote 9
Producer 1 wrote 10
Producer 2 wrote 22
Producer 1 wrote 11
Consumer 2 read 10
Consumer 1 read 11
Consumer 2 read 23
Consumer 1 read 12
Producer 1 wrote 12
Producer 2 wrote 23
Consumer 2 read 13
Producer 1 wrote 13
Producer 2 wrote 24
Producer 1 wrote 14
Consumer 1 read 24
Producer 1 wrote 15
Producer 1 wrote 16
Producer 1 wrote 17
Producer 1 wrote 18
Producer 1 wrote 19
Producer 1 wrote 20
Producer 1 wrote 21
Consumer 1 read 25
Producer 1 wrote 22
Producer 1 wrote 23
Producer 1 wrote 24
Producer 1 wrote 25
Consumer 1 read 15
Producer 2 wrote 25
Producer 1 wrote 26
Consumer 1 read 16
Consumer 2 read 14
Consumer 1 read 17
Producer 2 wrote 26
Producer 2 wrote 27
Consumer 1 read 19
Consumer 2 read 18
Consumer 1 read 20
Consumer 1 read 22
Consumer 1 read 23
Producer 1 wrote 27
Consumer 2 read 21
Consumer 2 read 25
Consumer 2 read 26
Consumer 2 read 26
Consumer 2 read 27
Consumer 1 read 24
Consumer 2 read 27
Producer 1 wrote 28
Producer 1 wrote 29
Producer 1 wrote 30
Consumer 2 read 28
Consumer 2 read 29
Consumer 2 read 30
Consumer 2 read 31
Consumer 1 read 28
Producer 1 wrote 31
Producer 2 wrote 28
Producer 1 wrote 32
Producer 2 wrote 29
Producer 2 wrote 30
Producer 2 wrote 31
Producer 2 wrote 32
Producer 2 wrote 33
Producer 2 wrote 34
Producer 2 wrote 35
Producer 2 wrote 36
Producer 2 wrote 37
Producer 2 wrote 38
Consumer 2 read 32
Producer 1 wrote 33
Consumer 1 read 29
Consumer 2 read 33
Consumer 1 read 30
Consumer 1 read 32
Consumer 1 read 33
Consumer 1 read 34
Consumer 1 read 35
Consumer 1 read 36
Consumer 1 read 37
Producer 1 wrote 34
Consumer 1 read 38
Producer 1 wrote 35
Consumer 2 read 31
Consumer 1 read 39
Consumer 1 read 35
Consumer 1 read 36
Producer 1 wrote 36
Consumer 2 read 34
Consumer 1 read 37
Producer 1 wrote 37
Producer 1 wrote 38
Producer 2 wrote 39
Consumer 2 read 38
Consumer 1 read 39
Consumer 2 read 40
Producer 1 wrote 39
Producer 2 wrote 40
Consumer 1 read 40
Producer 1 wrote 40
Consumer 2 read 41
Consumer 1 read 41
Producer 1 wrote 41
Producer 2 wrote 41
Producer 1 wrote 42
Consumer 2 read 42
Producer 2 wrote 42
Producer 2 wrote 43
Producer 2 wrote 44
Producer 2 wrote 45
Producer 2 wrote 46
Producer 2 wrote 47
Producer 2 wrote 48
Producer 2 wrote 49
Producer 2 wrote 50
Producer 2 wrote 51
Consumer 1 read 42
Producer 1 wrote 43
Producer 2 wrote 52
Consumer 2 read 43
Consumer 1 read 43
Consumer 2 read 44
Consumer 2 read 46
Consumer 2 read 47
Consumer 1 read 45
Consumer 2 read 48
Consumer 2 read 50
Consumer 2 read 51
Consumer 2 read 52
Consumer 1 read 49
Consumer 1 read 44
Consumer 2 read 53
Producer 2 wrote 53
Producer 2 wrote 54
Producer 1 wrote 44
Consumer 1 read 54
Consumer 2 read 55
Consumer 1 read 45
Producer 2 wrote 55
Producer 1 wrote 45
Producer 2 wrote 56
Consumer 2 read 56
Producer 2 wrote 57
Consumer 1 read 57

Related

Is there a way to change the value of an eBPF map incrementally each time the function is called?

I'm currently using eBPF maps, and whenever I try to set the value (associated with a key in a hash table type map) to a variable that I increment at the end of the eBPF program, such that the value is incremented every time the function is run, the verifier throws an error,
invalid indirect read from stack R3 off -128+6 size 8
processed 188 insns (limit 1000000) max_states_per_insn 1 total_states 11 peak_states 11 mark_read 8
The main goal is to directly take the value and increment it every time the function is run.
I was under the impression that this would work.
bpf_spin_lock(&read_value->semaphore);
read_value->value += 1;
bpf_spin_unlock(&read_value->semaphore);
But this also throws the following error,
R1 type=inv expected=map_value
processed 222 insns (limit 1000000) max_states_per_insn 1 total_states 15 peak_states 15 mark_read 9

Efficient Reading of Input File

Currently for a task, I am working with input files which give Matrix related test cases (Matrix Multiplication) i.e., example of an input file ->
N M
1 3 5 ... 6 (M columns)
....
5 4 2 ... 1 (N rows)
I was using simple read() to access them till now, but this is not efficient for large files of size > 10^2.
So I wanted to know is there some way to use processes to do this in parallel.
Also I was thinking of using multiple IO readers based on line, so then each process could read different segments of the file but couldn't find any helpful resources.
Thank you.
PS: Current code is using this:
io:fread(IoDev, "", "~d")
Did you consider to use re module? I did not make a performance test, but it may be efficient. In the following example I do not use the first "M N" line. So I did not put it in the matrix.txt file.
matrix file:
1 2 3 4 5 6 7 8 9
11 12 13 14 15 16 17 18 19
21 22 23 24 25 26 27 28 29
31 32 33 34 35 36 37 38 39
I made the conversion in the shell
1> {ok,B} = file:read_file("matrix.txt"). % read the complete file and store it in a binary
{ok,<<"1 2 3 4 5 6 7 8 9\r\n11 12 13 14 15 16 17 18 19\r\n21 22 23 24 25 26 27 28 29\r\n31 32 33 34 35 36 37 38 39">>}
2> {ok,ML} = re:compile("[\r\n]+"). % to split the complete binary in a list a binary, one for each line
{ok,{re_pattern,0,0,0,
<<69,82,67,80,105,0,0,0,0,0,0,0,1,8,0,0,255,255,255,255,
255,255,...>>}}
3> {ok,MN} = re:compile("[ ]+"). % to split the line into binaries one for each integer
{ok,{re_pattern,0,0,0,
<<69,82,67,80,73,0,0,0,0,0,0,0,17,0,0,0,255,255,255,255,
255,255,...>>}}
4> % a function to split a line and convert each chunk into integer
4> F = fun(Line) -> Nums = re:split(Line,MN), [binary_to_integer(N) || N <- Nums] end.
#Fun<erl_eval.7.126501267>
5> Lines = re:split(B,ML). % split the file into lines
[<<"1 2 3 4 5 6 7 8 9">>,<<"11 12 13 14 15 16 17 18 19">>,
<<"21 22 23 24 25 26 27 28 29">>,
<<"31 32 33 34 35 36 37 38 39">>]
6> lists:map(F,Lines). % map the function to each lines
[[1,2,3,4,5,6,7,8,9],
[11,12,13,14,15,16,17,18,19],
[21,22,23,24,25,26,27,28,29],
[31,32,33,34,35,36,37,38,39]]
7>
if you want to check the matrix size, you can replace the last line with:
[[NbRows,NbCols]|Matrix] = lists:map(F,Lines),
case (length(Matrix) == NbRows) andalso
lists:foldl(fun(X,Acc) -> Acc andalso (length(X) == NbCols) end,true,Matrix) of
true -> {ok,Matrix};
_ -> {error_size,Matrix}
end.
is there some way to use processes to do this in parallel.
Of course.
Also I was thinking of using multiple IO readers based on line, so
then each process could read different segments of the file but
couldn't find any helpful resources.
You don't seek to positions in a file by line, rather you seek to byte positions. While a file may look like a bunch of lines, a file is actually just one long sequence of characters. Therefore, you will need to figure out what byte positions you want to seek to in the file.
Check out file:position, file:pread.

Multilevel Sum up (related child levels to its parent level) without macro

in one of my workbooks ı will have dynamic Bill of Material like (BoM) structure. Table will be dynamic so indenture levels can be change in time.
constants are:
only childs can take value and parents will get their value from
their child.
Parent value = sum of its children value
Aim is:
any parent labeled row is the sum of its children's values. level (n+1) are child of level n
for example
1 {30+50} parent
2 {10+10+10} parent
3 10 child
3 10 child
3 10 child
2 50 parent
what I tried:
I could achieve parent/child labeling. assuming Level heading is in
cell A1 then related formula is:
=IF(NOT(ISBLANK(A3));IF(A3>A2;"parent";"child");IF(A46=A45;"child";"parent"))
searched the web especially SO however couldn't find a beneficial
example
After searching a lot, I concluded that it can be achieved with offset,match,index,row and usage of array formulas may be however ı couldn't achieve
These dynamic structure has lots of rows so it will be really beneficial to me to make it auto. I can't run a macro (not allowed)
I think solution will be a long command sentence and If someone can help with some explanations also (logic, a very brief aim of the substep maybe) it'll be very appreciated
I like here cause I learn a lot (rather than getting a ready solution until next same case)
I studied with the example data below. (edit: "Manually Calculated Vals" column added to clarify what is being asked for. Actually that column is what I need done auto by excel)
edit2: there was an error in "Manually Calculated Vals" column. Thanks to XORLX. I corrected it.
regards
Level Value Parent/Child Manually Calculated Vals
0 parent 1815
1 parent 668
2 parent 110
3 19 child
3 91 child
2 parent 330
3 parent 200
4 40 child
4 79 child
4 81 child
3 60 child
3 42 child
3 28 child
2 3 child
2 35 child
2 parent 137
3 parent 113
4 46 child
4 67 child
3 24 child
2 53 child
1 parent 1147
2 parent 195
3 96 child
3 99 child
2 parent 325
3 parent 142
4 59 child
4 83 child
3 40 child
3 79 child
3 64 child
2 parent 240
3 parent 151
4 80 child
4 71 child
3 89 child
2 parent 157
3 57 child
3 100 child
2 parent 169
3 91 child
3 20 child
3 58 child
2 61 child
Assuming your table is in A1:C46 (with headers in row 1), put this array formula** in D2:
=IF(C2="child","",SUM(B3:INDEX(B3:B$46,LOOKUP(10^10,MATCH({6,1},SEARCH("T",(A3:A$46<=A2)&"T"),0))-1)))
Copy down as required.
Regards
**Array formulas are not entered in the same way as 'standard' formulas. Instead of pressing just ENTER, you first hold down CTRL and SHIFT, and only then press ENTER. If you've done it correctly, you'll notice Excel puts curly brackets {} around the formula (though do not attempt to manually insert these yourself).

blktrace to measure the IO performance

This is the ouput of the blktrace. I could not understand what is "N 0 (00 ..) [multipathd]". I'm testing the write IO performance of the FS.
I have 2 doubts,
N - is a action, but I dont find the usage of it in the blktrace.pdf.
What is the difference between IOSTAT and BLKTRACE.
blktrace o/p:
8,128 7 11 85.638053443 4009 I N 0 (00 ..) [multipathd]
8,128 7 12 85.638054275 4009 D N 0 (00 ..) [multipathd]
8,128 2 88 89.861199377 5210 A W 384 + 8 <- (253,0) 384
8,128 2 89 89.861199876 5210 Q W 384 + 8 [i_worker_0]
8,128 2 90 89.861202645 5210 G W 384 + 8 [i_worker_0]
8,128 2 91 89.861204604 5210 P N [i_worker_0]
8,128 2 92 89.861205587 5210 I WA 384 + 8 [i_worker_0]
8,128 2 93 89.861210869 5210 D WA 384 + 8 [i_worker_0]
8,128 2 94 89.861499857 0 C WA 384 + 8 [0]
8,128 2 95 99.845910681 5230 A W 384 + 8 <- (253,0) 384
8,128 2 96 99.845911148 5230 Q W 384 + 8 [i_worker_20]
8,128 2 97 99.845913846 5230 G W 384 + 8 [i_worker_20]
8,128 2 98 99.845915910 5230 P N [i_worker_20]
8,128 2 99 99.845917081 5230 I WA 384 + 8 [i_worker_20]
8,128 2 100 99.845922597 5230 D WA 384 + 8 [i_worker_20]
There is introduction to blktrace http://duch.mimuw.edu.pl/~lichota/09-10/Optymalizacja-open-source/Materialy/10%20-%20Dysk/gelato_ICE06apr_blktrace_brunelle_hp.pdf
difference between IOSTAT and BLKTRACE.
Check slides 5 and 6:
The iostat utility does provide information pertaining to request queues associated with 
specifics devices
– Average I/O time on queue, number of merges, number of  blocks read/written, ...
– However, it does not provide detailed information  on a per­I/O basis
Blktrace. Low-overhead, configurable kernel component which emits events for specific operations performed on each I/O entering the block I/O layer
So, iostat is generic tool to output statistics; and blktrace is tool to capture and output more information about all I/O requests served in the time when tool was active.
Slide 11 has some decoding intro
8,128 7 11 85.638053443 4009 I N 0 (00 ..) [multipathd]
maj/min cpu seq# timestamp_s.ns pid ACT RWBS blocks process
multipathd is kernel daemon, because its name is included into [] braces.
The default format is described in the blktrace.pdf (here is source of the pdf: http://git.kernel.org/cgit/linux/kernel/git/axboe/blktrace.git/tree/doc/blktrace.tex)
"%D %2c %8s %5T.%9t %5p %2a %3d "
%D Displays the event's device major/minor as: \%3d,\%-3d.
%2c CPU ID (2-character field).
%8s Sequence number
%5T.%9t 5-charcter field for the seconds portion of the
time stamp and a 9-character field for the nanoseconds in the time stamp.
%5p 5-character field for the process ID.
%2a 2-character field for one of the actions.
%3d 3-character field for the RWBS data.
Actions
C -- complete
D -- issued
I -- inserted
Q -- queued
B -- bounced
M -- back merge
F -- front merge
G -- get request
S -- sleep
P -- plug
U -- unplug
T -- unplug due to timer
X -- split
A -- remap
m -- message
RWBS
'R' - read,
'W' - write
'D' - block discard operation
'B' for barrier operation or
'S' for synchronous operation.
So, for multipathd we have "I" action = "inserted" and N for RWBS, and the N is strange. There is no N in the doc and even in the source: blkparse_fmt.c - fill_rwbs(). Why? Because it is old doc and old source.
In modern kernel, for example, 3.12 there is N in the fill_rwbs: http://sources.debian.net/src/linux/3.12.6-2/kernel/trace/blktrace.c?hl=1038#L1038
if (t->action == BLK_TN_MESSAGE) {
rwbs[i++] = 'N';
goto out;
}
And the blktrace_api.h declares BLK_TN_MESSAGE as
#define BLK_TN_MESSAGE (__BLK_TN_MESSAGE | BLK_TC_ACT(BLK_TC_NOTIFY))
* Trace categories
BLK_TC_NOTIFY = 1 << 10, /* special message */
* Notify events.
__BLK_TN_MESSAGE, /* Character string message */
So, 'N' is notify action with string message. I think the message is seen instead of "blocks" field. I was able to find the patch which added the TN_MESSAGE, but there was no update of the documentation (just as planned in bazaar-model like linux) http://lkml.org/lkml/2009/3/27/31 "[PATCH v2 6/7] blktrace: print out BLK_TN_MESSAGE properly" 2009

DES: (Using sbox 2) to show that Two output bits from each S-box affect middle bits of the next round and the other two affect the end bits

Data Encryption Standard (DES) algorithm : (Using sbox 2) to show that Two output bits from each S-box affect middle bits of the next round and the other two affect the end bits.
The permutation table P is defined in the following table.
16 7 20 21 29 12 28 17 [END BITS]
1 15 23 26 5 18 31 10 [MIDDLE BITS]
2 8 24 14 32 27 3 9 [MIDDLE BITS]
19 13 30 6 22 11 4 25 [END BITS]
From the table above you can see that bits 7 and 6 refer to the end bits and 5 and 8 refer to the middle bits.
However am not sure if this is correct because if we consider E table the 5,6 are end bits and 7,8 affecting middle bit. What is correct ?
Don't fully understand the question but your first statement about bits 7,6,5 and 8 is true, but remember that the "cascade effect" will make all the changes made by the P-table will go to the "right side" of the equation; but at the same time these will interact in the next round in the left side!
To fully understand the process check out this link: http://www.cronos.est.pr/DES.php

Resources