Journal/Paper.thy
changeset 17 105715a0a807
parent 16 9764023f719e
child 20 b56616fd88dd
equal deleted inserted replaced
16:9764023f719e 17:105715a0a807
   300   \end{tabular}
   300   \end{tabular}
   301   \end{isabelle}
   301   \end{isabelle}
   302 
   302 
   303   \noindent
   303   \noindent
   304   In this definition we assume @{text "set"} converts a list into a set.
   304   In this definition we assume @{text "set"} converts a list into a set.
       
   305   Note that in the first definition the condition about @{text "th \<in> set (wq cs)"} does not follow
       
   306   from @{text "th = hd (set (wq cs))"}, since the head of an empty list is undefined in Isabelle/HOL. 
   305   At the beginning, that is in the state where no thread is created yet, 
   307   At the beginning, that is in the state where no thread is created yet, 
   306   the waiting queue function will be the function that returns the
   308   the waiting queue function will be the function that returns the
   307   empty list for every resource.
   309   empty list for every resource.
   308 
   310 
   309   \begin{isabelle}\ \ \ \ \ %%%
   311   \begin{isabelle}\ \ \ \ \ %%%
   378   waiting edge. The reason is that when a thread asks for resource that is locked
   380   waiting edge. The reason is that when a thread asks for resource that is locked
   379   already, then the process is blocked and cannot ask for another resource.
   381   already, then the process is blocked and cannot ask for another resource.
   380   Clearly, also every resource can only have at most one outgoing holding edge---indicating
   382   Clearly, also every resource can only have at most one outgoing holding edge---indicating
   381   that the resource is locked. In this way we can always start at a thread waiting for a 
   383   that the resource is locked. In this way we can always start at a thread waiting for a 
   382   resource and ``chase'' outgoing arrows leading to a single root of a tree. 
   384   resource and ``chase'' outgoing arrows leading to a single root of a tree. 
       
   385   
   383 
   386 
   384 
   387 
   385   The use of relations for representing RAGs allows us to conveniently define
   388   The use of relations for representing RAGs allows us to conveniently define
   386   the notion of the \emph{dependants} of a thread using the transitive closure
   389   the notion of the \emph{dependants} of a thread using the transitive closure
   387   operation for relations. This gives
   390   operation for relations. This gives
   525  
   528  
   526   \begin{isabelle}\ \ \ \ \ %%%
   529   \begin{isabelle}\ \ \ \ \ %%%
   527   \begin{tabular}{@ {}l}
   530   \begin{tabular}{@ {}l}
   528   @{thm (lhs) schs.simps(6)} @{text "\<equiv>"}\\
   531   @{thm (lhs) schs.simps(6)} @{text "\<equiv>"}\\
   529   \hspace{5mm}@{text "let"} @{text "wq = wq_fun (schs s)"} @{text "in"}\\
   532   \hspace{5mm}@{text "let"} @{text "wq = wq_fun (schs s)"} @{text "in"}\\
   530   \hspace{5mm}@{text "let"} @{text "new_wq = release (wq cs)"} @{text "in"}\\
   533   \hspace{5mm}@{text "let"} @{text "new_wq = wq(cs := release (wq cs))"} @{text "in"}\\
   531   \hspace{8mm}@{term "(|wq_fun = new_wq, cprec_fun = cpreced new_wq (V th cs # s)|)"}
   534   \hspace{8mm}@{term "(|wq_fun = new_wq, cprec_fun = cpreced new_wq (V th cs # s)|)"}
   532   \end{tabular}
   535   \end{tabular}
   533   \end{isabelle}
   536   \end{isabelle}
   534 
   537 
   535   Having the scheduler function @{term schs} at our disposal, we can ``lift'', or
   538   Having the scheduler function @{term schs} at our disposal, we can ``lift'', or
  1287   Our implicit assumption that every event is an atomic operation is ensured by the architecture of 
  1290   Our implicit assumption that every event is an atomic operation is ensured by the architecture of 
  1288   PINTOS (which allows disabling of interrupts when some operations are performed). The case where 
  1291   PINTOS (which allows disabling of interrupts when some operations are performed). The case where 
  1289   an unlocked resource is given next to the waiting thread with the
  1292   an unlocked resource is given next to the waiting thread with the
  1290   highest precedence is realised in our implementation by priority queues. We implemented
  1293   highest precedence is realised in our implementation by priority queues. We implemented
  1291   them as \emph{Braun trees} \cite{Paulson96}, which provide efficient @{text "O(log n)"}-operations
  1294   them as \emph{Braun trees} \cite{Paulson96}, which provide efficient @{text "O(log n)"}-operations
  1292   for accessing and updating. Apart from having to implement relatively complex data\-structures in C
  1295   for accessing and updating. In the code we shall describe below, we use the function
       
  1296   @{ML_text "queue_insert"}, for inserting a new element into a priority queue, and 
       
  1297   @{ML_text "queue_update"}, for updating the position of an element that is already
       
  1298   in a queue. Both functions take an extra argument that specifies the
       
  1299   comparison function used for organising the priority queue.
       
  1300   
       
  1301   Apart from having to implement relatively complex data\-structures in C
  1293   using pointers, our experience with the implementation has been very positive: our specification 
  1302   using pointers, our experience with the implementation has been very positive: our specification 
  1294   and formalisation of PIP translates smoothly to an efficent implementation in PINTOS. 
  1303   and formalisation of PIP translates smoothly to an efficent implementation in PINTOS. 
  1295   Let us illustrate this with the C-code for the function @{ML_text "lock_acquire"}, 
  1304   Let us illustrate this with the C-code for the function @{ML_text "lock_acquire"}, 
  1296   shown in Figure~\ref{code}.  This function implements the operation of requesting and, if free, 
  1305   shown in Figure~\ref{code}.  This function implements the operation of requesting and, if free, 
  1297   locking of a resource by the current running thread. The convention in the PINTOS
  1306   locking of a resource by the current running thread. The convention in the PINTOS
  1298   code is to use the terminology \emph{locks} rather than resources. 
  1307   code is to use the terminology \emph{locks} rather than resources. 
  1299   A lock is represented as a pointer to the structure {\tt lock} (Line 1). 
  1308   A lock is represented as a pointer to the structure {\tt lock} (Line 1). 
  1300 
       
  1301   Lines 2 to 4 are taken from the original 
  1309   Lines 2 to 4 are taken from the original 
  1302   code of @{ML_text "lock_acquire"} in PINTOS. They contain diagnostic code: first, 
  1310   code of @{ML_text "lock_acquire"} in PINTOS. They contain diagnostic code: first, 
  1303   there is a check that 
  1311   there is a check that 
  1304   the lock is a ``valid'' lock 
  1312   the lock is a ``valid'' lock 
  1305   by testing whether it is not {\tt NULL}; second, a check that the code is not called
  1313   by testing whether it is not {\tt NULL}; second, a check that the code is not called
  1306   as part of an interrupt---acquiring a lock should only be initiated by a 
  1314   as part of an interrupt---acquiring a lock should only be initiated by a 
  1307   request from a (user) thread, not from an interrupt; third, it is ensured that the 
  1315   request from a (user) thread, not from an interrupt; third, it is ensured that the 
  1308   current thread does not ask twice for a lock. These assertions are supposed
  1316   current thread does not ask twice for a lock. These assertions are supposed
  1309   to be satisfied because of the assumptions in PINTOS about how this code is called.
  1317   to be satisfied because of the assumptions in PINTOS about how this code is called.
  1310   If not, then the assertions indicate a bug in PINTOS and the result will be
  1318   If not, then the assertions indicate a bug in PINTOS and the result will be
  1311   a \emph{kernel panic}. 
  1319   a ``kernel panic''. 
  1312 
  1320 
  1313 
  1321 
  1314 
  1322 
  1315   \begin{figure}[t]
  1323   \begin{figure}[t]
  1316   \begin{lstlisting}
  1324   \begin{lstlisting}
  1345     queue_insert(lock_prec, &thread_current()->held, &lock->helem); 
  1353     queue_insert(lock_prec, &thread_current()->held, &lock->helem); 
  1346   };
  1354   };
  1347   intr_set_level(old_level);
  1355   intr_set_level(old_level);
  1348 }
  1356 }
  1349   \end{lstlisting}
  1357   \end{lstlisting}
  1350   \caption{Our version of the {\tt lock\_release} function for the small operating 
  1358   \caption{Our version of the {\tt lock\_acquire} function for the small operating 
  1351   system PINTOS.  It implements the operation corresponding to a @{text P}-event.\label{code}}
  1359   system PINTOS.  It implements the operation corresponding to a @{text P}-event.\label{code}}
  1352   \end{figure}
  1360   \end{figure}
  1353 
  1361 
  1354  
  1362  
  1355   Line 6 and 7 of {\tt lock\_acquire} make the operation of acquiring a lock atomic by disabling all 
  1363   Line 6 and 7 of {\tt lock\_acquire} make the operation of acquiring a lock atomic by disabling all 
  1364   current thread, and the other from the currend thread pointing to the lock.
  1372   current thread, and the other from the currend thread pointing to the lock.
  1365   According to our specification in Section~\ref{model} and the properties we were able 
  1373   According to our specification in Section~\ref{model} and the properties we were able 
  1366   to prove for @{text P}, we need to ``chase'' all the dependants 
  1374   to prove for @{text P}, we need to ``chase'' all the dependants 
  1367   in the RAG (Resource Allocation Graph) and update their
  1375   in the RAG (Resource Allocation Graph) and update their
  1368   current precedence; however we only have to do this as long as there is change in the 
  1376   current precedence; however we only have to do this as long as there is change in the 
  1369   current precedence from one thread at hand to another. 
  1377   current precedence.
  1370 
  1378 
  1371   The ``chase'' is implemented in the while-loop in Lines 13 to 24. 
  1379   The ``chase'' is implemented in the while-loop in Lines 13 to 24. 
  1372   To initialise the loop, we 
  1380   To initialise the loop, we 
  1373   assign in Lines 11 and 12 the variable @{ML_text pt} to the owner 
  1381   assign in Lines 11 and 12 the variable @{ML_text pt} to the owner 
  1374   of the lock.
  1382   of the lock.
  1393   
  1401   
  1394 
  1402 
  1395   Similar operations need to be implementated for the @{ML_text lock_release} function, which
  1403   Similar operations need to be implementated for the @{ML_text lock_release} function, which
  1396   we however do not show. The reader should note though that we did \emph{not} verify our C-code. 
  1404   we however do not show. The reader should note though that we did \emph{not} verify our C-code. 
  1397   This is in contrast, for example, to the work on seL4, which actually verified in Isabelle/HOL
  1405   This is in contrast, for example, to the work on seL4, which actually verified in Isabelle/HOL
  1398   that their C-code satisfies its specification \cite{sel4}.
  1406   that their C-code satisfies its specification, thought this specification does not contain 
  1399   Our verification however provided us with the justification for designing 
  1407   anything about PIP \cite{sel4}.
       
  1408   Our verification of PIP however provided us with the justification for designing 
  1400   the C-code. It gave us confidence that leaving the ``chase'' early, whenever
  1409   the C-code. It gave us confidence that leaving the ``chase'' early, whenever
  1401   there is no change in the calculated current precedence, does not break the
  1410   there is no change in the calculated current precedence, does not break the
  1402   correctness of the algorithm.
  1411   correctness of the algorithm.
  1403 *}
  1412 *}
  1404 
  1413 
  1442   the proof of Sha et al.: they require that critical sections nest properly, 
  1451   the proof of Sha et al.: they require that critical sections nest properly, 
  1443   whereas our scheduler allows critical sections to overlap. 
  1452   whereas our scheduler allows critical sections to overlap. 
  1444 
  1453 
  1445   PIP is a scheduling algorithm for single-processor systems. We are
  1454   PIP is a scheduling algorithm for single-processor systems. We are
  1446   now living in a multi-processor world. Priority Inversion certainly
  1455   now living in a multi-processor world. Priority Inversion certainly
  1447   occurs also there, see for example \cite{Brandenburg11, Davis11}  
  1456   occurs also there, see for example \cite{Brandenburg11, Davis11}.  
  1448   However, there is very little ``foundational''
  1457   However, there is very little ``foundational''
  1449   work about PIP-algorithms on multi-processor systems.  We are not
  1458   work about PIP-algorithms on multi-processor systems.  We are not
  1450   aware of any correctness proofs, not even informal ones. There is an
  1459   aware of any correctness proofs, not even informal ones. There is an
  1451   implementation of a PIP-algorithm for multi-processors as part of the
  1460   implementation of a PIP-algorithm for multi-processors as part of the
  1452   ``real-time'' effort in Linux, including an informal description of the implemented scheduling
  1461   ``real-time'' effort in Linux, including an informal description of the implemented scheduling