···11+/*
22+ * Darling Mach Linux Kernel Module
33+ * Copyright (C) 2015 Lubos Dolezel
44+ *
55+ * This program is free software; you can redistribute it and/or
66+ * modify it under the terms of the GNU General Public License
77+ * as published by the Free Software Foundation; either version 2
88+ * of the License, or (at your option) any later version.
99+ *
1010+ * This program is distributed in the hope that it will be useful,
1111+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1313+ * GNU General Public License for more details.
1414+ *
1515+ * You should have received a copy of the GNU General Public License
1616+ * along with this program; if not, write to the Free Software
1717+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1818+ */
1919+2020+#include "psynch_mutex.h"
2121+#include "../darling_task.h"
2222+#include <linux/sched.h>
2323+#include <linux/wait.h>
2424+#include <linux/list.h>
2525+#include <linux/uaccess.h>
2626+#include <linux/slab.h>
2727+2828+struct pthread_mutex
2929+{
3030+ struct hlist_node node;
3131+ uint64_t pointer;
3232+ uint32_t mgen;
3333+ wait_queue_head_t wq;
3434+ struct list_head waiting;
3535+ unsigned int refcount;
3636+};
3737+typedef struct pthread_mutex pthread_mutex_t;
3838+3939+struct pthread_waiter
4040+{
4141+ struct list_head entry;
4242+ int wakeup;
4343+};
4444+4545+static pthread_mutex_t* mutex_get(mach_task_t* task, uint64_t address);
4646+static void mutex_put(mach_task_t* task, pthread_mutex_t* mutex);
4747+4848+int psynch_mutexwait_trap(mach_task_t* task,
4949+ struct psynch_mutexwait_args* in_args)
5050+{
5151+ struct psynch_mutexwait_args args;
5252+ struct pthread_waiter waiter;
5353+ pthread_mutex_t* mutex;
5454+ int retval = 0;
5555+5656+ if (copy_from_user(&args, in_args, sizeof(args)))
5757+ return -EFAULT;
5858+5959+ spin_lock(&task->mutex_wq_lock);
6060+6161+ mutex = mutex_get(task, args.mutex);
6262+6363+ if (mutex->mgen == 0)
6464+ {
6565+ spin_unlock(&task->mutex_wq_lock);
6666+6767+ retval = 0;
6868+ goto out;
6969+ }
7070+7171+ waiter.wakeup = 0;
7272+ list_add(&waiter.entry, &mutex->waiting);
7373+7474+ spin_unlock(&task->mutex_wq_lock);
7575+7676+ retval = wait_event_interruptible(mutex->wq, waiter.wakeup != 0);
7777+7878+ spin_lock(&task->mutex_wq_lock);
7979+ list_del(&waiter.entry);
8080+8181+ if (waiter.wakeup)
8282+ retval = mutex->mgen;
8383+8484+ mutex_put(task, mutex);
8585+ spin_unlock(&task->mutex_wq_lock);
8686+8787+out:
8888+ return retval;
8989+}
9090+9191+int psynch_mutexdrop_trap(mach_task_t* task,
9292+ struct psynch_mutexdrop_args* args)
9393+{
9494+ return 0;
9595+}
9696+9797+pthread_mutex_t* mutex_get(mach_task_t* task, uint64_t address)
9898+{
9999+ pthread_mutex_t* node;
100100+ hash_for_each_possible(task->mutex_wq, node, node, address)
101101+ {
102102+ if (node->pointer != address)
103103+ continue;
104104+105105+ node->refcount++;
106106+ return node;
107107+ }
108108+109109+ node = (pthread_mutex_t*) kmalloc(sizeof(pthread_mutex_t), GFP_KERNEL);
110110+ node->refcount = 1;
111111+ node->mgen = 0;
112112+ node->pointer = address;
113113+114114+ init_waitqueue_head(&node->wq);
115115+ INIT_LIST_HEAD(&node->waiting);
116116+ hash_add(task->mutex_wq, &node->node, address);
117117+118118+ return node;
119119+}
120120+121121+void mutex_put(mach_task_t* task, pthread_mutex_t* mutex)
122122+{
123123+ mutex->refcount--;
124124+125125+ if (mutex->refcount == 0)
126126+ {
127127+ hash_del(&mutex->node);
128128+ kfree(mutex);
129129+ }
130130+}
+31
src/lkm/psynch/psynch_mutex.h
···11+/*
22+ * Darling Mach Linux Kernel Module
33+ * Copyright (C) 2015 Lubos Dolezel
44+ *
55+ * This program is free software; you can redistribute it and/or
66+ * modify it under the terms of the GNU General Public License
77+ * as published by the Free Software Foundation; either version 2
88+ * of the License, or (at your option) any later version.
99+ *
1010+ * This program is distributed in the hope that it will be useful,
1111+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1313+ * GNU General Public License for more details.
1414+ *
1515+ * You should have received a copy of the GNU General Public License
1616+ * along with this program; if not, write to the Free Software
1717+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1818+ */
1919+2020+#ifndef PSYNCH_MUTEX_H
2121+#define PSYNCH_MUTEX_H
2222+#include "../api.h"
2323+#include "../ipc_types.h"
2424+2525+int psynch_mutexwait_trap(mach_task_t* task,
2626+ struct psynch_mutexwait_args* args);
2727+int psynch_mutexdrop_trap(mach_task_t* task,
2828+ struct psynch_mutexdrop_args* args);
2929+3030+#endif /* PSYNCH_MUTEX_H */
3131+