summaryrefslogtreecommitdiff
path: root/src/platform/darwin/platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/darwin/platform.c')
-rw-r--r--src/platform/darwin/platform.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/src/platform/darwin/platform.c b/src/platform/darwin/platform.c
new file mode 100644
index 0000000..4a2ed70
--- /dev/null
+++ b/src/platform/darwin/platform.c
@@ -0,0 +1,276 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "platform-darwin.h"
+
+static struct procenv_map signal_map_darwin[] = {
+
+ mk_map_entry (SIGALRM),
+ mk_map_entry (SIGBUS),
+ mk_map_entry (SIGCONT),
+ mk_map_entry (SIGFPE),
+ mk_map_entry (SIGHUP),
+ mk_map_entry (SIGILL),
+ mk_map_entry (SIGINT),
+ mk_map_entry (SIGKILL),
+ mk_map_entry (SIGPIPE),
+ mk_map_entry (SIGQUIT),
+ mk_map_entry (SIGSEGV),
+ mk_map_entry (SIGSTOP),
+ mk_map_entry (SIGTERM),
+ mk_map_entry (SIGTRAP),
+ mk_map_entry (SIGTSTP),
+ mk_map_entry (SIGTTIN),
+ mk_map_entry (SIGTTOU),
+ mk_map_entry (SIGUSR1),
+ mk_map_entry (SIGUSR2),
+ mk_map_entry (SIGXCPU),
+ mk_map_entry (SIGXFSZ),
+ mk_map_entry (SIGIOT),
+ mk_map_entry (SIGPROF),
+ mk_map_entry (SIGSYS),
+ mk_map_entry (SIGURG),
+ mk_map_entry (SIGVTALRM),
+
+#if defined (SIGIO)
+ mk_map_entry (SIGIO),
+#endif
+
+#if defined (SIGWINCH)
+ mk_map_entry (SIGWINCH),
+#endif
+
+#if defined (SIGINFO)
+ mk_map_entry (SIGINFO),
+#endif
+
+#if defined (SIGPOLL)
+ { SIGPOLL, "SIGPOLL|SIGEMT" },
+#elif defined (SIGEMT)
+ { SIGEMT, "SIGPOLL|SIGEMT" },
+#endif
+
+ { SIGCHLD, "SIGCHLD|SIGCLD" },
+ { SIGABRT, "SIGABRT|SIGIOT" },
+
+ { 0, NULL },
+};
+
+static struct procenv_map64 mntopt_map_darwin[] = {
+
+ { MNT_ASYNC , "asynchronous" },
+ { MNT_EXPORTED , "NFS-exported" },
+ { MNT_LOCAL , "local" },
+ { MNT_MULTILABEL , "multilabel" },
+ { MNT_NOATIME , "noatime" },
+ { MNT_NOEXEC , "noexec" },
+ { MNT_NOSUID , "nosuid" },
+ { MNT_QUOTA , "with quotas" },
+ { MNT_RDONLY , "read-only" },
+ { MNT_SYNCHRONOUS , "synchronous" },
+ { MNT_UNION , "union" },
+
+ { 0, NULL }
+};
+
+static struct procenv_map if_flag_map_darwin[] = {
+ mk_map_entry (IFF_UP),
+ mk_map_entry (IFF_BROADCAST),
+ mk_map_entry (IFF_DEBUG),
+ mk_map_entry (IFF_LOOPBACK),
+ mk_map_entry (IFF_POINTOPOINT),
+ mk_map_entry (IFF_RUNNING),
+ mk_map_entry (IFF_NOARP),
+ mk_map_entry (IFF_PROMISC),
+ mk_map_entry (IFF_ALLMULTI),
+ mk_map_entry (IFF_SIMPLEX),
+ mk_map_entry (IFF_MULTICAST),
+
+ { 0, NULL }
+};
+
+static void
+show_cpu_darwin (void)
+{
+ long max;
+
+ max = get_sysconf (_SC_NPROCESSORS_ONLN);
+
+ /* XXX: possible to determine current cpu? */
+ entry ("number", "%s of %lu", UNKNOWN_STR, max);
+}
+
+static bool
+get_time_darwin (struct timespec *ts)
+{
+ clock_serv_t cs;
+ mach_timespec_t mts;
+
+ // FIXME: can this fail?
+ host_get_clock_service (mach_host_self(), CALENDAR_CLOCK, &cs);
+
+ // FIXME: can this fail?
+ clock_get_time (cs, &mts);
+
+ // FIXME: can this fail?
+ mach_port_deallocate (mach_task_self(), cs);
+
+ ts->tv_sec = mts.tv_sec;
+ ts->tv_nsec = mts.tv_nsec;
+
+ return 0;
+}
+
+static void
+handle_proc_branch_darwin (void)
+{
+ struct kinfo_proc *procs = NULL;
+ struct kinfo_proc *p;
+ static const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
+ int ret;
+ int done = false;
+ size_t bytes;
+ size_t count;
+ size_t i;
+ pid_t current;
+ pid_t ultimate_parent = 0;
+ char *str = NULL;
+
+ /* arbitrary */
+ int attempts = 20;
+
+ current = getpid ();
+
+ /* XXX: This system interface seems horribly racy - what if the numbe of pids
+ * XXX: changes between the 1st and 2nd call to sysctl() ???
+ */
+ while (! done) {
+ attempts--;
+ if (! attempts)
+ return;
+
+ /* determine how much space required to store details of all
+ * processes.
+ */
+ ret = sysctl ((int *)mib, mib_len (mib), NULL, &bytes, NULL, 0);
+ if (ret < 0)
+ return;
+
+ count = bytes / sizeof (struct kinfo_proc);
+
+ /* allocate space */
+ procs = calloc (count, sizeof (struct kinfo_proc));
+ if (! procs)
+ return;
+
+ /* request the details of the processes */
+ ret = sysctl ((int *)mib, mib_len (mib), procs, &bytes, NULL, 0);
+ if (ret < 0) {
+ free (procs);
+ procs = NULL;
+ if (errno != ENOMEM) {
+ /* unknown error, so give up */
+ return;
+ }
+ } else {
+ done = true;
+ }
+ }
+
+ if (! done)
+ goto out;
+
+ /* reset */
+ done = false;
+
+ /* Calculate the lowest PID number which gives us the ultimate
+ * parent of all processes.
+ */
+ p = &procs[0];
+ ultimate_parent = p->kp_proc.p_pid;
+
+ for (i = 1; i < count; i++) {
+ p = &procs[i];
+ if (p->kp_proc.p_pid < ultimate_parent)
+ ultimate_parent = p->kp_proc.p_pid;
+ }
+
+ while (! done) {
+ for (i = 0; i < count && !done; i++) {
+ p = &procs[i];
+
+ if (p->kp_proc.p_pid == current) {
+
+ if (! ultimate_parent && current == ultimate_parent) {
+
+ /* Found the "last" PID so record it and hop out */
+ appendf (&str, "%d ('%s')",
+ (int)current, p->kp_proc.p_comm);
+
+ done = true;
+ break;
+ } else {
+ /* Found a valid parent pid */
+ appendf (&str, "%d ('%s'), ",
+ (int)current, p->kp_proc.p_comm);
+ }
+
+ /* Move on */
+ current = p->kp_eproc.e_ppid;
+ }
+ }
+ }
+
+ entry ("ancestry", "%s", str);
+
+out:
+ free_if_set (str);
+ free_if_set (procs);
+}
+
+
+static void
+show_mounts_darwin (ShowMountType what)
+{
+ show_mounts_generic_bsd (what, mntopt_map_darwin);
+}
+
+/* Darwin lacks:
+ *
+ * - cpusets and cpu affinities.
+ *
+ */
+struct procenv_ops platform_ops =
+{
+ .driver = PROCENV_SET_DRIVER (darwin),
+
+ .signal_map = signal_map_darwin,
+ .if_flag_map = if_flag_map_darwin,
+
+ .get_time = get_time_darwin,
+ .get_kernel_bits = get_kernel_bits_generic,
+ .get_mtu = get_mtu_generic,
+
+ .handle_proc_branch = handle_proc_branch_darwin,
+
+ .show_confstrs = show_confstrs_generic,
+ .show_cpu = show_cpu_darwin,
+ .show_fds = show_fds_generic,
+ .show_mounts = show_mounts_darwin,
+ .show_rlimits = show_rlimits_generic,
+};