]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/kern/sync_sema.c
xnu-4903.221.2.tar.gz
[apple/xnu.git] / osfmk / kern / sync_sema.c
index 4304559e67d3011188330dbf871c73447c58857a..98f33ba8d69dae1e37e6ce1111ee1a92ec1a5911 100644 (file)
@@ -66,6 +66,8 @@ static unsigned int semaphore_event;
 zone_t semaphore_zone;
 unsigned int semaphore_max;
 
+os_refgrp_decl(static, sema_refgrp, "semaphore", NULL);
+
 /* Forward declarations */
 
 
@@ -184,7 +186,7 @@ semaphore_create(
         * Initialize the semaphore values.
         */
        s->port = IP_NULL;
-       s->ref_count = 1;
+       os_ref_init(&s->ref_count, &sema_refgrp);
        s->count = value;
        s->active = TRUE;
        s->owner = task;
@@ -280,11 +282,12 @@ semaphore_destroy(
 
        if (semaphore->owner != task) {
                semaphore_unlock(semaphore);
+               semaphore_dereference(semaphore);
                splx(spl_level);
                task_unlock(task);
                return KERN_INVALID_ARGUMENT;
        }
-                       
+
        semaphore_destroy_internal(task, semaphore);
        /* semaphore unlocked */
 
@@ -687,7 +690,8 @@ semaphore_wait_internal(
                thread_t        self = current_thread();
 
                wait_semaphore->count = -1;  /* we don't keep an actual count */
-               thread_lock(self);
+
+               thread_set_pending_block_hint(self, kThreadWaitSemaphore);
                (void)waitq_assert_wait64_locked(
                                        &wait_semaphore->waitq,
                                        SEMAPHORE_EVENT,
@@ -695,7 +699,6 @@ semaphore_wait_internal(
                                        TIMEOUT_URGENCY_USER_NORMAL,
                                        deadline, TIMEOUT_NO_LEEWAY,
                                        self);
-               thread_unlock(self);
        }
        semaphore_unlock(wait_semaphore);
        splx(spl_level);
@@ -1105,7 +1108,7 @@ void
 semaphore_reference(
        semaphore_t             semaphore)
 {
-       (void)hw_atomic_add(&semaphore->ref_count, 1);
+       os_ref_retain(&semaphore->ref_count);
 }
 
 /*
@@ -1124,8 +1127,9 @@ semaphore_dereference(
        if (semaphore == NULL)
                return;
 
-       if (hw_atomic_sub(&semaphore->ref_count, 1) != 0)
+       if (os_ref_release(&semaphore->ref_count) > 0) {
                return;
+       }
 
        /*
         * Last ref, clean up the port [if any]
@@ -1173,4 +1177,15 @@ semaphore_dereference(
        zfree(semaphore_zone, semaphore);
 }
 
+#define WAITQ_TO_SEMA(wq) ((semaphore_t) ((uintptr_t)(wq) - offsetof(struct semaphore, waitq)))
+void
+kdp_sema_find_owner(struct waitq * waitq, __assert_only event64_t event, thread_waitinfo_t * waitinfo)
+{
+       semaphore_t sem = WAITQ_TO_SEMA(waitq);
+       assert(event == SEMAPHORE_EVENT);
+       assert(kdp_is_in_zone(sem, "semaphores"));
 
+       waitinfo->context = VM_KERNEL_UNSLIDE_OR_PERM(sem->port);
+       if (sem->owner)
+               waitinfo->owner = pid_from_task(sem->owner);
+}