]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_lockf.c
xnu-4570.51.1.tar.gz
[apple/xnu.git] / bsd / kern / kern_lockf.c
index 0a3165cf21ccf253edcf9fec71fcc38d723cb651..5284f060cf419e82a54c942a0fff43c8966db89b 100644 (file)
@@ -149,6 +149,7 @@ static void  lf_hold_assertion(task_t, struct lockf *);
 static void     lf_jump_to_queue_head(struct lockf *, struct lockf *);
 static void     lf_drop_assertion(struct lockf *);
 static void     lf_boost_blocking_proc(struct lockf *, struct lockf *);
 static void     lf_jump_to_queue_head(struct lockf *, struct lockf *);
 static void     lf_drop_assertion(struct lockf *);
 static void     lf_boost_blocking_proc(struct lockf *, struct lockf *);
+static void     lf_adjust_assertion(struct lockf *block);
 #endif /* IMPORTANCE_INHERITANCE */
 
 /*
 #endif /* IMPORTANCE_INHERITANCE */
 
 /*
@@ -329,6 +330,12 @@ lf_advlock(struct vnop_advlock_args *ap)
                FREE(lock, M_LOCKF);
                break;
 
                FREE(lock, M_LOCKF);
                break;
 
+#if CONFIG_EMBEDDED
+       case F_GETLKPID:
+               error = lf_getlock(lock, fl, fl->l_pid);
+               FREE(lock, M_LOCKF);
+               break;
+#endif
 
        default:
                FREE(lock, M_LOCKF);
 
        default:
                FREE(lock, M_LOCKF);
@@ -665,6 +672,12 @@ lf_setlock(struct lockf *lock, struct timespec *timeout)
                         * in the spurious case, which would create a cycle)
                         */
                        TAILQ_REMOVE(&lock->lf_next->lf_blkhd, lock, lf_block);
                         * in the spurious case, which would create a cycle)
                         */
                        TAILQ_REMOVE(&lock->lf_next->lf_blkhd, lock, lf_block);
+#if IMPORTANCE_INHERITANCE
+                       /*
+                        * Adjust the boost on lf_next.
+                        */
+                       lf_adjust_assertion(lock->lf_next);
+#endif /* IMPORTANCE_INHERITANCE */
                        lock->lf_next = NULL;
 
                        if (error == 0) {
                        lock->lf_next = NULL;
 
                        if (error == 0) {
@@ -1483,6 +1496,50 @@ lf_drop_assertion(struct lockf *block)
        block->lf_boosted = LF_NOT_BOOSTED;
 }
 
        block->lf_boosted = LF_NOT_BOOSTED;
 }
 
+/*
+ * lf_adjust_assertion
+ *
+ * Adjusts importance assertion of file lock. Goes through
+ * all the blocking locks and checks if the file lock needs
+ * to be boosted anymore.
+ *
+ * Parameters: block   lockf structure which needs to be adjusted.
+ *
+ * Returns:    <void>
+ */
+static void
+lf_adjust_assertion(struct lockf *block)
+{
+       boolean_t drop_boost = TRUE;
+       struct lockf *next;
+
+       /* Return if the lock is not boosted */
+       if (block->lf_boosted == LF_NOT_BOOSTED) {
+               return;
+       }
+
+       TAILQ_FOREACH(next, &block->lf_blkhd, lf_block) {
+               /* Check if block and next are same type of locks */
+               if (((block->lf_flags & next->lf_flags & F_POSIX) != 0) ||
+                   ((block->lf_flags & next->lf_flags & F_OFD_LOCK) &&
+                    (block->lf_owner != next->lf_owner) &&
+                    (NULL != block->lf_owner && NULL != next->lf_owner))) {
+
+                       /* Check if next would be boosting block */
+                       if (task_is_importance_donor(proc_task(next->lf_owner)) &&
+                           task_is_importance_receiver_type(proc_task(block->lf_owner))) {
+                               /* Found a lock boosting block */
+                               drop_boost = FALSE;
+                               break;
+                       }
+               }
+       }
+
+       if (drop_boost) {
+               lf_drop_assertion(block);
+       }
+}
+
 static void
 lf_boost_blocking_proc(struct lockf *lock, struct lockf *block)
 {
 static void
 lf_boost_blocking_proc(struct lockf *lock, struct lockf *block)
 {